mirror of
https://github.com/soconnor0919/beenvoice.git
synced 2025-12-13 17:44:44 -05:00
feat: polish invoice editor and viewer UI with custom NumberInput
component - Create custom NumberInput component with increment/decrement buttons - Add 0.25 step increments for hours and rates in invoice forms - Implement emerald-themed styling with hover states and accessibility - Add keyboard navigation (arrow keys) and proper ARIA support - Condense invoice editor tax/totals section into efficient grid layout - Update client dropdown to single-line format (name + email) - Add fixed footer with floating action bar pattern matching business forms - Redesign invoice viewer with better space utilization and visual hierarchy - Maintain professional appearance and consistent design system - Fix Next.js 15 params Promise handling across all invoice pages - Resolve TypeScript compilation errors and type-only imports
This commit is contained in:
324
docs/UI_UNIFORMITY_GUIDE.md
Normal file
324
docs/UI_UNIFORMITY_GUIDE.md
Normal file
@@ -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
|
||||
<PageContent spacing="default">
|
||||
{/* Page sections */}
|
||||
</PageContent>
|
||||
```
|
||||
|
||||
#### `PageSection`
|
||||
Groups related content with optional title and actions:
|
||||
```tsx
|
||||
<PageSection
|
||||
title="Section Title"
|
||||
description="Optional description"
|
||||
actions={<Button>Action</Button>}
|
||||
>
|
||||
{/* Section content */}
|
||||
</PageSection>
|
||||
```
|
||||
|
||||
#### `PageGrid`
|
||||
Responsive grid layout with preset column options:
|
||||
```tsx
|
||||
<PageGrid columns={3} gap="default">
|
||||
{/* Grid items */}
|
||||
</PageGrid>
|
||||
```
|
||||
|
||||
### 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<DataType>[] = [
|
||||
{
|
||||
accessorKey: "name",
|
||||
header: ({ column }) => (
|
||||
<DataTableColumnHeader column={column} title="Name" />
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
const name = row.getValue("name") as string;
|
||||
return <div className="font-medium">{name}</div>;
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
cell: ({ row }) => {
|
||||
const item = row.original;
|
||||
return (
|
||||
<Button variant="ghost" size="sm" className="h-8 w-8 p-0">
|
||||
<Edit className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const filterableColumns = [
|
||||
{
|
||||
id: "status",
|
||||
title: "Status",
|
||||
options: [
|
||||
{ label: "Active", value: "active" },
|
||||
{ label: "Inactive", value: "inactive" }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// Wrap in PageSection for title/description
|
||||
<PageSection
|
||||
title="Table Title"
|
||||
description="Optional description"
|
||||
>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={data}
|
||||
searchPlaceholder="Search by name..."
|
||||
filterableColumns={filterableColumns}
|
||||
/>
|
||||
</PageSection>
|
||||
```
|
||||
|
||||
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
|
||||
<StatsCard
|
||||
title="Total Revenue"
|
||||
value="$10,000"
|
||||
icon={DollarSign}
|
||||
description="From 50 invoices"
|
||||
variant="success"
|
||||
/>
|
||||
```
|
||||
|
||||
#### `QuickActionCard`
|
||||
Interactive cards for navigation or actions:
|
||||
```tsx
|
||||
<QuickActionCard
|
||||
title="Create Invoice"
|
||||
description="Start a new invoice"
|
||||
icon={Plus}
|
||||
variant="success"
|
||||
>
|
||||
<Link href="/invoices/new">
|
||||
<div className="h-full w-full" />
|
||||
</Link>
|
||||
</QuickActionCard>
|
||||
```
|
||||
|
||||
### Feedback Components
|
||||
|
||||
#### `EmptyState`
|
||||
Consistent empty state displays:
|
||||
```tsx
|
||||
<EmptyState
|
||||
icon={<FileText className="h-8 w-8" />}
|
||||
title="No invoices yet"
|
||||
description="Create your first invoice to get started"
|
||||
action={<Button>Create Invoice</Button>}
|
||||
/>
|
||||
```
|
||||
|
||||
## 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 (
|
||||
<PageContent>
|
||||
<PageHeader
|
||||
title="Page Title"
|
||||
description="Page description"
|
||||
variant="gradient"
|
||||
>
|
||||
<Button variant="brand">
|
||||
Primary Action
|
||||
</Button>
|
||||
</PageHeader>
|
||||
|
||||
<PageSection>
|
||||
<PageGrid columns={4}>
|
||||
<StatsCard {...statsProps} />
|
||||
</PageGrid>
|
||||
</PageSection>
|
||||
|
||||
<PageSection
|
||||
title="Data Table Title"
|
||||
description="Table description"
|
||||
>
|
||||
<DataTable {...tableProps} />
|
||||
</PageSection>
|
||||
</PageContent>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Consistent Button Usage
|
||||
```tsx
|
||||
// Primary actions
|
||||
<Button variant="brand">Create New</Button>
|
||||
|
||||
// Secondary actions
|
||||
<Button variant="outline">Cancel</Button>
|
||||
|
||||
// Destructive actions
|
||||
<Button variant="destructive">Delete</Button>
|
||||
|
||||
// Icon-only actions
|
||||
<Button variant="ghost" size="icon">
|
||||
<Edit className="h-4 w-4" />
|
||||
</Button>
|
||||
```
|
||||
|
||||
## 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
|
||||
Reference in New Issue
Block a user