Suede#
SvelteKit starter template. Entry point for stack, conventions, and process: AGENTS.md.
For self-hosted knots, clone URLs may differ based on your setup.
`src/stories/Button.stories.svelte` and `src/stories/Accordion.stories.svelte`
both imported `$lib/components/ui/{Button,Accordion}.svelte` which no longer
exist on this branch (deleted in working tree). The deletion left the
stories with unresolvable imports, and Storybook's vite import-analysis
fails at build time on those files (the same asChild-related issue
surfaced earlier would have hit if the broken imports were repaired).
`src/stories/Page.stories.svelte` and `src/stories/Header.stories.svelte`
are kept: their imports are local (`./Page.svelte`, `./Header.svelte`)
and still resolve.
Verified via Playwright across 6 story URLs (all 4 SuedeButton + the two
remaining examples): 0 console errors, 0 vite import-analysis errors.
Only warnings are Storybook 11 deprecations on Storybook's internal UI
(`ariaLabel` on its own Button/PopoverProvider), not user code.
`pnpm check` is now fully clean (0 errors, 0 warnings) — no more
pre-existing noise from the deleted stories.
@storybook/addon-svelte-csf's Story.svelte, when given both a
`component` in defineMeta and children in the <Story> block, wraps
the children in another instance of that component
(line 148: `<renderer.storyContext.component {...renderer.args} {children} />`).
In our case `component: SuedeButton` + `<SuedeButton>Click me</SuedeButton>`
as Story children produced `<button class="suede-button"><button class="suede-button">Click me</button></button>`
— an accessibility violation (interactive element nested in interactive element)
and semantically wrong markup.
`asChild` on each <Story> routes the children through the
`{@render children()}` branch (no component wrapping) so the story
renders as static markup. Trade-off: args-driven controls don't
update the canvas for `asChild` stories, which is acceptable for
discrete-variant learning demos.
Verified via Playwright against the running Storybook dev server:
Primary / Disabled / With-class-override each render exactly one
`<button data-button-root="true" class="suede-button ...">` at the
root of the story canvas; As link renders as a single
`<a data-button-root="true">`. `button button` and `a button`
nested-selector counts: 0 in every story.
Adds a Suede-wrapped bits-ui Button as a learning scaffold for the
bits-ui + stylebase + Svelte 5 pattern. Distinguishes functionality
(bits-ui's polymorphic Button.Root via ButtonRootProps) from style
(stylebase utility class + scoped <style> block in the same file).
Story at src/stories/SuedeButton.stories.svelte exercises four
variants: Primary, Disabled, As link, With class override.
TypeScript escape hatch: rest is spread via
`{...rest as Record<string, unknown>}` because bits-ui's
ButtonRootProps is a union (AnchorElement | ButtonElement) that
exceeds TypeScript's type complexity budget when re-spread into
another Svelte component. Cast is local to one line; polymorphic
behavior (button vs anchor via href) still works at runtime.
CSS pruner workaround: `<!-- svelte-ignore css_unused_selector -->`
on the <style> block, because the class name is built from a
template literal in the class attribute and is therefore invisible
to Svelte's static class-extraction pass.
Existing example stories (Button, Accordion, Header, Page) are
left untouched per option C; pre-existing pnpm check errors
(missing /components/ui/Button.svelte and Accordion.svelte
references) are out of scope for this change.
- .deciduous/ : local decision-graph database
- docs/ : generated web viewer export (regenerate via 'deciduous sync')
- CLAUDE.md : explicit Claude-Code instruction file, not part of this project
- .claude/ : explicit Claude-Code config directory, not part of this project
The last two are defensive: if 'deciduous install' re-runs, the Claude
artifacts will be re-created locally but stay untracked.
Cross-agent view of the deciduous decision-graph tool. Source content was
copied from CLAUDE.md's managed block (which we will not commit) and stripped
of tool-specific syntax:
- Removed slash command table (Claude Code only)
- Removed skills table (Claude Code only)
- Removed inline slash-command references
- Replaced the .claude/commands/decision.md git-staging example with
project-relevant paths
A header note at the top of the section explains that this is the
tool-agnostic view; tool-specific commands and skills live in
.opencode/commands/ and .opencode/skills/ (loaded at runtime by OpenCode,
not duplicated here).
First suede release. Bump placeholder 0.0.1 -> 2026.6.4 (chronver, today's date).
Tag 2026.6.4 will be applied to the merge commit on main after this PR merges.
SvelteKit starter template. Entry point for stack, conventions, and process: AGENTS.md.