diff --git a/docs/COMPONENT_IMPLEMENTATION.md b/docs/COMPONENT_IMPLEMENTATION.md deleted file mode 100644 index f0461a5..0000000 --- a/docs/COMPONENT_IMPLEMENTATION.md +++ /dev/null @@ -1,433 +0,0 @@ -# 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"` -- `"invertDefault"` creates a full-width inverted section with `bg-foreground` -- `"noInvert"` is the standard section with no background -- Always use explicit string equality checks (not truthy/falsy) -- Text colors should check for `"invertDefault"` mode - -## 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 (`
`, `