feat: add algorithmic size and font scales

Add :scales config to tokens.edn with two generated scales:
- Size (linear): --size-1 through --size-16, base 0.25rem × N
- Font (geometric): --font-xs through --font-3xl, ratio 1.25

gen.clj computes values and emits them into :root only (not dark
theme blocks). button.css now uses scale vars instead of raw rem.
Change base or ratio in tokens.edn to recompute the entire scale.
This commit is contained in:
Florian Schroedl
2026-03-03 11:16:23 +01:00
parent 988617617c
commit 609613f4fb
5 changed files with 114 additions and 13 deletions

View File

@@ -1,4 +1,16 @@
{:tokens
{:scales
{:size {:base 0.25 :unit "rem" :steps 16}
:font {:base 1 :unit "rem" :ratio 1.25
:steps [[-2 "xs"]
[-1 "sm"]
[0 "base"]
[1 "md"]
[2 "lg"]
[3 "xl"]
[4 "2xl"]
[5 "3xl"]]}}
:tokens
{:bg-0 "#ffffff"
:bg-1 "#f5f5f5"
:bg-2 "#e8e8e8"

View File

@@ -3,10 +3,10 @@
align-items: center;
justify-content: center;
gap: 0.5em;
padding: 0.5rem 1rem;
font-size: 0.875rem;
padding: var(--size-2) var(--size-4);
font-size: var(--font-sm);
font-weight: 500;
line-height: 1.25rem;
line-height: var(--size-5);
border: none;
border-radius: var(--radius-md);
cursor: pointer;
@@ -48,15 +48,15 @@
}
.btn-sm {
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
line-height: 1rem;
padding: var(--size-1) var(--size-2);
font-size: var(--font-xs);
line-height: var(--size-4);
}
.btn-lg {
padding: 0.75rem 1.5rem;
font-size: 1rem;
line-height: 1.5rem;
padding: var(--size-3) var(--size-6);
font-size: var(--font-base);
line-height: var(--size-6);
}
.btn:disabled {

View File

@@ -21,6 +21,40 @@
(map (fn [[k v]] (str " " (token->css-var k) ": " v ";")))
(str/join "\n")))
(defn format-number
"Format a number: strip trailing zeros, max 3 decimal places."
[n]
(let [s (format "%.3f" (double n))]
(-> s
(str/replace #"0+$" "")
(str/replace #"\.$" ""))))
(defn generate-size-scale
"Generate linear size scale: --size-N = base * N."
[{:keys [base unit steps]}]
(->> (range 1 (inc steps))
(map (fn [n]
(str " --size-" n ": " (format-number (* base n)) unit ";")))
(str/join "\n")))
(defn generate-font-scale
"Generate geometric font scale: --font-{name} = base * ratio^power."
[{:keys [base unit ratio steps]}]
(->> steps
(map (fn [[power label]]
(str " --font-" label ": "
(format-number (* base (Math/pow ratio power)))
unit ";")))
(str/join "\n")))
(defn generate-scales
"Generate CSS variable declarations for all scales."
[scales]
(str/join "\n"
(cond-> []
(:size scales) (conj (generate-size-scale (:size scales)))
(:font scales) (conj (generate-font-scale (:font scales))))))
(defn base-css
"Generate base body/reset styles."
[]
@@ -42,9 +76,12 @@
(defn generate-css
"Generate the full CSS output from parsed token data."
[{:keys [tokens themes]}]
[{:keys [tokens themes scales]}]
(let [dark-tokens (get themes :dark)
root-block (str ":root {\n" (tokens->css-block tokens) "\n}")
scale-vars (when scales (generate-scales scales))
root-block (str ":root {\n" (tokens->css-block tokens)
(when scale-vars (str "\n" scale-vars))
"\n}")
dark-attr (str "[data-theme=\"dark\"] {\n" (tokens->css-block dark-tokens) "\n}")
dark-media (str "@media (prefers-color-scheme: dark) {\n"
" :root:not([data-theme=\"light\"]) {\n"