Skip to main content

Component Style Guide

This document outlines the recommended patterns and best practices for building components in the BuildAppsWith platform.

Table of Contents

  1. Folder Structure
  2. Component Organization
  3. Import Standards
  4. Component Patterns
  5. Accessibility
  6. Magic UI Components
  7. Performance Considerations

Folder Structure

Components are organized following a domain-first approach:
/components
├── [domain]/         # Domain-specific components
│   ├── ui/           # Domain-specific UI components
│   │   └── index.ts  # Barrel exports
│   └── index.ts      # Barrel exports
├── ui/               # Shared UI components
│   ├── core/         # Foundational UI components (mostly shadcn/ui)
│   ├── composite/    # Composed UI components reused across domains
│   └── index.ts      # Barrel exports
└── providers/        # Context providers
See the Folder Structure Guide for more details on the overall project organization.

Component Organization

UI Component Hierarchy

Components follow a hierarchical organization:
  1. Core UI Components: Foundational building blocks (buttons, inputs, etc.)
  2. Composite UI Components: Combinations of core components that are reused across domains
  3. Domain-specific UI Components: Components tailored to a specific domain’s needs

Component File Structure

Each component file should follow this structure:
"use client"; // Only if using client-side hooks or APIs

// Imports organized by category
import { useState } from "react";
import { motion, useReducedMotion } from "framer-motion";

import { cn } from "@/lib/utils";
import { useComponentState } from "@/hooks/use-component-state";

import { Button } from "@/components/ui";
import { SomeOtherComponent } from "@/components/some-domain";

// Types and interfaces
interface MyComponentProps {
  // Props definition
}

// Component implementation
export function MyComponent({ prop1, prop2, ...props }: MyComponentProps) {
  // Implementation
}

Import Standards

Using Barrel Exports

Always import components from barrel exports (index.ts files) rather than directly from component files:
// ✅ Good - Use barrel exports
import { Button, Card } from "@/components/ui";
import { ValidationTierBadge } from "@/components/profile";

// ❌ Bad - Don't import directly from component files
import { Button } from "@/components/ui/button";
import { ValidationTierBadge } from "@/components/profile/ui/validation-tier-badge";

Benefits of Barrel Exports

Using barrel exports provides several advantages:
  1. Simplified Imports: Fewer import statements and shorter paths
  2. Encapsulation: Implementation details can change without affecting imports
  3. Refactoring Support: Components can be moved within their domain without breaking imports
  4. Cleaner Code: Reduces import clutter at the top of files

Import Order

Organize imports in the following order, with a blank line between each group:
  1. External Libraries: React, framer-motion, etc.
  2. Internal Utilities: Utilities and hooks from /lib and /hooks
  3. Internal Components: Components from /components
  4. Types: Type imports if separate from component imports
// External libraries
import { useState } from 'react';
import { motion } from 'framer-motion';

// Internal utilities
import { cn } from '@/lib/utils';
import { useAuth } from '@/hooks/use-auth';

// Internal components
import { Button } from '@/components/ui';
import { ValidationTierBadge } from '@/components/profile';

// Types
import type { UserProfile } from '@/types/user';

Component Patterns

Client vs. Server Components

  • Use server components by default for better performance
  • Add "use client"; directive only when needed (hooks, event handlers, browser APIs)
  • Keep client components as small as possible

Props Interface Pattern

  • Use TypeScript interfaces for component props
  • Document complex props with JSDoc comments
  • Use optional props with default values where appropriate
  • Put props interface directly above the component

Styling Approach

  • Use Tailwind CSS for styling
  • Use the cn() utility for conditional class names
  • Compose styles with component composition rather than complex class logic
  • Use CSS variables for themeable values
Example:
import { cn } from "@/lib/utils";

interface ButtonProps {
  variant?: "default" | "outline" | "ghost";
  size?: "sm" | "md" | "lg";
  className?: string;
}

export function Button({ 
  variant = "default", 
  size = "md", 
  className,
  ...props 
}: ButtonProps) {
  return (
    <button
      className={cn(
        "rounded font-medium", 
        {
          "bg-blue-500 text-white": variant === "default",
          "border border-gray-300": variant === "outline",
          "hover:bg-gray-100": variant === "ghost",
        },
        {
          "px-2 py-1 text-sm": size === "sm",
          "px-4 py-2": size === "md",
          "px-6 py-3 text-lg": size === "lg",
        },
        className
      )}
      {...props}
    />
  );
}

Accessibility

All components must be accessible according to WCAG 2.1 AA standards:
  • Use semantic HTML elements
  • Include proper ARIA attributes when needed
  • Support keyboard navigation
  • Ensure sufficient color contrast
  • Provide text alternatives for non-text content
  • Support screen readers

Reduced Motion

Support users who prefer reduced motion:
import { motion, useReducedMotion } from "framer-motion";

export function AnimatedComponent() {
  const prefersReducedMotion = useReducedMotion();
  
  const animationSettings = prefersReducedMotion 
    ? { 
        // Minimal or no animation
        transition: { duration: 0 } 
      } 
    : { 
        // Full animation
        animate: { opacity: 1, y: 0 },
        initial: { opacity: 0, y: 20 },
        transition: { duration: 0.5 }
      };
  
  return (
    <motion.div {...animationSettings}>
      Content
    </motion.div>
  );
}

Magic UI Components

BuildAppsWith uses a component library called Magic UI which is built on top of shadcn/ui. These components follow consistent patterns:
  • Composition-based: Components are composed rather than configured
  • Style-flexible: Uses Tailwind classes for styling
  • Accessible: Built with accessibility in mind
  • Form Components: Form components use React Hook Form integration

Using Magic UI Components

import { Button, Card, CardContent, CardFooter, CardHeader } from "@/components/ui/core";

export function ExampleCard() {
  return (
    <Card>
      <CardHeader>
        <h3 className="text-lg font-medium">Card Title</h3>
      </CardHeader>
      <CardContent>
        <p>Card content goes here</p>
      </CardContent>
      <CardFooter>
        <Button>Action</Button>
      </CardFooter>
    </Card>
  );
}

Performance Considerations

Component Optimization

  • Use memo sparingly and only when needed (with performance tests)
  • Avoid unnecessary re-renders by keeping state as local as possible
  • Use useCallback for functions passed to child components
  • Use useMemo for expensive computations

Code Splitting

  • Use dynamic imports for large components or libraries
  • Lazy load components not needed for initial render
  • Prioritize core functionality loading

Image Optimization

  • Always use the Image component from Next.js for automatic optimization
  • Specify width and height to prevent layout shifts
  • Use responsive images with appropriate sizes

Code Formatting and Standards

BuildAppsWith uses industry-standard tools to maintain code quality:
  • Prettier for consistent code formatting
  • ESLint for code quality analysis
  • TypeScript for type safety
All component code should be formatted using Prettier with our standard configuration. Your IDE should be configured to format on save, or you can run:
npm run format
New components should have at least 90% test coverage using Vitest and React Testing Library.