Skip to content
Open
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
34 changes: 34 additions & 0 deletions .claude/skills/implement-recipe/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,40 @@ export const useSpinnerRecipe = createUseRecipe(
);
```

#### Spacing multipliers inside a `setup` callback — use `calc(@token * N)`

Bare numeric spacing refs like `@0.125` / `@0.25` are **multiplier tokens** that
resolve to a variable *named* `"0.125"`. In a recipe's `base` / `variants` these are
auto-declared on the fly (e.g. spinner/badge size variants use `@0.25`, `@0.5`). But
raw `selector(...)` calls inside a `setup` callback only **reference** — they do NOT
auto-declare. Referencing `@0.125` in a setup selector throws at Storybook build init:
`Variable "0.125" is not defined` (typecheck + theme tests do NOT catch this).

To scale a token by a fraction inside a setup selector, use an **embedded reference
expression wrapped in `calc()`** as a plain string:

```ts
(s) => {
const { selector } = s;
selector(".input-date-field", {
gap: "calc(@spacing * 0.125)", // → gap: calc(var(--spacing) * .125)
});
}
```

Styleframe's resolver (`engine/core/src/tokens/resolve.ts`) treats an *exact* `@name`
match as a validated reference (throws if undefined) but parses an *embedded* expression
like `@spacing * 0.125` without validation — it resolves `@spacing` and keeps the rest
literal. This is the same pattern used by dropdown/tooltip/popover (`"calc(@tooltip.arrow.size * -1)"`).

- **Keep the arithmetic inside `calc(...)`.** Bare `"@spacing * 0.125"` parses but emits
invalid CSS `gap:var(--spacing) * .125` (no `calc` → the browser drops the declaration).
- **Test gotcha:** in the recipe test instance, declare `s.variable("spacing", "1rem")` and
let the calc resolve — do NOT hand-declare a fake `s.variable("0.125", ...)`, which masks
the real build failure.
- **Always run `pnpm --filter @styleframe/storybook build` during verification** — it is the
only check that exercises real token resolution in a fresh instance.

---

### Deliverable 2: Barrel index
Expand Down
26 changes: 20 additions & 6 deletions .claude/skills/verify-recipe/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,25 @@ Parse output. Capture:
- Exit status.
- For each issue: file:line, rule, message.

### Step 3: (Optional) Storybook spot-check

If the user wants, offer to start Storybook briefly to verify the story renders:
### Step 3: Storybook build (required)

```bash
pnpm storybook
pnpm --filter @styleframe/storybook build
```

This is a manual check — the assistant cannot verify rendering automatically. Prompt the user to open the component story in the browser and confirm it looks correct.
Run the **production build**, not just the dev server. This is the **only** check that
exercises real token resolution in a fresh Styleframe instance — typecheck and theme
tests pass even when a recipe references an undefined variable. A `setup` callback that
references an undeclared spacing multiplier (e.g. a raw `selector` using `@0.125`) throws
here with `Variable "0.125" is not defined`; the fix lives in `/implement-recipe` (use
`calc(@spacing * 0.125)` instead — see that skill's Step 12). Capture exit status and any
`Variable "..." is not defined` errors with the originating recipe file.

#### (Optional) Storybook render spot-check

If the user wants a visual check, offer to start Storybook (`pnpm storybook`) — but this is
manual; the assistant cannot verify rendering automatically. Prompt the user to open the
story and confirm it looks correct.

### Step 4: Write `verification.md`

Expand Down Expand Up @@ -115,7 +125,10 @@ Do NOT attempt to fix issues automatically.
## Lint: <pass | fail>
<!-- If fail, list: file:line — rule — message — suggested sub-skill -->

## Storybook spot-check: <pass | not run | manual-deferred>
## Storybook build: <pass | fail>
<!-- If fail, list: recipe file — "Variable ... is not defined" — suggested sub-skill (/implement-recipe) -->

## Storybook render spot-check: <pass | not run | manual-deferred>

## Summary
- Total failures: <N>
Expand All @@ -129,6 +142,7 @@ Do NOT attempt to fix issues automatically.
- [ ] `pnpm typecheck` was run from the project root.
- [ ] `pnpm --filter @styleframe/theme test` was run.
- [ ] `pnpm lint` was run.
- [ ] `pnpm --filter @styleframe/storybook build` was run (catches token-resolution errors).
- [ ] Each failure is reported with file:line and a suggested sub-skill.
- [ ] `verification.md` is written to `.context/recipe-<name>/`.
- [ ] User received a short pass/fail summary.
Expand Down
Loading
Loading