feat: add comprehensive full-api-demo files with token overrides - #454
Conversation
- full-api-demo.html: Comprehensive demo exercising all SLASHED tokens and classes * 128 layout primitives (stack, cluster, grid, sidebar, divider, etc.) * 691 color tokens with all palettes (primary, action, neutral, semantic) * 8 typography scales (text-2xs to text-3xl) with 3 font families * Complete spacing scale (space-4xs to space-4xl) * Border styles, radius tokens, shadow elevations * 9 animation examples (fade, spin, float, ping, shimmer, etc.) * 40 state classes (.is-active, .is-disabled, .is-error, etc.) * 42 macro classes (.sf-prose, .sf-truncate, .sf-flow, etc.) * Accessibility features and focus styles * Loads optimal bundle from jsDelivr CDN - full-api-demo-with-overrides.html: Same demo with ultimate-override.css * Demonstrates that all tokens are customizable * Overrides change all 7 color palettes * Changes all 3 font families and increases spacing tokens * Strengthens shadows and rounds corners - ultimate-override.css: Comprehensive token override file * 184 custom property overrides testing every category * Color palettes (primary→purple, action→teal, danger→orange, etc.) * Typography, spacing, borders, radius, shadows, animations * Layout configuration and z-index values Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QCMzUyUS62KUSkr4AzrF7M
Changed 'Courier' to lowercase 'courier' to comply with stylelint value-keyword-case rules. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QCMzUyUS62KUSkr4AzrF7M
|
Warning Review limit reached
Next review available in: 26 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughAdds ChangesFull-API Demo Generator and Validator
Sequence Diagram(s)sequenceDiagram
participant generate_mjs
participant api_index as docs/api-index.json
participant fs as File System
participant validate_mjs
participant Chromium
generate_mjs->>api_index: read tokens/classes/knobs
generate_mjs->>generate_mjs: buildOverride() → ultimate-override.css
generate_mjs->>fs: write ultimate-override.css
generate_mjs->>generate_mjs: buildDemo(withOverride=false/true)
generate_mjs->>fs: write full-api-demo.html + full-api-demo-with-overrides.html
validate_mjs->>fs: copy ultimate-override.css to temp dir
validate_mjs->>fs: rewrite full-api-demo.html (CDN → local CSS)
validate_mjs->>Chromium: launch + navigate to rewritten page
Chromium-->>validate_mjs: page loaded
validate_mjs->>Chromium: snap() light state
validate_mjs->>Chromium: click dark toggle → snap() dark state
validate_mjs->>Chromium: click `#ovBtn` → snap() override state
validate_mjs->>validate_mjs: assert tile counts, theme/style changes, no errors
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoAdd full API demo pages and comprehensive token override stylesheet
AI Description
Diagram
High-Level Assessment
Files changed (4)
|
Code Review by Qodo
Context used✅ Compliance rules (platform):
6 rules 1.
|
Replace the hand-written demo/override (which covered ~26% of classes and contained 21 invented token names) with files generated from docs/api-index.json, so coverage is exact and stays correct as the token set changes. - demos/generate.mjs reads the API index and emits all three artifacts. It renders one example per class (239/239) and overrides every configurable knob token (202/225), with a build-time assertion that every knob is either perturbed by a typed rule, a curated value, or an explicitly-documented skip — a new unhandled knob fails the generator instead of being dropped. - 23 knobs are intentionally not perturbed (z-index/stacking, env() insets, runtime is-* flags, color-scheme, none-sentinels); each is listed with a reason in ultimate-override.css. - Colors use relative-color hue-shift so every override is valid CSS and preserves alpha; lengths/numbers/ratios/percentages get typed transforms. - demos/validate.mjs drives both pages in Chromium against the local optimal bundle: asserts 0 console errors, all 239 class tiles present, and that the override visibly changes computed styles (color, spacing, font, type scale). - Tile stages use contain:layout/paint so position:fixed classes (is-fullscreen, is-overlay, sf-imposter--fixed) stay in their own cell. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QCMzUyUS62KUSkr4AzrF7M
Expand the generated demo so every part of the API is exercisable in one page. Toolbar controls (wired by a small inline script): - Theme: Auto / Light / Dark via data-theme on the root (Auto falls back to prefers-color-scheme), exactly as core/themes.css drives it. - LumLocker and Cross-fade (.sf-theme-transition) toggles. - Ultimate override: injects/removes ultimate-override.css at runtime so the same page shows baseline and overridden side by side. - Replay all: re-triggers every animation/easing/duration/transition. Interactive Functions section — every motion/effect token is runnable: animations (replay), easing curves (animated dot), durations (growing bar), transitions (toggle state), all gradients, and drop-shadow filters. Part 2 — Complete token reference: all 691 tokens (knob + consumption, every tier) grouped by namespace, each with a best-effort visual (colour, gradient, shadow, radius, length bar, type sample, opacity, motion) and its LIVE computed value filled by JS. Toggling theme or override recomputes every value in place, so derived/semantic/private layout+macro tokens are all observable. A build assertion fails unless all 691 tokens render. validate.mjs now also checks: dark-mode restyles the page (bg lightness flips), the runtime override toggle changes computed styles, and JS populates the live token values — all against the locally built optimal bundle, 0 console errors. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QCMzUyUS62KUSkr4AzrF7M
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
badges/badge-optimal.json (1)
3-6: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winVerify badge value is generated, not hand-edited.
The
messagevalue changed from37.0 kB gzipto17.6 kB gzip. Perscripts/bundle.js:216-241, this file should be auto-generated bywriteSizeBadge()from the actual bundle's gzip size. If this was hand-edited, it risks going stale again. Ensure the generator script was run to produce this value.🤖 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 `@badges/badge-optimal.json` around lines 3 - 6, The badge value appears to have been manually edited instead of generated, so regenerate the badge JSON from the build output rather than changing the message directly. Use the badge generation flow in writeSizeBadge() from scripts/bundle.js to produce the correct gzip size for the optimal badge, and ensure the updated value comes from the actual bundle artifact so it stays in sync.
🤖 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 `@demos/generate.mjs`:
- Around line 533-541: The completeness check in the class-rendering flow only
verifies de-duplication of the input list, so a class with an unlisted kind can
still be omitted from the emitted HTML without failing. Update the coverage
assertion around the kind mapping and the emitted list so it validates rendered
output from the actual class data, not just the `classes` input, using the
`kinds` definition and the `emitted` construction in `generate.mjs` as the key
points to adjust. Ensure the check fails when any class kind is not represented
in the rendered HTML, not merely when duplicate inputs exist.
- Around line 293-294: The overlay demo links in the generate.mjs demo output
are empty anchors, so they need an accessible name. Update the
sf-clickable-parent and sf-clickable-parent__overlay branches in the demo
generator to give the overlay <a> elements an aria-label or hidden text so
assistive tech announces them as meaningful links while keeping the visual demo
unchanged.
In `@demos/validate.mjs`:
- Line 92: The token-value coverage check in the validation script is too
permissive because it allows a large portion of missing values to pass. Tighten
the assertion in the token coverage logic around the filledVals versus
expectTokens check so the generator/runtime contract fails when tokens are not
populated, and if any tokens are intentionally empty, handle them with an
explicit allowlist instead of the current percentage threshold.
- Line 29: The Chromium launch in validate.mjs is hardcoded to a
container-specific executable path, which breaks portability. Update the
chromium.launch usage in the validate script to let Playwright resolve its
managed browser by default, and add an environment-based override only if a
custom binary path is explicitly provided. Keep the change localized to the
browser startup logic so the rest of the validation flow stays unchanged.
---
Nitpick comments:
In `@badges/badge-optimal.json`:
- Around line 3-6: The badge value appears to have been manually edited instead
of generated, so regenerate the badge JSON from the build output rather than
changing the message directly. Use the badge generation flow in writeSizeBadge()
from scripts/bundle.js to produce the correct gzip size for the optimal badge,
and ensure the updated value comes from the actual bundle artifact so it stays
in sync.
🪄 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: afb709d5-7dbd-4395-bf01-ebd4a6610782
📒 Files selected for processing (7)
.gitignorebadges/badge-optimal.jsondemos/generate.mjsdemos/validate.mjsfull-api-demo-with-overrides.htmlfull-api-demo.htmlultimate-override.css
| if (n === 'sf-clickable-parent') return `<div class="${n}" style="position:relative;padding:var(--sf-space-m)">card <a href="#x" class="sf-clickable-parent__overlay"></a></div>`; | ||
| if (n === 'sf-clickable-parent__overlay') return `<div class="sf-clickable-parent" style="position:relative;padding:var(--sf-space-m)">card <a href="#x" class="${n}"></a> (overlay link)</div>`; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Give overlay demo links an accessible name.
These empty anchors demonstrate clickable overlays, but assistive tech exposes them as unnamed links. Add an aria-label or visually hidden text.
Proposed fix
- if (n === 'sf-clickable-parent') return `<div class="${n}" style="position:relative;padding:var(--sf-space-m)">card <a href="`#x`" class="sf-clickable-parent__overlay"></a></div>`;
- if (n === 'sf-clickable-parent__overlay') return `<div class="sf-clickable-parent" style="position:relative;padding:var(--sf-space-m)">card <a href="`#x`" class="${n}"></a> (overlay link)</div>`;
+ if (n === 'sf-clickable-parent') return `<div class="${n}" style="position:relative;padding:var(--sf-space-m)">card <a href="`#x`" class="sf-clickable-parent__overlay" aria-label="Open card"></a></div>`;
+ if (n === 'sf-clickable-parent__overlay') return `<div class="sf-clickable-parent" style="position:relative;padding:var(--sf-space-m)">card <a href="`#x`" class="${n}" aria-label="Open card"></a> (overlay link)</div>`;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (n === 'sf-clickable-parent') return `<div class="${n}" style="position:relative;padding:var(--sf-space-m)">card <a href="#x" class="sf-clickable-parent__overlay"></a></div>`; | |
| if (n === 'sf-clickable-parent__overlay') return `<div class="sf-clickable-parent" style="position:relative;padding:var(--sf-space-m)">card <a href="#x" class="${n}"></a> (overlay link)</div>`; | |
| if (n === 'sf-clickable-parent') return `<div class="${n}" style="position:relative;padding:var(--sf-space-m)">card <a href="`#x`" class="sf-clickable-parent__overlay" aria-label="Open card"></a></div>`; | |
| if (n === 'sf-clickable-parent__overlay') return `<div class="sf-clickable-parent" style="position:relative;padding:var(--sf-space-m)">card <a href="`#x`" class="${n}" aria-label="Open card"></a> (overlay link)</div>`; |
🤖 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 `@demos/generate.mjs` around lines 293 - 294, The overlay demo links in the
generate.mjs demo output are empty anchors, so they need an accessible name.
Update the sf-clickable-parent and sf-clickable-parent__overlay branches in the
demo generator to give the overlay <a> elements an aria-label or hidden text so
assistive tech announces them as meaningful links while keeping the visual demo
unchanged.
| const kinds = [ | ||
| ['layout', 'Layout primitives'], | ||
| ['macro', 'Macro classes'], | ||
| ['state', 'State classes'], | ||
| ['motion', 'Motion / animation'], | ||
| ['accessibility', 'Accessibility'], | ||
| ['print', 'Print'], | ||
| ['theme', 'Theme'], | ||
| ]; |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Assert rendered class coverage, not just input de-duplication.
Line 689 builds emitted directly from classes, so a class with a new kind not listed in lines 533-541 would be silently omitted from the HTML while this “completeness” check still passes.
Proposed fix
const baseHtml = buildDemo({ withOverride: false });
fs.writeFileSync(path.join(ROOT, 'full-api-demo.html'), baseHtml);
fs.writeFileSync(path.join(ROOT, 'full-api-demo-with-overrides.html'), buildDemo({ withOverride: true }));
+
+const classTiles = (baseHtml.match(/data-class="/g) || []).length;
+if (classTiles !== classes.length) {
+ throw new Error(`class reference: ${classTiles} tiles != ${classes.length} classes`);
+}Also applies to: 689-692
🤖 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 `@demos/generate.mjs` around lines 533 - 541, The completeness check in the
class-rendering flow only verifies de-duplication of the input list, so a class
with an unlisted kind can still be omitted from the emitted HTML without
failing. Update the coverage assertion around the kind mapping and the emitted
list so it validates rendered output from the actual class data, not just the
`classes` input, using the `kinds` definition and the `emitted` construction in
`generate.mjs` as the key points to adjust. Ensure the check fails when any
class kind is not represented in the rendered HTML, not merely when duplicate
inputs exist.
| const expectClasses = (fs.readFileSync(path.join(ROOT, 'full-api-demo.html'), 'utf8').match(/class="tile"/g) || []).length; | ||
| const expectTokens = (fs.readFileSync(path.join(ROOT, 'full-api-demo.html'), 'utf8').match(/data-token="/g) || []).length; | ||
|
|
||
| const browser = await chromium.launch({ executablePath: '/opt/pw-browsers/chromium' }); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== demos/validate.mjs ==\n'
wc -l demos/validate.mjs
sed -n '1,220p' demos/validate.mjs
printf '\n== package files mentioning Playwright or validate ==\n'
rg -n "playwright|validate\.mjs|pw-browsers|executablePath|chromium.launch" package.json . -g 'package.json' -g '*.md' -g '*.mjs' -g '*.js'Repository: codeslash-dev/SLASHED
Length of output: 9133
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== playwright.config.js ==\n'
wc -l playwright.config.js
sed -n '1,220p' playwright.config.js
printf '\n== search for browser path/env assumptions ==\n'
rg -n "pw-browsers|PLAYWRIGHT_BROWSERS_PATH|PLAYWRIGHT_CHROMIUM_EXECUTABLE|executablePath|launchOptions|channel:" . -g '*.js' -g '*.mjs' -g '*.json' -g '*.md'Repository: codeslash-dev/SLASHED
Length of output: 1626
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== references to demos/validate.mjs ==\n'
rg -n "demos/validate\.mjs|validate\.mjs" . -g '*.yml' -g '*.yaml' -g '*.md' -g '*.json' -g '*.js' -g '*.mjs'
printf '\n== CI/workflow files ==\n'
fd -a -t f '.github' . | sed -n '1,80p'
find .github -maxdepth 3 -type f \( -name '*.yml' -o -name '*.yaml' \) -print 2>/dev/null | sortRepository: codeslash-dev/SLASHED
Length of output: 199
Avoid hardcoding the Chromium binary path. This pins the validator to one container layout and can make it fail before any checks run on local machines or CI that use Playwright’s managed browser. Let Playwright resolve the browser by default, with an env override only when a custom binary is needed.
🤖 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 `@demos/validate.mjs` at line 29, The Chromium launch in validate.mjs is
hardcoded to a container-specific executable path, which breaks portability.
Update the chromium.launch usage in the validate script to let Playwright
resolve its managed browser by default, and add an environment-based override
only if a custom binary path is explicitly provided. Keep the change localized
to the browser startup logic so the rest of the validation flow stays unchanged.
|
|
||
| if (light.classTiles !== expectClasses) fails.push(`class tiles ${light.classTiles} != ${expectClasses}`); | ||
| if (light.tokenTiles !== expectTokens) fails.push(`token tiles ${light.tokenTiles} != ${expectTokens}`); | ||
| if (light.filledVals < expectTokens * 0.6) fails.push(`only ${light.filledVals}/${expectTokens} token values populated by JS`); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Tighten the token-value coverage assertion.
The generator/runtime contract is “every token gets a live computed value”, but this check still passes when 40% of the reference is blank. That means a large regression in refresh() or token rendering would not fail the build.
Proposed fix
-if (light.filledVals < expectTokens * 0.6) fails.push(`only ${light.filledVals}/${expectTokens} token values populated by JS`);
+if (light.filledVals !== expectTokens) fails.push(`token values populated ${light.filledVals}/${expectTokens}`);If a small set of tokens is intentionally empty, encode that as an explicit allowlist instead of a percentage heuristic.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (light.filledVals < expectTokens * 0.6) fails.push(`only ${light.filledVals}/${expectTokens} token values populated by JS`); | |
| if (light.filledVals !== expectTokens) fails.push(`token values populated ${light.filledVals}/${expectTokens}`); |
🤖 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 `@demos/validate.mjs` at line 92, The token-value coverage check in the
validation script is too permissive because it allows a large portion of missing
values to pass. Tighten the assertion in the token coverage logic around the
filledVals versus expectTokens check so the generator/runtime contract fails
when tokens are not populated, and if any tokens are intentionally empty, handle
them with an explicit allowlist instead of the current percentage threshold.
- Relocate the generated artifacts (full-api-demo.html, full-api-demo-with-overrides.html, ultimate-override.css) from the repo root into demos/, alongside their generator and validator. generate.mjs and validate.mjs now write/read there. The override link and runtime injection stay relative, so they resolve within demos/. - index.md: link both demos from the hero actions and the Developer column, so the GitHub Pages site exposes them at /demos/full-api-demo.html and /demos/full-api-demo-with-overrides.html. - _config.yml: exclude the dev scripts (generate.mjs, validate.mjs) and the validator scratch dir from the published site; the HTML/CSS demos ship as static files (no front matter), served verbatim like docs/demo.html. The pages load the optimal bundle from the jsDelivr @dist CDN (verified present on the dist branch), so they render with styles publicly once on the Pages branch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QCMzUyUS62KUSkr4AzrF7M
full-api-demo.html: Comprehensive demo exercising all SLASHED tokens and classes
full-api-demo-with-overrides.html: Same demo with ultimate-override.css
ultimate-override.css: Comprehensive token override file
Co-Authored-By: Claude Haiku 4.5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01QCMzUyUS62KUSkr4AzrF7M
Summary by CodeRabbit
New Features
Bug Fixes
Chores