# Component Implementation Standards This document outlines the core implementation patterns for creating components in this library, optimized for AI website builders. ## Component Structure Template Every component should follow this structure: ```tsx "use client"; import React from "react"; import { cls } from "@/lib/utils"; interface ComponentProps { // Required props first text: string; // Optional props with explicit types onClick?: () => void; className?: string; disabled?: boolean; ariaLabel?: string; type?: "button" | "submit" | "reset"; } const Component = ({ text, onClick, className = "", disabled = false, ariaLabel, type = "button", }: ComponentProps) => { return ( {text} ); }; Component.displayName = "Component"; export default React.memo(Component); ``` **Key Requirements:** - `"use client"` directive when needed (interactive components, hooks) - Named exports with `displayName` for debugging - Wrap in `React.memo()` for performance optimization - Use `cls()` utility for class composition (never plain string concatenation) ## Prop Structure & Defaults ### Required Props Core content props should be **required** with no default values: - Section components: `title`, `description` - Button components: `text` - Media components: `imageSrc` or `videoSrc` (when applicable) ### Optional Props with Defaults **Standard className defaults:** ```tsx className = "", textClassName = "", iconClassName = "", containerClassName = "", ``` Empty string defaults prevent undefined checks and are standard practice. **Common optional props:** ```tsx disabled = false, type = "button", ariaLabel, // No default, falls back to sensible value in component ``` **Component-specific props:** Document defaults clearly in both code and registry: ```tsx strengthFactor = 20, carouselMode = "buttons", uniformGridCustomHeightClasses = "min-h-80 2xl:min-h-90", ``` ## Naming Conventions ### Section Components (Hero, About, Feature, etc.) **✅ CORRECT:** ```tsx interface HeroProps { title: string; // Primary heading description: string; // Supporting text buttons?: ButtonConfig[]; } ``` **❌ WRONG:** ```tsx interface HeroProps { heading: string; // Should be "title" subtitle: string; // Should be "description" text: string; // Ambiguous } ``` ### Button Components **✅ CORRECT:** ```tsx interface ButtonProps { text: string; // Button label onClick?: () => void; } ``` **❌ WRONG:** ```tsx interface ButtonProps { title: string; // Should be "text" label: string; // Should be "text" } ``` ### Button Config (for sections) ```tsx interface ButtonConfig { text: string; // Button label (not "title" or "label") href?: string; onClick?: () => void; props?: Partial>; // NO variant property - controlled by ThemeProvider } ``` **Consistency is critical:** - All hero sections must use the same prop names - All about sections must use the same prop names - Registry documentation must match component prop names exactly ## Component Customizability Provide className props for **all major elements** to allow full styling control: ```tsx interface SectionProps { title: string; description: string; // Main wrapper className?: string; // Inner container containerClassName?: string; // Content areas textClassName?: string; mediaWrapperClassName?: string; imageClassName?: string; } const Section = ({ title, description, className = "", containerClassName = "", textClassName = "", mediaWrapperClassName = "", imageClassName = "", }: SectionProps) => { return (
{/* content */}
); }; ``` **Naming convention:** - `className` - Main wrapper element - `containerClassName` - Inner container - `[element]ClassName` - Specific elements (e.g., `textClassName`, `imageClassName`) ## Component Composition & Base Styles When composing higher-level components from base components, **set sensible base styles** while accepting className overrides: ```tsx interface HeroProps { title: string; description: string; titleClassName?: string; descriptionClassName?: string; textBoxClassName?: string; } const Hero = ({ title, description, titleClassName = "", descriptionClassName = "", textBoxClassName = "", }: HeroProps) => { return (
); }; ``` **Key principles:** - Base styles come first in `cls()`, overrides second - This ensures good defaults while maintaining full customizability - AI builders can use components without styling knowledge, but advanced users can override - Use `cls()` utility for proper class merging (prevents Tailwind conflicts) ## Type Safety ### Use Explicit Prop Interfaces ```tsx // ✅ CORRECT - Clear and explicit interface ButtonProps { text: string; onClick?: () => void; variant?: "primary" | "secondary"; } // ❌ WRONG - Over-complicated interface ButtonProps extends React.ComponentPropsWithoutRef<'button'> { // ... harder for AI to understand } ``` ### Use Discriminated Unions for Variants ```tsx type MediaProps = | { imageSrc: string; imageAlt?: string; videoSrc?: never; } | { videoSrc: string; videoAriaLabel?: string; imageSrc?: never; }; ``` ### Export Reusable Types ```tsx export type ButtonConfig = { text: string; href?: string; onClick?: () => void; }; export type GridVariant = | "uniform-all-items-equal" | "two-columns-alternating-heights" | "asymmetric-60-wide-40-narrow" // ... etc ``` ## Responsive Design ### Mobile-First Approach **Default styles apply to mobile devices:** ```tsx // ✅ CORRECT - Mobile until md breakpoint (768px)
// ❌ WRONG - Using lg: breakpoint
``` **Breakpoint Rules:** - **Mobile styles**: No prefix (default) - **Desktop styles**: `md:` prefix only (768px breakpoint) - **Never use**: `lg:`, `xl:`, `2xl:` breakpoints for layout changes **Exceptions:** Only use larger breakpoints for minor tweaks: ```tsx // Acceptable for minor adjustments className="min-h-80 2xl:min-h-90" ``` ## Content Width Pattern All section content must follow this structure: ```tsx
{/* content */}
``` **Rules:** - Section: `w-full py-20` (full width with vertical padding) - Inner div: `w-content-width mx-auto` (centered content with max width) - `w-content-width` is controlled by ThemeProvider (small/medium/large) **Exceptions:** - Heroes and footers do NOT use `py-20` (they have custom spacing) - Full-bleed sections may skip inner wrapper ## Vertical Spacing **Standard sections:** ```tsx className="w-full py-20" ``` **Exceptions (NO py-20):** - Hero sections (custom spacing) - Footer sections (custom spacing) - Full-bleed sections with background colors ## Text Constraints For button text and short labels: ```tsx { "text": { "required": true, "example": "Get Started", "minChars": 2, "maxChars": 15 } } ``` **Button text rules:** - Minimum: 2 characters - Maximum: 15 characters - Single-line only (no multiline support) ## Section Structure Pattern ```tsx
{/* Section-specific content */}
``` **Key Pattern Notes:** - `useInvertedBackground` is a required prop: `"noInvert" | "invertDefault" | "invertCard"` - `"invertCard"` creates a card-style section with expanded width and rounded corners - `"invertDefault"` creates a full-width inverted section - `"noInvert"` is the standard section with no background - Always use explicit string equality checks (not truthy/falsy) - Text colors must check for both `"invertDefault"` and `"invertCard"` modes ## Implementation Checklist ### Core Requirements - [ ] Add `"use client"` directive if needed (hooks, interactivity) - [ ] Use explicit prop interfaces (no over-complicated types) - [ ] Set appropriate defaults for optional props - [ ] Add `displayName` for debugging - [ ] Wrap in `React.memo()` for performance - [ ] Use semantic HTML tags (`
`, `