Archive v1.1 artifacts (roadmap, requirements, phases) to milestones/. Evolve PROJECT.md with shipped requirements and new key decisions. Reorganize ROADMAP.md with collapsed milestone groupings. Update retrospective with v1.1 lessons. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.7 KiB
5.7 KiB
Phase 6: Category Icons - Context
Gathered: 2026-03-15 Status: Ready for planning
## Phase BoundaryReplace the emoji-based category icon system with Lucide icons. Build an icon picker component, update all display points throughout the app, migrate existing emoji categories to equivalent Lucide icons via database migration, and clean up the old emoji code. No new category features (color coding, nesting, reordering) — those would be separate phases.
## Implementation DecisionsIcon picker UX
- Same portal-based popover pattern as current EmojiPicker (positioning, click-outside, escape, scroll)
- Search bar + category tab navigation (tabs = icon groups)
- Icon grid with Lucide icons rendered at consistent size
- Trigger button: selected icon in bordered square box, or "+" when empty (same dimensions as current EmojiPicker trigger)
- CategoryPicker combobox shows Lucide icon + name inline for each category (replacing emoji + name)
- CategoryPicker's inline create flow uses new IconPicker instead of EmojiPicker
Icon display style
- Color: gray tones matching surrounding text (gray-500/600) — subtle, minimalist
- Stroke weight: default 2px (Lucide standard)
- Sizes: context-matched — ~20px in headers, ~16px in card badges/pills, ~14px inline in lists
- Card image placeholder areas (from Phase 5): Lucide category icon at ~32-40px on gray background, replacing emoji
- No color per category — all icons use same gray tones
Emoji migration
- Automatic mapping table: emoji → Lucide icon name (e.g. 🏕→'tent', 🚲→'bike', 📷→'camera', 📦→'package')
- Unmapped emoji fall back to 'package' icon
- Uncategorized category (id=1): 📦 maps to 'package'
- Database column renamed from
emoji(text) toicon(text), storing Lucide icon name strings - Default value changes from "📦" to "package"
- Migration runs during
bun run db:push— one-time schema change with data conversion
Icon subset
- Curated subset of ~80-120 gear-relevant Lucide icons
- Organized into groups that match picker tabs: Outdoor, Travel, Sports, Electronics, Clothing, Tools, General
- Groups serve as both picker tabs and browsing categories
- Search filters across all groups
Cleanup
- Old EmojiPicker.tsx and emojiData.ts fully removed after migration
- No emoji references remain anywhere in the codebase
- OnboardingWizard default categories updated to use Lucide icon names
Claude's Discretion
- Exact icon selections for each curated group
- Icon data file structure (static data file similar to emojiData.ts or alternative)
- Migration script implementation details
- Exact emoji-to-icon mapping table completeness
- Popover sizing and grid column count
- Search algorithm (fuzzy vs exact match on icon names)
<code_context>
Existing Code Insights
Reusable Assets
EmojiPickercomponent (src/client/components/EmojiPicker.tsx): 215-line component with portal popover, search, category tabs, click-outside, escape handling — architecture to replicate for IconPickerCategoryPicker(src/client/components/CategoryPicker.tsx): Combobox with search, keyboard nav, inline create — needs EmojiPicker → IconPicker swapCategoryHeader(src/client/components/CategoryHeader.tsx): Edit mode uses EmojiPicker — needs IconPicker swapemojiData.ts(src/client/lib/emojiData.ts): Data structure pattern to replicate for icon groups
Established Patterns
- Portal-based popover rendering via
createPortal(EmojiPicker) - Click-outside detection via document mousedown listener
- Category data flows:
useCategorieshook → components rendercat.emojieverywhere - Drizzle ORM schema in
src/db/schema.ts—emojicolumn on categories table @hono/zod-validatorfor request validation —createCategorySchemain schemas.ts
Integration Points
src/db/schema.ts: Renameemojicolumn toicon, change default from "📦" to "package"src/shared/schemas.ts: Update category schemas (field name emoji → icon)src/shared/types.ts: Types inferred from schemas — will auto-updatesrc/server/services/category.service.ts: Update service functionssrc/server/routes/categories.ts: Update route handlers if neededsrc/client/components/CategoryHeader.tsx: Replace EmojiPicker with IconPicker, emoji → icon propsrc/client/components/CategoryPicker.tsx: Replace EmojiPicker with IconPicker, emoji → icon displaysrc/client/components/ItemCard.tsx: ReplacecategoryEmojiprop withcategoryIcon, render Lucide iconsrc/client/components/CandidateCard.tsx: Same as ItemCardsrc/client/components/ThreadCard.tsx: Category icon displaysrc/client/components/OnboardingWizard.tsx: Default categories use icon names instead of emojisrc/client/routes/collection/index.tsx: Category display in collection viewsrc/client/routes/index.tsx: Dashboard category displaysrc/db/seed.ts: Seed data emoji → icontests/helpers/db.ts: Update test helper CREATE TABLE and seed data
</code_context>
## Specific Ideas- Icon picker should feel like a natural evolution of the EmojiPicker — same popover behavior, just rendering Lucide SVGs instead of emoji characters
- Curated icon groups should focus on gear/hobby relevance: outdoor camping, cycling, travel, electronics, clothing, tools
- The migration mapping should cover common gear emoji (tent, bike, backpack, camera, etc.) with 'package' as the universal fallback
- After migration, zero emoji should remain — fully consistent Lucide icon experience
None — discussion stayed within phase scope
Phase: 06-category-icons Context gathered: 2026-03-15