Skip to content
Back to skills

Shadcn Ui

ASecurity

Project-aware shadcn/ui components, registry MCP, theming, and design-system lint feedback. Use when adding or changing React/Tailwind UI, a primitive, theme, registry, or component contract in an Agent-Native app.

  • 6,969 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 27, 2026
developmentgoreactspringgitapifrontendsecurity

Works with

  • cli
  • api
  • mcp

Security analysis

A100/100

Scanned September 20, 2026

npx -y skills add BuilderIO/agent-native --skill shadcn-ui --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Shadcn Ui?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Shadcn Ui
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/builderio-shadcn-ui/badge)](https://www.skillsdirectory.com/skills/builderio-shadcn-ui)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: shadcn-ui
description: >-
  Project-aware shadcn/ui components, registry MCP, theming, and design-system
  lint feedback. Use when adding or changing React/Tailwind UI, a primitive,
  theme, registry, or component contract in an Agent-Native app.
scope: dev
source: https://ui.shadcn.com/docs/skills
local-changes: >-
  Description narrowed deliberately; an upstream sync must not restore the
  "any project with a components.json file" trigger.
metadata:
  internal: true
---

# shadcn/ui

This skill keeps shadcn/ui work project-aware. Components are source files in the
app, so always inspect the local project before adding, importing, or rewriting
them. When `@shadcn/lint` is configured, treat its feedback as implementation
guidance, not cosmetic noise. The framework repository runs it through the root
Oxlint configuration; generated workspaces carry this skill and the MCP
workflow, but do not automatically inherit that repository-only lint setup.

## First Steps

1. Work from the app root that owns `components.json`. In this monorepo, that is
   the selected app/template directory (usually under `templates/`), not the
   repository root.
2. In an Agent-Native app, inspect `app/design-system.ts` and
   `ToolkitProvider` before choosing a primitive. A registered company design
   system takes precedence over the default shadcn adapter.
3. Run `pnpm dlx shadcn@latest info --json` when you need current project context: framework, Tailwind version, aliases, icon library, installed components, and resolved paths.
4. Use the actual aliases from `components.json` or `shadcn info`; do not assume `@/components/ui` if the project says otherwise.
5. Check `app/components/ui/` or the resolved `ui` path before importing a component.
6. For unfamiliar components, run `pnpm dlx shadcn@latest docs <component>` and read the returned docs or examples before coding.

## MCP Registry Workflow

Each first-party app keeps the official shadcn MCP configuration in `.mcp.json`
next to its `components.json`. Start the agent from that app root so the MCP
server resolves the correct aliases, local UI directory, and Tailwind theme.
Do not add a single repository-root server: the root is a workspace, not a
shadcn project, and would make installs target the wrong project.

- Use the shadcn MCP to search, inspect, and install registry items when it is
  connected. Prefer the app's configured registries over copied source.
- Use `pnpm dlx shadcn@latest info --json` for project context; the MCP has no
  equivalent project-info tool.
- If the MCP is unavailable, use the equivalent `pnpm dlx shadcn@latest`
  command from the same app root and continue following this skill.
- Keep registry URLs and aliases in that app's `components.json`. Never put
  registry credentials in MCP config or checked-in source.

## Design-System Lint Feedback

In the framework repository, `pnpm lint` runs Oxlint with `@shadcn/lint` for the
scoped template UI paths. Run it after UI changes and fix every `shadcn/*`
finding before handing off. Template packages use the workspace lint
configuration; do not create a second local lint configuration just for one
app.

Before claiming that shadcn lint ran in another workspace, inspect its root
`package.json` and `.oxlintrc.json`. The generic generated workspace currently
exposes `pnpm lint` as formatting-only and does not ship `@shadcn/lint` or the
framework repository's Oxlint config. In that scaffold, use this skill plus the
connected shadcn MCP (or the CLI fallback) for design-system guidance, and do
not report `shadcn/*` checks as having run. If the workspace owner adopts the
linter, add the dependency, scoped config, and lint script together.

The Plan template is intentionally excluded from this rollout. Its files remain
under `templates/plan/**`, but the root Oxlint ignore list keeps them out of the
shadcn checks until that template has a separate lint baseline.

- `no-restyle`: use the component's `variant`, `size`, and semantic props; put
  layout on a parent and add a component variant only when the design system
  genuinely needs a new treatment.
- `no-raw-colors`: use the theme tokens in the app's `global.css`, not raw
  Tailwind palette classes or hard-coded color attributes.
- `no-arbitrary-values`: use the theme scale or a declared token instead of
  one-off bracket values.
- `no-inline-styles`: use classes or CSS custom properties for dynamic layout;
  keep intentional editor/export exceptions scoped to their owning subsystem.
- `no-unknown-classes` and `require-static-classes`: use classes Tailwind can
  generate and keep class strings statically discoverable.

The local primitive source is the contract boundary. Product code should consume
its props and variants; update `packages/toolkit/src/ui/` or an app's
`components/ui/` only when the design-system contract itself changes.

## Agent-Native Adapter Rule

Pages, routes, and domain components import controls through the app's local UI
adapter layer. Never import `@agent-native/toolkit/ui/*` directly in app product
code. Direct imports bypass `app/design-system.ts` and make Toolkit/Core
surfaces use different controls from the app.

When shadcn is the app's adapter, add or update the local primitive and keep
product code on that local import. When a company design system is registered,
adapt its components to the semantic contracts from
`@agent-native/toolkit/design-system`; do not recreate a parallel shadcn
surface. The semantic API is styling-runtime agnostic, so do not require
Tailwind, CVA, or `className` in customer adapters.

For shared Toolkit features, customize presentation through semantic
components, a feature-level controller, and product-level render slots. Keep
the same controller for default and custom views. Use the conformance kit for
behavior components whose focus, portal, keyboard, dismissal, or stacking
behavior comes from the company design system.

## Adding Or Updating Components

- Add missing primitives with `pnpm dlx shadcn@latest add <component>` from the app root.
- Before overwriting an existing component, use `pnpm dlx shadcn@latest add <component> --dry-run` and `--diff` to inspect the change.
- After adding registry code, read the generated files. Fix import aliases, icon imports, missing subcomponents, and composition issues before using the component.
- Do not fetch raw component files manually from GitHub when the shadcn CLI can resolve the registry item.
- If a user asks to add a third-party block but does not name a registry, ask which registry to use instead of guessing.

## Component Composition

- Use existing primitives before custom markup: `Alert` for callouts, `Badge` for small status labels, `Separator` for dividers, `Skeleton` for placeholders, `Table` for tabular data, and `Card` for framed content.
- Compose cards from `CardHeader`, `CardTitle`, `CardContent`, and `CardFooter`. Leave `CardDescription` out: a card gets a title or a description, never both. See `frontend-design` → Default Surface Density.
- Dialog, Sheet, Drawer, and AlertDialog content must include an accessible title. Use visually hidden titles only when the visible UI already communicates the title.
- Put items inside their group components: `SelectItem` in `SelectGroup`, `DropdownMenuItem` in `DropdownMenuGroup`, `CommandItem` in `CommandGroup`, and equivalent menu groups.
- `TabsTrigger` belongs inside `TabsList`.
- `Avatar` always needs `AvatarFallback`.
- Buttons do not have magic loading props. Compose loading with `disabled`, `Spinner`, and clear text.

## Forms And Inputs

- Use the app's shadcn form primitives instead of raw div stacks.
- If `Field`, `FieldGroup`, `FieldSet`, or `InputGroup` are installed or worth adding, use them for form layout, grouped fields, and input add-ons.
- Do not place buttons inside inputs with absolute positioning. Use `InputGroup` and `InputGroupAddon` when available.
- Use `ToggleGroup` for small option sets, `RadioGroup` for one-of-many choices, `Checkbox` for multi-select, `Switch` for settings toggles, `Select` or `Combobox` for predefined choices, and `Slider` or numeric input for numeric values.
- Validation must be accessible: pair visual invalid states with `aria-invalid`, and connect descriptions/errors to controls.

## Styling And Theming

- Use semantic tokens (`bg-background`, `text-foreground`, `text-muted-foreground`, `bg-primary`, `border-border`, `text-destructive`) instead of raw colors for reusable app UI.
- Prefer built-in variants and sizes before custom classes.
- Use `className` mostly for layout and spacing; avoid overriding component colors and typography unless the component is intentionally being extended.
- Use `gap-*` instead of `space-x-*` / `space-y-*`.
- Use `size-*` when width and height are equal.
- Use `truncate` for single-line clipping.
- Use `cn()` for conditional classes.
- Do not add manual `z-index` to overlay primitives unless you are fixing a verified stacking bug.
- Add custom colors as CSS variables in the existing Tailwind CSS file reported by shadcn info. For Tailwind v4, register variables with `@theme inline`.

## Transitions And Motion

shadcn's built-in component animations are the right level of polish — keep them. The goal is a snappy, clean UI, not a motionless one. Match shadcn's motion vocabulary; don't strip it and don't pile on decorative custom animation.

- **Never remove or override a shadcn component's default animation.** `data-[state=open]:animate-in`, `data-[state=closed]:animate-out`, `fade-in/out`, `zoom-in/out`, `slide-in-from-*`, accordion height, the `tailwindcss-animate` utilities — these ship for a reason. Leave them as-is.
- **Custom transitions are fine when they communicate a state change and match shadcn's feel.** Reuse the same vocabulary: short durations (~120–200ms), `ease-out`, opacity/transform only, gated on `data-[state=...]`. Examples that are good and welcome:
  - A portaled custom popover/tooltip/sheet that fades + scales/slides in on `data-[state=delayed-open]` / `data-[state=closed]`, mirroring Radix's own content animation.
  - A list row or toast that fades/slides in on mount and out on dismiss.
  - A chevron/caret `rotate` on expand, a subtle `opacity`/`color` hover on an icon button, skeleton shimmer, a progress/height transition on a collapsible.
  - Continuous, product-defining motion where it _is_ the experience (e.g. a multi-stage booking flow's stage transitions) — fine, and framer-motion is acceptable there.
- **Avoid decorative, attention-seeking, or slow motion:** hand-rolled `duration-700` hero fade-ins, parallax, bouncing/spring entrances on ordinary content, animated gradients, staggered cascades on long lists, anything that delays the user seeing or acting on content. If an animation makes the UI feel slower, cut it.
- Rule of thumb: if the motion clarifies what just changed and is over in well under a quarter-second, it's polish; if it's there to look impressive, it's bloat.

## Icons

- Agent-Native apps use `@tabler/icons-react`. Do not add `lucide-react` because a registry example used it.
- If registry code imports a different icon package, replace those imports with Tabler equivalents before finishing.
- Let shadcn components size icons through their CSS. Avoid manual icon sizing inside buttons, menus, alerts, and sidebars unless the local component API requires it.

## Base-Specific APIs

Check the project context before using trigger composition APIs:

- Radix-based components use `asChild` for custom triggers.
- Base UI components may use `render` and sometimes `nativeButton={false}`.

Do not wrap triggers in extra divs just to place a Button or Link inside them.

## Related Skills

- **frontend-design** — Product UX, visual direction, responsive polish, and verification
- **customizing-agent-native** — Registered design systems, controllers, slots, conformance, and ejection
- **actions** — Data fetching and mutation patterns for agent-native apps
- **security** — User data, forms, external input, and action safety

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…