| name | create-component |
| description | Create new Preact components following project conventions with proper file structure, TypeScript types, and Tailwind styling. Use when adding UI components, sections, or interactive elements to the site. Use when this capability is needed. |
| metadata | {"author":"agentconfig"} |
Create Component
Create Preact components for agentconfig.org following project conventions.
File Structure
Every component lives in its own folder under site/src/components/:
site/src/components/
โโโ {ComponentName}/
โโโ index.ts # Re-exports component and types
โโโ {ComponentName}.tsx # Main implementation
Step-by-Step Process
- Create the component folder in
site/src/components/{ComponentName}/
- Copy the template from
assets/component-template.tsx
- Rename and customize the component
- Create index.ts with exports
- Import in App.tsx or parent component
Template Files
index.ts
export { ComponentName } from './ComponentName'
export type { ComponentNameProps } from './ComponentName'
ComponentName.tsx
See assets/component-template.tsx for the full template.
TypeScript Rules
- No semicolons - Omit semicolons at end of statements
- Explicit return types - Always specify
: ReactNode
- Interface over type - Use
interface for props
- JSDoc comments - Document props with
/** */
- No
any - Use proper types or unknown
- Readonly arrays - Use
readonly for array props
interface ListProps {
readonly items: readonly string[]
}
type ListProps = {
items: string[];
}
Styling Rules
- Tailwind utilities - Use Tailwind classes for all styling
- cn() helper - Use
cn() from @/lib/utils for conditional classes
- Mobile-first - Start with mobile, add
md: and lg: for larger screens
- Theme-aware - Use CSS variables for theme colors
<div className="p-4 md:p-6 lg:p-8 bg-background text-foreground">
<div className="p-8 sm:p-4">
Component Guidelines
Keep Components Focused
- One component = one responsibility
- Under 150 lines (split if longer)
- Extract complex logic into custom hooks in
site/src/hooks/
Props Design
- Always include
className prop for style overrides
- Use
children for flexible content
- Use discriminated unions for variants
interface ButtonProps {
variant: 'primary' | 'secondary' | 'ghost'
className?: string
children?: ReactNode
}
Event Handlers
- Prefix with
on: onClick, onToggle, onSelect
- Use specific types, not generic
Function
interface Props {
onSelect: (id: string) => void
onSelect: Function
}
Accessibility
- Semantic HTML - Use
button for buttons, nav for navigation
- ARIA attributes - Add
aria-label, aria-expanded for interactive elements
- Keyboard navigation - Ensure focusable and keyboard-usable
- Focus visible - Use
focus-visible: for focus rings
<button
aria-expanded={isOpen}
aria-controls="menu-content"
className="focus-visible:ring-2 focus-visible:ring-primary"
>
Checklist
Before considering the component complete:
Converted and distributed by TomeVault โ claim your Tome and manage your conversions.