+```
+
+### Responsive Actions
+```tsx
+// Compact action buttons that work on all screen sizes
+
+
+
+
+```
+
+## Filter Bar Behavior
+
+### Mobile
+- Search input takes full width
+- Filter dropdowns stack vertically
+- Column visibility hidden
+- Clear filters button visible when filters active
+
+### Tablet+
+- Search input limited to max-width
+- Filter dropdowns in horizontal row
+- Column visibility toggle appears
+- All controls in single row
+
+## Pagination Behavior
+
+### Mobile
+- Simplified page indicator (1/5 format)
+- Compact button spacing
+- Page size selector with smaller text
+
+### Desktop
+- Full "Page 1 of 5" text
+- Comfortable button spacing
+- First/Last page buttons visible
+- Entries count with detailed information
+
+## Best Practices
+
+1. **Priority Content**: Always show the most important data on mobile
+2. **Progressive Enhancement**: Add columns as screen size increases
+3. **Touch Targets**: Maintain 44px minimum touch targets on mobile
+4. **Text Truncation**: Use `truncate` class for long text in narrow columns
+5. **Icon Usage**: Hide decorative icons on mobile, keep functional ones
+6. **Testing**: Always test at 375px (iPhone SE), 768px (iPad), and 1440px (Desktop)
\ No newline at end of file
diff --git a/docs/UI_UNIFORMITY_GUIDE.md b/docs/UI_UNIFORMITY_GUIDE.md
new file mode 100644
index 0000000..5194361
--- /dev/null
+++ b/docs/UI_UNIFORMITY_GUIDE.md
@@ -0,0 +1,324 @@
+# UI Uniformity Guide for beenvoice
+
+## Overview
+
+This guide documents the unified component system implemented across the beenvoice application to ensure consistent UI/UX patterns. The system follows a hierarchical approach where:
+
+1. **CSS Variables** (in `globals.css`) define the design tokens
+2. **UI Components** (in `components/ui`) consume these variables
+3. **Pages** use components with minimal additional styling
+
+## Design System Principles
+
+### 1. Variable-Based Theming
+All colors, spacing, and other design tokens are defined as CSS variables in `globals.css`:
+- Brand colors: `--brand-primary`, `--brand-secondary`
+- Status colors: `--status-success`, `--status-warning`, `--status-error`, `--status-info`
+- Semantic colors: `--background`, `--foreground`, `--muted`, etc.
+
+### 2. Component Composition
+Complex UI patterns are built from smaller, reusable components rather than duplicating code.
+
+### 3. Minimal Page-Level Styling
+Pages should primarily compose pre-built components and avoid custom Tailwind classes where possible.
+
+## Core Unified Components
+
+### Page Layout Components
+
+#### `PageContent`
+Wraps page content with consistent spacing:
+```tsx
+
+ {/* Page sections */}
+
+```
+
+#### `PageSection`
+Groups related content with optional title and actions:
+```tsx
+Action}
+>
+ {/* Section content */}
+
+```
+
+#### `PageGrid`
+Responsive grid layout with preset column options:
+```tsx
+
+ {/* Grid items */}
+
+```
+
+### Data Display Components
+
+#### `DataTable`
+Unified table component using @tanstack/react-table with floating card design:
+```tsx
+import { ColumnDef } from "@tanstack/react-table";
+import { DataTable, DataTableColumnHeader } from "~/components/ui/data-table";
+import { PageSection } from "~/components/ui/page-layout";
+
+const columns: ColumnDef[] = [
+ {
+ accessorKey: "name",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => {
+ const name = row.getValue("name") as string;
+ return
{name}
;
+ }
+ },
+ {
+ id: "actions",
+ cell: ({ row }) => {
+ const item = row.original;
+ return (
+
+ );
+ }
+ }
+];
+
+const filterableColumns = [
+ {
+ id: "status",
+ title: "Status",
+ options: [
+ { label: "Active", value: "active" },
+ { label: "Inactive", value: "inactive" }
+ ]
+ }
+];
+
+// Wrap in PageSection for title/description
+
+
+
+```
+
+Features:
+- **Floating Card Design**: Three separate cards for filter bar, table content, and pagination
+- **Filter Bar Card**: Minimal padding (p-3) with global search and column filters
+- **Table Content Card**: Clean borders with overflow handling
+- **Pagination Card**: Compact controls with page size selector
+- **Responsive Design**: Mobile-optimized with hidden columns on smaller screens
+- **Tight Appearance**: Compact spacing with smaller action buttons
+- **Sorting**: Visual indicators with proper arrow directions
+- **Column Visibility**: Toggle columns (hidden on mobile)
+- **Dark Mode**: Consistent styling across light/dark themes
+- **Loading States**: DataTableSkeleton component with matching card structure
+
+#### `StatsCard`
+Displays statistics with consistent styling:
+```tsx
+
+```
+
+#### `QuickActionCard`
+Interactive cards for navigation or actions:
+```tsx
+
+
+
+
+
+```
+
+### Feedback Components
+
+#### `EmptyState`
+Consistent empty state displays:
+```tsx
+}
+ title="No invoices yet"
+ description="Create your first invoice to get started"
+ action={}
+/>
+```
+
+## Component Variants
+
+### Color Variants
+Most components support these variants:
+- `default` - Uses default theme colors
+- `success` - Green color scheme for positive states
+- `warning` - Orange/amber for warnings
+- `error` - Red for errors or destructive actions
+- `info` - Blue for informational content
+
+### Size Variants
+- `sm` - Small size
+- `default` - Normal size
+- `lg` - Large size
+
+## Usage Examples
+
+### Standard Page Structure
+```tsx
+export default function ExamplePage() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+```
+
+### Consistent Button Usage
+```tsx
+// Primary actions
+
+
+// Secondary actions
+
+
+// Destructive actions
+
+
+// Icon-only actions
+
+```
+
+## Styling Guidelines
+
+### Do's
+- ✅ Use predefined color variables from globals.css
+- ✅ Compose existing UI components
+- ✅ Use semantic variant names (success, error, etc.)
+- ✅ Follow the established spacing patterns
+- ✅ Use the PageLayout components for structure
+
+### Don'ts
+- ❌ Add custom colors directly in components
+- ❌ Create one-off table or card implementations
+- ❌ Override component styles with important flags
+- ❌ Use arbitrary spacing values
+- ❌ Mix different UI patterns on the same page
+
+## Migration Checklist
+
+When updating a page to use the unified system:
+
+1. Replace custom tables with `DataTable` using @tanstack/react-table ColumnDef
+2. Replace statistics displays with `StatsCard`
+3. Replace action cards with `QuickActionCard`
+4. Wrap content in `PageContent` and `PageSection`
+5. Use `PageGrid` for responsive layouts
+6. Replace custom empty states with `EmptyState`
+7. Update buttons to use the `brand` variant for primary actions
+8. Remove page-specific color classes
+9. Use `DataTableColumnHeader` for sortable column headers
+10. Use `DataTableSkeleton` for loading states
+
+## Color System Reference
+
+### Brand Colors
+- Primary: Green (`#16a34a` / `oklch(0.646 0.222 164.25)`)
+- Secondary: Teal/cyan shades
+- Gradients: Use `bg-brand-gradient` class
+
+### Status Colors
+- Success: Green shades
+- Warning: Amber/orange shades
+- Error: Red shades
+- Info: Blue shades
+
+### Semantic Colors
+- Background: White/dark gray
+- Foreground: Black/white text
+- Muted: Gray shades for secondary content
+- Border: Light gray borders
+
+## Component Documentation
+
+For detailed component APIs and props, refer to:
+- `/src/components/ui/data-table.tsx` - TanStack Table-based data table with sorting, filtering, and pagination
+- `/src/components/ui/stats-card.tsx` - Statistics display cards
+- `/src/components/ui/quick-action-card.tsx` - Interactive action cards
+- `/src/components/ui/page-layout.tsx` - Page structure components
+
+### DataTable Props
+- `columns`: ColumnDef array from @tanstack/react-table
+- `data`: Array of data to display
+- `searchPlaceholder?`: Placeholder text for search input
+- `showColumnVisibility?`: Show/hide column visibility toggle (default: true)
+- `showPagination?`: Show/hide pagination controls (default: true)
+- `showSearch?`: Show/hide search input (default: true)
+- `pageSize?`: Number of items per page (default: 10)
+- `filterableColumns?`: Array of column filters with options
+
+Note: `title` and `description` should be provided via the wrapping `PageSection` component for consistent spacing and typography.
+
+### Responsive Table Guidelines
+- Use `hidden sm:flex` classes for icons in table cells
+- Use `hidden md:inline` for less important columns on mobile
+- Use `min-w-0` and `truncate` for text that might overflow
+- Keep action buttons small with `h-8 w-8 p-0` sizing
+- Test tables at all breakpoints (mobile, tablet, desktop)
+
+## Future Considerations
+
+1. **Form Components**: Create unified form field components
+2. **Modal Patterns**: Standardize modal and dialog usage
+3. **Loading States**: Create consistent skeleton loaders
+4. **Animation**: Define standard transition patterns
+5. **Icons**: Establish icon usage guidelines
+
+## Maintenance
+
+To maintain UI consistency:
+1. Always check for existing components before creating new ones
+2. Update this guide when adding new unified components
+3. Review PRs for adherence to these patterns
+4. Refactor pages that deviate from the system
\ No newline at end of file
diff --git a/docs/breadcrumbs-guide.md b/docs/breadcrumbs-guide.md
new file mode 100644
index 0000000..63dfbc3
--- /dev/null
+++ b/docs/breadcrumbs-guide.md
@@ -0,0 +1,198 @@
+# Dynamic Breadcrumbs Guide
+
+## Overview
+
+The breadcrumb system in beenvoice automatically generates navigation trails based on the current URL path. It features intelligent pluralization, proper capitalization, and dynamic resource name fetching.
+
+## Key Features
+
+### 1. Automatic Pluralization
+
+The breadcrumb system intelligently handles singular and plural forms:
+
+- **List pages** (e.g., `/dashboard/businesses`) → "Businesses"
+- **Detail pages** (e.g., `/dashboard/businesses/[id]`) → "Business"
+- **New pages** (e.g., `/dashboard/businesses/new`) → "Business" (singular context)
+
+### 2. Smart Capitalization
+
+All route segments are automatically capitalized:
+- `businesses` → "Businesses"
+- `clients` → "Clients"
+- `invoices` → "Invoices"
+
+### 3. Dynamic Resource Names
+
+Instead of showing UUIDs, breadcrumbs fetch and display actual resource names:
+- `/dashboard/clients/123e4567-e89b-12d3-a456-426614174000` → "Dashboard / Clients / John Doe"
+- `/dashboard/invoices/987fcdeb-51a2-43f1-b321-123456789abc` → "Dashboard / Invoices / INV-2024-001"
+
+### 4. Context-Aware Labels
+
+Special pages are handled intelligently:
+- **Edit pages**: Show the resource name instead of "Edit" as the last breadcrumb
+- **New pages**: Show "New" as the last breadcrumb
+- **Import/Export pages**: Show appropriate action labels
+
+## Implementation Details
+
+### Pluralization Rules
+
+The system uses a comprehensive pluralization utility (`src/lib/pluralize.ts`) that handles:
+
+```typescript
+// Common business terms
+business → businesses
+client → clients
+invoice → invoices
+category → categories
+company → companies
+
+// General rules
+- Words ending in 's', 'ss', 'sh', 'ch', 'x', 'z' → add 'es'
+- Words ending in consonant + 'y' → change to 'ies'
+- Words ending in 'f' or 'fe' → change to 'ves'
+- Default → add 's'
+```
+
+### Resource Fetching
+
+The breadcrumbs automatically detect resource IDs and fetch the appropriate data:
+
+```typescript
+// Detects UUID patterns in the URL
+const isUUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/
+
+// Fetches data based on resource type
+- Clients: Shows client name
+- Invoices: Shows invoice number or formatted date
+- Businesses: Shows business name
+```
+
+### Loading States
+
+While fetching resource data, breadcrumbs show loading skeletons:
+```tsx
+
+```
+
+## Usage Examples
+
+### Basic List Page
+**URL**: `/dashboard/clients`
+**Breadcrumbs**: Dashboard / Clients
+
+### Resource Detail Page
+**URL**: `/dashboard/clients/550e8400-e29b-41d4-a716-446655440000`
+**Breadcrumbs**: Dashboard / Clients / Jane Smith
+
+### Resource Edit Page
+**URL**: `/dashboard/businesses/550e8400-e29b-41d4-a716-446655440000/edit`
+**Breadcrumbs**: Dashboard / Businesses / Acme Corp
+*(Note: "Edit" is hidden when showing the resource name)*
+
+### New Resource Page
+**URL**: `/dashboard/invoices/new`
+**Breadcrumbs**: Dashboard / Invoices / New
+
+### Nested Resources
+**URL**: `/dashboard/clients/550e8400-e29b-41d4-a716-446655440000/invoices`
+**Breadcrumbs**: Dashboard / Clients / John Doe / Invoices
+
+## Customization
+
+### Adding New Resource Types
+
+To add a new resource type, update the pluralization rules:
+
+```typescript
+// In src/lib/pluralize.ts
+const PLURALIZATION_RULES = {
+ // ... existing rules
+ product: { singular: "Product", plural: "Products" },
+ service: { singular: "Service", plural: "Services" },
+};
+```
+
+### Custom Resource Labels
+
+For resources that need custom display logic, add to the breadcrumb component:
+
+```typescript
+// For invoices, show invoice number instead of ID
+if (prevSegment === "invoices") {
+ label = invoice.invoiceNumber || format(new Date(invoice.issueDate), "MMM dd, yyyy");
+}
+```
+
+### Special Segments
+
+Add new special segments to the `SPECIAL_SEGMENTS` object:
+
+```typescript
+const SPECIAL_SEGMENTS = {
+ new: "New",
+ edit: "Edit",
+ import: "Import",
+ export: "Export",
+ duplicate: "Duplicate",
+ archive: "Archive",
+};
+```
+
+## Best Practices
+
+1. **Consistent Naming**: Use consistent URL patterns across your app
+ - List pages: `/dashboard/[resource]`
+ - Detail pages: `/dashboard/[resource]/[id]`
+ - Actions: `/dashboard/[resource]/[id]/[action]`
+
+2. **Resource Fetching**: Only fetch data when needed
+ - Check resource type before enabling queries
+ - Use proper loading states
+
+3. **Error Handling**: Handle cases where resources don't exist
+ - Show fallback text or maintain UUID display
+ - Don't break the breadcrumb trail
+
+4. **Performance**: Breadcrumb queries are lightweight
+ - Only fetch minimal data (id, name)
+ - Use React Query caching effectively
+
+## API Integration
+
+The breadcrumb component integrates with tRPC routers:
+
+```typescript
+// Each resource router should have a getById method
+getById: protectedProcedure
+ .input(z.object({ id: z.string() }))
+ .query(async ({ ctx, input }) => {
+ // Return resource with at least id and name/title
+ })
+```
+
+## Accessibility
+
+- Breadcrumbs use semantic HTML with proper ARIA labels
+- Each segment is a link except the current page
+- Proper keyboard navigation support
+- Screen reader friendly with role="navigation"
+
+## Responsive Design
+
+- Breadcrumbs wrap on smaller screens
+- Font sizes adjust: `text-sm sm:text-base`
+- Separators scale appropriately
+- Loading skeletons match text size
+
+## Migration from Static Breadcrumbs
+
+If migrating from hardcoded breadcrumbs:
+
+1. Remove static breadcrumb definitions
+2. Ensure URLs follow consistent patterns
+3. Add getById methods to resource routers
+4. Update imports to use `DashboardBreadcrumbs`
+
+The dynamic system will automatically generate appropriate breadcrumbs based on the URL structure.
\ No newline at end of file
diff --git a/docs/data-table-improvements.md b/docs/data-table-improvements.md
new file mode 100644
index 0000000..41d6d4f
--- /dev/null
+++ b/docs/data-table-improvements.md
@@ -0,0 +1,154 @@
+# Data Table Improvements Summary
+
+## Overview
+
+The data table component has been significantly improved to address padding, scaling, and responsiveness issues. The tables now provide a cleaner, more compact appearance while maintaining excellent usability across all device sizes.
+
+## Key Improvements Made
+
+### 1. Tighter, More Consistent Padding
+
+**Before:**
+- Inconsistent padding across different table sections
+- Excessive vertical padding making tables feel loose
+- Cards had default py-6 padding that was too spacious
+
+**After:**
+- Table cells: `py-1.5` (mobile) / `py-2` (desktop) - reduced from `py-2.5` / `py-3`
+- Table headers: `h-9` (mobile) / `h-10` (desktop) - reduced from `h-10` / `h-12`
+- Filter/pagination cards: `py-2` with `px-3` horizontal padding
+- Table card: `p-0` to wrap content tightly
+
+### 2. Improved Responsive Column Handling
+
+**Before:**
+```tsx
+// Cells would hide but headers remained visible
+cell: ({ row }) => (
+ {row.original.phone}
+),
+```
+
+**After:**
+```tsx
+// Both header and cell hide together
+cell: ({ row }) => row.original.phone || "—",
+meta: {
+ headerClassName: "hidden md:table-cell",
+ cellClassName: "hidden md:table-cell",
+},
+```
+
+### 3. Better Small Card Appearance
+
+- Filter card: Compact `py-2` padding with proper horizontal spacing
+- Pagination card: Matching `py-2` padding for consistency
+- Content aligned properly within smaller card boundaries
+- Removed excessive gaps between elements
+- Search box now has consistent padding without extra bottom spacing on mobile
+
+### 4. Responsive Font Sizing
+
+- Base text: `text-xs` on mobile, `text-sm` on desktop
+- Consistent scaling across all table elements
+- Better readability on small screens without wasting space
+
+## Visual Comparison
+
+### Table Density
+- **Before**: ~60px per row with excessive padding
+- **After**: ~40px per row with comfortable but efficient spacing
+
+### Card Heights
+- **Filter Card**: Reduced from ~80px to ~56px
+- **Pagination Card**: Reduced from ~72px to ~48px
+- **Table Card**: Now wraps content exactly with no extra space
+- **Pagination Layout**: Entry count and pagination controls now stay on the same line on mobile
+
+## Implementation Examples
+
+### Responsive Column Definition
+```tsx
+const columns: ColumnDef[] = [
+ {
+ accessorKey: "name",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => row.original.name,
+ // Always visible
+ },
+ {
+ accessorKey: "email",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => row.original.email,
+ meta: {
+ // Hidden on mobile, visible on tablets and up
+ headerClassName: "hidden md:table-cell",
+ cellClassName: "hidden md:table-cell",
+ },
+ },
+ {
+ accessorKey: "createdAt",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => formatDate(row.getValue("createdAt")),
+ meta: {
+ // Only visible on large screens
+ headerClassName: "hidden lg:table-cell",
+ cellClassName: "hidden lg:table-cell",
+ },
+ },
+];
+```
+
+### Page Header Actions
+Page headers now properly position action buttons to the right on all screen sizes:
+
+```tsx
+
+
+
+```
+
+### Breakpoint Reference
+- `sm`: 640px and up
+- `md`: 768px and up
+- `lg`: 1024px and up
+- `xl`: 1280px and up
+
+## Benefits
+
+1. **More Data Visible**: Tighter spacing allows more rows to be visible without scrolling
+2. **Professional Appearance**: Clean, compact design suitable for business applications
+3. **Better Mobile UX**: Properly hidden columns prevent layout breaking
+4. **Consistent Styling**: All table instances now follow the same spacing rules
+5. **Performance**: CSS-only solution with no JavaScript overhead
+6. **Improved Mobile Layout**: Pagination controls stay inline with entry count on mobile
+7. **Consistent Header Actions**: Action buttons properly positioned to the right
+
+## Migration Checklist
+
+- [x] Update column definitions to use `meta` properties
+- [x] Remove inline responsive classes from cell content
+- [x] Test on actual mobile devices
+- [x] Verify touch targets remain accessible (min 44x44px)
+- [x] Check that critical data remains visible on small screens
+
+## Best Practices Going Forward
+
+1. **Column Priority**: Always keep the most important 2-3 columns visible on mobile
+2. **Content Density**: Use the tighter spacing for data tables, looser spacing for content lists
+3. **Responsive Testing**: Test at 320px, 768px, and 1024px minimum
+4. **Accessibility**: Ensure interactive elements maintain proper touch targets despite tighter spacing
\ No newline at end of file
diff --git a/docs/data-table-responsive-guide.md b/docs/data-table-responsive-guide.md
new file mode 100644
index 0000000..b8bc32f
--- /dev/null
+++ b/docs/data-table-responsive-guide.md
@@ -0,0 +1,246 @@
+# Data Table Responsive Design Guide
+
+## Overview
+
+The data table component has been updated to provide better responsive behavior, consistent padding, and proper scaling across different screen sizes.
+
+## Key Improvements
+
+### 1. Consistent Padding
+- Uniform padding across all table elements
+- Responsive padding that scales with screen size
+- Cards now have consistent spacing (p-3 on mobile, p-4 on desktop)
+
+### 2. Proper Responsive Column Hiding
+- Columns now properly hide both headers and cells on smaller screens
+- Uses `meta` properties for clean column visibility control
+- No more orphaned headers on mobile devices
+
+### 3. Better Scaling
+- Font sizes adapt to screen size (text-xs on mobile, text-sm on desktop)
+- Button sizes and spacing adjust appropriately
+- Pagination controls are optimized for touch devices
+
+## Using Responsive Columns
+
+### Basic Column Definition
+
+```tsx
+const columns: ColumnDef[] = [
+ {
+ accessorKey: "name",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => row.original.name,
+ // Always visible on all screen sizes
+ },
+ {
+ accessorKey: "phone",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => row.original.phone || "—",
+ meta: {
+ // Hidden on mobile, visible on md screens and up
+ headerClassName: "hidden md:table-cell",
+ cellClassName: "hidden md:table-cell",
+ },
+ },
+ {
+ accessorKey: "address",
+ header: "Address",
+ cell: ({ row }) => formatAddress(row.original),
+ meta: {
+ // Hidden on mobile and tablet, visible on lg screens and up
+ headerClassName: "hidden lg:table-cell",
+ cellClassName: "hidden lg:table-cell",
+ },
+ },
+ {
+ accessorKey: "createdAt",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => formatDate(row.getValue("createdAt")),
+ meta: {
+ // Only visible on xl screens and up
+ headerClassName: "hidden xl:table-cell",
+ cellClassName: "hidden xl:table-cell",
+ },
+ },
+];
+```
+
+### Responsive Breakpoints
+
+- **Always visible**: No meta properties needed
+- **md and up** (768px+): `hidden md:table-cell`
+- **lg and up** (1024px+): `hidden lg:table-cell`
+- **xl and up** (1280px+): `hidden xl:table-cell`
+
+## Complex Cell Content
+
+For cells with complex content that should partially hide on mobile:
+
+```tsx
+{
+ accessorKey: "client",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => {
+ const client = row.original;
+ return (
+
+ {/* Icon hidden on mobile, shown on sm screens */}
+
+
+
+
+
{client.name}
+ {/* Secondary info can be hidden on very small screens if needed */}
+
+ {client.email || "—"}
+
+
+
+ );
+ },
+}
+```
+
+## Best Practices
+
+### 1. Priority-Based Column Hiding
+- Always show the most important columns (e.g., name, status, primary action)
+- Hide supplementary information first (e.g., dates, secondary details)
+- Consider hiding decorative elements (icons) on mobile while keeping text
+
+### 2. Mobile-First Design
+- Ensure at least 2-3 columns are visible on mobile
+- Test on actual devices, not just browser dev tools
+- Consider the minimum viable information for each row
+
+### 3. Touch-Friendly Actions
+- Action buttons should be at least 44x44px on mobile
+- Use appropriate spacing between interactive elements
+- Consider grouping actions in a dropdown on mobile
+
+### 4. Performance
+- The responsive system uses CSS classes, so there's no JavaScript overhead
+- Column visibility is handled by Tailwind's responsive utilities
+- No re-renders needed when resizing
+
+## Migration Guide
+
+If you have existing data tables, update them as follows:
+
+### Before:
+```tsx
+{
+ accessorKey: "phone",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => (
+ {row.original.phone || "—"}
+ ),
+}
+```
+
+### After:
+```tsx
+{
+ accessorKey: "phone",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => row.original.phone || "—",
+ meta: {
+ headerClassName: "hidden md:table-cell",
+ cellClassName: "hidden md:table-cell",
+ },
+}
+```
+
+## Common Patterns
+
+### Status Columns
+Always visible, use color and icons to convey information efficiently:
+
+```tsx
+{
+ accessorKey: "status",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => ,
+}
+```
+
+### Date Columns
+Often hidden on mobile, show relative dates when space is limited:
+
+```tsx
+{
+ accessorKey: "createdAt",
+ header: ({ column }) => (
+
+ ),
+ cell: ({ row }) => {
+ const date = row.getValue("createdAt") as Date;
+ return (
+ <>
+ {/* Full date on larger screens */}
+ {formatDate(date)}
+ {/* Relative date on mobile */}
+ {formatRelativeDate(date)}
+ >
+ );
+ },
+}
+```
+
+### Action Columns
+Keep actions accessible but space-efficient:
+
+```tsx
+{
+ id: "actions",
+ cell: ({ row }) => {
+ const item = row.original;
+ return (
+
+ {/* Show individual buttons on larger screens */}
+
+
+
+
+ {/* Dropdown menu on mobile */}
+
+
+
+
+ );
+ },
+}
+```
+
+## Testing Checklist
+
+- [ ] Table is readable on 320px wide screens
+- [ ] Headers and cells align properly at all breakpoints
+- [ ] Touch targets are at least 44x44px on mobile
+- [ ] Horizontal scrolling works smoothly when needed
+- [ ] Critical information is always visible
+- [ ] Loading states work correctly
+- [ ] Empty states are responsive
+- [ ] Pagination controls are touch-friendly
+
+## Accessibility Notes
+
+- Hidden columns are properly hidden from screen readers
+- Table remains navigable with keyboard at all screen sizes
+- Sort controls are accessible on mobile
+- Focus indicators are visible on all interactive elements
\ No newline at end of file
diff --git a/docs/forms-guide.md b/docs/forms-guide.md
new file mode 100644
index 0000000..8a0a6bd
--- /dev/null
+++ b/docs/forms-guide.md
@@ -0,0 +1,279 @@
+# Forms Improvement Guide
+
+## Overview
+
+The business and client creation/editing forms have been significantly improved with better organization, shared components, enhanced validation, and improved user experience.
+
+## Key Improvements
+
+### 1. Shared Components & Utilities
+
+#### Address Form Component (`src/components/ui/address-form.tsx`)
+A reusable address form component that handles:
+- Country-aware formatting (US ZIP codes, Canadian postal codes)
+- State dropdown for US addresses, text input for other countries
+- Popular countries listed first in country dropdown
+- Automatic field adjustments based on country selection
+
+```tsx
+
+```
+
+#### Form Constants & Utilities (`src/lib/form-constants.ts`)
+Centralized location for:
+- US states list with proper formatting
+- All countries with ISO codes
+- Popular countries for quick selection
+- Format functions for phone, postal codes, tax IDs, and URLs
+- Validation utilities and messages
+
+### 2. Enhanced Form Validation
+
+#### Real-time Validation
+- Errors clear as soon as user starts typing
+- Field-specific validation messages
+- Visual feedback with red borders on invalid fields
+
+#### Smart Validation Rules
+- Email: Proper email format checking
+- Phone: US phone number format validation
+- Address: Required fields only if any address field is filled
+- URL: Automatic https:// prefix addition
+
+```typescript
+// Example validation
+if (formData.email && !isValidEmail(formData.email)) {
+ newErrors.email = VALIDATION_MESSAGES.email;
+}
+```
+
+### 3. Better Form Organization
+
+#### Card-based Sections
+Forms are now organized into logical sections using cards:
+- **Basic Information**: Core fields like name, tax ID
+- **Contact Information**: Email, phone, website
+- **Address**: Complete address form with smart country handling
+- **Settings**: Business-specific settings like default business flag
+
+#### Consistent Layout
+- Maximum width container for better readability
+- Responsive grid layouts that stack on mobile
+- Proper spacing between sections
+- Clear visual hierarchy
+
+### 4. Improved User Experience
+
+#### Loading States
+- Skeleton loader while fetching data in edit mode
+- Disabled form fields during submission
+- Loading spinner in submit button
+
+#### Unsaved Changes Warning
+```typescript
+const handleCancel = () => {
+ if (isDirty) {
+ const confirmed = window.confirm(
+ "You have unsaved changes. Are you sure you want to leave?"
+ );
+ if (!confirmed) return;
+ }
+ router.push("/dashboard/businesses");
+};
+```
+
+#### Smart Field Formatting
+- Phone numbers: Auto-format as (555) 123-4567
+- Tax ID: Auto-format as 12-3456789
+- Postal codes: Format based on country (US vs Canadian)
+- Website URLs: Auto-add https:// if missing
+
+### 5. Responsive Design
+
+#### Mobile Optimizations
+- Form sections stack vertically on small screens
+- Touch-friendly input sizes
+- Proper button positioning
+- Readable font sizes
+
+#### Desktop Enhancements
+- Two-column layouts for related fields
+- Optimal reading width
+- Side-by-side form actions
+
+### 6. Code Reusability
+
+#### Shared Between Business & Client Forms
+- Address form component
+- Validation logic
+- Format functions
+- Constants (states, countries)
+- Error handling patterns
+
+#### TypeScript Interfaces
+```typescript
+interface FormData {
+ name: string;
+ email: string;
+ phone: string;
+ // ... other fields
+}
+
+interface FormErrors {
+ name?: string;
+ email?: string;
+ // ... validation errors
+}
+```
+
+## Usage Examples
+
+### Basic Form Implementation
+```tsx
+export function BusinessForm({ businessId, mode }: BusinessFormProps) {
+ const [formData, setFormData] = useState(initialFormData);
+ const [errors, setErrors] = useState({});
+ const [isSubmitting, setIsSubmitting] = useState(false);
+ const [isDirty, setIsDirty] = useState(false);
+
+ // Handle input changes
+ const handleInputChange = (field: string, value: string | boolean) => {
+ setFormData((prev) => ({ ...prev, [field]: value }));
+ setIsDirty(true);
+
+ // Clear error when user types
+ if (errors[field as keyof FormErrors]) {
+ setErrors((prev) => ({ ...prev, [field]: undefined }));
+ }
+ };
+
+ // Validate and submit
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault();
+
+ if (!validateForm()) {
+ toast.error("Please correct the errors in the form");
+ return;
+ }
+
+ // Submit logic...
+ };
+}
+```
+
+### Field with Icon and Validation
+```tsx
+
+```
+
+## Best Practices
+
+### 1. Form State Management
+- Use controlled components for all inputs
+- Track dirty state for unsaved changes warnings
+- Clear errors when user corrects them
+- Disable form during submission
+
+### 2. Validation Strategy
+- Validate on submit, not on blur (less annoying)
+- Clear errors immediately when user starts fixing them
+- Show field-level errors below each input
+- Use consistent error message format
+
+### 3. Accessibility
+- Proper label associations with htmlFor
+- Required field indicators
+- Error messages linked to fields
+- Keyboard navigation support
+- Focus management
+
+### 4. Performance
+- Memoize expensive computations
+- Use debouncing for format functions if needed
+- Lazy load country lists
+- Optimize re-renders with proper state management
+
+## Migration Guide
+
+### From Old Forms
+1. Replace inline state/country arrays with imported constants
+2. Use `AddressForm` component instead of individual address fields
+3. Apply format functions from `form-constants.ts`
+4. Update validation to use shared utilities
+5. Wrap sections in Card components
+6. Add loading and dirty state tracking
+
+### Example Migration
+```tsx
+// Before
+const US_STATES = [
+ { value: "AL", label: "Alabama" },
+ // ... duplicated in each form
+];
+
+// After
+import { US_STATES, formatPhoneNumber } from "~/lib/form-constants";
+import { AddressForm } from "~/components/ui/address-form";
+```
+
+## Future Enhancements
+
+### Planned Improvements
+1. **Field-level permissions**: Disable fields based on user role
+2. **Auto-save**: Save draft as user types
+3. **Multi-step forms**: Break long forms into steps
+4. **Conditional fields**: Show/hide fields based on other values
+5. **Bulk operations**: Create multiple records at once
+6. **Import from templates**: Pre-fill common business types
+
+### Extensibility
+The form system is designed to be easily extended:
+- Add new format functions to `form-constants.ts`
+- Create additional shared form components
+- Extend validation rules as needed
+- Add new field types with consistent patterns
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Validation not working**: Ensure field names match FormErrors interface
+2. **Format function not applying**: Check that onChange uses the format function
+3. **Country dropdown not searching**: Verify SearchableSelect has search enabled
+4. **Address validation failing**: Check if country field affects validation rules
+
+### Debug Tips
+- Use React DevTools to inspect form state
+- Check console for validation errors
+- Verify API responses match expected format
+- Test with different country selections
\ No newline at end of file
diff --git a/package.json b/package.json
index 43fc857..bfcf56c 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"@libsql/client": "^0.14.0",
"@radix-ui/react-alert-dialog": "^1.1.14",
"@radix-ui/react-checkbox": "^1.3.2",
+ "@radix-ui/react-collapsible": "^1.1.11",
"@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-label": "^2.1.7",
@@ -42,10 +43,12 @@
"@radix-ui/react-select": "^2.2.5",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "^1.2.3",
+ "@radix-ui/react-switch": "^1.2.5",
"@radix-ui/react-tabs": "^1.1.12",
"@react-pdf/renderer": "^4.3.0",
"@t3-oss/env-nextjs": "^0.12.0",
"@tanstack/react-query": "^5.69.0",
+ "@tanstack/react-table": "^8.21.3",
"@trpc/client": "^11.0.0",
"@trpc/react-query": "^11.0.0",
"@trpc/server": "^11.0.0",
@@ -59,7 +62,7 @@
"file-saver": "^2.0.5",
"lucide": "^0.525.0",
"lucide-react": "^0.525.0",
- "next": "^15.2.3",
+ "next": "^15.4.1",
"next-auth": "5.0.0-beta.25",
"react": "^19.0.0",
"react-day-picker": "^9.8.0",
@@ -101,6 +104,8 @@
"@tailwindcss/oxide",
"better-sqlite3",
"core-js",
+ "esbuild",
+ "sharp",
"unrs-resolver"
]
}
diff --git a/src/app/auth/register/page.tsx b/src/app/auth/register/page.tsx
index 0310c3f..c74077d 100644
--- a/src/app/auth/register/page.tsx
+++ b/src/app/auth/register/page.tsx
@@ -49,25 +49,25 @@ function RegisterForm() {
}
return (
-
+
{/* Logo and Welcome */}
-
+
Join beenvoice
-
+
Create your account to get started
{/* Registration Form */}
-
+
-
+
Create Account
@@ -77,7 +77,7 @@ function RegisterForm() {
-
+
-
+
-
+
-
+
-
+
Must be at least 6 characters
@@ -152,7 +152,7 @@ function RegisterForm() {
-
+
Already have an account?{" "}
-
+
Start invoicing like a pro
-
+
✓ Free to start✓ No credit card✓ Cancel anytime
@@ -185,17 +185,15 @@ export default function RegisterPage() {
return (
+