Best for
- Project is Blade + Livewire + Flux (use flux / livewire / blade-ui).
- Project is Vue (use the Vue stack skills).
- Plain React without shadcn/ui — fall back to manual composition; this skill
event4u-app/agent-config/src/skills/react-shadcn-ui/SKILL.md
Use when building React UI on shadcn/ui primitives + Tailwind — the apply/review/polish skill dispatched by `directives/ui/*` for the `react-shadcn` stack.
Decision brief
Grounded stack guidance: pull idiomatic Do/Don't + docs URLs via ./scripts-run /corpus-grounding/scripts/ground search --manifest /design-intelligence/data/manifest.json --stack shadcn "" (also --stack react, --stack nextjs). See design-intelligence.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/event4u-app/agent-config --skill "src/skills/react-shadcn-ui"Inspect the Agent Skill "react-shadcn-ui" from https://github.com/event4u-app/agent-config/blob/6a5670b7881a676c0da90d2afb950298087c4ccb/src/skills/react-shadcn-ui/SKILL.md at commit 6a5670b7881a676c0da90d2afb950298087c4ccb. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
1. Read state.uiaudit.shadcninventory.version and confirm it matches the version in Compatibility within the same major. If audit flagged a mismatch, the user already chose to proceed — note that in state.changes. 2. Read state.uiaudit.designtokens — every color, spacing, and ra…
1. Read state.uiaudit.shadcninventory.version and confirm it matches the version in Compatibility within the same major. If audit flagged a mismatch, the user already chose to proceed — note that in state.changes. 2. Read state.uiaudit.designtokens — every color, spacing, and ra…
1. Import primitives from the project's components/ui/ path (@/components/ui/button, …) — never from shadcn or radix-ui. 2. Compose Radix-style: → → → → . Never wrap DialogTrigger around a pre-styled ; pass asChild. 3. Use the variant API of Button (variant="default" | "destruct…
1. Colors via semantic classes: bg-background, text-foreground, bg-primary text-primary-foreground, text-muted-foreground. No bg-white / text-black / hardcoded fff. 2. Spacing / radius from theme tokens (rounded-lg mapped to --radius — in the @theme block on tailwind-v4, in tail…
1. Empty: render the design-brief empty-state copy in a Card or inline placeholder; never null. 2. Loading: Skeleton rows for tables; Button disabled + Loader2 icon for submit-in-flight. 3. Error: Alert variant="destructive" with the design-brief message; FormMessage for field-l…
Permission review
The documentation asks the agent to run terminal commands or scripts.
**Propose, never silent-run** — always show the exact `npx` command +The documentation asks the agent to run terminal commands or scripts.
**What it must never do** — run without the exact `npx` command and theEvidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 93/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 9 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Grounded stack guidance: pull idiomatic Do/Don't + docs URLs via
./scripts-run <skills-root>/corpus-grounding/scripts/ground search --manifest <skills-root>/design-intelligence/data/manifest.json --stack shadcn "<topic>"(also--stack react,--stack nextjs). Seedesign-intelligence.
scripts/shadcn_add.ts (gated, assisted)Bundled installer (Apache-2.0-derived, see header + design-intelligence/ATTRIBUTION.md)
wraps npx shadcn@latest add <components> — the only subprocess+network
surface in the adopted suite. Per runtime-safety + the execution
block above:
npx command +
component list first (use --dry-run); the user confirms before any
live run.missing-tool-handling: if npx/Node is
absent, STOP and ask (install vs. manual component copy) — never
silently work around.components/ui/<name>.tsx exists, components.json unchanged or
sanely updated) before reporting success.shadcn@4, Tailwind CSS 4.x, React 19, primitives from
@base-ui/react@1, components.json style base-nova — every major read out
of tests/fixtures/stack/shadcn-current/package.json, the verbatim output of
npx shadcn@latest init -d --template vite on 2026-08-24. No version on this
line may be stated from prose; move it only by re-running that scaffold and
re-committing the fixture.3.x and Radix primitives stay supported through the v3 branch
under § Gotcha — the CLI moved on, existing projects did not.directives/ui/audit.ts) reads the line above and
compares it with state.ui_audit.shadcn_inventory.version; a major
mismatch triggers a soft halt before this skill runs.Use when state.stack.frontend == "react-shadcn" and directives/ui/apply.ts,
review.ts, or polish.ts dispatches to this skill, or when a React project
clearly uses shadcn/ui (presence of components.json, a @base-ui/react or
@radix-ui/* dependency, a components/ui/ folder of generated primitives).
Do NOT use when:
flux / livewire / blade-ui).components/ui/ and edited in-place. Do not npm install shadcn-ui.
Run npx shadcn@latest add <primitive> to scaffold; then edit.## Compatibility line and
the project's installed primitives is a real risk. The audit step
writes state.ui_audit.shadcn_inventory with the detected version —
when it diverges by a major, audit emits a soft halt before this
skill runs.@base-ui/react in a CLI-4 scaffold,
@radix-ui/* in older projects. Accessibility is built in either way, but
only when the wrapper components are used correctly (asChild,
<DialogTrigger> instead of a bare <button>).css axis, never guess. detect_stack()
emits axes.css as tailwind-v4 or tailwind-v3
(work_engine/stack/detect.ts:521-524); existing-ui-audit reads tokens on
the same key.
tailwind-v4 — no config file exists. Tokens live in the @theme block
of the entry CSS named by components.json → tailwind.css, and that file's
"tailwind": {"config": ""} — an empty config string — IS the v4 marker.
Never write tailwind.config.{js,ts} in a v4 project.tailwind-v3 — tokens come from tailwind.config.{js,ts}
(theme.extend.colors).:root and .dark
(--background, --foreground, --primary, --ring, …). Audit writes them
into state.ui_audit.design_tokens. Use those tokens; never hardcode values.<html class="dark">). Every color must come
from bg-background, text-foreground, etc. — never raw bg-white.focus-visible:ring-2 focus-visible:ring-ring; that comes for free with
the generated primitives but is easy to remove during a refactor.Inter-as-system-fallback + neutral grays reads as
template across projects (catalog T7/T8 + C5). Unless
state.ui_audit.design_tokens pins the neutral palette as the
project's identity, the polish step should match typography and color
tokens to the design brief's aesthetic: line (from fe-design
aesthetic-direction). Theme/font drift within a single audited project
breaks consistency — variation lives between projects, not between
components in the same surface.docs/guidelines/design-antipatterns.md
before the polish step (Visual V1–V7, Layout L1–L8 are the React-component
slop tells); the objective quality floors (WCAG contrast, focus-visible,
reduced-motion) are validated via accessibility-auditor's checklist —
cite its verdict rather than eyeballing.This skill is validated against the following shadcn primitives at the declared version:
Button, Input, Textarea, Checkbox,
RadioGroup, Select, Switch, Label, Form (react-hook-form
wrapper + zodResolver).Dialog, Sheet, Popover, Tooltip, DropdownMenu,
AlertDialog.Card, Separator, Tabs, Accordion, ScrollArea.Table (with @tanstack/react-table), Badge,
Avatar, Skeleton, Progress.Toast (sonner), Alert.Calendar / DatePicker — composition skill required, not generated.Combobox — built from Command + Popover; case-by-case.The default path is the bundled scripts/shadcn_add.ts CLI wrapper + reading
components.json — it works on most shadcn projects and stays the default.
The modern registry model is an opt-in enhancement; do not add round-trips
to every component op. Full JSON-schema + namespace detail is lazy-loaded from
references/registry.md — read it only on this path,
not on the vanilla add.
shadcn info --json handshake — run it as the grounding step when the
project declares custom/namespaced registries in components.json, OR when
theme-alignment is in scope. It returns framework, aliases, installed
components, icon lib, and base settings. Do NOT make it a forced first action
on every add (over-gating; low ROI on vanilla projects).
shadcn info --json when
available; fall back to state.ui_audit.shadcn_inventory (from
existing-ui-audit) when the CLI/MCP is not reachable. They answer the same
question (project context) — the live read wins.Namespaced installs — @ns/item resolves via the registries map to a
registry-item.json URL (see the reference). Run view @ns/item to inspect
the JSON before add. Honour registryDependencies (install the graph,
including version-pinned GitHub refs like acme/ui/button#v1.2.0); keep
propose-never-silent-run + --dry-run.
Token-aware scaffolding — when a registry-item.json carries cssVars
(OKLCH, light/dark/theme), align additions to the project's existing tokens
(from info --json / components.json / state.ui_audit.design_tokens) —
never inject the default shadcn neutral theme (it is a flagged anti-slop
tell: default theme + Inter fallback + neutral grays).
MCP path (opt-in) — the shadcn MCP server exposes browse / search-across-
registries / install-with-natural-language over MCP; configure per the
mcp skill. It is an alternative to the CLI, never a hard
dependency. Decision note: CLI path = default + universal; MCP path = opt-in
when the user has it configured; registry-JSON literacy underpins both.
The sections above consume a registry. This one publishes one: a component library in this repository can expose its own components the same way, so a consumer installs them with the tool they already use instead of copying files.
registry.json at the library root — the index — and one
registry-item.json per exposed component, each naming its files, its
registryDependencies, and its cssVars when it carries token requirements.public/r with the registry build command. The installer gate applies
here exactly as it does to add: propose it, run --dry-run first, and let the user
confirm. A build writes files, so nothing about it being "our own" registry lifts the
gate.registries map entry pointing at the published index; from then
on @ns/item resolves through it.Two registry item types are FORBIDDEN, deprecated in v4: registry:build and
registry:mcp. Use registry:base and registry:font instead. Writing either
deprecated type produces an item the current CLI does not understand, and the failure surfaces
at the consumer rather than at authoring time.
dependencies in a registry item never names react or react-dom. They are peers of
the consuming app, and a registry item that installs its own copy reproduces the "invalid hook
call" failure one layer up — see
js-library-packaging. check_package_surface enforces
this over a registry file.
Provenance. The registry-publishing shape and the deprecated-type list come from an external plugin reference's component-CLI skill, read at a pinned revision. The source is deliberately not named here, per
source-confidentiality: a shipped artifact does not carry derivation attribution to a named external project. The identifier and revision stay with the maintainer-side record.
state.ui_audit.shadcn_inventory.version and confirm it matches
the version in ## Compatibility within the same major. If audit
flagged a mismatch, the user already chose to proceed — note that
in state.changes.state.ui_audit.design_tokens — every color, spacing, and radius
in the rendered output must reference a token from this map.state.ui_design:
components → the primitive list to compose.microcopy → button labels, empty-state text, validation messages.
Lock — render verbatim.states → empty / loading / error / success / disabled coverage.a11y → ARIA labels, keyboard nav, focus order.components/ui/ path
(@/components/ui/button, …) — never from shadcn or radix-ui.<Dialog> → <DialogTrigger asChild> →
<DialogContent> → <DialogHeader> → <DialogTitle>. Never wrap
DialogTrigger around a pre-styled <button>; pass asChild.Button (variant="default" | "destructive" | "outline" | "secondary" | "ghost" | "link"); do not override with
raw Tailwind for the variant set.useForm (react-hook-form) + zodResolver(schema) →
<Form> → <FormField> → <FormItem> → <FormLabel> →
<FormControl> → <FormMessage>. Validation messages come from
the zod schema, mirrored to the design-brief microcopy.bg-background, text-foreground,
bg-primary text-primary-foreground, text-muted-foreground. No
bg-white / text-black / hardcoded #fff.rounded-lg mapped to --radius
— in the @theme block on tailwind-v4, in tailwind.config.{js,ts} on
tailwind-v3). Polish refactors hardcoded values when a token exists.dark prop; rely on the .dark class
on the root and semantic tokens.aria-label from state.ui_design.a11y when icon-only.Card or
inline placeholder; never null.Skeleton rows for tables; Button disabled +
Loader2 icon for submit-in-flight.Alert variant="destructive" with the design-brief message;
FormMessage for field-level errors.toast.success(...) from sonner with the design-brief
confirmation copy.disabled prop on the trigger plus the design-brief
reason as aria-describedby text.<input> / <button> / <select> outside the primitive set.state.ui_design.microcopy byte-for-byte..dark on <html>, render the component, every
surface still legible (no text-white on bg-white).components/ (or app/)
tree, importing primitives from @/components/ui/*.state.changes with kind="ui",
stack="react-shadcn", and the design-brief summary.When this skill is dispatched by directives/ui/review.ts (test slot)
or directives/ui/polish.ts (verify slot) — i.e. a review/polish run,
not the initial apply — it also emits:
state.ui_review.a11y — {violations: [{rule, selector, severity}, ...], severity_floor?, accepted_violations?}. Run an a11y tool against the
rendered output (e.g. axe-core via Playwright, @axe-core/react,
jest-axe) and translate hits into this shape. Use the same
(rule, selector) shape as state.ui_audit.a11y_baseline so the
engine's de-dup matches pre-existing entries on replay. Omit the
envelope on apply passes; the engine's _apply_a11y_gate only fires
when a baseline is present.state.ui_review.preview — {render_ok: bool, screenshot_path?, dom_dump_path?, error?, skipped?, skip_reason?}. Render evidence is
required, not optional on a review/polish pass: you MUST drive the
headless browser (Playwright + axe-core) against the rendered output and
write render_ok. Omitting it now triggers the preview_render_required
halt — a render-capable stack can no longer claim success without
rendering. render_ok: false with error populated triggers the
preview_render_failed halt; render_ok: true with screenshot_path
threads the screenshot into the delivery report's artifacts list. The
only no-render path is an explicit, reasoned skip: set skipped: true
plus a skip_reason (e.g. no Playwright runner in this env). Browser
tooling (Playwright/Cypress/…) is a consumer-project dependency — this
package does not ship one.Polish dispatch: when the dispatcher skips review because a previous
review pass already returned SUCCESS, this skill MUST itself
synthesise the updated state.ui_review.findings (including any
remaining a11y_violation entries) so the engine's gate sees the
current state on the next polish round.
When DESIGN.md declares ## Taste Dials, honour them: Variance → layout-family spread + asymmetry tolerance; Motion → animation budget + reduced-motion posture; Density → spacing scale + information-per-viewport. Absent → follow the design brief's inferred dials.
The workshop discipline (one concept per story, @summary on every export, stories run as
tests, the !manifest tag, the opt-in MCP channel) lives in
storybook-workshop. It is stack-agnostic and was lifted
out of here rather than duplicated beside it.
What stays React-specific and therefore stays here: the state-coverage matrix in Step 3 that
the story set is derived from, the token discipline of Step 2 that stories render under, and
the (rule, selector, severity) a11y shape in § Review pass that the workshop's validate
step writes into.
scripts/shadcn_add.ts is the only shipped script, and it is the single
subprocess-plus-network surface in this suite — treat it accordingly.
--project-root (default
cwd): it reads components.json there and lets the upstream CLI write
the generated primitives under that root. Nothing outside it.npx command and the
component list having been shown to the user first, per the gate above.
Never pass --overwrite unprompted; never treat a non-zero exit as
success; never work around a missing npx silently
(missing-tool-handling).shadcn_add <component>
spawns npx shadcn@latest add <component> and writes into the project.
--dry-run is the read-only path and prints the command it would run;
--list is read-only too. Use --dry-run for the proposal step.npx resolves
shadcn@latest from the public npm registry on every live run, so both
the code fetched and the components written are chosen upstream, at run
time, not pinned here. That is the egress leg of the lethal trifecta
(lethal-trifecta-guard); the
human confirmation is what keeps it off an autonomous path.shadcn-ui from npm — primitives are scaffolded.dark prop — use semantic tokens + the .dark class.state.ui_design.asChild on DialogTrigger / SheetTrigger / similar
Radix wrappers — it breaks the accessibility contract.Frequently asked questions
Grounded stack guidance: pull idiomatic Do/Don't + docs URLs via ./scripts-run /corpus-grounding/scripts/ground search --manifest /design-intelligence/data/manifest.json --stack shadcn "" (also --stack react, --stack nextjs). See design-intelligence.
The source record exposes this install command: npx skills add https://github.com/event4u-app/agent-config --skill "src/skills/react-shadcn-ui". Inspect the command and pinned source before running it.
Static rules flagged exec-script in the source; the page lists the matching lines and excerpts.
Alternatives
event4u-app/agent-config
Use BEFORE writing or editing any non-trivial UI — inventories components, design tokens, shadcn primitives, and reusable patterns into state.ui_audit. Hard gate for the ui directive set.
fcakyon/claude-codex-settings
Guide for implementing smooth, native-feeling animations using React's View Transition API (`<ViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter/exit of components, animate list reorder, implement directional (forward/back) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view
yonatangross/orchestkit
json-render component catalog patterns for AI-safe generative UI. Define Zod-typed catalogs that constrain what AI can generate, use @json-render/shadcn for 36 pre-built components, optimize specs with YAML mode, and apply the three edit modes (patch/merge/diff) for progressive updates. Use when building AI-generated UIs, defining component catalogs, or integrating json-render into React/Vue/Svelte/React Native/Ink/Next.js projects.
theBGuy/GitDesktop
Guide for implementing smooth, native-feeling animations using React's View Transition API (`<ViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter/exit of components, animate list reorder, implement directional (forward/back) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view