|
| 1 | +# SLASHED Token Cleanup Proposal |
| 2 | + |
| 3 | +> **Purpose:** Reduce the *conceptual surface* of SLASHED's `--sf-*` token API for its real audience — |
| 4 | +> people building **marketing sites, landing pages, and business/corporate websites**. Bytes are not |
| 5 | +> the goal (gzip handles those); the goal is shrinking what an author must understand when they open |
| 6 | +> `core/tokens.css` or an optional bundle. |
| 7 | +> |
| 8 | +> **Decision rule:** keep a family if a landing-page / business-site builder would plausibly reach for |
| 9 | +> it; trim or cut it if it's power-user or vestigial (they'd inline a value or use the base scale). |
| 10 | +> |
| 11 | +> **How to use this doc:** edit the `Decision:` line on each item (`CUT` / `TRIM` / `KEEP`), adjust |
| 12 | +> counts or kept-subsets in the tables, and leave notes inline. Nothing here is implemented yet. |
| 13 | +
|
| 14 | +- **Current surface:** ~899 `--sf-*` tokens |
| 15 | +- **Proposed removal:** ~205 tokens (~23%) |
| 16 | +- **Target after cuts:** ~695 tokens |
| 17 | +- **Release:** single breaking change, `0.5.47 → 0.6.0` |
| 18 | +- **Branch:** `claude/confident-maxwell-5dd0pa` |
| 19 | + |
| 20 | +--- |
| 21 | + |
| 22 | +## Summary table |
| 23 | + |
| 24 | +| # | Family | Location | Count | Proposal | Audience need | |
| 25 | +|---|---|---|---|---|---| |
| 26 | +| 1 | Fluid-pair "bridge" matrix | `optional/tokens.sizes-extended.css` | ~130 | **TRIM** → keep ~8–10 | Very low | |
| 27 | +| 2 | Alpha color ramps | `optional/tokens.palette.css` | ~66 | **TRIM** → keep 5/family (~30 kept, ~36 cut) | Low–medium | |
| 28 | +| 3 | Blur presets | `core/tokens.css` | 5 | **CUT** | Low | |
| 29 | +| 4 | Stroke presets | `core/tokens.css` | 4 | **CUT** | Very low | |
| 30 | +| 5 | Multi-column presets | `core/tokens.css` | 6 | **CUT** | Very low | |
| 31 | +| 6 | Numeric opacity scale | `core/tokens.css` | 6 | **CUT** (keep `-disabled`) | Low | |
| 32 | +| 7 | `truncate-suffix` | `core/tokens.macros.css` | 1 | **CUT** | Minimal | |
| 33 | +| 8 | Unused state flags | `core/tokens.css` | 2 | **CUT** (keep `-current`/`-active`/`-dark`) | Low | |
| 34 | +| 9 | Rare font-weights | `core/tokens.css` | 4 | **CUT** (keep light/normal/medium/semibold/bold) | Low | |
| 35 | +| 10 | Fluid custom slots | `core/tokens.css` | 9 | **CUT** | Low (advanced) | |
| 36 | +| — | Z-index ladder + aliases | `core/tokens.css` | — | **KEEP ALL** | High | |
| 37 | +| — | Per-level heading max-width | `core/tokens.css` / `core/base.css` | — | **KEEP** | Medium–high | |
| 38 | +| — | 7 scale knobs | `core/tokens.css` | — | **KEEP** | High | |
| 39 | +| — | All `:root` color / theming blocks | `core/tokens.css`, `core/themes.css` | — | **KEEP** | Critical | |
| 40 | +| — | Safe-area insets | `core/tokens.css` | — | **KEEP** | Medium (mobile) | |
| 41 | + |
| 42 | +> Counts marked `~` are approximate and must be confirmed against the live files during |
| 43 | +> implementation (the generated families differ slightly between earlier scans: bridge matrix reported |
| 44 | +> as both ~72 and ~140; alpha as ~66). |
| 45 | +
|
| 46 | +--- |
| 47 | + |
| 48 | +## CUT / TRIM candidates (detailed) |
| 49 | + |
| 50 | +### 1. Fluid-pair "bridge" matrix — **TRIM** |
| 51 | + |
| 52 | +- **Location:** `optional/tokens.sizes-extended.css` (generated by `scripts/gen-sizes-extended.js`) |
| 53 | +- **Tokens:** the full combinatorial set `--sf-space-{step}-to-{step}` and `--sf-text-{step}-to-{step}` |
| 54 | + (every pairing of scale steps fluidly interpolated across the viewport). |
| 55 | +- **Count:** ~130 (confirm exact) |
| 56 | +- **Internal consumers:** none — no core component or utility uses a specific pair. |
| 57 | +- **Why cut:** An author building a landing page uses the base `--sf-space-*` / `--sf-text-*` scale, |
| 58 | + which is *already* fluid via `clamp()`. Nobody hand-picks `--sf-text-2xl-to-s`. An N×N menu is the |
| 59 | + clearest case of concept bloat in the framework. |
| 60 | +- **Proposal:** keep a small curated set of common adjacent-step pairs (for fluid section spacing and |
| 61 | + hero type), cut the rest. Update the generator to emit only the kept pairs. |
| 62 | +- **Suggested keep-list (edit freely):** |
| 63 | + - `--sf-space-m-to-xl`, `--sf-space-l-to-2xl`, `--sf-space-s-to-l` (fluid section padding) |
| 64 | + - `--sf-text-l-to-2xl`, `--sf-text-xl-to-3xl`, `--sf-text-2xl-to-4xl` (fluid hero/heading) |
| 65 | +- **Migration:** authors needing a custom pair write their own `clamp()` or import a generated extra. |
| 66 | +- **Decision:** `TRIM` ▢ — keep-list: ____________________ |
| 67 | + |
| 68 | +### 2. Alpha color ramps — **TRIM** |
| 69 | + |
| 70 | +- **Location:** `optional/tokens.palette.css` (+ its generator) |
| 71 | +- **Tokens:** `--sf-color-{family}-a5 … -a95` for ~6 families (11 steps each). |
| 72 | +- **Count:** ~66 total → keep 5/family (~30), cut ~36. |
| 73 | +- **Internal consumers:** functional aliases (hover/active/subtle/muted/ghost) redirect into these |
| 74 | + steps, but no rule needs the full ladder. |
| 75 | +- **Why trim:** real sites use ~2–3 alpha levels — a subtle tint (hover/focus ~10%), a moderate scrim |
| 76 | + (~50%), a strong overlay (~80%). 11 steps is granularity nobody dials in by hand. |
| 77 | +- **Proposal:** keep `a5, a10, a30, a50, a80` per family; drop `a20, a40, a60, a70, a90, a95`. |
| 78 | + **Re-point any functional alias** that currently targets a dropped step onto a kept step. |
| 79 | +- **Migration:** intermediate steps via `oklch(from var(--sf-color-x) l c h / .NN)`. |
| 80 | +- **Decision:** `TRIM` ▢ — keep-steps: `a5, a10, a30, a50, a80` (edit) ____________________ |
| 81 | + |
| 82 | +### 3. Blur presets — **CUT** |
| 83 | + |
| 84 | +- **Location:** `core/tokens.css:1172-1176` |
| 85 | +- **Tokens:** `--sf-blur-xs`, `--sf-blur-s`, `--sf-blur-m`, `--sf-blur-l`, `--sf-blur-xl` (4px–48px) |
| 86 | +- **Internal consumers:** none. |
| 87 | +- **Why cut:** glassmorphism/backdrop-blur is a trend, not a business-site need; no bundled component |
| 88 | + uses it. Authors who want a frosted nav inline `backdrop-filter: blur(12px)`. |
| 89 | +- **Counter-argument (kept for your review):** frosted sticky navs *are* fashionable on some landing |
| 90 | + pages. If you want to keep one knob, retain a single `--sf-blur` default instead of the 5-step scale. |
| 91 | +- **Decision:** `CUT` ▢ / keep single `--sf-blur` ▢ |
| 92 | + |
| 93 | +### 4. Stroke presets — **CUT** |
| 94 | + |
| 95 | +- **Location:** `core/tokens.css:1348-1351` |
| 96 | +- **Tokens:** `--sf-stroke-thin`, `--sf-stroke-regular`, `--sf-stroke-bold`, `--sf-stroke-heavy` (1–3px) |
| 97 | +- **Internal consumers:** none. |
| 98 | +- **Why cut:** SVG `stroke-width` styling is niche; authors set it on the SVG or reuse |
| 99 | + `--sf-border-width-*`. |
| 100 | +- **Decision:** `CUT` ▢ |
| 101 | + |
| 102 | +### 5. Multi-column presets — **CUT** |
| 103 | + |
| 104 | +- **Location:** `core/tokens.css:1366-1371` |
| 105 | +- **Tokens:** `--sf-col-width-s/m/l`, `--sf-col-rule-width-s/m/l` |
| 106 | +- **Internal consumers:** none. |
| 107 | +- **Why cut:** CSS multi-column breaks on mobile and is essentially unused in modern marketing layout |
| 108 | + (Grid/Flex instead). |
| 109 | +- **Decision:** `CUT` ▢ |
| 110 | + |
| 111 | +### 6. Numeric opacity scale — **CUT (keep `-disabled`)** |
| 112 | + |
| 113 | +- **Location:** `core/tokens.css:1178-1183` (scale) and `:482` (`--sf-opacity-disabled`) |
| 114 | +- **Cut:** `--sf-opacity-0/10/25/50/75/100` |
| 115 | +- **KEEP:** `--sf-opacity-disabled` — actively used by `core/states.css:44`, `optional/forms.css`, |
| 116 | + `core/accessibility.css:107`. |
| 117 | +- **Why cut the scale:** authors know whether they want 0.5 or 0.3; a preset 0–100 ladder is academic. |
| 118 | +- **Decision:** `CUT scale / KEEP disabled` ▢ |
| 119 | + |
| 120 | +### 7. `truncate-suffix` — **CUT** |
| 121 | + |
| 122 | +- **Location:** `core/tokens.macros.css:45` (default `"\2026"` = `…`) |
| 123 | +- **Internal consumers:** none — the `.sf-truncate` macro (`core/macros.css:100-104`) hardcodes |
| 124 | + `text-overflow: ellipsis` and never reads this token. |
| 125 | +- **Why cut:** aspirational ellipsis-override hook nobody discovers or uses. |
| 126 | +- **Decision:** `CUT` ▢ |
| 127 | + |
| 128 | +### 8. Unused interaction-state flags — **CUT 2 of 5** |
| 129 | + |
| 130 | +- **Location:** `core/tokens.css:278-281` (+ `--sf-is-dark:273`) |
| 131 | +- **Cut:** `--sf-is-pressed`, `--sf-is-open` — never set or read anywhere. |
| 132 | +- **KEEP:** `--sf-is-current` (drives nav "current page" styling, `core/states.css:144`), |
| 133 | + `--sf-is-active` (real toggle/dropdown hook, `core/states.css:132`), `--sf-is-dark` (theming flag). |
| 134 | +- **Decision:** `CUT pressed+open` ▢ |
| 135 | + |
| 136 | +### 9. Rare font-weights — **CUT 4 of 9 numeric** |
| 137 | + |
| 138 | +- **Location:** `core/tokens.css:924-941` |
| 139 | +- **Full list:** thin(100), extralight(200), light(300), normal(400), medium(500), semibold(600), |
| 140 | + bold(700), extrabold(800), black(900) + semantic `body→400`, `heading→600`, `display→700`. |
| 141 | +- **Cut:** `thin`, `extralight`, `extrabold`, `black`. |
| 142 | +- **KEEP:** `light, normal, medium, semibold, bold` + the three semantic aliases. |
| 143 | +- **Why this split:** light (elegant hero display) and medium (buttons/labels) are common in real |
| 144 | + marketing/business type even though no *bundled* component applies them; the four extremes are |
| 145 | + showroom weights nobody puts on a corporate site. |
| 146 | +- **⚠️ Open question for you:** the author-facing scan found **`light` and `medium` are not used by any |
| 147 | + bundled component** (only normal/semibold/bold/body/heading are). If you want the leanest possible |
| 148 | + set, also cut `light` + `medium` (→ cut 6, keep normal/semibold/bold + semantic). Your call. |
| 149 | +- **Decision:** `CUT thin/extralight/extrabold/black` ▢ also cut light+medium? ▢ |
| 150 | + |
| 151 | +### 10. Fluid custom slots — **CUT** |
| 152 | + |
| 153 | +- **Location:** `core/tokens.css:328-360` (`@property` regs + `:root` mirrors + 3 `clamp()` outputs) |
| 154 | +- **Tokens:** `--sf-fluid-custom-{1,2,3}` + `--sf-fluid-custom-{1,2,3}-{min,max}` (9 total) |
| 155 | +- **Internal consumers:** none — only `tests/fluid-custom.spec.js` and commented examples. |
| 156 | +- **KEEP the shared engine knobs** `--sf-fluid-min-vw` / `--sf-fluid-max-vw` (power the core scales). |
| 157 | +- **Why cut:** a "bring-your-own fluid value" power-user feature; the target author writes their own |
| 158 | + `clamp()` or uses the scale. Too advanced to earn 9 tokens of surface. |
| 159 | +- **Side tasks:** delete `tests/fluid-custom.spec.js`; fix `--sf-fluid-custom-1` ref in |
| 160 | + `configurator/tests/domains.test.js`; remove commented example in `optional/config-example.css`. |
| 161 | +- **Decision:** `CUT` ▢ |
| 162 | + |
| 163 | +--- |
| 164 | + |
| 165 | +## KEEP — re-judged as genuinely useful (do not cut) |
| 166 | + |
| 167 | +### Z-index ladder + semantic aliases — **KEEP ALL** |
| 168 | +- `core/tokens.css:1233-1246`. Ladder: `below(-1) base(0) raised(1) low(10) mid(100) high(500) |
| 169 | + top(900) max(9999)`; aliases: `sticky/fixed/dropdown/toast/overlay`. |
| 170 | +- Essential mental model for nav, sticky headers, dropdowns, modals, toasts — the core of any |
| 171 | + marketing/business site. *(This reverses an earlier proposal to collapse it.)* |
| 172 | + |
| 173 | +### Per-level heading max-width — **KEEP** |
| 174 | +- `--sf-h1-max-width … --sf-h6-max-width`, applied in `core/base.css:35-40`. |
| 175 | +- Controls line length for readability; per-level override is cheap and occasionally wanted. |
| 176 | + *(Reverses an earlier collapse-to-one proposal.)* |
| 177 | + |
| 178 | +### 7 scale knobs — **KEEP ALL** |
| 179 | +- `--sf-{space,text,text-display,radius,motion,section,border}-scale` (`core/tokens.css`, all default `1`). |
| 180 | +- Global retuning via the configurator + 6 presets is a core value prop. Removing any would require |
| 181 | + rewiring the configurator, presets, and ~50 tests. |
| 182 | + |
| 183 | +### All `:root` color / theming blocks — **KEEP (theming-critical)** |
| 184 | +- The `light-dark()` block (`core/tokens.css` ~498-519), the no-`light-dark()` fallback chain |
| 185 | + (~256-268), and `core/themes.css` dark-mode derivations + `[data-theme="dark"]/[data-theme="light"]` |
| 186 | + reassignments (~167-236) are the **sole** source of light/dark switching and per-element theming. |
| 187 | + An `@property initial-value` is one static color and can't encode light-vs-dark. Only the 11 static |
| 188 | + `-light` mirrors (199-209) are true duplicates, and deleting them regresses pre-`@property` browsers |
| 189 | + — not worth it. |
| 190 | + |
| 191 | +### Safe-area insets — **KEEP** |
| 192 | +- `--sf-safe-top/bottom/left/right` (`env(safe-area-inset-*)`). Real need for sticky headers/footers |
| 193 | + and bottom CTAs on notched mobile devices. |
| 194 | + |
| 195 | +--- |
| 196 | + |
| 197 | +## Implementation pipeline (per cut) |
| 198 | + |
| 199 | +The repo enforces a token contract — every removal must flow through this or CI fails: |
| 200 | + |
| 201 | +1. **Edit token file(s)**; for generated families update the generator |
| 202 | + (`scripts/gen-sizes-extended.js`, palette generator). |
| 203 | +2. **No core rewiring** for any cut here (all target families with zero internal consumers). Only grep |
| 204 | + `core/` + `optional/` to confirm trimmed font-weight/opacity/state names aren't referenced first. |
| 205 | +3. **Regenerate:** `npm run build` (10 bundles) + `npm run docs` (rebuilds `docs/tokens.md`, |
| 206 | + `docs/api-index.json`, `docs/token-index.json`, configurator data). |
| 207 | +4. **Update API lock:** regenerate/accept `tests/token-api.snapshot.json` (the deliberate-breakage gate). |
| 208 | +5. **Update consequential tests:** `tests/color-semantic.spec.js` (alpha), `tests/tokens.spec.js`, |
| 209 | + delete `tests/fluid-custom.spec.js`, fix `configurator/tests/domains.test.js`. |
| 210 | +6. **CHANGELOG + migration:** `## [0.6.0]` ⚠️ Breaking Changes listing every removed token; upgrade |
| 211 | + table in `docs/migration.md` with inline-CSS replacements. |
| 212 | + |
| 213 | +## Verification |
| 214 | +1. `npm run lint:css` |
| 215 | +2. `npm run build` (confirm token count drops in size report) |
| 216 | +3. `node --test tests/tier1-*.test.js tests/api-index-sync.test.js` |
| 217 | +4. `npx playwright test` — green in **both light and dark** (dark-mode is the theming guard) |
| 218 | +5. **Author-experience smoke check** — open the configurator + a sample landing page from `docs/`: |
| 219 | + nav/sticky/modal z-index, headings, buttons (semibold/medium), disabled form opacity, light/dark |
| 220 | + all render correctly. |
| 221 | +6. **Surface re-count:** `grep -rhoE -- "--sf-[a-z0-9-]+\s*:"` → expect ~899 → ~695. |
| 222 | + |
| 223 | +## Out of scope |
| 224 | +- Collapsing z-index or heading max-width (re-judged useful, kept). |
| 225 | +- The mirror cut (theming-critical, kept). |
| 226 | +- Precomputing the fluid engine to static `clamp()` (removes the runtime-retunable scale the |
| 227 | + configurator needs; separate decision). |
0 commit comments