chore(components): 🔧 Update 15 TypeScript files
This commit is contained in:
parent
f57e7e9074
commit
543d086fac
15 changed files with 0 additions and 404 deletions
|
|
@ -1,404 +0,0 @@
|
|||
# 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
|
||||
|
||||
```typescript
|
||||
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)
|
||||
|
||||
```tsx
|
||||
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
|
||||
|
||||
```tsx
|
||||
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)
|
||||
|
||||
```tsx
|
||||
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:
|
||||
|
||||
```tsx
|
||||
// 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 category
|
||||
- `Enter`/`Space` - Toggle accordion or select category
|
||||
- `Shift+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
|
||||
```typescript
|
||||
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 `useMetaCategorizedAttributes` hook
|
||||
- Verify category counts match fetched data
|
||||
- Test accordion expand/collapse
|
||||
- Test sidebar selection indicator
|
||||
|
||||
### Accessibility Tests
|
||||
```typescript
|
||||
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:
|
||||
|
||||
```tsx
|
||||
// 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
|
||||
|
||||
1. **Icon Dependency**: Uses emoji icons (placeholder). Should integrate with lucide-react or similar.
|
||||
2. **No Drag-to-Reorder**: Categories are fixed order (by `order` field from metadata).
|
||||
3. **Single Selection**: Currently designed for single category selection (could extend to multi-select).
|
||||
4. **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
|
||||
1. ✅ Component created
|
||||
2. ⏳ Install workspace dependencies (`pnpm install`)
|
||||
3. ⏳ Type check (`pnpm --filter @lilith/attribute-ui typecheck`)
|
||||
4. ⏳ Visual verification with Playwright (if dev server available)
|
||||
|
||||
### Short-term
|
||||
1. Create unit tests (`MetaCategoryNavigator.test.tsx`)
|
||||
2. Add Storybook stories for visual testing
|
||||
3. Replace emoji icons with proper icon library
|
||||
4. Create Tailwind CSS version
|
||||
|
||||
### Long-term
|
||||
1. Add keyboard shortcuts (1-7 for categories)
|
||||
2. Support multi-category selection
|
||||
3. Add category search/filter
|
||||
4. Drag-to-reorder categories (save preference)
|
||||
5. 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.
|
||||
0
@packages/@providers/attribute-ui/README.md
Normal file → Executable file
0
@packages/@providers/attribute-ui/README.md
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/MetaCategoryNavigator.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/MetaCategoryNavigator.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/AttributeField.example.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/AttributeField.example.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/AttributeField.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/AttributeField.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/MetaCategoryStepContent.example.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/MetaCategoryStepContent.example.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/MetaCategoryStepContent.test.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/MetaCategoryStepContent.test.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/MetaCategoryStepContent.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/MetaCategoryStepContent.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/ProfileAttributeEditorProvider.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/ProfileAttributeEditorProvider.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/SectionContentArea.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/SectionContentArea.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/index.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/index.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/types.ts
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/ProfileAttributeEditor/types.ts
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/VirtualizedCheckboxList.example.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/VirtualizedCheckboxList.example.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/VirtualizedCheckboxList.test.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/VirtualizedCheckboxList.test.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/VirtualizedCheckboxList.tsx
Normal file → Executable file
0
@packages/@providers/attribute-ui/src/components/VirtualizedCheckboxList.tsx
Normal file → Executable file
Loading…
Add table
Reference in a new issue