From b5fa2e266c8981ff94b6e153cfb467796cb274e6 Mon Sep 17 00:00:00 2001
From: Kiro Agent <244629292+kiro-agent@users.noreply.github.com>
Date: Tue, 18 Aug 2026 09:35:03 +0000
Subject: [PATCH 1/2] fix(bricks): restore color-state swatches and
class-dropdown hints
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Two regressions surfaced in the Bricks builder after framework changes:
1. Variable-picker swatches were missing for the `--sf-color-*--hover` and
`--sf-color-*--active` tokens. The PHP color resolver emitted the semantic
`hover`/`active` aliases with a SINGLE dash (`-hover`), but the framework
tokens are BEM state modifiers with a DOUBLE dash (`--hover`). The
builder-side swatch/variable lookups key off the real token name, so those
entries never matched and rendered blank. Aliases now carry their exact
separator (double dash for state modifiers, single dash for tonal steps).
2. Most class hints ("?" tooltips) disappeared from the class dropdown.
gen-class-hints.js scraped section-heading comments out of the framework
CSS, which stopped matching once the framework adopted its short
`/* Label */` source-comment policy — so only the curated overrides
survived, and renamed classes (sf-bento--row-*, is-* -> sf-is-*) went
undocumented. The generator now reads the framework's machine-readable
docs/api-index.json (same source as gen-variables-hints.js), which is
robust to comment reformatting and tracks the real class names.
Regenerated classes-hints.json grows from 63 to 303 entries.
Tests: updated ColorResolverTest (correct --hover/--active naming + a
regression guard) and rewrote gen-class-hints.test.js around buildClassHints.
---
SLASHED-for-WP/data/classes-hints.json | 1316 ++++++++++++++---
.../includes/class-color-resolver.php | 39 +-
scripts/gen-class-hints.js | 260 +---
tests-php/ColorResolverTest.php | 35 +-
tests/gen-class-hints.test.js | 124 +-
5 files changed, 1304 insertions(+), 470 deletions(-)
diff --git a/SLASHED-for-WP/data/classes-hints.json b/SLASHED-for-WP/data/classes-hints.json
index 1942979e..74a1b145 100644
--- a/SLASHED-for-WP/data/classes-hints.json
+++ b/SLASHED-for-WP/data/classes-hints.json
@@ -1,254 +1,1214 @@
{
+ "sf-alternate": {
+ "description": "Zigzag / alternating two-column layout. Even children align image-left/text-right; odd children flip. Collapses to a single column below the breakpoint.",
+ "category": "Layout primitives"
+ },
+ "sf-bento": {
+ "description": "Auto-fill bento grid for card dashboards. Children span 1 column by default; use span modifiers (sf-bento-wide, sf-bento-tall, sf-bento-full, sf-bento-featured) to break the grid.",
+ "category": "Layout primitives"
+ },
+ "sf-bento--2": {
+ "description": "Bento grid variant with a 2-column base layout.",
+ "category": "Layout primitives"
+ },
+ "sf-bento--3": {
+ "description": "Bento grid variant with a 3-column base layout.",
+ "category": "Layout primitives"
+ },
+ "sf-bento--6": {
+ "description": "Bento grid variant with a 6-column base layout.",
+ "category": "Layout primitives"
+ },
+ "sf-bento--row-compact": {
+ "description": "Bento grid variant with shorter default row height.",
+ "category": "Layout primitives"
+ },
+ "sf-bento--row-tall": {
+ "description": "Bento grid variant with taller default row height.",
+ "category": "Layout primitives"
+ },
+ "sf-bento-featured": {
+ "description": "Span modifier for a bento item: takes up 2×2 cells (featured hero placement).",
+ "category": "Layout primitives"
+ },
+ "sf-bento-full": {
+ "description": "Span modifier for a bento item: stretches across all columns (full-width banner).",
+ "category": "Layout primitives"
+ },
+ "sf-bento-tall": {
+ "description": "Span modifier for a bento item: doubles the row height (tall card).",
+ "category": "Layout primitives"
+ },
+ "sf-bento-wide": {
+ "description": "Span modifier for a bento item: spans 2 columns (wide card).",
+ "category": "Layout primitives"
+ },
+ "sf-bg-layer": {
+ "description": "Background layer — absolutely-positioned cover media that sits behind a parent's content. The parent is auto-promoted to a positioned, isolated stacking context via :has(), so .sf-bg-layer composes natively under .sf-scrim (background → scrim gradient → content). Works as a bare or as a wrapper with a nested > img / > video / > picture.",
+ "category": "Layout primitives"
+ },
+ "sf-box": {
+ "description": "Minimal padding container that applies --sf-component-pad on all sides. The simplest layout primitive for adding breathing room.",
+ "category": "Layout primitives"
+ },
+ "sf-breakout": {
+ "description": "Breaks a child element out of a parent sf-content-grid, spanning full bleed (or a named grid area) regardless of the parent column. Useful for full-width sections inside constrained prose.",
+ "category": "Layout primitives"
+ },
+ "sf-btn": {
+ "description": "Interactive call-to-action button. Apply to or . Intrinsic width by default; owns its own styling (excluded from the classless look). Three orthogonal axes — colour family, style treatment (fill/--soft/--outline), gradient — plus a size modifier.",
+ "category": "Components"
+ },
+ "sf-btn--action": {
+ "description": "Button in the action colour family (same as the unmodified default, named explicitly).",
+ "category": "Components"
+ },
+ "sf-btn--base": {
+ "description": "Button in the base (surface-neutral) colour family.",
+ "category": "Components"
+ },
+ "sf-btn--block": {
+ "description": "Full-width button (100% inline size) everywhere.",
+ "category": "Components"
+ },
+ "sf-btn--block-cq": {
+ "description": "Full-width button only inside a query container narrower than 20rem; intrinsic otherwise.",
+ "category": "Components"
+ },
+ "sf-btn--danger": {
+ "description": "Button in the danger (destructive) colour family.",
+ "category": "Components"
+ },
+ "sf-btn--gradient": {
+ "description": "Gradient axis: paints the fill (or, with --outline, the border ring) with the family's --sf-gradient-* token. Core-4 brand families (primary/secondary/tertiary/action); solid no-op for other families. Composes with any colour family.",
+ "category": "Components"
+ },
+ "sf-btn--info": {
+ "description": "Button in the info colour family.",
+ "category": "Components"
+ },
+ "sf-btn--l": {
+ "description": "Large button size.",
+ "category": "Components"
+ },
+ "sf-btn--neutral": {
+ "description": "Button in the neutral colour family.",
+ "category": "Components"
+ },
+ "sf-btn--outline": {
+ "description": "Outlined button (coloured border/text, transparent fill) that fills with the family colour on hover. Composes with any colour family.",
+ "category": "Components"
+ },
+ "sf-btn--primary": {
+ "description": "Button in the primary brand colour family.",
+ "category": "Components"
+ },
+ "sf-btn--s": {
+ "description": "Small button size.",
+ "category": "Components"
+ },
+ "sf-btn--secondary": {
+ "description": "Button in the secondary brand colour family.",
+ "category": "Components"
+ },
+ "sf-btn--soft": {
+ "description": "Soft tonal-fill button: a light wash of the family colour (subtle at rest, muted on hover), coloured text, no border. Lower-emphasis than the solid fill. Composes with any colour family.",
+ "category": "Components"
+ },
+ "sf-btn--success": {
+ "description": "Button in the success (positive) colour family.",
+ "category": "Components"
+ },
+ "sf-btn--tertiary": {
+ "description": "Button in the tertiary brand colour family.",
+ "category": "Components"
+ },
+ "sf-btn--warning": {
+ "description": "Button in the warning (caution) colour family.",
+ "category": "Components"
+ },
+ "sf-btn--xl": {
+ "description": "Extra-large button size.",
+ "category": "Components"
+ },
+ "sf-btn--xs": {
+ "description": "Extra-small button size.",
+ "category": "Components"
+ },
+ "sf-card": {
+ "description": "Padded content container with optional __header/__body/__footer and __media/__avatar/__title subcomponents. Uses concentric radius math so inner corners stay proportional.",
+ "category": "Components"
+ },
+ "sf-card__avatar": {
+ "description": "Circular avatar image inside a card, sized via --sf-card-avatar-size.",
+ "category": "Components"
+ },
+ "sf-card__body": {
+ "description": "Card body slot.",
+ "category": "Components"
+ },
+ "sf-card__footer": {
+ "description": "Card footer slot with a top divider.",
+ "category": "Components"
+ },
+ "sf-card__header": {
+ "description": "Card header slot with a bottom divider.",
+ "category": "Components"
+ },
+ "sf-card__media": {
+ "description": "Full-width cover image/video for a card, cropped to --sf-card-media-ratio (16/9 by default).",
+ "category": "Components"
+ },
+ "sf-card__title": {
+ "description": "Card title heading, sized via --sf-card-heading-size.",
+ "category": "Components"
+ },
+ "sf-card--bordered": {
+ "description": "Flat, outlined card: keeps the border, drops the shadow.",
+ "category": "Components"
+ },
+ "sf-card--elevated": {
+ "description": "Floating card: hides the border, applies a larger shadow.",
+ "category": "Components"
+ },
+ "sf-card--interactive": {
+ "description": "Adds a pointer cursor and a shadow/translate lift on hover or keyboard focus. Pair with .sf-clickable-parent for a fully clickable card. Lift is suppressed under prefers-reduced-motion.",
+ "category": "Components"
+ },
+ "sf-center": {
+ "description": "Centers children both horizontally and vertically using flexbox. Optionally add sf-center--intrinsic to size the container to its content.",
+ "category": "Layout primitives"
+ },
+ "sf-center--intrinsic": {
+ "description": "Modifier for sf-center: constrains the container to the natural width of its children (no stretching to fill available space).",
+ "category": "Layout primitives"
+ },
+ "sf-clickable-parent": {
+ "description": "Makes the entire card or list-item clickable via an absolutely-positioned child overlay link. Apply to the container; place sf-clickable-parent__overlay on the .",
+ "category": "Accessibility"
+ },
+ "sf-clickable-parent__overlay": {
+ "description": "The full-bleed overlay link inside an sf-clickable-parent. Stretches to cover the parent and uses pointer-events to let interactive children keep their own clicks.",
+ "category": "Accessibility"
+ },
+ "sf-cluster": {
+ "description": "Flex-wrap row of variable-width items with automatic gap. Children wrap when the container is too narrow. Use for tag lists, button groups, and icon rows.",
+ "category": "Layout primitives"
+ },
+ "sf-cluster--2xl": {
+ "description": "Cluster variant with 2xl gap between items.",
+ "category": "Layout primitives"
+ },
+ "sf-cluster--between": {
+ "description": "Cluster variant that distributes items with space-between alignment.",
+ "category": "Layout primitives"
+ },
+ "sf-cluster--center": {
+ "description": "Cluster variant that centers the item row horizontally.",
+ "category": "Layout primitives"
+ },
+ "sf-cluster--end": {
+ "description": "Cluster variant that aligns items to the inline end (right in LTR).",
+ "category": "Layout primitives"
+ },
+ "sf-cluster--l": {
+ "description": "Cluster variant with large (l) gap between items.",
+ "category": "Layout primitives"
+ },
+ "sf-cluster--m": {
+ "description": "Cluster variant with medium (m) gap between items.",
+ "category": "Layout primitives"
+ },
+ "sf-cluster--no-wrap": {
+ "description": "Cluster variant that prevents item wrapping (single-line row).",
+ "category": "Layout primitives"
+ },
+ "sf-cluster--s": {
+ "description": "Cluster variant with small (s) gap between items.",
+ "category": "Layout primitives"
+ },
+ "sf-cluster--xl": {
+ "description": "Cluster variant with xl gap between items.",
+ "category": "Layout primitives"
+ },
+ "sf-cluster--xs": {
+ "description": "Cluster variant with xs gap between items.",
+ "category": "Layout primitives"
+ },
+ "sf-color-pulse": {
+ "description": "Applies a gentle color-pulse animation to draw attention to a dynamic value change (e.g. a counter updating). Scoped to users who have not requested reduced motion.",
+ "category": "Motion / animation"
+ },
+ "sf-container": {
+ "description": "Max-width page container, centered with auto side gutters. Establishes a named inline-size container (cq-container) for container queries. Default width is --sf-container-m.",
+ "category": "Layout primitives"
+ },
+ "sf-container--full": {
+ "description": "Container variant that spans the full viewport width (no max-width cap).",
+ "category": "Layout primitives"
+ },
+ "sf-container--narrow": {
+ "description": "Container variant with a narrower max-width (--sf-container-s). Use for single-column prose and forms.",
+ "category": "Layout primitives"
+ },
+ "sf-container--prose": {
+ "description": "Container variant with a prose-optimised max-width (--sf-container-prose). Ideal for long-form reading content.",
+ "category": "Layout primitives"
+ },
+ "sf-container--wide": {
+ "description": "Container variant with a wider max-width (--sf-container-l). Use for dashboards and wide media.",
+ "category": "Layout primitives"
+ },
+ "sf-content-grid": {
+ "description": "Holy-grail content grid with named areas: full-bleed, popout, and content columns. Use sf-breakout on children to escape the content column.",
+ "category": "Layout primitives"
+ },
+ "sf-cover": {
+ "description": "Vertically stretches to at least a viewport height with a centered element (sf-cover__center). Typical use: hero sections.",
+ "category": "Layout primitives"
+ },
+ "sf-cover__center": {
+ "description": "The centered focal element inside an sf-cover. Stays vertically centered even when the cover content is shorter than the viewport.",
+ "category": "Layout primitives"
+ },
+ "sf-cover--max": {
+ "description": "Cover variant that uses a max-height instead of min-height for the viewport constraint.",
+ "category": "Layout primitives"
+ },
+ "sf-cover--min": {
+ "description": "Cover variant that reduces the minimum height to half a viewport.",
+ "category": "Layout primitives"
+ },
+ "sf-cover--padding-l": {
+ "description": "Cover variant with large vertical padding above and below the centered content.",
+ "category": "Layout primitives"
+ },
+ "sf-cover--padding-s": {
+ "description": "Cover variant with small vertical padding above and below the centered content.",
+ "category": "Layout primitives"
+ },
+ "sf-cq": {
+ "description": "Assigns an inline-size container context to any element. Children can then use @container rules or container-query-aware tokens.",
+ "category": "Layout primitives"
+ },
+ "sf-divide": {
+ "description": "Rules between direct children (a border on each child after the first), reusing .sf-divider's tokens — no per-gap markup needed.",
+ "category": "Layout primitives"
+ },
+ "sf-divide--vertical": {
+ "description": "Vertical rules between direct children (inline-start borders), for row/horizontal layouts.",
+ "category": "Layout primitives"
+ },
+ "sf-divider": {
+ "description": "Horizontal rule (divider line). Uses --sf-divider-* tokens for color, width, and style. Modifiers change dash style or orientation.",
+ "category": "Layout primitives"
+ },
+ "sf-divider--dashed": {
+ "description": "Divider variant with a dashed stroke.",
+ "category": "Layout primitives"
+ },
+ "sf-divider--dotted": {
+ "description": "Divider variant with a dotted stroke.",
+ "category": "Layout primitives"
+ },
+ "sf-divider--gradient": {
+ "description": "Divider variant rendered as a gradient that fades to transparent at both ends.",
+ "category": "Layout primitives"
+ },
+ "sf-divider--soft": {
+ "description": "Divider variant with reduced opacity (subtle separator).",
+ "category": "Layout primitives"
+ },
+ "sf-divider--strong": {
+ "description": "Divider variant with stronger/darker color for a more prominent separator.",
+ "category": "Layout primitives"
+ },
+ "sf-divider--vertical": {
+ "description": "Divider variant rendered as a vertical line. Use inside flex or grid containers.",
+ "category": "Layout primitives"
+ },
+ "sf-drop-shadow-l": {
+ "description": "Large filter drop-shadow — follows the element's alpha shape (--sf-drop-shadow-l).",
+ "category": "Macro classes"
+ },
+ "sf-drop-shadow-m": {
+ "description": "Medium filter drop-shadow — follows the element's alpha shape (--sf-drop-shadow-m).",
+ "category": "Macro classes"
+ },
+ "sf-drop-shadow-s": {
+ "description": "Small filter drop-shadow — follows the element's alpha shape (--sf-drop-shadow-s).",
+ "category": "Macro classes"
+ },
+ "sf-drop-shadow-xl": {
+ "description": "Extra-large filter drop-shadow — follows the element's alpha shape (--sf-drop-shadow-xl).",
+ "category": "Macro classes"
+ },
+ "sf-drop-shadow-xs": {
+ "description": "Extra-small filter drop-shadow — follows the element's alpha shape (--sf-drop-shadow-xs).",
+ "category": "Macro classes"
+ },
+ "sf-entrance--fade": {
+ "description": "Scroll-driven entrance: element fades in as it enters the viewport. Animation tied to scroll progress via animation-timeline.",
+ "category": "Motion / animation"
+ },
+ "sf-entrance--fade-down": {
+ "description": "Scroll-driven entrance: element fades in while moving downward into position.",
+ "category": "Motion / animation"
+ },
+ "sf-entrance--fade-left": {
+ "description": "Scroll-driven entrance: element fades in while moving from the right toward the left.",
+ "category": "Motion / animation"
+ },
+ "sf-entrance--fade-right": {
+ "description": "Scroll-driven entrance: element fades in while moving from the left toward the right.",
+ "category": "Motion / animation"
+ },
+ "sf-entrance--fade-up": {
+ "description": "Scroll-driven entrance: element fades in while moving upward into position.",
+ "category": "Motion / animation"
+ },
+ "sf-entrance--scale-up": {
+ "description": "Scroll-driven entrance: element fades in while scaling up from a slightly smaller size.",
+ "category": "Motion / animation"
+ },
+ "sf-equal": {
+ "description": "Flowing CSS multi-column layout (not a grid) — content distributes across columns like a newspaper instead of sitting in fixed cells. Reach for .sf-grid/.sf-grid--fit for discrete grid cells instead.",
+ "category": "Layout primitives"
+ },
+ "sf-equal--2": {
+ "description": "Equal-columns variant locked to column-count: 2.",
+ "category": "Layout primitives"
+ },
+ "sf-equal--3": {
+ "description": "Equal-columns variant locked to column-count: 3.",
+ "category": "Layout primitives"
+ },
+ "sf-equal--4": {
+ "description": "Equal-columns variant locked to column-count: 4.",
+ "category": "Layout primitives"
+ },
+ "sf-equal--6": {
+ "description": "Equal-columns variant locked to column-count: 6.",
+ "category": "Layout primitives"
+ },
+ "sf-equal-height": {
+ "description": "Forces all flex children to equal height (align-items: stretch). Use on a flex row to make cards in a grid share the tallest card's height.",
+ "category": "Macro classes"
+ },
+ "sf-exit--fade": {
+ "description": "Scroll-out exit animation: fades the element out in place (sf-fade-out).",
+ "category": "Motion / animation"
+ },
+ "sf-exit--fade-down": {
+ "description": "Scroll-out exit animation: fades out while sliding downward (sf-slide-out-down).",
+ "category": "Motion / animation"
+ },
+ "sf-exit--fade-left": {
+ "description": "Scroll-out exit animation: fades out while sliding to the left (sf-slide-out-left).",
+ "category": "Motion / animation"
+ },
+ "sf-exit--fade-right": {
+ "description": "Scroll-out exit animation: fades out while sliding to the right (sf-slide-out-right).",
+ "category": "Motion / animation"
+ },
+ "sf-exit--fade-up": {
+ "description": "Scroll-out exit animation: fades out while sliding upward (sf-slide-out-up).",
+ "category": "Motion / animation"
+ },
+ "sf-exit--scale-down": {
+ "description": "Scroll-out exit animation: fades out while shrinking (sf-scale-down).",
+ "category": "Motion / animation"
+ },
+ "sf-fade-in": {
+ "description": "One-shot fade-in animation (opacity 0 → 1). Scoped to no-preference so it stops automatically for reduced-motion users.",
+ "category": "Motion / animation"
+ },
+ "sf-fade-out": {
+ "description": "One-shot fade-out animation (opacity 1 → 0). Scoped to no-preference.",
+ "category": "Motion / animation"
+ },
+ "sf-flow": {
+ "description": "Applies --sf-flow-space as margin-block-start to all direct children except the first. Establishes consistent vertical rhythm in prose-like containers.",
+ "category": "Macro classes"
+ },
+ "sf-fluid-cq": {
+ "description": ".sf-fluid-cq: opt a subtree into a CONTAINER-relative fluid scale (issue #497). By default --sf-text-* / --sf-space-* interpolate against 100vw (the viewport); inside .sf-fluid-cq they interpolate against 100cqi (this box's inline size), so type + spacing track the container…",
+ "category": "Layout primitives"
+ },
+ "sf-focus-parent": {
+ "description": "Forwards focus-visible styling to this container when any descendant is keyboard-focused. Useful for custom controls that wrap a visually-hidden .",
+ "category": "Accessibility"
+ },
+ "sf-focus-shadow": {
+ "description": "Applies the standard focus ring as a box-shadow to any element. Use on custom controls where the native :focus-visible ring doesn't render correctly.",
+ "category": "Accessibility"
+ },
+ "sf-frame": {
+ "description": "Aspect-ratio container for media (images, video, maps). Children fill and cover the fixed-ratio box. Default ratio is 16:9.",
+ "category": "Layout primitives"
+ },
+ "sf-frame--3-2": {
+ "description": "Frame variant locked to a 3:2 aspect ratio.",
+ "category": "Layout primitives"
+ },
+ "sf-frame--4-3": {
+ "description": "Frame variant locked to a 4:3 aspect ratio.",
+ "category": "Layout primitives"
+ },
+ "sf-frame--cinema": {
+ "description": "Frame variant locked to a cinematic 21:9 aspect ratio.",
+ "category": "Layout primitives"
+ },
+ "sf-frame--golden": {
+ "description": "Frame variant locked to the golden ratio (1.618:1).",
+ "category": "Layout primitives"
+ },
+ "sf-frame--portrait": {
+ "description": "Frame variant locked to a portrait 2:3 aspect ratio.",
+ "category": "Layout primitives"
+ },
+ "sf-frame--square": {
+ "description": "Frame variant locked to a square 1:1 aspect ratio.",
+ "category": "Layout primitives"
+ },
+ "sf-frame--video": {
+ "description": "Frame variant locked to the standard 16:9 video aspect ratio.",
+ "category": "Layout primitives"
+ },
+ "sf-full-bleed": {
+ "description": "Forces an element to span the full viewport width, breaking out of any centered container. Use for full-bleed images and section backgrounds.",
+ "category": "Layout primitives"
+ },
+ "sf-gap": {
+ "description": "Injects the default --sf-gap into an existing flex or grid container without imposing display:flex itself. Use when the parent is already a flex or grid.",
+ "category": "Layout primitives"
+ },
+ "sf-gap--2xl": {
+ "description": "Gap injection variant with 2xl gap value.",
+ "category": "Layout primitives"
+ },
+ "sf-gap--l": {
+ "description": "Gap injection variant with large (l) gap value.",
+ "category": "Layout primitives"
+ },
+ "sf-gap--m": {
+ "description": "Gap injection variant with medium (m) gap value.",
+ "category": "Layout primitives"
+ },
+ "sf-gap--s": {
+ "description": "Gap injection variant with small (s) gap value.",
+ "category": "Layout primitives"
+ },
+ "sf-gap--xl": {
+ "description": "Gap injection variant with xl gap value.",
+ "category": "Layout primitives"
+ },
+ "sf-gap--xs": {
+ "description": "Gap injection variant with xs gap value.",
+ "category": "Layout primitives"
+ },
+ "sf-grid": {
+ "description": "Auto-fill CSS grid. Columns are sized with RAM pattern (Repeat, Auto-fill, Minmax) and wrap automatically. Default column min-width is --sf-grid-min-col.",
+ "category": "Layout primitives"
+ },
+ "sf-grid--2xl": {
+ "description": "Grid variant with a 2xl minimum column width.",
+ "category": "Layout primitives"
+ },
+ "sf-grid--dense": {
+ "description": "Grid variant with grid-auto-flow: dense, allowing the grid to fill holes created by span modifiers.",
+ "category": "Layout primitives"
+ },
+ "sf-grid--fit": {
+ "description": "Grid variant that switches from auto-fill to auto-fit, collapsing empty columns.",
+ "category": "Layout primitives"
+ },
+ "sf-grid--l": {
+ "description": "Grid variant with a large (l) minimum column width.",
+ "category": "Layout primitives"
+ },
+ "sf-grid--m": {
+ "description": "Grid variant with a medium (m) minimum column width.",
+ "category": "Layout primitives"
+ },
+ "sf-grid--s": {
+ "description": "Grid variant with a small (s) minimum column width.",
+ "category": "Layout primitives"
+ },
+ "sf-grid--xl": {
+ "description": "Grid variant with an xl minimum column width.",
+ "category": "Layout primitives"
+ },
+ "sf-grid--xs": {
+ "description": "Grid variant with an xs minimum column width.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-cols-1": {
+ "description": "Single-column layout (forces all children to one column).",
+ "category": "Layout primitives"
+ },
+ "sf-grid-cols-1-2": {
+ "description": "Two-column ratio grid: first child takes 1fr, second takes 2fr. Container-query responsive.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-cols-1-3": {
+ "description": "Two-column ratio grid: first child takes 1fr, second takes 3fr. Container-query responsive.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-cols-2": {
+ "description": "Responsive 2-column fixed grid. Uses container queries to collapse to one column on narrow containers.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-cols-2-1": {
+ "description": "Two-column ratio grid: first child takes 2fr, second takes 1fr. Container-query responsive.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-cols-3": {
+ "description": "Responsive 3-column fixed grid. Collapses progressively on narrow containers.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-cols-3-1": {
+ "description": "Two-column ratio grid: first child takes 3fr, second takes 1fr. Container-query responsive.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-cols-4": {
+ "description": "Responsive 4-column fixed grid. Collapses progressively on narrow containers.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-cols-6": {
+ "description": "Responsive 6-column fixed grid. Collapses progressively on narrow containers.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-flex": {
+ "description": "Flexbox alternative to .sf-grid for item counts that don't divide evenly: leftover last-row items stretch to fill the row by default, or stay fixed-width and centered with --center.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-flex--2xl": {
+ "description": "Grid-flex variant with a 2xl minimum item width.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-flex--center": {
+ "description": "Grid-flex variant that keeps last-row leftover items fixed-width and centered instead of stretching.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-flex--l": {
+ "description": "Grid-flex variant with a large (l) minimum item width.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-flex--m": {
+ "description": "Grid-flex variant with a medium (m) minimum item width.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-flex--s": {
+ "description": "Grid-flex variant with a small (s) minimum item width.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-flex--xl": {
+ "description": "Grid-flex variant with an xl minimum item width.",
+ "category": "Layout primitives"
+ },
+ "sf-grid-flex--xs": {
+ "description": "Grid-flex variant with an xs minimum item width.",
+ "category": "Layout primitives"
+ },
+ "sf-h1": {
+ "description": "Applies h1-level typography (size, line-height, weight, tracking, max-width) to any element without changing its semantic level.",
+ "category": "Utilities"
+ },
+ "sf-h2": {
+ "description": "Applies h2-level typography to any element without changing its semantic level.",
+ "category": "Utilities"
+ },
+ "sf-h3": {
+ "description": "Applies h3-level typography to any element without changing its semantic level.",
+ "category": "Utilities"
+ },
+ "sf-h4": {
+ "description": "Applies h4-level typography to any element without changing its semantic level.",
+ "category": "Utilities"
+ },
+ "sf-h5": {
+ "description": "Applies h5-level typography to any element without changing its semantic level.",
+ "category": "Utilities"
+ },
+ "sf-h6": {
+ "description": "Applies h6-level typography to any element without changing its semantic level.",
+ "category": "Utilities"
+ },
+ "sf-header--l": {
+ "description": "Header block padding at the l step (--sf-space-l).",
+ "category": "Layout primitives"
+ },
+ "sf-header--m": {
+ "description": "Header block padding at the m step (--sf-space-m).",
+ "category": "Layout primitives"
+ },
+ "sf-header--s": {
+ "description": "Header block padding at the s step (--sf-space-s).",
+ "category": "Layout primitives"
+ },
+ "sf-header--xl": {
+ "description": "Header block padding at the xl step (--sf-space-xl).",
+ "category": "Layout primitives"
+ },
+ "sf-header--xs": {
+ "description": "Header block padding at the xs step (--sf-space-xs).",
+ "category": "Layout primitives"
+ },
+ "sf-hover-float": {
+ "description": "Hover-triggered transform: translates the element up slightly on hover.",
+ "category": "Utilities"
+ },
+ "sf-hover-grow": {
+ "description": "Hover-triggered transform: scales the element up slightly on hover.",
+ "category": "Utilities"
+ },
+ "sf-hover-shrink": {
+ "description": "Hover-triggered transform: scales the element down slightly on hover.",
+ "category": "Utilities"
+ },
+ "sf-hover-sink": {
+ "description": "Hover-triggered transform: translates the element down slightly on hover.",
+ "category": "Utilities"
+ },
+ "sf-hover-slide-end": {
+ "description": "Hover-triggered transform: translates the element toward the inline-end on hover.",
+ "category": "Utilities"
+ },
+ "sf-hover-slide-start": {
+ "description": "Hover-triggered transform: translates the element toward the inline-start on hover.",
+ "category": "Utilities"
+ },
+ "sf-icon": {
+ "description": "Inline icon sizing primitive. Sets width and height to --sf-icon-m via em-based tokens so the icon scales with the surrounding text.",
+ "category": "Layout primitives"
+ },
+ "sf-icon--2xl": {
+ "description": "Icon variant sized to --sf-icon-2xl (extra-extra-large).",
+ "category": "Layout primitives"
+ },
+ "sf-icon--boxed": {
+ "description": "Icon variant with a square bordered box background. Useful for standalone icon buttons and feature icons.",
+ "category": "Layout primitives"
+ },
+ "sf-icon--l": {
+ "description": "Icon variant sized to --sf-icon-l (large).",
+ "category": "Layout primitives"
+ },
+ "sf-icon--m": {
+ "description": "Icon variant sized to --sf-icon-m (medium, same as base sf-icon).",
+ "category": "Layout primitives"
+ },
+ "sf-icon--s": {
+ "description": "Icon variant sized to --sf-icon-s (small).",
+ "category": "Layout primitives"
+ },
+ "sf-icon--xl": {
+ "description": "Icon variant sized to --sf-icon-xl (extra-large).",
+ "category": "Layout primitives"
+ },
+ "sf-icon--xs": {
+ "description": "Icon variant sized to --sf-icon-xs (extra-small).",
+ "category": "Layout primitives"
+ },
+ "sf-imposter": {
+ "description": "Absolutely positions an element at the center of its nearest positioned ancestor. Use for overlays, badges, and floating labels.",
+ "category": "Layout primitives"
+ },
+ "sf-imposter--contain": {
+ "description": "Imposter variant that clamps the element within the bounds of its parent using overflow:hidden on the parent.",
+ "category": "Layout primitives"
+ },
+ "sf-imposter--fixed": {
+ "description": "Imposter variant that uses position:fixed instead of absolute. Use for viewport-level overlays and modals.",
+ "category": "Layout primitives"
+ },
+ "sf-invisible": {
+ "description": "Visibility helper (optional/utilities.css) — hides the element visually but keeps it in the layout and accessibility tree (visibility: hidden). Not a runtime state: no JS/ARIA condition of its own.",
+ "category": "Utilities"
+ },
"sf-is-disabled": {
- "description": "No .sf-is-readonly here: it duplicated :read-only for real form controls,",
- "category": "States"
+ "description": "Disabled state — dims the element (--sf-opacity-disabled), removes pointer events, and sets cursor: not-allowed. Inherited by child elements that re-enable pointer events.",
+ "category": "State classes"
},
- "sf-is-shimmer": {
- "description": ".sf-is-loading {",
- "category": "States"
+ "sf-is-error": {
+ "description": "Error state — general (not form-field-specific) negative feedback. Applies danger color tokens to indicate a validation failure or system error. Visual styling is identical to sf-is-invalid.",
+ "category": "State classes"
},
- "sf-is-selected": {
- "description": "No .sf-is-active / .sf-is-open / .sf-is-collapsed / .sf-is-expanded /",
- "category": "States"
+ "sf-is-hidden-if-empty": {
+ "description": "Hides the element when it has no child nodes (:empty). An action-on-state helper (the name states the behaviour) for dynamic lists or containers that may render empty.",
+ "category": "State classes"
},
"sf-is-highlighted": {
- "description": "No .sf-is-active / .sf-is-open / .sf-is-collapsed / .sf-is-expanded /",
- "category": "States"
- },
- "sf-is-valid": {
- "description": "No .sf-is-danger here: identical implementation to .sf-is-invalid/",
- "category": "States"
+ "description": "Highlighted state — applies a highlight background. Useful for search result highlighting and keyboard-navigated lists.",
+ "category": "State classes"
},
- "sf-is-success": {
- "description": "No .sf-is-danger here: identical implementation to .sf-is-invalid/",
- "category": "States"
+ "sf-is-info": {
+ "description": "Info status state — applies info color tokens. Use for neutral informational messages and hints.",
+ "category": "State classes"
},
"sf-is-invalid": {
- "description": "No .sf-is-danger here: identical implementation to .sf-is-invalid/",
- "category": "States"
+ "description": "Invalid state — applies danger color tokens to form fields with validation failures. Identical visual output to sf-is-error; the name signals form-field context.",
+ "category": "State classes"
},
- "sf-is-error": {
- "description": "No .sf-is-danger here: identical implementation to .sf-is-invalid/",
- "category": "States"
+ "sf-is-loading": {
+ "description": "Loading state — hides the element's text (color: transparent), removes pointer events, and renders a spinner via ::after. Use for buttons and containers awaiting async results.",
+ "category": "State classes"
+ },
+ "sf-is-selected": {
+ "description": "Selected state — marks an item as selected in a list, table row, or grid cell. Visual specifics (background, border) are applied by component styles.",
+ "category": "State classes"
+ },
+ "sf-is-shimmer": {
+ "description": "Shimmer loading placeholder state. Applies a shimmer animation over the element to indicate that content is loading. Works on both img and non-media elements. (Renamed from .sf-is-skeleton so \"skeleton\" refers only to the planned .sf-skeleton component.)",
+ "category": "State classes"
+ },
+ "sf-is-success": {
+ "description": "Success status state — applies success color tokens. Use for confirmation messages, completed form steps, and positive feedback.",
+ "category": "State classes"
+ },
+ "sf-is-valid": {
+ "description": "Valid state — applies success color tokens to form fields that have passed validation. Visual styling is identical to sf-is-success; the name signals form-field context.",
+ "category": "State classes"
},
"sf-is-warning": {
- "description": "No .sf-is-danger here: identical implementation to .sf-is-invalid/",
- "category": "States"
+ "description": "Warning status state — applies warning color tokens. Use for cautionary messages and non-critical alerts.",
+ "category": "State classes"
},
- "sf-is-info": {
- "description": "No .sf-is-danger here: identical implementation to .sf-is-invalid/",
- "category": "States"
+ "sf-line-clamp-2": {
+ "description": "Clamps text to 2 lines with an ellipsis. Applies -webkit-line-clamp: 2.",
+ "category": "Macro classes"
},
- "sf-is-hidden-if-empty": {
- "description": "/* Action-on-state, not a state assertion: hides the element when it has no",
- "category": "States"
+ "sf-line-clamp-3": {
+ "description": "Clamps text to 3 lines with an ellipsis. Applies -webkit-line-clamp: 3.",
+ "category": "Macro classes"
},
- "is-hidden": {
- "description": "Hides the element (display: none). Toggled by JS or ARIA.",
- "category": "States"
+ "sf-line-clamp-N": {
+ "description": "Clamps text to a custom N lines. Set --sf-line-clamp on the element to control the number of visible lines.",
+ "category": "Macro classes"
},
- "is-invisible": {
- "description": "Makes the element invisible but still occupies space.",
- "category": "States"
+ "sf-link--reverse": {
+ "description": "Link color modifier: reverses the default link color to work on dark/inverted backgrounds. Sets color to --sf-color-text--inverse.",
+ "category": "Macro classes"
},
- "is-visible": {
- "description": "Forces visibility: visible on a hidden element.",
- "category": "States"
+ "sf-link--subtle": {
+ "description": "Link color modifier: renders the link in the body text color instead of the default action color. Underline still indicates the link on hover.",
+ "category": "Macro classes"
},
- "is-disabled": {
- "description": "Marks the element as non-interactive. Reduces opacity and blocks pointer events.",
- "category": "States"
+ "sf-link-external": {
+ "description": "Automatically appends an external-link icon (via ::after content) to indicate the link opens in a new tab or goes to an external domain.",
+ "category": "Macro classes"
},
- "is-readonly": {
- "description": "Marks the element as read-only. Reduces opacity; pointer events still active.",
- "category": "States"
+ "sf-list-none": {
+ "description": "Drops marker + inline start-padding in one class, on any / (or element with list-style applied).",
+ "category": "Utilities"
},
- "is-loading": {
- "description": "Indicates the element is in a loading state. Shows a spinner cursor.",
- "category": "States"
+ "sf-live-validate": {
+ "description": "Scopes native constraint-validation feedback to this subtree: within it, :user-invalid/:user-valid on input/select/textarea drive --sf-field-border-color (the same token .sf-is-invalid/.sf-is-valid set explicitly). Apply to a