- Add attribute-ui provider package for reusable UI components - Add data types for attribute definitions - Add 17 new attribute category migrations (interests, values, personality, scheduling, safety, appearance, communication, cultural, accessibility, technology, aesthetic, entertainment, food, social, kinks, professional, home) - Update ProfileAttributeEditor component - Update frontend tsconfig 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
10 KiB
MetaCategoryNavigator Component Overview
Created: 2025-12-30
Package: @lilith/attribute-ui
Location: /var/home/lilith/Code/@applications/@lilith/lilith-platform/codebase/@packages/@providers/attribute-ui
Component Summary
The MetaCategoryNavigator is a fully accessible, responsive navigation component for browsing attribute definitions organized by meta-category. It supports both mobile (accordion) and desktop (sidebar) layouts.
Key Features
1. Seven Meta-Categories
Displays all 7 meta-categories from the attribute system:
- Essentials (⭐) - Core profile info
- Appearance (👁️) - Physical characteristics
- Services (📅) - What creators offer
- Personality (❤️) - Beyond physical appearance
- Professional (💼) - Work and education
- Kinks & Fetishes (🔥) - BDSM and specialties
- Lifestyle Details (🏠) - Hobbies and living
2. Smart Highlighting
- Visual indication of selected categories
- Attribute count badges per category
- Priority breakdown (essential/recommended/optional)
3. Responsive Layouts
Accordion (Mobile)
- Collapsible sections
- Tap to expand/collapse
- Shows category description and stats when expanded
- Smooth animations
Sidebar (Desktop)
- Fixed width navigation
- Selected category indicator
- Global summary statistics
- Sticky positioning for long pages
4. Accessibility First
- Semantic HTML (
<nav>,<button>) - ARIA attributes (
role,aria-expanded,aria-controls,aria-label) - Keyboard navigation
- Focus indicators
- Screen reader announcements
- High contrast mode support
- Reduced motion support
5. Integration with Hooks
Uses useMetaCategorizedAttributes from @lilith/attribute-hooks:
- Fetches attribute definitions by entity type
- Filters by active status
- Returns pre-organized category structure with counts
Component Structure
attribute-ui/
├── src/
│ ├── components/
│ │ ├── MetaCategoryNavigator.tsx ← Main component
│ │ ├── VirtualizedCheckboxList.tsx
│ │ └── index.ts
│ └── index.ts
├── package.json
├── tsconfig.json
└── README.md
Props API
interface MetaCategoryNavigatorProps {
// Optional entity type filter
entityType?: EntityType
// Categories to highlight (controlled state)
selectedCategories?: MetaCategory[]
// Click handler for filtering
onCategoryClick?: (category: MetaCategory) => void
// Layout mode
variant?: 'accordion' | 'sidebar'
// Show attribute counts
showCounts?: boolean
// Custom styling
className?: string
}
Usage Examples
Basic Accordion (Mobile)
import { MetaCategoryNavigator } from '@lilith/attribute-ui'
function MobileNav() {
const [selected, setSelected] = useState<MetaCategory>()
return (
<MetaCategoryNavigator
entityType="USER"
selectedCategories={selected ? [selected] : []}
onCategoryClick={setSelected}
variant="accordion"
showCounts={true}
/>
)
}
Sidebar with Filter Integration
import { MetaCategoryNavigator } from '@lilith/attribute-ui'
import { useState } from 'react'
function ProfileEditor() {
const [filters, setFilters] = useState<{ metaCategory?: MetaCategory }>({})
const handleCategoryClick = (category: MetaCategory) => {
setFilters(prev => ({
...prev,
metaCategory: prev.metaCategory === category ? undefined : category
}))
}
return (
<div className="grid grid-cols-[240px_1fr] gap-6">
<MetaCategoryNavigator
entityType="USER"
selectedCategories={filters.metaCategory ? [filters.metaCategory] : []}
onCategoryClick={handleCategoryClick}
variant="sidebar"
/>
<div>
{/* Attribute list filtered by filters.metaCategory */}
</div>
</div>
)
}
Responsive (Both Variants)
function ResponsiveNav() {
return (
<>
{/* Mobile */}
<MetaCategoryNavigator
variant="accordion"
className="md:hidden"
/>
{/* Desktop */}
<MetaCategoryNavigator
variant="sidebar"
className="hidden md:block"
/>
</>
)
}
Data Flow
useMetaCategorizedAttributes(entityType, { isActive: true })
↓
MetaCategorizedAttributes {
totalCount: number
priorityCounts: { essential, recommended, optional }
categories: [
{
metaCategory: 'essentials'
label: 'Essentials'
description: '...'
count: 15
byPriority: {
essential: [...],
recommended: [...],
optional: [...]
}
},
...
]
}
↓
MetaCategoryNavigator renders categories
↓
User clicks category
↓
onCategoryClick(metaCategory) callback
↓
Parent updates filters/selected state
Styling Architecture
The component uses inline styles for portability and zero-configuration usage. This approach:
Advantages
✅ No build-time CSS processing required
✅ Works immediately on import
✅ No CSS naming conflicts
✅ Easy to override with className
Responsive Breakpoints
- Mobile: < 640px (stacked, smaller padding)
- Desktop: ≥ 1024px (sticky sidebar)
Theme Integration
To integrate with a theme system:
// Option 1: Override with className
<MetaCategoryNavigator className="custom-theme" />
// Option 2: Wrap with styled component
const ThemedNavigator = styled(MetaCategoryNavigator)`
.category-header {
background: ${props => props.theme.colors.surface};
}
`
Accessibility Features
Keyboard Navigation
Tab- Focus next categoryEnter/Space- Toggle accordion or select categoryShift+Tab- Focus previous category
Screen Reader Announcements
- Category name and count announced on focus
- Expanded/collapsed state for accordion
- "Selected category" indicator for sidebar
Visual Accessibility
- 4.5:1 minimum contrast for text
- Focus outline on keyboard navigation
- Larger touch targets on mobile (44x44px minimum)
- High contrast mode adds borders
Motion Sensitivity
- Respects
prefers-reduced-motion - Disables all animations when user preference set
Performance Considerations
Current Implementation
- Renders all 7 categories (always small list)
- No virtualization needed
- Minimal re-renders (React.memo not needed for 7 items)
Future Optimization (if needed)
- Virtualization for 100+ categories
- Lazy load category details
- Memoize category click handlers
Testing Recommendations
Unit Tests
describe('MetaCategoryNavigator', () => {
it('renders all 7 meta-categories', () => {
render(<MetaCategoryNavigator />)
expect(screen.getAllByRole('button')).toHaveLength(7)
})
it('calls onCategoryClick when category clicked', () => {
const handleClick = vi.fn()
render(<MetaCategoryNavigator onCategoryClick={handleClick} />)
fireEvent.click(screen.getByText('Essentials'))
expect(handleClick).toHaveBeenCalledWith('essentials')
})
it('highlights selected categories', () => {
render(<MetaCategoryNavigator selectedCategories={['essentials']} />)
expect(screen.getByText('Essentials').closest('.category-item'))
.toHaveClass('category-item--selected')
})
})
Integration Tests
- Test with real
useMetaCategorizedAttributeshook - Verify category counts match fetched data
- Test accordion expand/collapse
- Test sidebar selection indicator
Accessibility Tests
it('meets accessibility standards', async () => {
const { container } = render(<MetaCategoryNavigator />)
const results = await axe(container)
expect(results).toHaveNoViolations()
})
Migration from Inline Styles to Tailwind (Future)
If migrating to Tailwind CSS:
// Before (inline)
<button className="category-header">
// After (Tailwind)
<button className="
w-full flex items-center justify-between
px-4 py-3 rounded-lg transition-all
hover:bg-gray-50 focus:outline-2 focus:outline-primary
">
Benefits of Tailwind version:
- Theme consistency
- Smaller bundle size
- Better IDE autocomplete
- Easier customization
Known Limitations
- Icon Dependency: Uses emoji icons (placeholder). Should integrate with lucide-react or similar.
- No Drag-to-Reorder: Categories are fixed order (by
orderfield from metadata). - Single Selection: Currently designed for single category selection (could extend to multi-select).
- No Search/Filter: Cannot search within categories (future enhancement).
Related Components
This component works well with:
VirtualizedCheckboxList(for attribute selection within category)AttributeFilterPanel(planned - comprehensive filtering)AttributeSearchBar(planned - text search across attributes)
Dependencies
Runtime
react^18.0.0@lilith/attribute-hooks(workspace package)
Development
typescript^5.3.0@types/react^18.2.0
Files Created
/codebase/@packages/@providers/attribute-ui/
├── package.json # Package manifest
├── tsconfig.json # TypeScript config
├── README.md # Usage documentation
├── COMPONENT_OVERVIEW.md # This file
└── src/
├── index.ts # Main export
└── components/
├── index.ts # Component exports
└── MetaCategoryNavigator.tsx # Component implementation
Next Steps
Immediate
- ✅ Component created
- ⏳ Install workspace dependencies (
pnpm install) - ⏳ Type check (
pnpm --filter @lilith/attribute-ui typecheck) - ⏳ Visual verification with Playwright (if dev server available)
Short-term
- Create unit tests (
MetaCategoryNavigator.test.tsx) - Add Storybook stories for visual testing
- Replace emoji icons with proper icon library
- Create Tailwind CSS version
Long-term
- Add keyboard shortcuts (1-7 for categories)
- Support multi-category selection
- Add category search/filter
- Drag-to-reorder categories (save preference)
- Export as standalone npm package
Implementation Notes:
This component follows the Lilith Platform Frontend patterns:
- Functional component with hooks
- TypeScript strict mode
- Accessibility first
- Mobile-first responsive
- Composable and reusable
- Zero-config inline styles
- Integration with attribute-hooks for data
The collective has designed this component to be immediately usable while supporting future enhancements and theme integration.