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
5.6 KiB
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:
// 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:
// 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:
<Skeleton className="inline-block h-5 w-24 align-middle" />
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:
// 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:
// 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:
const SPECIAL_SEGMENTS = {
new: "New",
edit: "Edit",
import: "Import",
export: "Export",
duplicate: "Duplicate",
archive: "Archive",
};
Best Practices
-
Consistent Naming: Use consistent URL patterns across your app
- List pages:
/dashboard/[resource] - Detail pages:
/dashboard/[resource]/[id] - Actions:
/dashboard/[resource]/[id]/[action]
- List pages:
-
Resource Fetching: Only fetch data when needed
- Check resource type before enabling queries
- Use proper loading states
-
Error Handling: Handle cases where resources don't exist
- Show fallback text or maintain UUID display
- Don't break the breadcrumb trail
-
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:
// 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:
- Remove static breadcrumb definitions
- Ensure URLs follow consistent patterns
- Add getById methods to resource routers
- Update imports to use
DashboardBreadcrumbs
The dynamic system will automatically generate appropriate breadcrumbs based on the URL structure.