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 the repository keeps its alerting in code, or a person asks for alerts outside TaskTrooper - PrometheusRule YAML, a Cloud Monitoring alert policy in Terraform, a Datadog monitor, each routed to TaskTrooper's alert ingest URL so it opens an incident here
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.