Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when styling any web UI - style with Tailwind utility classes and design tokens, avoid custom CSS, and build on the existing Radix/shadcn primitives instead of hand-rolling
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Styling is Tailwind-first with a shared token system, on top of Radix/shadcn primitives. Custom CSS and hand-rolled interactive widgets are what this skill exists to prevent — they fragment the design and re-introduce accessibility bugs the primitives already solved.
Core principle: Avoid custom CSS. Style with Tailwind utilities and the design tokens; reach for the existing shadcn primitive before building an interactive widget, and its built-in variant before a custom class.
@tailwindcss/vite and @import "tailwindcss", with tokens defined in @theme/:root in the main CSS file. A repo already on Tailwind v3 keeps tailwind.config — check package.json and follow what the repo already uses, don't migrate it mid-task..css files, no <style> blocks, no bespoke class names. Compose utilities; use cn() for conditional variants. An inline style={{}} object is allowed ONLY for a genuinely dynamic, computed value (a measured width, a transform) — tag it // ui-guard-allow: <reason> if the project runs ui-guard.<Button variant="outline">, size="sm" — not className="border border-input bg-transparent hover:bg-accent".bg-primary, text-muted-foreground, border-border — never bg-blue-500, text-gray-600, or a hex code. No arbitrary pixel values (w-[327px]) — use the scale.className is for layout, not restyling. w-full, max-w-md, self-end, col-span-2 are fine (spacing between siblings comes from the parent's gap, not margins on the child); overriding a component's own colour or typography through className is not — change the variant or the token instead.gap-* over space-x-*/space-y-*. flex flex-col gap-4, not space-y-4.size-* for square elements. size-10, not w-10 h-10.dark: colour overrides — the semantic tokens already carry both themes.Dialog, Sheet, Drawer, Popover, DropdownMenu, Tooltip manage their own stacking; never add z-50/z-[999] to them. The fixed z-scale — z-10 raised content, z-20 sticky header, z-30 dropdown/popover, z-40 overlay, z-50 modal/toast — is for your own layered content, never arbitrary z-[…].components/ui — never hand-roll one that exists (you'll lose focus trapping, keyboard nav, and ARIA). Dialog/Sheet/Drawer always render a Title (visually hidden with sr-only if the design doesn't show one).Field/FieldGroup (or the project's own FormField molecule) — not a raw div with space-y-*. Validation state is data-invalid on the Field, aria-invalid on the control.Empty for empty states, Skeleton for loading (no custom animate-pulse div), AlertDialog for destructive confirmation, Spinner composed into Button for a pending submit.npm run build must stay green — a TypeScript error or failed build is a broken task, not a warning.components/ui — see component-composition for the rest of the atomic levels and the import-direction rule.web-design-system-foundation to set up @theme, cn(), and the base atoms before building the first screen.| Situation | Verdict |
|---|---|
| Static padding/color/size | Tailwind token class |
| Conditional variant | cn() with utility classes |
| Value computed at runtime (measured px, dynamic transform) | inline style={{}} — the only valid case, tag ui-guard-allow: if ui-guard runs |
| A one-off pixel that "isn't in the scale" | No — use the nearest scale token; extend the scale via tokens if truly needed |
grid-cols-[repeat(auto-fit,minmax(...))], max-w-[..ch], aspect-[..] | Allowed arbitrary values (ui-guard's allow-list) |
// ❌ custom CSS + magic values + hand-rolled dropdown
<div className="my-custom-menu" style={{ padding: "13px", background: "#f5f5f5" }}>
{/* hand-built menu: no keyboard nav, no ARIA */}
</div>
// ✅ tokens + primitive + built-in variant
<DropdownMenu> {/* Radix primitive from components/ui */}
<DropdownMenuTrigger asChild><Button variant="ghost">Actions</Button></DropdownMenuTrigger>
<DropdownMenuContent className="p-3">
<DropdownMenuGroup>
<DropdownMenuItem onSelect={onExport}>Export</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
The primitive brings focus management, escape-to-close, and ARIA for free; the token classes and DropdownMenuGroup keep it visually and structurally identical to every other menu.
.css file or <style> block instead of utilities.w-[327px], text-[#3a3a3a]) or raw palette classes instead of scale tokens.components/ui.space-x-*/space-y-* instead of gap-*; a manual z-50 on an overlay primitive.style={{}} for static styling that a class would cover.divs with onClick instead of a primitive.dark: override scattered across the component.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
日本語の概要は準備中です。原文の説明を表示しています。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
日本語の概要は準備中です。原文の説明を表示しています。
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
日本語の概要は準備中です。原文の説明を表示しています。
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
日本語の概要は準備中です。原文の説明を表示しています。
Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation
日本語の概要は準備中です。原文の説明を表示しています。