Skip to main content

design-system

Build a new design system (tokens, variants, theming). Use when "create a design system" or "component library from scratch". Drifted existing system → housekeep-design. Plan-only unification → plan-uiux-unification.

معلومات المصدر

المستودع
kensaurus/cursor-kenji
آخر نشاط في المصدر
١٢ سبتمبر ٢٠٢٦ في ١٤:٢٠
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٩
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
design-system
description
Build a new design system (tokens, variants, theming). Use when "create a design system" or "component library from scratch". Drifted existing system → housekeep-design. Plan-only unification → plan-uiux-unification.
license
MIT
# Design System Skill **Degree of freedom: MIXED.** Token taxonomy and variants `[HIGH freedom]`; existing `ui/` / token inventory `[LOW freedom — run exactly]`. Build scalable, maintainable design systems with consistent tokens, variants, and documentation. ## How to reason 1. **Inventory** — `components/ui`, tokens, `cva`, shadcn/Radix 2. **Tokenize** — semantic tokens, not raw hex in components 3. **Variant** — `cva` covers real states (default/destructive/disabled) 4. **Document** — JSDoc, keyboard/focus, dark mode ## Worked example > **Inventory:** shadcn `Button` exists; colors are raw `#3B82F6` in three pages; no `--primary`. > **Tokenize:** `--primary` / `--primary-foreground` in `globals.css`; Tailwind maps `hsl(var(--primary))`. > **Variant:** extend existing `buttonVariants` — do not add `components/Button2.tsx`. > **Document:** JSDoc lists variants/sizes; focus ring + dark `.dark` overrides. ## Self-critique before reporting - **Did not fork** — existing primitives were extended, not recreated - **Semantic tokens** — components reference tokens, not primitives or hex - **A11y + dark** — focus, disabled, and dark variants exist - **Right owner** — drifted existing system → `housekeep-design`; plan-only unification → `plan-uiux-unification` ## Check existing first [LOW freedom — run exactly] **Before creating ANY design system components, verify:** 1. **Check for existing design system:** ```bash ls -la src/components/ui/ cat package.json | grep -i "shadcn\|radix\|headless" cat components.json 2>/dev/null # shadcn config ``` 2. **Check for existing tokens:** ```bash cat tailwind.config.* | head -100 cat src/styles/globals.css | head -50 rg "var\(--" --type css | head -20 ``` 3. **Check for existing patterns:** ```bash rg "cva\(|variants:" --type ts --type tsx | head -10 rg "cn\(|clsx\(|twMerge" --type tsx | head -5 ``` **Why:** Don't recreate existing primitives. Extend and enhance what exists. ## Design Tokens [HIGH freedom] ### CSS Custom Properties ```css /* globals.css */ :root { /* Colors - Semantic */ --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; --card: 0 0% 100%; --card-foreground: 222.2 84% 4.9%; --popover: 0 0% 100%; --popover-foreground: 222.2 84% 4.9%; --primary: 221.2 83.2% 53.3%; --primary-foreground: 210 40% 98%; --secondary: 210 40% 96.1%; --secondary-foreground: 222.2 47.4% 11.2%; --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; --accent: 210 40% 96.1%; --accent-foreground: 222.2 47.4% 11.2%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 210 40% 98%; --border: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%; --ring: 221.2 83.2% 53.3%; /* Spacing */ --spacing-xs: 0.25rem; --spacing-sm: 0.5rem; --spacing-md: 1rem; --spacing-lg: 1.5rem; --spacing-xl: 2rem; /* Border Radius */ --radius: 0.5rem; --radius-sm: calc(var(--radius) - 4px); --radius-lg: calc(var(--radius) + 4px); /* Shadows */ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); /* Animation */ --duration-fast: 150ms; --duration-normal: 200ms; --duration-slow: 300ms; --ease-default: cubic-bezier(0.4, 0, 0.2, 1); --ease-in: cubic-bezier(0.4, 0, 1, 1); --ease-out: cubic-bezier(0, 0, 0.2, 1); --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); } .dark { --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; /* ... dark mode overrides */ } ``` ### Tailwind Config Integration ```ts // tailwind.config.ts import type { Config } from 'tailwindcss' const config: Config = { content: ['./src/**/*.{ts,tsx}'], darkMode: 'class', theme: { extend: { colors: { border: 'hsl(var(--border))', input: 'hsl(var(--input))', ring: 'hsl(var(--ring))', background: 'hsl(var(--background))', foreground: 'hsl(var(--foreground))', primary: { DEFAULT: 'hsl(var(--primary))', foreground: 'hsl(var(--primary-foreground))', }, secondary: { DEFAULT: 'hsl(var(--secondary))', foreground: 'hsl(var(--secondary-foreground))', }, destructive: { DEFAULT: 'hsl(var(--destructive))', foreground: 'hsl(var(--destructive-foreground))', }, muted: { DEFAULT: 'hsl(var(--muted))', foreground: 'hsl(var(--muted-foreground))', }, accent: { DEFAULT: 'hsl(var(--accent))', foreground: 'hsl(var(--accent-foreground))', }, }, borderRadius: { lg: 'var(--radius-lg)', md: 'var(--radius)', sm: 'var(--radius-sm)', }, boxShadow: { sm: 'var(--shadow-sm)', DEFAULT: 'var(--shadow)', md: 'var(--shadow-md)', lg: 'var(--shadow-lg)', }, transitionDuration: { fast: 'var(--duration-fast)', normal: 'var(--duration-normal)', slow: 'var(--duration-slow)', }, }, }, } export default config ``` ## Component Variants with CVA ```tsx // lib/utils.ts import { type ClassValue, clsx } from 'clsx' import { twMerge } from 'tailwind-merge' export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } ``` ```tsx // components/ui/button.tsx import { cva, type VariantProps } from 'class-variance-authority' import { forwardRef } from 'react' import { cn } from '@/lib/utils' const buttonVariants = cva( // Base styles 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50', { variants: { variant: { default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90', destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90', outline: 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground', secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80', ghost: 'hover:bg-accent hover:text-accent-foreground', link: 'text-primary underline-offset-4 hover:underline', }, size: { default: 'h-9 px-4 py-2', sm: 'h-8 rounded-md px-3 text-xs', lg: 'h-10 rounded-md px-8', icon: 'h-9 w-9', }, }, defaultVariants: { variant: 'default', size: 'default', }, } ) export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> { asChild?: boolean } const Button = forwardRef<HTMLButtonElement, ButtonProps>( ({ className, variant, size, asChild = false, ...props }, ref) => { const Comp = asChild ? Slot : 'button' return ( <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} /> ) } ) Button.displayName = 'Button' export { Button, buttonVariants } ``` ## Compound Components Pattern ```tsx // components/ui/card.tsx import { cn } from '@/lib/utils' import { forwardRef } from 'react' const Card = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( ({ className, ...props }, ref) => ( <div ref={ref} className={cn( 'rounded-xl border bg-card text-card-foreground shadow', className )} {...props} /> ) ) Card.displayName = 'Card' const CardHeader = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( ({ className, ...props }, ref) => ( <div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} /> ) ) CardHeader.displayName = 'CardHeader' const CardTitle = forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>( ({ className, ...props }, ref) => ( <h3 ref={ref} className={cn('font-semibold leading-none tracking-tight', className)} {...props} /> ) ) CardTitle.displayName = 'CardTitle' const CardDescription = forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>( ({ className, ...props }, ref) => ( <p ref={ref} className={cn('text-sm text-muted-foreground', className)} {...props} /> ) ) CardDescription.displayName = 'CardDescription' const CardContent = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( ({ className, ...props }, ref) => ( <div ref={ref} className={cn('p-6 pt-0', className)} {...props} /> ) ) CardContent.displayName = 'CardContent' const CardFooter = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>( ({ className, ...props }, ref) => ( <div ref={ref} className={cn('flex items-center p-6 pt-0', className)} {...props} /> ) ) CardFooter.displayName = 'CardFooter' export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } ``` ## Accessible Components with Radix ```tsx // components/ui/dialog.tsx 'use client' import * as DialogPrimitive from '@radix-ui/react-dialog' import { X } from 'lucide-react' import { cn } from '@/lib/utils' const Dialog = DialogPrimitive.Root const DialogTrigger = DialogPrimitive.Trigger const DialogPortal = DialogPrimitive.Portal const DialogClose = DialogPrimitive.Close const DialogOverlay = forwardRef<
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub