Skip to content

Component Architecture

Sparkle’s component library is built on key principles that ensure consistency, accessibility, and developer experience:

All components are built with TypeScript from the ground up, providing:

  • Type safety for props and component APIs
  • IntelliSense support in modern IDEs
  • Compile-time validation to catch errors early
  • Self-documenting interfaces through type definitions

Every component implements accessibility standards:

  • ARIA attributes properly configured
  • Keyboard navigation support
  • Screen reader compatibility tested
  • Focus management handled automatically
  • WCAG 2.1 AA compliance as minimum standard

Components follow React composition patterns:

  • Single responsibility for each component
  • Compound components for complex UI patterns
  • Render props and children functions where appropriate
  • Forward refs for DOM access
  • Polymorphic components using as prop when needed

All components integrate with the Sparkle theme system:

  • Design tokens for consistent styling
  • CSS custom properties for dynamic theming
  • Cross-platform compatibility with React Native
  • Dark/light mode support built-in

Form-related components for user input and data collection:

  • Form: Root form context provider
  • FormField: Generic field wrapper with validation
  • FormControl: Base control with label and error handling
  • FormInput: Text input with validation
  • FormPassword: Password input with show/hide toggle
  • FormTextarea: Multi-line text input
  • FormSelect: Dropdown selection component
  • FormLabel: Accessible form labels
  • FormDescription: Help text for form fields
  • FormMessage: Error and status messages
  • FormSubmit: Form submission button

Basic UI building blocks:

  • Button: Primary interface element for actions

Each component follows a consistent file structure:

Component/
├── Component.tsx # Main component implementation
├── Component.types.ts # Type definitions (if complex)
├── Component.test.tsx # Unit tests
├── Component.stories.tsx # Storybook stories
└── index.ts # Public exports
Button/Button.tsx
export interface ButtonProps extends HTMLButtonElement {
variant?: 'primary' | 'secondary' | 'outline'
size?: 'sm' | 'md' | 'lg'
children: React.ReactNode
}
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ variant = 'primary', size = 'md', className, children, ...props }, ref) => {
return (
<button
ref={ref}
className={cx('btn', `btn-${variant}`, `btn-${size}`, className)}
{...props}
>
{children}
</button>
)
}
)
Button.displayName = 'Button'

Most components extend base props interfaces:

import { HTMLProps } from '@sparkle/types'
interface ComponentProps extends HTMLProps<HTMLElement> {
// Component-specific props
variant?: string
size?: string
// Always include children when appropriate
children?: React.ReactNode
}

Components use a consistent variant system:

  • Primary variants: Main styling options (primary, secondary, etc.)
  • Size variants: Consistent sizing scale (sm, md, lg, xl)
  • State variants: Visual states (default, hover, active, disabled)

All interactive components forward refs to the underlying DOM element:

export const Component = React.forwardRef<HTMLElement, ComponentProps>(
(props, ref) => {
return <element ref={ref} {...props} />
}
)

Each component includes comprehensive unit tests:

  • Rendering tests verify component renders correctly
  • Props tests validate prop handling and default values
  • Interaction tests check user interactions work properly
  • Accessibility tests ensure ARIA attributes and keyboard navigation

Components are tested visually through Storybook:

  • All variants documented in stories
  • Different states shown in examples
  • Responsive behavior tested across viewports
  • Theme variations tested in light/dark modes
  • Tree-shakable exports for reduced bundle size
  • Lazy loading for complex components when appropriate
  • Minimal dependencies to reduce package size
  • Memoization for expensive computations
  • Event handler optimization to prevent unnecessary re-renders
  • Virtual scrolling for large lists when needed

Components follow semantic versioning:

  • Major versions: Breaking API changes
  • Minor versions: New features and components
  • Patch versions: Bug fixes and improvements

When components change:

  1. Deprecation warnings in TypeScript and console
  2. Migration guides in documentation
  3. Compatibility shims when possible
  4. Clear timelines for removal