diff --git a/.agents/skills/create-component/SKILL.md b/.agents/skills/create-component/SKILL.md index d44b465..0e143b2 100644 --- a/.agents/skills/create-component/SKILL.md +++ b/.agents/skills/create-component/SKILL.md @@ -7,7 +7,7 @@ description: >- # Create Component Workflow for @creativecodeco/ui -Follow this standardized 6-step workflow whenever creating a new component or form control in `@creativecodeco/ui`. +Follow this standardized workflow and best-practices checklist whenever creating or updating a UI component or Form control in `@creativecodeco/ui`. --- @@ -17,17 +17,40 @@ Create the props interface co-located in `src/ui/components//Type` (e.g. `CardType`, `StepsType`). -- Mark all optional props with `?`. -- Use specific types (`React.ReactNode`, `React.Key`, `ColorType`, `SizeType`, etc.). +- Name the interface `Type` (e.g. `CardType`, `StepsType`, `SelectType`). +- **Always include `className?: string`** on every component interface so consumers can compose layout utilities cleanly. +- **For Form controls (`src/ui/forms/*`)**: Always extend `ErrorType` (`import type { ErrorType } from '@/types'`) so the control supports both `isError?: boolean` and `error?: string`, plus `id?: string`, `name?: string`, `label?: string`, and `disabled?: boolean`. +- Mark all non-mandatory props as optional with `?` to prevent friction in unit tests, Storybook, and React Hook Form `Controller`. +- Use specific types (`React.ReactNode`, `React.Key`, `ColorType`, `SizeType`, etc.) — **zero `any` or implicit types**. - Re-export the types from the component's `index.ts` (`export type * from './.types';`), which automatically flows through `src/types/index.ts`. +### UI Component Interface Example + ```ts -import type { ColorType } from '@/types'; +import type { ColorType, SizeType } from '@/types'; export interface ComponentNameType { children?: React.ReactNode; - variant?: ColorType; + color?: ColorType; + size?: SizeType; + disabled?: boolean; + className?: string; +} +``` + +### Form Control Interface Example + +```ts +import type { ColorType, ErrorType, SizeType } from '@/types'; + +export interface FormControlNameType extends ErrorType { + id?: string; + name?: string; + label?: string; + value?: string; + onChange?: React.ChangeEventHandler; + color?: ColorType; + size?: SizeType; disabled?: boolean; className?: string; } @@ -35,46 +58,128 @@ export interface ComponentNameType { --- -## Step 2: Implement Component Logic & Layout +## Step 2: Implement Component Logic, A11y & Responsive Design Create `src/ui/components///.component.tsx` (or `src/ui/forms//.component.tsx`). -**Rules:** +### 2.1 Core Implementation Rules - Use `classnames` imported as `import cls from 'classnames'`. - Import types from `@/types`. -- Use default parameters for optional props. -- Ensure strict React key handling when mapping arrays: `key={item.id || index}`. +- **Safe `className` Merging**: Always destructure `className` and merge it via `cls('base-class', className, { ... })` **after** or separately from `{...restProps}` so spreading HTML attributes never overwrites internal DaisyUI classes. +- **Prevent Custom Prop Leakage to DOM**: Always destructure custom library props (`isError`, `error`, `label`, `color`, `size`, `bordered`) before spreading `{...restProps}` onto native DOM elements (``, `