Source profileQuality 94/100Review permissions

event4u-app/agent-config/src/skills/react-shadcn-ui/SKILL.md

react-shadcn-ui

Use when building React UI on shadcn/ui primitives + Tailwind — the apply/review/polish skill dispatched by `directives/ui/*` for the `react-shadcn` stack.

Source repository stars
7
Declared platforms
0
Static risk flags
1
Last source update
2026-07-28
Source checked
2026-07-28

Decision brief

What it does—and where it fits

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.

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

Not for

  • Tasks that require unconfirmed production actions or broad system permissions.
  • Environments where the pinned source and install steps cannot be inspected.

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/event4u-app/agent-config --skill "src/skills/react-shadcn-ui"
Safe inspection promptEditorial

Inspect the Agent Skill "react-shadcn-ui" from https://github.com/event4u-app/agent-config/blob/0adf49a8ae84b0ff6e2de8759eea43257e020eff/src/skills/react-shadcn-ui/SKILL.md at commit 0adf49a8ae84b0ff6e2de8759eea43257e020eff. 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

What the source asks the agent to do

  1. 01

    Procedure: render a shadcn/ui component for the design brief

    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…

    Read state.uiaudit.shadcninventory.version and confirm it matchesRead state.uiaudit.designtokens — every color, spacing, and radiusRead state.uidesign:
  2. 02

    Step 0: Inspect

    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…

    Read state.uiaudit.shadcninventory.version and confirm it matchesRead state.uiaudit.designtokens — every color, spacing, and radiusRead state.uidesign:
  3. 03

    Step 1: Compose primitives

    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…

    Import primitives from the project's components/ui/ pathCompose Radix-style: → →Use the variant API of Button (variant="default" | "destructive" |
  4. 04

    Step 2: Apply tokens, dark mode, a11y

    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 tailwind.config.{js,ts}). Polish refactors…

    Colors via semantic classes: bg-background, text-foreground,Spacing / radius from theme tokens (rounded-lg mapped to --radiusDark mode: never branch on a dark prop; rely on the .dark class
  5. 05

    Step 3: State coverage

    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…

    Empty: render the design-brief empty-state copy in a Card orLoading: Skeleton rows for tables; Button disabled +Error: Alert variant="destructive" with the design-brief message;

Permission review

Static risk signals and limitations

Runs scripts

medium · line 16

The documentation asks the agent to run terminal commands or scripts.

**Propose, never silent-run** — always show the exact `npx` command +

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score94/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars7SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
event4u-app/agent-config
Skill path
src/skills/react-shadcn-ui/SKILL.md
Commit
0adf49a8ae84b0ff6e2de8759eea43257e020eff
License
MIT
Collected
2026-07-28
Default branch
main
View the original SKILL.md

react-shadcn-ui

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). See design-intelligence.

Component installer — 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:

  1. Propose, never silent-run — always show the exact npx command + component list first (use --dry-run); the user confirms before any live run.
  2. Missing tool → per missing-tool-handling: if npx/Node is absent, STOP and ask (install vs. manual component copy) — never silently work around.
  3. Verify after run — confirm the component landed (components/ui/<name>.tsx exists, components.json unchanged or sanely updated) before reporting success.

