Skip to content

feat: fix token bugs, modernize tokens, expand palette, add regression suite - #29

Merged
jackgranatowski merged 4 commits into
mainfrom
claude/framework-audit-plan-gGaP5
May 20, 2026
Merged

feat: fix token bugs, modernize tokens, expand palette, add regression suite#29
jackgranatowski merged 4 commits into
mainfrom
claude/framework-audit-plan-gGaP5

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented May 20, 2026

Copy link
Copy Markdown
Contributor

Correctness (verified against audits/):

  • cap every shadow-layer alpha at 0.7 so dark mode no longer renders opaque slabs
  • repair --sf-shadow-color (was malformed/dead) into a neutral-derived tint and
    wire it into every shadow; colored shadows are now an opt-in override
  • link hover/active darken in light, lighten in dark (was reducing contrast)
  • clamp --sf-color-text--inverse to stay in-gamut on custom neutral overrides

Modernization (benchmarked vs Tailwind v4 / Open Props):

  • full font-weight 100-900 scale; font-feature/variation/optical-sizing tokens
  • humanist/geometric/slab font stacks; bounce/overshoot easings
  • text-shadow/drop-shadow, breakpoint, perspective, scroll-timeline tokens
  • named animation presets (keyframes + .sf-* classes) in motion.css
  • forced-colors handling in accessibility.css

Palette: implement the alias layer in optional/tokens.palette.css — full 50-950
scale, a5-a95 alpha, shade + functional aliases per brand color (drops off-grid a75).

Tooling & docs: Playwright regression suite (light+dark + token coverage) wired into
CI; slashed.full.css bundle; multi-bundle pre-commit hook; English comments/docs;
documented intentional tradeoffs.

https://claude.ai/code/session_01MoV2rAESh77QMzsc4kL3fo

Summary by CodeRabbit

  • New Features
    • Opt-in motion/animation utilities (fade/slide/scale), expanded typography controls (numeric weights, font features), accessibility forced-colors focus rules, 3D perspective tokens, and richer shadow/text/drop-shadow presets.
  • Documentation
    • Updated docs, README and demo to reflect bundles, palette scales, token examples, and developer commands.
  • Tests
    • Added Playwright token regression suite and a test fixture; test scripts/configuration added.
  • Chores
    • Multi‑bundle build/watch support, pre-commit now rebuilds and stages generated bundles, CI test job added, ignore test-results.

Review Change Stack

…n suite

Correctness (verified against audits/):
- cap every shadow-layer alpha at 0.7 so dark mode no longer renders opaque slabs
- repair --sf-shadow-color (was malformed/dead) into a neutral-derived tint and
  wire it into every shadow; colored shadows are now an opt-in override
- link hover/active darken in light, lighten in dark (was reducing contrast)
- clamp --sf-color-text--inverse to stay in-gamut on custom neutral overrides

Modernization (benchmarked vs Tailwind v4 / Open Props):
- full font-weight 100-900 scale; font-feature/variation/optical-sizing tokens
- humanist/geometric/slab font stacks; bounce/overshoot easings
- text-shadow/drop-shadow, breakpoint, perspective, scroll-timeline tokens
- named animation presets (keyframes + .sf-* classes) in motion.css
- forced-colors handling in accessibility.css

Palette: implement the alias layer in optional/tokens.palette.css — full 50-950
scale, a5-a95 alpha, shade + functional aliases per brand color (drops off-grid a75).

Tooling & docs: Playwright regression suite (light+dark + token coverage) wired into
CI; slashed.full.css bundle; multi-bundle pre-commit hook; English comments/docs;
documented intentional tradeoffs.

https://claude.ai/code/session_01MoV2rAESh77QMzsc4kL3fo
@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 64e2aa22-85fd-4795-a02d-62cee946b013

📥 Commits

Reviewing files that changed from the base of the PR and between 7e4ec70 and 88dc2a4.

