Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ jobs:
- run: node scripts/check-token-registry.js
- run: node scripts/check-llm-guide.js
- run: node scripts/check-macro-catalog.js
# #582 source-CSS audit gates: false wiring claims, annotation/value
# drift, fallback-only hook tokens, hand-maintained mirrors, and
# per-bundle token definitions.
- run: node scripts/check-dead-knobs.js
- run: node scripts/check-annotations.js
- run: node scripts/check-hook-tokens.js
- run: node scripts/check-mirrors.js
- run: node scripts/check-bundle-defs.js

dependency-audit:
name: Dependency vulnerability audit
Expand Down
32 changes: 16 additions & 16 deletions configurator/src/data/api-index.generated.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"_sync": {
"generatedBy": "configurator/scripts/sync-api.mjs",
"source": "docs/api-index.json",
"tokensHash": "3a36b882c8dd",
"tokensHash": "edc94fa13e23",
"bundles": [
"full",
"optimal"
Expand Down Expand Up @@ -7820,7 +7820,7 @@
"category": "Core tokens",
"group": "Motion & easing",
"description": "Duration and easing tokens. Build all transitions and animations from these to ensure consistent motion across the system.",
"note": "Fast duration (~100ms). Hover transitions, tooltip appear.",
"note": "Fast duration (~150ms). Hover transitions, tooltip appear.",
"value": "calc(150ms * var(--sf-motion-scale))",
"aliasOf": null,
"registered": false,
Expand All @@ -7841,7 +7841,7 @@
"category": "Core tokens",
"group": "Motion & easing",
"description": "Duration and easing tokens. Build all transitions and animations from these to ensure consistent motion across the system.",
"note": "Near-instant duration (~50ms). Micro-interactions and cursor-follow effects.",
"note": "Near-instant duration (~100ms). Micro-interactions and cursor-follow effects.",
"value": "calc(100ms * var(--sf-motion-scale))",
"aliasOf": null,
"registered": false,
Expand Down Expand Up @@ -7883,7 +7883,7 @@
"category": "Core tokens",
"group": "Motion & easing",
"description": "Duration and easing tokens. Build all transitions and animations from these to ensure consistent motion across the system.",
"note": "Normal duration (~200ms). Default for most transitions.",
"note": "Normal duration (~250ms). Default for most transitions.",
"value": "calc(250ms * var(--sf-motion-scale))",
"aliasOf": null,
"registered": false,
Expand All @@ -7904,7 +7904,7 @@
"category": "Core tokens",
"group": "Motion & easing",
"description": "Duration and easing tokens. Build all transitions and animations from these to ensure consistent motion across the system.",
"note": "Slow duration (~350ms). Emphasis transitions, drawers.",
"note": "Slow duration (~400ms). Emphasis transitions, drawers.",
"value": "calc(400ms * var(--sf-motion-scale))",
"aliasOf": null,
"registered": false,
Expand Down Expand Up @@ -8220,8 +8220,8 @@
"group": "Output token @property registrations",
"description": "Vertical (block) padding inside form fields.",
"note": "Vertical (block) padding inside form fields.",
"value": "var(--sf-space-l)",
"aliasOf": "--sf-space-l",
"value": "var(--sf-space-xs)",
"aliasOf": "--sf-space-xs",
"registered": true,
"syntax": "<length>",
"fallbackOnly": false,
Expand Down Expand Up @@ -12794,8 +12794,8 @@
"category": "Core tokens",
"group": "UI sizes",
"description": "Fixed sizes for interactive components (buttons, inputs, chips) at S / M / L.",
"note": "Large UI component height (~44px). Touch-friendly interactive elements.",
"value": "2.75rem",
"note": "Large UI component height (~48px). Touch-friendly interactive elements.",
"value": "3rem",
"aliasOf": null,
"registered": false,
"syntax": null,
Expand All @@ -12815,7 +12815,7 @@
"category": "Core tokens",
"group": "UI sizes",
"description": "Fixed sizes for interactive components (buttons, inputs, chips) at S / M / L.",
"note": "Medium UI component height (~36px). Default size for buttons and inputs.",
"note": "~40px UI component height (scale rung `m`). The default `.sf-btn` min-height.",
"value": "2.5rem",
"aliasOf": null,
"registered": false,
Expand All @@ -12836,7 +12836,7 @@
"category": "Core tokens",
"group": "UI sizes",
"description": "Fixed sizes for interactive components (buttons, inputs, chips) at S / M / L.",
"note": "Small UI component height (~28px). Compact buttons and input variants.",
"note": "Small UI component height (~32px). Compact buttons and input variants.",
"value": "2rem",
"aliasOf": null,
"registered": false,
Expand All @@ -12857,7 +12857,7 @@
"category": "Core tokens",
"group": "UI sizes",
"description": "Fixed sizes for interactive components (buttons, inputs, chips) at S / M / L.",
"note": "Extra-large interactive component height (~52px). For oversized or prominently touch-friendly controls.",
"note": "Extra-large interactive component height (~56px). For oversized or prominently touch-friendly controls.",
"value": "3.5rem",
"aliasOf": null,
"registered": false,
Expand Down Expand Up @@ -14889,14 +14889,14 @@
{
"name": "--sf-touch-target",
"tier": "PUBLIC",
"role": "consumption",
"role": "knob",
"namespace": "touch",
"category": "Core tokens",
"group": "Layout & a11y",
"description": "Focus ring, header height, sticky offset, touch-target, text-contrast knobs, and device safe-area insets. These govern keyboard accessibility, scroll behaviour, and adaptive contrast globally.",
"note": "Minimum touch-target size for interactive elements per WCAG 2.5.5.",
"value": "var(--sf-size-l)",
"aliasOf": "--sf-size-l",
"note": "Minimum touch-target size for interactive elements per WCAG 2.5.5. Fixed 44px anchor, independent of the --sf-size-* scale.",
"value": "2.75rem",
"aliasOf": null,
"registered": false,
"syntax": null,
"fallbackOnly": false,
Expand Down
9 changes: 7 additions & 2 deletions core/print.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@

@media print {

/* --sf-print-page-size / -margin are read here so a :root override retunes
the printed page box. Each fallback equals the historical literal, so the
default print render is unchanged. Verified in Chromium that var() is
substituted inside @page descriptors; engines lacking general custom-
property substitution in @page fall back to the literal. */
@page {

size: a4 portrait;
margin: 2cm;
size: var(--sf-print-page-size, a4) portrait;
margin: var(--sf-print-page-margin, 2cm);
}

body {
Expand Down
29 changes: 23 additions & 6 deletions core/tokens.css
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,16 @@
Radius + space: <length> syntax enables CSS transitions on layout values —
border-radius/padding/gap etc. now interpolate instead of snapping.
Shadow: syntax:"*" (no <shadow> type in spec); inherits:true so :root values
cascade normally; registers the properties formally for DevTools inspection. */
cascade normally; registers the properties formally for DevTools inspection.

initial-value ≠ :root default (by spec): a registered <length> requires a
computationally-independent initial-value, so these carry `initial-value: 0`
while their real defaults are the calc()-derived values set on :root below
(see --sf-fluid-width above for the same constraint stated at length). One
consequence worth flagging: once a property is registered, the initial
value IS a value — so a fallback like `var(--sf-radius-m, 12px)` will NEVER
fire; an unset --sf-radius-m resolves to the registered `0`, not to "no
value". Author fallbacks against the token's :root default, not this 0. */

@property --sf-radius-none { syntax: "<length>"; inherits: true; initial-value: 0; }
@property --sf-radius-2xs { syntax: "<length>"; inherits: true; initial-value: 0; }
Expand Down Expand Up @@ -1167,12 +1176,16 @@
--sf-space-4xl: calc(clamp(calc(var(--sf-space-base-min) * pow(var(--sf-space-ratio-min), 5) * 1rem), calc((var(--sf-space-base-max) * pow(var(--sf-space-ratio-max), 5) - var(--sf-space-base-min) * pow(var(--sf-space-ratio-min), 5)) / (var(--sf-fluid-max-vw) - var(--sf-fluid-min-vw)) * (var(--sf-fluid-width) - var(--sf-fluid-min-vw) * 1rem) + var(--sf-space-base-min) * pow(var(--sf-space-ratio-min), 5) * 1rem), calc(var(--sf-space-base-max) * pow(var(--sf-space-ratio-max), 5) * 1rem)) * var(--sf-space-scale));

/* ----------------------------------------------------------
UI sizes
UI sizes — a purely geometric rung ladder (+0.5rem / 8px per
step: 24 · 32 · 40 · 48 · 56 px). These are free design knobs:
nothing external constrains them, so overriding them just
rescales component heights. Accessibility floors live on their
own tokens (--sf-touch-target), never on a rung — see below.
---------------------------------------------------------- */
--sf-size-xs: 1.5rem;
--sf-size-s: 2rem;
--sf-size-m: 2.5rem;
--sf-size-l: 2.75rem;
--sf-size-l: 3rem;
--sf-size-xl: 3.5rem;

/* ----------------------------------------------------------
Expand Down Expand Up @@ -1428,11 +1441,15 @@
calc((var(--sf-sticky-offset-desktop) - var(--sf-sticky-offset-mobile)) / ((var(--sf-fluid-max-vw) - var(--sf-fluid-min-vw)) * 1rem) * (100vw - var(--sf-fluid-min-vw) * 1rem) + var(--sf-sticky-offset-mobile)),
var(--sf-sticky-offset-desktop));
/* Focus ring dimensions and minimum touch-target size. Governs keyboard
navigation affordance and WCAG 2.5.5 pointer-target requirements. */
navigation affordance and WCAG 2.5.5 pointer-target requirements.
--sf-touch-target owns the 44px WCAG floor as a literal — it is NOT an
alias of a --sf-size-* rung, so retuning the size scale can never drag
the accessibility minimum below spec. Override it deliberately if you
have your own target policy. */
--sf-focus-ring-width: 2px;
--sf-focus-ring-offset: 2px;
--sf-focus-ring-style: solid;
--sf-touch-target: var(--sf-size-l);
--sf-touch-target: 2.75rem; /* 44px — WCAG 2.5.5 minimum, independent of the size scale */
/* Global text-contrast knob. Nudges derived reading-text colours
toward the extremes (darker in light mode, lighter in dark mode).
Positive = more contrast; 0 = no change. Consumed by
Expand Down Expand Up @@ -1609,7 +1626,7 @@
--sf-content-gap: var(--sf-space-s); /* tight: within content */
--sf-gutter: var(--sf-space-l); /* wide: page/section gutters */
--sf-component-pad: var(--sf-space-m); /* standard component padding */
--sf-field-block: var(--sf-space-l); /* form-field block spacing */
--sf-field-block: var(--sf-space-xs); /* form-field block padding — matches the shipped field default (see optional/forms.css) */
Comment thread
coderabbitai[bot] marked this conversation as resolved.
--sf-field-required-marker: " *";
/* Leading space is baked into the default so consumers can fully
disable the indicator with `--sf-link-external-marker: ""` —
Expand Down
2 changes: 1 addition & 1 deletion demos/full-api-demo-with-overrides.html
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
</nav>
<main id="main">
<h1>SLASHED Full API Demo</h1>
<p style="color:var(--sf-color-text--muted)">v0.7.8 · full bundle from jsDelivr CDN · 328 classes · 735 tokens (243 configurable)</p>
<p style="color:var(--sf-color-text--muted)">v0.7.8 · full bundle from jsDelivr CDN · 328 classes · 735 tokens (244 configurable)</p>
<div class="notice"><strong>ultimate-override.css is ACTIVE.</strong> Every value below is recomputed from perturbed knob tokens — toggle it off in the toolbar, or compare against <a href="full-api-demo.html">the un-overridden page</a>.</div>

<section id="tokens">
Expand Down
2 changes: 1 addition & 1 deletion demos/full-api-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
</nav>
<main id="main">
<h1>SLASHED Full API Demo</h1>
<p style="color:var(--sf-color-text--muted)">v0.7.8 · full bundle from jsDelivr CDN · 328 classes · 735 tokens (243 configurable)</p>
<p style="color:var(--sf-color-text--muted)">v0.7.8 · full bundle from jsDelivr CDN · 328 classes · 735 tokens (244 configurable)</p>
<div class="notice">Baseline render with default tokens. Use the toolbar to switch theme, toggle the ultimate override live, or replay motion. The always-on override variant is <a href="full-api-demo-with-overrides.html">full-api-demo-with-overrides.html</a>.</div>

<section id="tokens">
Expand Down
7 changes: 5 additions & 2 deletions demos/ultimate-override.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Perturbs every CONFIGURABLE (role: "knob") token to a valid, visibly-distinct
value so full-api-demo.html can prove each one is wired end to end.

Coverage: 219 of 243 knob tokens overridden.
Coverage: 220 of 244 knob tokens overridden.
24 knobs are intentionally NOT perturbed (structural /
meta / sentinel) — listed with reasons at the bottom of this file.
============================================================================ */
Expand Down Expand Up @@ -303,7 +303,7 @@
--sf-sidebar-width: 28.8rem; /* was: 18rem */

/* size */
--sf-size-l: 4.4rem; /* was: 2.75rem */
--sf-size-l: 4.8rem; /* was: 3rem */
--sf-size-m: 4rem; /* was: 2.5rem */
--sf-size-s: 3.2rem; /* was: 2rem */
--sf-size-xl: 5.6rem; /* was: 3.5rem */
Expand Down Expand Up @@ -352,6 +352,9 @@
--sf-text-xl-max-width: 50ch; /* was: none */
--sf-text-xs-max-width: 96ch; /* was: 60ch */

/* touch */
--sf-touch-target: 4.4rem; /* was: 2.75rem */

/* tracking */
--sf-tracking-normal: 0.03em; /* was: 0 */
--sf-tracking-tight: -0.04em; /* was: -0.025em */
Expand Down
20 changes: 10 additions & 10 deletions dist/css-custom-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -1863,12 +1863,12 @@
},
{
"name": "--sf-duration-fast",
"description": "Fast duration (~100ms). Hover transitions, tooltip appear.\n\nDefault: `calc(150ms * var(--sf-motion-scale))`",
"description": "Fast duration (~150ms). Hover transitions, tooltip appear.\n\nDefault: `calc(150ms * var(--sf-motion-scale))`",
"syntax": "*"
},
{
"name": "--sf-duration-instant",
"description": "Near-instant duration (~50ms). Micro-interactions and cursor-follow effects.\n\nDefault: `calc(100ms * var(--sf-motion-scale))`",
"description": "Near-instant duration (~100ms). Micro-interactions and cursor-follow effects.\n\nDefault: `calc(100ms * var(--sf-motion-scale))`",
"syntax": "*"
},
{
Expand All @@ -1878,12 +1878,12 @@
},
{
"name": "--sf-duration-normal",
"description": "Normal duration (~200ms). Default for most transitions.\n\nDefault: `calc(250ms * var(--sf-motion-scale))`",
"description": "Normal duration (~250ms). Default for most transitions.\n\nDefault: `calc(250ms * var(--sf-motion-scale))`",
"syntax": "*"
},
{
"name": "--sf-duration-slow",
"description": "Slow duration (~350ms). Emphasis transitions, drawers.\n\nDefault: `calc(400ms * var(--sf-motion-scale))`",
"description": "Slow duration (~400ms). Emphasis transitions, drawers.\n\nDefault: `calc(400ms * var(--sf-motion-scale))`",
"syntax": "*"
},
{
Expand Down Expand Up @@ -1958,7 +1958,7 @@
},
{
"name": "--sf-field-block",
"description": "Vertical (block) padding inside form fields.\n\nDefault: `var(--sf-space-l)`",
"description": "Vertical (block) padding inside form fields.\n\nDefault: `var(--sf-space-xs)`",
"syntax": "<length>"
},
{
Expand Down Expand Up @@ -3043,22 +3043,22 @@
},
{
"name": "--sf-size-l",
"description": "Large UI component height (~44px). Touch-friendly interactive elements.\n\nDefault: `2.75rem`",
"description": "Large UI component height (~48px). Touch-friendly interactive elements.\n\nDefault: `3rem`",
"syntax": "*"
},
{
"name": "--sf-size-m",
"description": "Medium UI component height (~36px). Default size for buttons and inputs.\n\nDefault: `2.5rem`",
"description": "~40px UI component height (scale rung `m`). The default `.sf-btn` min-height.\n\nDefault: `2.5rem`",
"syntax": "*"
},
{
"name": "--sf-size-s",
"description": "Small UI component height (~28px). Compact buttons and input variants.\n\nDefault: `2rem`",
"description": "Small UI component height (~32px). Compact buttons and input variants.\n\nDefault: `2rem`",
"syntax": "*"
},
{
"name": "--sf-size-xl",
"description": "Extra-large interactive component height (~52px). For oversized or prominently touch-friendly controls.\n\nDefault: `3.5rem`",
"description": "Extra-large interactive component height (~56px). For oversized or prominently touch-friendly controls.\n\nDefault: `3.5rem`",
"syntax": "*"
},
{
Expand Down Expand Up @@ -3543,7 +3543,7 @@
},
{
"name": "--sf-touch-target",
"description": "Minimum touch-target size for interactive elements per WCAG 2.5.5.\n\nDefault: `var(--sf-size-l)`",
"description": "Minimum touch-target size for interactive elements per WCAG 2.5.5. Fixed 44px anchor, independent of the --sf-size-* scale.\n\nDefault: `2.75rem`",
"syntax": "*"
},
{
Expand Down
Loading