Compatibility

  • Tested against: shadcn@2.1, Tailwind CSS 3.x, React 18+.
  • The audit step (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.

When to use

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, @radix-ui/* dependencies, a components/ui/ folder of generated primitives).

Do NOT use when:

  • 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 assumes the primitive set exists.

Gotcha

  • shadcn/ui is not an npm package. Primitives are copied into components/ui/ and edited in-place. Do not npm install shadcn-ui. Run npx shadcn@latest add <primitive> to scaffold; then edit.
  • Major-version drift between this skill's ## 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.
  • shadcn/ui composes Radix primitives. Accessibility is built in via Radix but only when you use the wrapper components correctly (asChild, <DialogTrigger> instead of a bare <button>).
  • Tailwind tokens come from tailwind.config.{js,ts} (theme.extend.colors) and CSS custom properties on :root and .dark (--background, --foreground, --primary, --ring, …). Audit writes them into state.ui_audit.design_tokens. Use those tokens; do not hardcode values.
  • Dark mode is class-based (<html class="dark">). Every color must come from bg-background, text-foreground, etc. — never raw bg-white.
  • Every interactive primitive must declare a focus-visible state via focus-visible:ring-2 focus-visible:ring-ring; that comes for free with the generated primitives but is easy to remove during a refactor.
  • Anti-AI-slop: shadcn-default look. The out-of-the-box shadcn theme + 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.
  • Anti-AI-slop catalog + linter. Pull 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.

Covered primitives

This skill is validated against the following shadcn primitives at the declared version:

  • Form / inputs: Button, Input, Textarea, Checkbox, RadioGroup, Select, Switch, Label, Form (react-hook-form wrapper + zodResolver).
  • Overlay: Dialog, Sheet, Popover, Tooltip, DropdownMenu, AlertDialog.
  • Layout: Card, Separator, Tabs, Accordion, ScrollArea.
  • Data display: Table (with @tanstack/react-table), Badge, Avatar, Skeleton, Progress.
  • Feedback: Toast (sonner), Alert.

Not covered — fall back to manual composition

  • Marketing-only components (Hero, Pricing, Features) — outside shadcn/ui.
  • Calendar / DatePicker — composition skill required, not generated.
  • Combobox — built from Command + Popover; case-by-case.
  • Streaming / partial-prerender boundaries — use the project's framework patterns (Next.js / Remix), not shadcn/ui.

Registry & MCP awareness (opt-in)

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 reference/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).

  • Precedence vs our own audit: prefer a live 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.

Procedure: render a shadcn/ui component for the design brief

Step 0: Inspect

  1. Read 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.
  2. Read state.ui_audit.design_tokens — every color, spacing, and radius in the rendered output must reference a token from this map.
  3. Read 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.

Step 1: Compose primitives

  1. Import primitives from the project's components/ui/ path (@/components/ui/button, …) — never from shadcn or radix-ui.
  2. Compose Radix-style: <Dialog><DialogTrigger asChild><DialogContent><DialogHeader><DialogTitle>. Never wrap DialogTrigger around a pre-styled <button>; pass asChild.
  3. Use the variant API of Button (variant="default" | "destructive" | "outline" | "secondary" | "ghost" | "link"); do not override with raw Tailwind for the variant set.
  4. Forms: 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.

Step 2: Apply tokens, dark mode, a11y

  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 tailwind.config.{js,ts}). Polish refactors hardcoded values when a token equivalent exists.
  3. Dark mode: never branch on a dark prop; rely on the .dark class on the root and semantic tokens.
  4. Every interactive primitive: keyboard trigger present (Enter/Space on buttons, Esc on dialogs — Radix free), visible focus ring, aria-label from state.ui_design.a11y when icon-only.

Step 3: State coverage

  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-level errors.
  4. Success: toast.success(...) from sonner with the design-brief confirmation copy.
  5. Disabled: disabled prop on the trigger plus the design-brief reason as aria-describedby text.

Step 4: Validate

  1. No raw <input> / <button> / <select> outside the primitive set.
  2. No hardcoded colors / spacing — every value is a token.
  3. Microcopy matches state.ui_design.microcopy byte-for-byte.
  4. Dark mode: toggle .dark on <html>, render the component, every surface still legible (no text-white on bg-white).
  5. Keyboard: Tab through every focusable element; focus ring visible.

Output format

  1. React component file(s) under the project's components/ (or app/) tree, importing primitives from @/components/ui/*.
  2. Per file, one entry recorded in state.changes with kind="ui", stack="react-shadcn", and the design-brief summary.

Review pass — a11y findings + preview envelope

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.

Taste Dials

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.

Component workshop (Storybook) — when the library is large enough

The generic "isolate + document reusable components" principle lives in fe-design § Component Architecture; this is the React carve-out for the tool-specific part.

  • When it pays off — a real, growing shared-component library (roughly: more than a handful of reused primitives, multiple consumers, ongoing UI work). Storybook makes each component discoverable, reviewable in isolation, and reused instead of re-invented. Skip it for a small surface of one-off components — the setup + maintenance is not worth it yet.
  • Story per reusable primitive, not per screen — a story covers a component and its states (default / loading / empty / error / dark), mirroring the Step 3 state-coverage matrix. Screens are composed, not story-fied.
  • Reuse the token layer — stories render under the same semantic tokens + .dark class; never hardcode a preview theme (same token discipline as Step 2).
  • A11y in-workshop — run the a11y addon so the isolation catches contrast / role / focus issues before the component reaches a screen.
  • Do NOT let stories drift from the component API — a story that props-drills values the component no longer accepts is stale documentation; keep them beside the component and update them in the same change.

Do NOT

  • Do NOT install shadcn-ui from npm — primitives are scaffolded.
  • Do NOT hardcode colors / spacing / radii — use the token map.
  • Do NOT branch on a dark prop — use semantic tokens + the .dark class.
  • Do NOT rewrite microcopy — it is locked by state.ui_design.
  • Do NOT skip asChild on DialogTrigger / SheetTrigger / similar Radix wrappers — it breaks the accessibility contract.
  • Do NOT introduce a non-shadcn UI library (MUI, Chakra) into the same surface — pick one system per surface.

Auto-trigger keywords

  • shadcn / shadcn ui / shadcn/ui
  • React component (when the project uses shadcn)
  • Radix primitive
  • Tailwind dark mode
  • React Hook Form + zod

Alternatives

Compare before choosing