⛔ Files ignored due to path filters (2)
  • dist/slashed.essential.css is excluded by !**/dist/**
  • dist/slashed.full.css is excluded by !**/dist/**
📒 Files selected for processing (5)
  • README.md
  • core/tokens.css
  • docs/color-aliases-design-decisions.md
  • scripts/bundle.js
  • tests/tokens.spec.js
✅ Files skipped from review due to trivial changes (1)
  • README.md

📝 Walkthrough

Walkthrough

Adds multi-bundle build/support and pre-commit staging, expands core and optional design tokens (colors, shadows, typography, motion), adds Playwright token-regression tests and CI job, and updates README/docs/demo to reflect new bundles and tokens.

Changes

Build System and Bundle Configuration

Layer / File(s) Summary
Multi-bundle configuration and tooling
bundle.config.json, .githooks/pre-commit, scripts/bundle.js
Bundle config expanded to define essential and full outputs; bundler normalized via getBundles() to build/watch multiple bundles; pre-commit hook stages all computed outputs.

Token System Expansion and Testing

Layer / File(s) Summary
Core color token refinements
core/tokens.css (color sections)
Color derivations updated: clamped luminance/lightness in inverse and link hover/active formulas; --sf-shadow-glow alpha bounded with clamp().
Typography and weight scale
core/tokens.css (typography)
Adds optional font stack variables, font-feature controls, and a full numeric font-weight scale with semantic aliases.
Shadow API refactor
core/tokens.css (shadow section)
Shadows refactored to use oklch()-derived neutral color and clamp()-bounded alpha/strength across box/text/drop shadow tokens.
Motion, easing, and animation presets
core/motion.css, core/tokens.css (motion section)
Adds easing tokens (bounce/overshoot), animation preset variables, and reduced-motion-aware utility classes with keyframes.
Accessibility & layout comments
core/accessibility.css, core/layout.css, core/tokens.layout.css
Adds forced-colors handling for High Contrast focus rings and removes decorative shadows; updates layout/tokens.layout header comments (no functional CSS changes).
Optional palette scales and aliases
optional/tokens.palette.css
Introduces full numeric palette ramps (50–950), alpha variants (a5–a95), shade aliases, and functional aliases for multiple color families.
Playwright test framework and token regression suite
playwright.config.js, package.json, tests/fixture.html, tests/tokens.spec.js, .github/workflows/ci.yml, .gitignore
Adds Playwright config, regression tests that assert token resolution and invariants across light/dark themes, package test scripts, CI test job, test fixture, and ignores test-results/.

Documentation and Demo

Layer / File(s) Summary
README and bundle guidance updates
README.md
Quick-start now includes core/motion.css; recommended bundle examples and development commands updated (adds test/install steps).
Architecture and design decision docs
docs/architecture.md, docs/color-aliases-design-decisions.md
Documents full-bundle composition, records intentional tradeoffs, standardizes color-alias design decisions and alias mapping semantics.
Demo page token and interaction showcase
docs/demo.html
Demo expanded with numeric/alpha palette swatches, full font-weight scale, shadow/text-shadow/drop-shadow examples, 3D perspective demo, added easing presets, animation preset controls, and a script to re-trigger animations.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: fixing token bugs, modernizing tokens, expanding the palette, and adding a regression test suite.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/framework-audit-plan-gGaP5

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
scripts/bundle.js (1)

60-62: ⚡ Quick win

Use relative paths for watch matching instead of basenames.

Line 60-Line 62 strips directory context; if core/ and optional/ ever share a filename, watch filtering becomes ambiguous. Track normalized relative paths (e.g. core/tokens.css) and compare against ${dir}/${filename}.

Diff proposal
-  const collectBasenames = () =>
-    getBundles().flatMap((b) => b.files).map((f) => path.basename(f));
+  const collectWatchedPaths = () =>
+    new Set(getBundles().flatMap((b) => b.files).map((f) => path.normalize(f)));

-  let watchedFiles = [];
+  let watchedFiles = new Set();
   try {
-    watchedFiles = collectBasenames();
+    watchedFiles = collectWatchedPaths();
   } catch (err) {
     console.error(`[watch] Failed to load config: ${err.message}`);
   }
@@
   ['core', 'optional'].forEach((dir) => {
     fs.watch(path.join(ROOT, dir), (event, filename) => {
       if (!filename) return;
-      if (watchedFiles.includes(filename)) {
+      const changedPath = path.normalize(path.join(dir, String(filename)));
+      if (watchedFiles.has(changedPath)) {
         console.log(`[watch] ${event}: ${dir}/${filename}`);
         rebuild();
       }
@@
       console.log('[watch] bundle.config.json changed');
       try {
-        watchedFiles = collectBasenames();
+        watchedFiles = collectWatchedPaths();
       } catch (err) {
         console.error(`[watch] Invalid config: ${err.message}`);
       }

Also applies to: 84-91

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/bundle.js` around lines 60 - 62, The current collectBasenames
function loses directory context by returning only path.basename(f), causing
ambiguous watch matching; change it to return normalized relative paths instead
(e.g., using path.posix.join or path.relative) so entries reflect "dir/filename"
like "core/tokens.css", and update any other similar utilities referenced in the
diff (e.g., the logic around lines 84-91 that filters watches) to compare
against `${dir}/${filename}` rather than basenames; locate collectBasenames and
the watch filtering code that uses its output and replace basename usage with
path.relative(pathRoot, f) (or equivalent normalization) so watch matching is
unambiguous.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 41-42: Replace the floating action versions with pinned commit
SHAs and disable checkout credential persistence: update the uses entries for
actions/checkout@v4 and actions/setup-node@v4 to specific commit SHAs (e.g.,
actions/checkout@<commit-sha> and actions/setup-node@<commit-sha>) and add the
checkout step input persist-credentials: false to the actions/checkout step so
the workflow does not expose tokens to checked-out code.

In `@docs/color-aliases-design-decisions.md`:
- Around line 113-117: The fenced code block containing the CSS variable
examples (--sf-color-{status}-subtle, --sf-color-{status}-muted,
--sf-color-{status}-strong) needs a language identifier for proper rendering and
markdown linting; update the opening fence from ``` to ```text (or another
appropriate language like ```css) so the block becomes a labeled fenced code
block (e.g., ```text) while keeping the content unchanged.

In `@README.md`:
- Line 71: The README table is missing tokens.layout in the
slashed.essential.css bundle entry; update the table row for
`slashed.essential.css` to include `tokens.layout` (or `tokens.layout.css`)
alongside `layers`, `tokens`, `reset`, `base`, `layout`, `states`, `motion`,
`accessibility`, and `print` so the essential bundle list matches the
quick-start and architecture docs; ensure the token name exactly matches other
references (`tokens.layout`/`tokens.layout.css`) for consistency.

In `@tests/tokens.spec.js`:
- Line 11: The FIXTURE constant is built by string concatenation with path.join
which breaks on Windows and with special characters; replace the construction of
FIXTURE to use pathToFileURL from the url module and take its href (i.e., import
or require pathToFileURL and call pathToFileURL(path.join(__dirname,
'fixture.html')).href) so the file URL is formed correctly; update any tests
referencing FIXTURE accordingly.

---

Nitpick comments:
In `@scripts/bundle.js`:
- Around line 60-62: The current collectBasenames function loses directory
context by returning only path.basename(f), causing ambiguous watch matching;
change it to return normalized relative paths instead (e.g., using
path.posix.join or path.relative) so entries reflect "dir/filename" like
"core/tokens.css", and update any other similar utilities referenced in the diff
(e.g., the logic around lines 84-91 that filters watches) to compare against
`${dir}/${filename}` rather than basenames; locate collectBasenames and the
watch filtering code that uses its output and replace basename usage with
path.relative(pathRoot, f) (or equivalent normalization) so watch matching is
unambiguous.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 046a4f7c-825f-4d3e-8010-782cdf6bd6d2

📥 Commits

Reviewing files that changed from the base of the PR and between 2ceba74 and e6b1cd2.

⛔ Files ignored due to path filters (3)
  • dist/slashed.essential.css is excluded by !**/dist/**
  • dist/slashed.full.css is excluded by !**/dist/**
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • .githooks/pre-commit
  • .github/workflows/ci.yml
  • .gitignore
  • README.md
  • bundle.config.json
  • core/accessibility.css
  • core/layout.css
  • core/motion.css
  • core/tokens.css
  • core/tokens.layout.css
  • docs/architecture.md
  • docs/color-aliases-design-decisions.md
  • docs/demo.html
  • optional/tokens.palette.css
  • package.json
  • playwright.config.js
  • scripts/bundle.js
  • tests/fixture.html
  • tests/tokens.spec.js

Comment thread .github/workflows/ci.yml
Comment on lines +41 to +42
- uses: actions/checkout@v4
- uses: actions/setup-node@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify workflow action pinning and checkout credential persistence settings.
rg -n '^\s*-\s*uses:\s*actions/' .github/workflows/ci.yml
rg -n 'persist-credentials' .github/workflows/ci.yml

Repository: codeslash-dev/SLASHED

Length of output: 337


Harden action usage in the new test job.

Lines 41–42 use floating version tags and lack credential persistence restrictions. Pin actions to commit SHAs and disable checkout credential persistence to reduce supply-chain and token exposure risk.

🔐 Suggested hardening
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@<pinned-commit-sha>
+        with:
+          persist-credentials: false
-      - uses: actions/setup-node@v4
+      - uses: actions/setup-node@<pinned-commit-sha>
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 41-41: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 41-41: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 42-42: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 41 - 42, Replace the floating action
versions with pinned commit SHAs and disable checkout credential persistence:
update the uses entries for actions/checkout@v4 and actions/setup-node@v4 to
specific commit SHAs (e.g., actions/checkout@<commit-sha> and
actions/setup-node@<commit-sha>) and add the checkout step input
persist-credentials: false to the actions/checkout step so the workflow does not
expose tokens to checked-out code.

Comment thread docs/color-aliases-design-decisions.md Outdated
Comment thread README.md Outdated
Comment thread tests/tokens.spec.js Outdated
claude added 2 commits May 20, 2026 13:18
Custom properties can't be used in @media/@container conditions — their only
natural use site — so the tokens couldn't deliver on their purpose. SLASHED is
container-query-first (fluid tokens + @container primitives), so they added
surface area without value. Removed from core/tokens.css and rebundled.

https://claude.ai/code/session_01MoV2rAESh77QMzsc4kL3fo
- shadow tint now inherits the neutral's own chroma (drop the *2 amplifier),
  so a colourless neutral yields colourless shadows and the tint never reads
  more saturated than the brand neutral
- note that animation presets are decorative and inert under reduced motion,
  so they must not be the sole show/hide mechanism
- reword the architecture breakpoint note now that no breakpoint tokens ship

https://claude.ai/code/session_01MoV2rAESh77QMzsc4kL3fo

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
core/tokens.css (1)

489-494: ⚡ Quick win

Use a darkened brand example for the override.

The var(--sf-color-primary) example skips the fixed L=0.15 darkening, so consumers copying it can end up with bright colored slabs again. Show the opt-in override as a dark-tinted derivation instead.

Suggested doc tweak
-       tinted shadows: var(--sf-color-primary). */
+       tinted shadows: oklch(from var(--sf-color-primary) 0.15 c h). */
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/tokens.css` around lines 489 - 494, The example override for
--sf-shadow-color uses var(--sf-color-primary) which skips the fixed darkening;
update the documentation/comment to show the opt-in override as a dark-tinted
derivation (i.e. derive from --sf-color-primary but force L=0.15 like the
neutral example) so consumers copy an explicitly darkened brand; reference the
symbols --sf-shadow-color, --sf-color-neutral, --sf-color-primary and the L=0.15
darkening when describing the correct override form.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@core/tokens.css`:
- Around line 489-494: The example override for --sf-shadow-color uses
var(--sf-color-primary) which skips the fixed darkening; update the
documentation/comment to show the opt-in override as a dark-tinted derivation
(i.e. derive from --sf-color-primary but force L=0.15 like the neutral example)
so consumers copy an explicitly darkened brand; reference the symbols
--sf-shadow-color, --sf-color-neutral, --sf-color-primary and the L=0.15
darkening when describing the correct override form.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa52a244-e3b1-461a-8880-b1376df913b0

📥 Commits

Reviewing files that changed from the base of the PR and between 3bed264 and 7e4ec70.

⛔ Files ignored due to path filters (2)
  • dist/slashed.essential.css is excluded by !**/dist/**
  • dist/slashed.full.css is excluded by !**/dist/**
📒 Files selected for processing (3)
  • core/motion.css
  • core/tokens.css
  • docs/architecture.md
✅ Files skipped from review due to trivial changes (1)
  • docs/architecture.md

- README: list tokens.layout in the essential-bundle contents (it ships in it)
- tests: build the fixture URL with pathToFileURL().href (cross-platform)
- docs: label bare code fences as text (markdownlint MD040)
- tokens: shadow-color override example now derives a dark tint
  (oklch(from … 0.15 c h)) so consumers don't recreate bright slabs
- bundle watch: match normalized relative paths, not basenames

CI action SHA-pinning / persist-credentials deferred to #31 (repo-wide).

https://claude.ai/code/session_01MoV2rAESh77QMzsc4kL3fo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants