Skip to main content

shade-new-component

Acceptance checklist for adding or editing a Shade component or pattern file — naming, sibling story, className forwarding, cva variants, required states, recipe usage. Trigger when editing files in apps/shade/src/components.

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

المستودع
TryGhost/Ghost
آخر نشاط في المصدر
١١ أكتوبر ٢٠٢٦ في ٠٨:٥٣
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٥٥٬٥٤٤
التفرعات
١١٬٩٩٥

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

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

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

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

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
Shade new component
description
Acceptance checklist for adding or editing a Shade component or pattern file — naming, sibling story, className forwarding, cva variants, required states, recipe usage. Trigger when editing files in apps/shade/src/components.
autoTrigger
[{"fileEdit":"apps/shade/src/components/**/*.{ts,tsx}"}]
# Shade — new component / pattern checklist Before marking a Shade component or pattern done, this checklist must pass. ## Files and naming - File: **kebab-case** (`dropdown-menu.tsx`) — matches ShadCN CLI output. Don't rename for casing. - Exported identifier: **PascalCase** (`DropdownMenu`). - Hooks, functions, variables: camelCase. - Sibling **`<name>.stories.tsx`** is required (same folder). - A component file exports only components and types, so Fast Refresh can hot-update it (ESLint enforces this). An exported `cva()` config goes in a sibling **`<name>-variants.ts`**; exported hooks, contexts and helpers go in their own sibling module (`sidebar-context.ts`). These siblings belong to the component; they aren't Recipes. - Inside Shade itself, import via the `@/` alias (`@/lib/utils`, `@/components/ui/input-surface`). ## Storybook title prefix | Layer | Title | | ------------- | --------------------- | | Primitive | `Primitives / <Name>` | | Component | `Components / <Name>` | | Recipe | `Recipes / <Name>` | | Pattern | `Patterns / <Name>` | | Token gallery | `Tokens / <Topic>` | Required on every story file: - `tags: ['autodocs']` - `parameters.docs.description.component` — short one-line summary - Per-story `parameters.docs.description.story` — one-liner explaining when to use that variant - One story per important variant/state. Many small focused stories > one prose-heavy story. ## Component shape ```ts // thing-variants.ts import {cva} from 'class-variance-authority'; const thingVariants = cva('base-classes-here', { variants: { variant: {default: '...', destructive: '...'}, size: {default: '...', sm: '...'} }, defaultVariants: {variant: 'default', size: 'default'} }); export {thingVariants}; ``` ```tsx // thing.tsx import * as React from 'react'; import {type VariantProps} from 'class-variance-authority'; import {thingVariants} from '@/components/ui/thing-variants'; import {cn} from '@/lib/utils'; export interface ThingProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof thingVariants> {} const Thing = React.forwardRef<HTMLDivElement, ThingProps>( ({className, variant, size, ...props}, ref) => ( <div ref={ref} className={cn(thingVariants({variant, size, className}))} {...props} /> ) ); Thing.displayName = 'Thing'; export {Thing}; ``` Hard requirements: - `className` forwarded and merged via `cn()` — never overwritten, never dropped. Applies to every component that renders DOM. - Visual/interactive props only (`variant`, `size`, `loading`). **No workflow props** (`isMembersPage`, `layoutMode`) — those mean you actually need a Pattern wrapper. - Multi-region components expose compound subcomponents (`.Title`, `.Actions`, `.Body`) — not a prop bag. When applicable: - **`forwardRef`** — use when the component renders a single DOM element consumers might need a ref to (most UI controls). Skip for: pure provider/context wrappers, Radix root re-exports that don't render DOM themselves, and components whose `ref` semantics are already handled by a child. - **`cva()`** — use when the component has variants or stateful class branches (`variant`, `size`, `tone`). Skip for simple single-style components where a `cn(...)` call is clearer. - **Recipes** (`<name>.ts`, no JSX): no `forwardRef`, no `cva()`, no React. They return class strings. ## Required states (all four) Every interactive component must work in: - **default** - **hover** - **focus-visible** (use `focus-visible:`, never `focus:`) - **disabled** Each state visible in the story. Optional states (active, loading, error, empty) only when they apply. For form controls, drive chrome through the **`inputSurface` recipe** — don't roll your own border/focus ring. See the `shade-input-surface-recipe` skill. ## Tokens - No hex values. No `bg-gray-200`-style raw palette utilities for UI chrome. - No `dark:` variants for colour — semantic tokens handle dark mode. See `shade-tokens-not-hex` and `shade-no-dark-variants`. ## Before marking done - [ ] Lives in the right layer (`shade-component-decision`) - [ ] kebab-case filename, PascalCase export, sibling `<name>.stories.tsx` - [ ] `className` forwarded and merged with `cn()` (always) - [ ] `forwardRef` if the component renders DOM consumers might ref - [ ] `cva()` if the component has variants; `defaultVariants` set - [ ] The component file exports only components and types; exported variants, hooks and contexts live in sibling modules - [ ] All four required states work and are visible in the story - [ ] Semantic tokens only — no hex, no raw greys, no `dark:` colour variants - [ ] No product-specific props on a generic Component - [ ] Story has `tags: ['autodocs']`, component description, and one-line per-story descriptions - [ ] `pnpm lint`, `pnpm test`, and Storybook all clean ## Source of truth Storybook → Overview / Contributing and the component's stories.
عرض على GitHub