NJ Municipality Lookup
CodebaseSrc

Components

UI component library organized by feature and function. Built with React 19, TypeScript, and Tailwind CSS.

React Components (components/)

UI component library organized by feature and function. Built with React 19, TypeScript, and Tailwind CSS.

What This Directory Contains

This directory houses all React components used in the application, organized into feature-specific and shared categories. Each subdirectory focuses on a specific concern, making it easy to find and modify components.

Why Components Are Organized This Way

Components follow a feature-first organization pattern:

  1. Discoverability: Related components live together (all address-lookup components in one place)
  2. Encapsulation: Each feature owns its components, reducing cross-feature dependencies
  3. Scalability: New features get their own directories without cluttering existing ones
  4. Testability: Feature directories can have their own test files alongside components

Directory Structure

Feature Components

DirectoryPurposeKey Components
address-lookup/Address geocoding form and resultsstructured-address-input.tsx, suggestion-list.tsx, address-result.tsx
errors/Error display and boundarieserror-page.tsx, page-error-boundary.tsx
i18n/Internationalization UIlanguage-selector.tsx
navigation/App navigationmain-nav.tsx, breadcrumb.tsx
theme/Dark mode and themingtheme-provider.tsx, theme-toggle.tsx

Base Components

DirectoryPurposeKey Components
ui/shadcn/ui primitivesbutton.tsx, input.tsx, card.tsx, badge.tsx, dropdown-menu.tsx, textarea.tsx, spinner.tsx

How Components Connect

Technology Stack

  • React 19: Server Components where applicable, Client Components for interactivity
  • TypeScript: Full type safety with strict mode
  • Tailwind CSS: Utility-first styling with dark mode support
  • shadcn/ui: Accessible component primitives built on Radix UI
  • Next.js App Router: Framework integration for server/client components

Component Patterns

Server vs Client Components

// Server component (default) - renders on server, no client JS
export default function AddressResults({ address }: Props) {
  return <div>{address}</div>;
}

// Client component - interactive, runs in browser
'use client';
export default function AddressForm() {
  const [value, setValue] = useState("");
  return <input value={value} onChange={e => setValue(e.target.value)} />;
}

When to use each:

  • Server Components: Static content, data fetching, no user interaction
  • Client Components: Forms, state, event handlers, browser APIs

Composition Pattern

Components compose rather than inherit:

<AddressLookupForm>
  <StructuredAddressInput />
  <SuggestionList />
  <SubmitButton />
</AddressLookupForm>

Props Interfaces

All components have strongly typed props with JSDoc documentation:

interface AddressInputProps {
  /** Current address value */
  value: string;
  /** Called when address changes */
  onChange: (value: string) => void;
  /** Optional placeholder text */
  placeholder?: string;
  /** Disable the input */
  disabled?: boolean;
}

Styling

Tailwind Classes

Utility-first approach for consistent styling:

<div className="flex items-center gap-4 rounded-lg bg-gray-100 p-4 dark:bg-gray-800">
  <span className="text-lg font-semibold">Address</span>
</div>

Dark Mode Support

All components support dark mode via the dark: prefix:

<div className="bg-white text-black dark:bg-gray-900 dark:text-white">
  Content adapts to theme automatically
</div>

Theme state is managed by theme/theme-provider.tsx and persisted to localStorage.

CSS Variables

Colors are defined as CSS variables for consistent theming:

:root {
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --primary: 221.2 83.2% 53.3%;
}

.dark {
  --background: 222.2 84% 4.9%;
  --foreground: 210 40% 98%;
}

Accessibility

All components are built with accessibility in mind:

  • Semantic HTML: Proper heading hierarchy, form labels, button elements
  • ARIA attributes: Labels, descriptions, and roles where needed
  • Keyboard navigation: All interactive elements are keyboard accessible
  • Focus management: Visible focus indicators, logical tab order
  • Screen reader support: Meaningful announcements for dynamic content
  • Color contrast: Meets WCAG 2.2 AA standards

Testing

Component tests verify:

  • Rendering with various props
  • User interactions (clicks, typing, keyboard navigation)
  • Accessibility compliance (via axe-core)
  • Dark mode styling
  • Error states and edge cases

Tests are co-located with components or in src/__tests__/.

Adding New Components

  1. Choose the right directory: Feature-specific or ui/ for shared primitives
  2. Create the component file: feature-name/my-component.tsx
  3. Define TypeScript interface: Export Props type with JSDoc comments
  4. Implement with Tailwind: Use utility classes, support dark mode
  5. Ensure accessibility: Semantic HTML, ARIA attributes, keyboard support
  6. Write tests: Unit tests for logic, E2E for user flows
  7. Update the README: Add to the directory's README if significant

On this page