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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

## Unreleased

### Features
- **motion:** add `.sf-stagger` — put it on a parent and every direct child gets an incrementing `animation-delay`, so a group of time-based entrance animations (`.sf-fade-in` / `.sf-slide-in-*`) plays in sequence. Works on any number of children with no manual per-item index: where `sibling-index()` is supported the ramp is unbounded, otherwise it falls back to an 8-step `:nth-child` ramp (covering a 4-column grid's first two rows) that plateaus. One knob, `--sf-stagger-step` (default `75ms`), retunes the whole sequence; each child's delay is `index × --sf-stagger-step × --sf-motion-scale`. Choreography only — a child without its own animation just carries an inert delay, so animating only some children needs no opt-out on the rest.
- **tokens:** the `.sf-hover-*` transform utilities now read magnitude knobs instead of hard-coded values — `--sf-hover-grow-scale` (1.05), `--sf-hover-shrink-scale` (0.95), `--sf-hover-lift` (0.25em, float/sink), `--sf-hover-slide` (0.5em, slide-start/end) — so each effect's strength is one global override.

### Breaking Changes
Comment on lines +9 to +11

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 CHANGELOG vs PR checklist mismatch

The CHANGELOG correctly adds a ### Breaking Changes section for the removal of --sf-animation-delay-1…5, but the PR description checklist is ticked for "No breaking changes." Token removals are semver-breaking regardless of how rarely the tokens were used. The checklist note ("old delay tokens removed, but they were rarely used") is a rationale for shipping the change, not grounds for declaring it non-breaking. Consider un-ticking that item or removing the "No breaking changes" qualifier so the checklist accurately reflects the CHANGELOG.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

- **tokens:** removed the fixed `--sf-animation-delay-1…5` stagger tokens, superseded by the new `.sf-stagger` utility + `--sf-stagger-step` knob. Replace `style="animation-delay: var(--sf-animation-delay-N)"` on hand-indexed children with a single `.sf-stagger` class on their parent (see `docs/motion.md`); to keep a fixed manual delay, use a literal (e.g. `animation-delay: 150ms`).

Comment thread
coderabbitai[bot] marked this conversation as resolved.
### Bug Fixes
- **layout:** `.sf-bento` and `.sf-grid-cols-2/3/4/6` now actually respond to their `@container` breakpoints — both used to declare a `container` on themselves and then query that same container to resize themselves, which is a no-op per spec (a container can't be the subject of its own `@container` query). Fixed by relying on an ancestor container (`.sf-container` / `.sf-cq` / `.sf-fluid-cq`) instead, matching how `.sf-alternate` and `.sf-grid-cols-1-2` etc. already do it. `.sf-bento-wide` / `.sf-bento-featured` also no longer force a phantom 2nd column once the grid collapses to 1 column at the mobile breakpoint.

Expand Down
2 changes: 1 addition & 1 deletion badges/badge-optimal.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schemaVersion": 1,
"label": "optimal",
"message": "19.5 kB gzip",
"message": "19.6 kB gzip",
"color": "brightgreen",
"namedLogo": "css3"
}
212 changes: 106 additions & 106 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": "ea14629a05b1",
"tokensHash": "5624c486ab4d",
"bundles": [
"full",
"optimal"
Expand Down Expand Up @@ -107,111 +107,6 @@
"optimal"
]
},
{
"name": "--sf-animation-delay-1",
"tier": "PUBLIC",
"role": "consumption",
"namespace": "animation",
"category": "Core tokens",
"group": "Animation presets",
"description": "Complete animation shorthand values — pair named @keyframes with duration and easing. Use directly as animation property values.",
"note": "Shortest stagger delay. Apply to the first element in a sequentially animated group.",
"value": "calc(75ms * var(--sf-motion-scale))",
"aliasOf": null,
"registered": false,
"syntax": null,
"fallbackOnly": false,
"optional": false,
"layer": "slashed.tokens",
"bundles": [
"full",
"optimal"
]
},
{
"name": "--sf-animation-delay-2",
"tier": "PUBLIC",
"role": "consumption",
"namespace": "animation",
"category": "Core tokens",
"group": "Animation presets",
"description": "Complete animation shorthand values — pair named @keyframes with duration and easing. Use directly as animation property values.",
"note": "Second stagger delay step.",
"value": "calc(150ms * var(--sf-motion-scale))",
"aliasOf": null,
"registered": false,
"syntax": null,
"fallbackOnly": false,
"optional": false,
"layer": "slashed.tokens",
"bundles": [
"full",
"optimal"
]
},
{
"name": "--sf-animation-delay-3",
"tier": "PUBLIC",
"role": "consumption",
"namespace": "animation",
"category": "Core tokens",
"group": "Animation presets",
"description": "Complete animation shorthand values — pair named @keyframes with duration and easing. Use directly as animation property values.",
"note": "Third stagger delay step.",
"value": "calc(225ms * var(--sf-motion-scale))",
"aliasOf": null,
"registered": false,
"syntax": null,
"fallbackOnly": false,
"optional": false,
"layer": "slashed.tokens",
"bundles": [
"full",
"optimal"
]
},
{
"name": "--sf-animation-delay-4",
"tier": "PUBLIC",
"role": "consumption",
"namespace": "animation",
"category": "Core tokens",
"group": "Animation presets",
"description": "Complete animation shorthand values — pair named @keyframes with duration and easing. Use directly as animation property values.",
"note": "Fourth stagger delay step.",
"value": "calc(300ms * var(--sf-motion-scale))",
"aliasOf": null,
"registered": false,
"syntax": null,
"fallbackOnly": false,
"optional": false,
"layer": "slashed.tokens",
"bundles": [
"full",
"optimal"
]
},
{
"name": "--sf-animation-delay-5",
"tier": "PUBLIC",
"role": "consumption",
"namespace": "animation",
"category": "Core tokens",
"group": "Animation presets",
"description": "Complete animation shorthand values — pair named @keyframes with duration and easing. Use directly as animation property values.",
"note": "Longest stagger delay. Apply to the last element in a sequentially animated group.",
"value": "calc(375ms * var(--sf-motion-scale))",
"aliasOf": null,
"registered": false,
"syntax": null,
"fallbackOnly": false,
"optional": false,
"layer": "slashed.tokens",
"bundles": [
"full",
"optimal"
]
},
{
"name": "--sf-animation-fade-in",
"tier": "PUBLIC",
Expand Down Expand Up @@ -10519,6 +10414,90 @@
"optimal"
]
},
{
"name": "--sf-hover-grow-scale",
"tier": "PUBLIC",
"role": "knob",
"namespace": "hover",
"category": "Core tokens",
"group": "Animation presets",
"description": "Complete animation shorthand values — pair named @keyframes with duration and easing. Use directly as animation property values.",
"note": "Scale factor applied by .sf-hover-grow on hover (>1 grows).",
"value": "1.05",
"aliasOf": null,
"registered": false,
"syntax": null,
"fallbackOnly": false,
"optional": false,
"layer": "slashed.tokens",
"bundles": [
"full",
"optimal"
]
},
{
"name": "--sf-hover-lift",
"tier": "PUBLIC",
"role": "knob",
"namespace": "hover",
"category": "Core tokens",
"group": "Animation presets",
"description": "Complete animation shorthand values — pair named @keyframes with duration and easing. Use directly as animation property values.",
"note": "Translate distance for .sf-hover-float (up) and .sf-hover-sink (down) on hover.",
"value": "0.25em",
"aliasOf": null,
"registered": false,
"syntax": null,
"fallbackOnly": false,
"optional": false,
"layer": "slashed.tokens",
"bundles": [
"full",
"optimal"
]
},
{
"name": "--sf-hover-shrink-scale",
"tier": "PUBLIC",
"role": "knob",
"namespace": "hover",
"category": "Core tokens",
"group": "Animation presets",
"description": "Complete animation shorthand values — pair named @keyframes with duration and easing. Use directly as animation property values.",
"note": "Scale factor applied by .sf-hover-shrink on hover (<1 shrinks).",
"value": "0.95",
"aliasOf": null,
"registered": false,
"syntax": null,
"fallbackOnly": false,
"optional": false,
"layer": "slashed.tokens",
"bundles": [
"full",
"optimal"
]
},
{
"name": "--sf-hover-slide",
"tier": "PUBLIC",
"role": "knob",
"namespace": "hover",
"category": "Core tokens",
"group": "Animation presets",
"description": "Complete animation shorthand values — pair named @keyframes with duration and easing. Use directly as animation property values.",
"note": "Translate distance for .sf-hover-slide-start / .sf-hover-slide-end on hover.",
"value": "0.5em",
"aliasOf": null,
"registered": false,
"syntax": null,
"fallbackOnly": false,
"optional": false,
"layer": "slashed.tokens",
"bundles": [
"full",
"optimal"
]
},
{
"name": "--sf-icon-2xl",
"tier": "PUBLIC",
Expand Down Expand Up @@ -13648,6 +13627,27 @@
"optimal"
]
},
{
"name": "--sf-stagger-step",
"tier": "PUBLIC",
"role": "knob",
"namespace": "stagger",
"category": "Core tokens",
"group": "Animation presets",
"description": "Complete animation shorthand values — pair named @keyframes with duration and easing. Use directly as animation property values.",
"note": "Per-item delay increment for the .sf-stagger utility. One knob retunes the whole staggered sequence; the class multiplies it by each child's index and by --sf-motion-scale.",
"value": "75ms",
"aliasOf": null,
"registered": false,
"syntax": null,
"fallbackOnly": false,
"optional": false,
"layer": "slashed.tokens",
"bundles": [
"full",
"optimal"
]
},
{
"name": "--sf-state-pending-opacity",
"tier": "PUBLIC",
Expand Down
10 changes: 10 additions & 0 deletions configurator/src/data/classes.generated.json
Original file line number Diff line number Diff line change
Expand Up @@ -2894,6 +2894,16 @@
"optional": false,
"layer": "slashed.layout"
},
{
"name": "sf-stagger",
"selector": ".sf-stagger",
"kind": "motion",
"category": "Motion / animation",
"group": "",
"description": "Stagger — choreography, not the animation itself. Put .sf-stagger on a PARENT; every direct child gets an incrementing animation-delay so a time-based entrance (.sf-fade-in / .sf-slide-in-*) plays in sequence. Children WITHOUT an animation just carry an inert delay (no-op), so…",
"optional": false,
"layer": "slashed.motion"
},
{
"name": "sf-sticky",
"selector": ".sf-sticky",
Expand Down
2 changes: 1 addition & 1 deletion configurator/src/data/domain-patterns.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"components": ["btn-", "card-"],
"borders": ["radius", "border-width", "border-scale", "border-style", "divider"],
"shadows": ["shadow"],
"motion": ["motion", "duration", "easing", "ease", "scroll-timeline"],
"motion": ["motion", "duration", "easing", "ease", "scroll-timeline", "stagger", "hover-"],
"effects": ["filter", "blur", "backdrop", "opacity", "effect"],
"misc": ["z-", "cursor", "ring", "focus", "outline", "selection", "icon",
"sf-is-active", "sf-is-current", "sf-is-open", "sf-is-pressed",
Expand Down
37 changes: 31 additions & 6 deletions configurator/src/data/token-registry.generated.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"_meta": {
"generatedBy": "scripts/gen-token-registry.js",
"nextId": 792
"nextId": 797
},
"tokens": [
{
Expand All @@ -22,23 +22,28 @@
},
{
"id": 4,
"name": "--sf-animation-delay-1"
"name": "--sf-animation-delay-1",
"removed": true
},
{
"id": 5,
"name": "--sf-animation-delay-2"
"name": "--sf-animation-delay-2",
"removed": true
},
{
"id": 6,
"name": "--sf-animation-delay-3"
"name": "--sf-animation-delay-3",
"removed": true
},
{
"id": 7,
"name": "--sf-animation-delay-4"
"name": "--sf-animation-delay-4",
"removed": true
},
{
"id": 8,
"name": "--sf-animation-delay-5"
"name": "--sf-animation-delay-5",
"removed": true
},
{
"id": 9,
Expand Down Expand Up @@ -3208,6 +3213,26 @@
{
"id": 791,
"name": "--sf-btn-xs-padding-inline"
},
{
"id": 792,
"name": "--sf-hover-grow-scale"
},
{
"id": 793,
"name": "--sf-hover-lift"
},
{
"id": 794,
"name": "--sf-hover-shrink-scale"
},
{
"id": 795,
"name": "--sf-hover-slide"
},
{
"id": 796,
"name": "--sf-stagger-step"
}
]
}
Loading