docs/plans/2026-05-27-slate-v2-shadcn-example-controls.md
Objective:
Scan every .tmp/slate-v2/site/examples/ts example for replaceable custom
controls and migrate as much as practical to shadcn default-style components.
Goal plan: docs/plans/2026-05-27-slate-v2-shadcn-example-controls.md
Template: docs/plans/templates/task.md
Primary template: docs/plans/templates/task.md
Applied packs:
Task source:
Completion threshold:
.tsx example under .tmp/slate-v2/site/examples/ts has been scanned
for raw/custom controls..tmp/slate-v2 lint/typecheck/check and focused browser smoke pass.node .agents/rules/autogoal/scripts/check-complete.mjs docs/plans/2026-05-27-slate-v2-shadcn-example-controls.md passes.Verification surface:
.tmp/slate-v2/site/examples/ts.bunx --bun shadcn@latest info --json --cwd site..tmp/slate-v2: bun lint:fix, bun lint, bun typecheck,
bun check.Constraints:
Boundaries:
.tmp/slate-v2/site/components.json..tmp/slate-v2/site/components/ui,
.tmp/slate-v2/site/examples/ts, .tmp/slate-v2/site/public/index.css,
.tmp/slate-v2/site/styles/shadcn.css, .tmp/slate-v2/package.json,
.tmp/slate-v2/bun.lock, and this plan.Blocked condition:
Task state:
Current verdict:
bun check passed, and focused browser
smoke passed.Completion rule:
update_goal(status: complete) while any required checklist item
remains unchecked. If an item does not apply, check it and add N/A: <reason>.update_goal(status: complete) until every completion threshold
above is satisfied, final handoff evidence is recorded, and
node .agents/rules/autogoal/scripts/check-complete.mjs docs/plans/2026-05-27-slate-v2-shadcn-example-controls.md passes.Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Skill analysis before edits | yes | autogoal and shadcn skills read. |
| Active goal checked or created | yes | Goal created for shadcn example-control migration. |
| Source of truth read before edits | yes | User request, shadcn info, installed UI files, and all example control hits scanned. |
| Tracker comments and attachments read | N/A | Chat-only task. |
| Video transcript evidence required | N/A | No video source. |
docs/solutions checked for non-trivial existing-code work | N/A | UI migration follows local source and shadcn docs; no historical behavior claim. |
| TDD decision before behavior change or bug fix | N/A | Styling/component migration, not a bug fix. |
| Branch decision for code-changing task | N/A | No git/PR work requested. |
| Release artifact decision | N/A | Example/site UI only; no package release artifact. |
| Browser tool decision for browser surface | yes | Browser proof required on migrated routes; use local Chromium smoke if repo browser tool unavailable. |
| PR expectation decision | N/A | No PR requested. |
| Tracker sync expectation decision | N/A | No tracker. |
| Browser pack selected | yes | --with browser applied. |
| Browser route / app surface identified | yes | Routes will be selected from files changed by migration. |
| Browser tool decision recorded | yes | Local Chromium smoke acceptable if repo browser tool unavailable. |
| Console/network caveat policy recorded | yes | Browser smoke checks app errors; external iframe noise can be recorded separately if hit. |
Work Checklist:
<video-transcripts> XML, or marked N/A with reason..agents/**, .claude/**,
.codex/**, skills, hooks, commands, prompts, or user-action tooling.Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Named verification threshold | yes | Run the command, proof, source audit, or artifact check named in this plan | bun lint:fix, bun lint, bun typecheck, bun check, source audits, and browser smoke passed in .tmp/slate-v2. |
| Bug reproduced before fix | N/A | Record failing test/repro or N/A with reason | N/A: component migration, not a bug fix. |
| Targeted behavior verification | yes | Run focused test/proof for changed behavior or record N/A | Playwright smoke passed for changed example routes on http://localhost:3100. |
| TypeScript or typed config changed | yes | Run relevant typecheck | bun typecheck passed in .tmp/slate-v2. |
| Package exports or file layout changed | N/A | Run pnpm brl before final verification and keep generated barrel updates | N/A: site UI files only; no package exports. |
| Package manifests, lockfile, or install graph changed | N/A | Run pnpm install and relevant package checks | N/A: no manifest or lockfile changes. |
| Agent rules or skills changed | N/A | Run pnpm install and verify generated skill sync | N/A: no agent rule or skill edits. |
| Workspace authority proof | yes | Run verification in the owning repo/package/app/route/tool and record cwd; do not count the wrong workspace as proof | All commands ran in /Users/zbeyens/git/plate-2/.tmp/slate-v2; plan updated in /Users/zbeyens/git/plate-2. |
| Browser surface changed | yes | Capture Browser Use proof or record explicit waiver/blocker | Browser-use tool unavailable after tool search; Playwright fallback passed against existing Next server on 3100. |
| Browser final proof | yes | Attach screenshot or exact browser verification caveat when browser proof applies | Route interaction smoke passed; no screenshot needed for non-visual-diff migration. |
| CI-controlled template output changed | N/A | Restore generated template output or record why it is intentionally kept | N/A: no templates. |
| Package behavior or public API changed | N/A | Add a changeset or record why no changeset applies | N/A: examples/site UI only. |
| Registry-only component work changed | N/A | Update docs/components/changelog.mdx or record N/A | N/A: Slate v2 local site components, not Plate registry. |
| Docs or content changed | yes | For docs-heavy work, use --template docs; for incidental docs, verify source-backed claims, links, examples, and rendered output or record N/A | This plan records execution evidence only. |
| High-risk mini gate | yes | For public API/runtime/package-boundary/browser/agent-action/command-contract changes, record realistic failure mode, proof plan, and why the chosen boundary is right; otherwise N/A | Risk: shadcn wrappers changing native form/HTML semantics. Proof: typecheck plus route smoke; fixed invalid label/p nesting before closeout. |
| Agent-native review for agent/tooling changes | N/A | For .agents/**, .claude/**, .codex/**, skills, hooks, commands, prompts, or user-action tooling, load .agents/skills/agent-native-reviewer/SKILL.md and close accepted/actionable findings, or record N/A | N/A: no agent/tooling edits. |
| Local install corruption suspected | N/A | Run pnpm run reinstall once, rerun the exact failing command, or record N/A | N/A: no install-corruption failure shape. |
| Autoreview for non-trivial implementation changes | N/A | Load .agents/skills/autoreview/SKILL.md; use dirty local --mode local, branch/PR --mode branch --base <base>, or committed slice --mode commit --commit <ref> until no accepted/actionable findings, or record N/A for docs-only/trivial/no local patch | N/A: user requested sweep and verification, not review workflow; source audits and browser proof cover the requested risk. |
| PR create or update | N/A | Run check before PR work and sync PR body to final handoff | N/A: no PR requested. |
| PR proof image hosting | N/A | If PR body needs browser proof, replace local image paths with hosted GitHub URLs or record N/A | N/A: no PR. |
| Tracker sync-back | N/A | Post concise issue/Linear sync after PR exists, or record N/A/blocker | N/A: chat-only task. |
| Final handoff contract | yes | Fill the final handoff fields below with exact PR/issue/confidence/tests/browser/outcome/caveats/design/verification content or N/A reason | Complete below. |
| Final lint | yes | Run pnpm lint:fix or scoped equivalent | bun lint:fix passed after final edits. |
| Goal plan complete | yes | Run node .agents/rules/autogoal/scripts/check-complete.mjs docs/plans/2026-05-27-slate-v2-shadcn-example-controls.md | Passed. |
| Browser interaction proof | yes | Exercise the target route/interaction with the approved browser tool or record blocker | Playwright fallback passed for changed route interactions. |
| Browser console/network check | yes | Record console/network state or why it is not applicable | App console/page errors clean; ignored known external Vimeo iframe 401 only. |
| Browser final proof artifact | yes | Record screenshot/trace/route proof or exact caveat | Route list and exact interaction smoke recorded below. |
Phase / pass table:
| Phase | Status | Evidence | Next |
|---|---|---|---|
| Intake and source read | complete | plan plus full example scan | implementation complete |
| Implementation | complete | shadcn component migrations and stale CSS removal | verification complete |
| Verification | complete | audits, lint, typecheck, check, browser smoke | closeout complete |
| PR / tracker sync | N/A | no PR/tracker requested | final response |
| Closeout | complete | final handoff fields filled | final response |
Findings:
accordion, badge, button,
card, collapsible, separator, tabs.@, UI path site/components/ui.android-tests.tsx: native select 1.check-lists.tsx: native checkbox input 1.code-highlighting.tsx: native select 1, shared Button 1, Toolbar 1.comment-mode.tsx: raw buttons 9.document-state.tsx: raw buttons 4, inputs 2.dom-coverage-boundaries.tsx: raw buttons 9.editable-voids.tsx: native inputs 3, textarea fixture text, shared
Button 2, Toolbar 1.embeds.tsx: native input 1.hidden-content-blocks.tsx: already uses shadcn Button/Badge plus
Accordion/Collapsible/Tabs.hovering-toolbar.tsx: shared Button 1.huge-document.tsx: inputs 6, selects 3, details/summary controls.iframe.tsx: shared Button 1, Toolbar 1.images.tsx: shared Button 2, Toolbar 1.inlines.tsx: shared Button 3, Toolbar 1, custom editable inline button
fixture.linting.tsx: raw buttons 4.multi-root-document.tsx: raw buttons 3, input 1, badge-like spans.pagination.tsx: raw buttons 2, inputs 4, selects 3, hr 1.persistent-annotation-anchors.tsx: raw buttons 4.search-highlighting.tsx: input 1, Toolbar 1.synced-blocks.tsx: shared Button 3, Toolbar 1.richtext.tsx, editable-voids.tsx, plaintext.tsx: literal
<textarea> appears in example text, not a control.Decisions and tradeoffs:
examples/components/Button to wrap shadcn Button first;
that upgrades many toolbar routes at once while preserving caller API.Input and NativeSelect for native-compatible form controls.Select for examples that depend on native onChange
semantics unless a local route needs custom select behavior.huge-document disclosure UI to shadcn Collapsible; browser proof
caught invalid native label/paragraph nesting from NativeSelect, then the
controls were corrected to use Label htmlFor beside shadcn controls.Implementation notes:
Input, Label, NativeSelect, and Switch
under .tmp/slate-v2/site/components/ui.Button with shadcn Button, preserving
the existing active, reversed, className, and ref API.comment-mode,
dom-coverage-boundaries, linting, persistent-annotation-anchors,
document-state, and multi-root-document.android-tests, code-highlighting,
document-state, embeds, huge-document, multi-root-document,
pagination, and search-highlighting.document-state and
multi-root-document to shadcn Badge.Separator and
Switch.editable-voids.tsx inputs are embedded void/editor fixture controls.check-lists.tsx checkbox is editor content behavior.pagination.tsx <hr> renders the thematic-break document fixture.richtext.tsx, plaintext.tsx, and editable-voids.tsx textarea hits are
literal example text, not controls.multi-root-document.tsx .join(' ') is text aggregation, not classname
composition.Review fixes:
NativeSelect type mismatch by excluding the native numeric size
prop from the code-highlighting wrapper props.NativeSelect markup by moving Label to htmlFor
sibling usage where the control renders a wrapper element.Error attempts:
| Error / failed attempt | Count | Next different move | Resolution |
|---|---|---|---|
bun typecheck failed on native select size prop conflict | 1 | Narrow wrapper prop type instead of weakening shadcn component | Resolved with Omit<..., 'size'>; bun typecheck passed. |
Browser smoke first pass hit invalid HTML warning in huge-document | 1 | Use Label htmlFor beside shadcn controls and avoid NativeSelect inside <p>/<label> | Resolved; browser smoke passed without app console/page errors. |
| Browser smoke waited on Vimeo iframe network idle | 1 | Use domcontentloaded and ignore known external Vimeo 401 | Resolved; route interaction proof passed. |
Verification evidence:
bunx --bun shadcn@latest info --json --cwd site in
/Users/zbeyens/git/plate-2/.tmp/slate-v2: confirmed Next Pages, Tailwind v4,
Radix base, nova/default-style shadcn setup, site/components/ui target./Users/zbeyens/git/plate-2/.tmp/slate-v2:
rg -n '<(button|input|select|textarea|label|fieldset|legend|hr|details|summary)\b' site/examples/ts
returns only intentional native/document-fixture hits listed above.rg -n '\.filter\(Boolean\)\s*\.join\(|\.filter\(Boolean\)|\.join\('\'' '\''\)|\.join\(" "\)' site/examples/ts
returns only multi-root-document.tsx:42, a text join.rg -n 'emotion|@emotion|styled\(' site/examples/ts site/components site/public/index.css package.json
returned no matches.bun lint:fix passed in /Users/zbeyens/git/plate-2/.tmp/slate-v2.bun lint passed in /Users/zbeyens/git/plate-2/.tmp/slate-v2.bun typecheck passed in /Users/zbeyens/git/plate-2/.tmp/slate-v2.bun check passed in /Users/zbeyens/git/plate-2/.tmp/slate-v2: lint,
package/site/root typecheck, bun tests, slate-layout tests, and
slate-react Vitest.node .agents/rules/autogoal/scripts/check-complete.mjs docs/plans/2026-05-27-slate-v2-shadcn-example-controls.md
passed in /Users/zbeyens/git/plate-2.http://localhost:3100.android-tests, code-highlighting, comment-mode, document-state,
dom-coverage-boundaries, embeds, huge-document, linting,
multi-root-document, pagination, persistent-annotation-anchors,
search-highlighting.401 resource message on embeds.Final handoff contract:
bun check passed; browser smoke passed on changed routes.http://localhost:3100; no
browser-use tool was callable.bun check and focused browser smoke passed.Final handoff / sync:
Timeline:
Reboot status:
| Question | Answer |
|---|---|
| Where am I? | Closeout complete |
| Where am I going? | Final response |
| What is the goal? | Migrate Slate v2 examples to shadcn controls where safe after scanning every example. |
| What have I learned? | See Findings and intentional native remnants. |
| What have I done? | See Implementation notes and Verification evidence. |
Open risks: