fix: improve note interactions and markdown LaTeX support
## Bug Fixes ### Note Card Actions - Fix broken size change functionality (missing state declaration) - Implement React 19 useOptimistic for instant UI feedback - Add startTransition for non-blocking updates - Ensure smooth animations without page refresh - All note actions now work: pin, archive, color, size, checklist ### Markdown LaTeX Rendering - Add remark-math and rehype-katex plugins - Support inline equations with dollar sign syntax - Support block equations with double dollar sign syntax - Import KaTeX CSS for proper styling - Equations now render correctly instead of showing raw LaTeX ## Technical Details - Replace undefined currentNote references with optimistic state - Add optimistic updates before server actions for instant feedback - Use router.refresh() in transitions for smart cache invalidation - Install remark-math, rehype-katex, and katex packages ## Testing - Build passes successfully with no TypeScript errors - Dev server hot-reloads changes correctly
This commit is contained in:
424
docs/component-inventory.md
Normal file
424
docs/component-inventory.md
Normal file
@@ -0,0 +1,424 @@
|
||||
# Component Inventory - keep-notes
|
||||
|
||||
## Overview
|
||||
|
||||
Complete inventory of React components in the Memento web application. The application uses 20+ domain-specific components organized by functionality.
|
||||
|
||||
**Total Components:** 20+
|
||||
**UI Library:** Radix UI
|
||||
**Icons:** Lucide React
|
||||
|
||||
---
|
||||
|
||||
## Component Categories
|
||||
|
||||
### 1. Authentication Components
|
||||
|
||||
| Component | File | Purpose | Props |
|
||||
|-----------|------|---------|-------|
|
||||
| **LoginForm** | `login-form.tsx` | User login form | email, password, handleSubmit |
|
||||
| **RegisterForm** | `register-form.tsx` | User registration | name, email, password, confirmPassword |
|
||||
|
||||
**Usage:** Used in `(auth)/login` and `(auth)/register` routes
|
||||
|
||||
---
|
||||
|
||||
### 2. Note Components
|
||||
|
||||
| Component | File | Purpose | Props |
|
||||
|-----------|------|---------|-------|
|
||||
| **NoteCard** | `note-card.tsx` | Individual note display | note, onPin, onArchive, onUpdate, onDelete |
|
||||
| **NoteEditor** | `note-editor.tsx` | Rich note editor | note, onChange, onSave |
|
||||
| **NoteInput** | `note-input.tsx` | Quick note creation | onCreate, autoFocus |
|
||||
| **NoteActions** | `note-actions.tsx` | Note action menu | note, onEdit, onPin, onArchive, onDelete |
|
||||
| **NoteChecklist** | `note-checklist.tsx` | Checklist items | items, onChange, onToggle |
|
||||
| **NoteImages** | `note-images.tsx` | Image gallery | images, onAdd, onRemove |
|
||||
| **EditorImages** | `editor-images.tsx` | Image upload/edit | images, onChange |
|
||||
|
||||
**Features:**
|
||||
- Drag-and-drop support via @dnd-kit
|
||||
- Color-coded backgrounds
|
||||
- Markdown rendering support
|
||||
- Checklist with checkbox items
|
||||
- Image attachments (base64 or URL)
|
||||
- Pin/unpin functionality
|
||||
- Archive/unarchive
|
||||
|
||||
---
|
||||
|
||||
### 3. Label Components
|
||||
|
||||
| Component | File | Purpose | Props |
|
||||
|-----------|------|---------|-------|
|
||||
| **LabelBadge** | `label-badge.tsx` | Label display badge | label, onRemove, color |
|
||||
| **LabelFilter** | `label-filter.tsx` | Filter by labels | labels, selectedLabels, onChange |
|
||||
| **LabelSelector** | `label-selector.tsx` | Select labels for note | availableLabels, selectedLabels, onChange |
|
||||
| **LabelManager** | `label-manager.tsx` | Manage user labels | labels, onCreate, onUpdate, onDelete |
|
||||
| **LabelManagementDialog** | `label-management-dialog.tsx` | Label management modal | isOpen, onClose, labels |
|
||||
| **GhostTags** | `ghost-tags.tsx` | Floating tag display | tags, onTagClick |
|
||||
|
||||
**Color Options:** red, orange, yellow, green, teal, blue, purple, pink, gray
|
||||
|
||||
---
|
||||
|
||||
### 4. Layout Components
|
||||
|
||||
| Component | File | Purpose | Props |
|
||||
|-----------|------|---------|-------|
|
||||
| **Header** | `header.tsx` | Application header | title, user |
|
||||
| **HeaderWrapper** | `header-wrapper.tsx` | Header container with logic | children, user |
|
||||
| **Sidebar** | `sidebar.tsx` | Navigation sidebar | isOpen, onClose |
|
||||
| **MasonryGrid** | `masonry-grid.tsx` | Masonry grid layout | items, renderItem |
|
||||
|
||||
**Layout Libraries:**
|
||||
- Muuri (masonry grid)
|
||||
- react-grid-layout
|
||||
- @dnd-kit (drag and drop)
|
||||
|
||||
---
|
||||
|
||||
### 5. Content Components
|
||||
|
||||
| Component | File | Purpose | Props |
|
||||
|-----------|------|---------|-------|
|
||||
| **MarkdownContent** | `markdown-content.tsx` | Markdown renderer | content, className |
|
||||
|
||||
**Features:**
|
||||
- GitHub Flavored Markdown (GFM)
|
||||
- Syntax highlighting (if configured)
|
||||
- Safe rendering (sanitization)
|
||||
|
||||
---
|
||||
|
||||
### 6. User Components
|
||||
|
||||
| Component | File | Purpose | Props |
|
||||
|-----------|------|---------|-------|
|
||||
| **UserNav** | `user-nav.tsx` (inferred) | User navigation menu | user, onLogout |
|
||||
|
||||
**Features:**
|
||||
- Profile settings access
|
||||
- Logout functionality
|
||||
- Theme toggle
|
||||
|
||||
---
|
||||
|
||||
### 7. Dialog/Modal Components
|
||||
|
||||
| Component | File | Purpose | Props |
|
||||
|-----------|------|---------|-------|
|
||||
| **ReminderDialog** | `reminder-dialog.tsx` | Set note reminders | note, onSave, onClose |
|
||||
|
||||
**Features:**
|
||||
- Date/time picker
|
||||
- Recurrence options
|
||||
- Location-based reminders (future)
|
||||
|
||||
---
|
||||
|
||||
### 8. UI Primitives (Radix UI)
|
||||
|
||||
Located in `components/ui/` - Auto-generated or minimal wrappers around Radix UI:
|
||||
|
||||
| Component | Radix Primitive | Purpose |
|
||||
|-----------|----------------|---------|
|
||||
| Avatar | @radix-ui/react-avatar | User avatar display |
|
||||
| Checkbox | @radix-ui/react-checkbox | Checkbox input |
|
||||
| Dialog | @radix-ui/react-dialog | Modal dialogs |
|
||||
| Dropdown Menu | @radix-ui/react-dropdown-menu | Dropdown menus |
|
||||
| Popover | @radix-ui/react-popover | Floating content |
|
||||
| Separator | @radix-ui/react-separator | Visual separators |
|
||||
| Slot | @radix-ui/react-slot | Component composition |
|
||||
| Tooltip | @radix-ui/react-tooltip | Hover tooltips |
|
||||
|
||||
**Usage:** Domain components compose these primitives
|
||||
|
||||
---
|
||||
|
||||
## Component Hierarchy
|
||||
|
||||
```
|
||||
Layout Components
|
||||
├── Header → HeaderWrapper
|
||||
│ └── UserNav
|
||||
├── Sidebar
|
||||
└── MasonryGrid
|
||||
└── NoteCard
|
||||
├── NoteEditor
|
||||
│ ├── NoteChecklist
|
||||
│ ├── NoteImages
|
||||
│ └── EditorImages
|
||||
└── NoteActions
|
||||
|
||||
Label Management
|
||||
├── LabelBadge
|
||||
├── LabelFilter
|
||||
├── LabelSelector
|
||||
├── LabelManager → LabelManagementDialog
|
||||
└── GhostTags
|
||||
|
||||
Authentication
|
||||
├── LoginForm
|
||||
└── RegisterForm
|
||||
|
||||
Content
|
||||
└── MarkdownContent
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Component Patterns
|
||||
|
||||
### 1. Compound Components
|
||||
|
||||
**NoteEditor** contains:
|
||||
- NoteChecklist (if type=checklist)
|
||||
- NoteImages
|
||||
- EditorImages
|
||||
|
||||
**HeaderWrapper** wraps:
|
||||
- Header
|
||||
- UserNav
|
||||
|
||||
### 2. Controlled Components
|
||||
|
||||
Most components are controlled (parent state):
|
||||
- NoteCard receives note object and callbacks
|
||||
- LabelFilter receives selected labels and onChange
|
||||
- NoteEditor manages local state, calls onSave
|
||||
|
||||
### 3. Modal Pattern
|
||||
|
||||
Dialogs use Radix Dialog:
|
||||
- LabelManagementDialog
|
||||
- ReminderDialog
|
||||
|
||||
Pattern:
|
||||
```tsx
|
||||
{isOpen && (
|
||||
<Dialog open={isOpen} onOpenChange={onClose}>
|
||||
<DialogContent>{/* content */}</DialogContent>
|
||||
</Dialog>
|
||||
)}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Component Communication
|
||||
|
||||
### Props Drilling
|
||||
- Components receive data via props
|
||||
- Callbacks passed for mutations
|
||||
|
||||
### Server Actions
|
||||
- Note mutations via `app/actions/notes.ts`
|
||||
- Label mutations via server actions
|
||||
- Auth mutations via `app/actions/register.ts`
|
||||
|
||||
### Context Providers
|
||||
- User session context (from NextAuth)
|
||||
- Theme context (light/dark mode)
|
||||
|
||||
---
|
||||
|
||||
## Design System
|
||||
|
||||
### Colors
|
||||
|
||||
**Note Colors:** default, red, orange, yellow, green, teal, blue, purple, pink, gray
|
||||
|
||||
**Label Colors:** Same palette as notes
|
||||
|
||||
### Typography
|
||||
|
||||
- **Font:** System font stack (Tailwind default)
|
||||
- **Sizes:** Based on Tailwind typography plugin
|
||||
|
||||
### Spacing
|
||||
|
||||
- **Gap:** Tailwind spacing scale
|
||||
- **Padding:** Consistent 4px/8px/16px/24px increments
|
||||
|
||||
---
|
||||
|
||||
## Component State Management
|
||||
|
||||
### Local State
|
||||
- Form inputs (controlled components)
|
||||
- Modal open/closed state
|
||||
- Temporary editing state
|
||||
|
||||
### Server State
|
||||
- Notes list (fetched from API)
|
||||
- User session (NextAuth)
|
||||
- Labels (fetched from API)
|
||||
|
||||
### State Updates
|
||||
1. User action → Server action / API call
|
||||
2. Database update (Prisma)
|
||||
3. Revalidate / refetch
|
||||
4. Component re-render
|
||||
|
||||
**No Global State Library:** Uses React Context + hooks instead of Redux/Zustand
|
||||
|
||||
---
|
||||
|
||||
## Component Dependencies
|
||||
|
||||
### UI Libraries
|
||||
- Radix UI (primitives)
|
||||
- Tailwind CSS (styling)
|
||||
- Lucide React (icons)
|
||||
- @dnd-kit (drag and drop)
|
||||
- Muuri (masonry layout)
|
||||
- react-grid-layout (grid system)
|
||||
- react-markdown (markdown rendering)
|
||||
- react-masonry-css (alternative masonry)
|
||||
|
||||
### Custom Hooks
|
||||
- Located in `hooks/`
|
||||
- Used for:
|
||||
- Form validation
|
||||
- Local storage
|
||||
- Debouncing
|
||||
- Media queries
|
||||
|
||||
---
|
||||
|
||||
## Component Performance
|
||||
|
||||
### Optimizations
|
||||
- React.memo (selective components)
|
||||
- Lazy loading (dynamic imports)
|
||||
- Image optimization (next/image)
|
||||
- Code splitting (route-based)
|
||||
|
||||
### Masonry Grid
|
||||
- Muuri for performant drag-and-drop
|
||||
- Virtualization for large note lists
|
||||
|
||||
---
|
||||
|
||||
## Component Testing
|
||||
|
||||
### E2E Coverage
|
||||
- Playwright tests in `tests/`
|
||||
- Coverage: Component interactions
|
||||
- Test file: `search-quality.spec.ts`
|
||||
|
||||
### Manual Testing
|
||||
- Test UI in `npm run test:headed`
|
||||
- Test reports: `playwright-report/`
|
||||
|
||||
---
|
||||
|
||||
## Component Styling
|
||||
|
||||
### CSS Strategy
|
||||
- **Framework:** Tailwind CSS 4
|
||||
- **Approach:** Utility-first
|
||||
- **Custom CSS:** In `globals.css`
|
||||
- **Component Styles:** Tailwind classes
|
||||
|
||||
### Responsive Design
|
||||
- Mobile-first approach
|
||||
- Breakpoints: sm, md, lg, xl
|
||||
- Grid adapts to screen size
|
||||
|
||||
### Theme Support
|
||||
- Light/dark mode via user preference
|
||||
- Theme stored in `User.theme`
|
||||
- CSS variables for theme colors
|
||||
|
||||
---
|
||||
|
||||
## Accessibility
|
||||
|
||||
### Radix UI Features
|
||||
- Keyboard navigation
|
||||
- ARIA attributes
|
||||
- Focus management
|
||||
- Screen reader support
|
||||
|
||||
### Custom A11y
|
||||
- Alt text for images
|
||||
- Semantic HTML
|
||||
- Form labels
|
||||
- Error messages
|
||||
|
||||
---
|
||||
|
||||
## Component Future Enhancements
|
||||
|
||||
**Potential Improvements:**
|
||||
1. Add skeleton loaders
|
||||
2. Implement error boundaries
|
||||
3. Add undo/redo for note edits
|
||||
4. Rich text editor (WYSIWYG)
|
||||
5. Collaborative editing
|
||||
6. Note templates
|
||||
7. Color picker for custom colors
|
||||
8. Drag-and-drop file upload
|
||||
9. Voice input (Web Speech API)
|
||||
10. Export/import notes
|
||||
|
||||
---
|
||||
|
||||
## Component Maintenance
|
||||
|
||||
**File Organization:**
|
||||
- Domain-driven (note-*, label-*, auth-*)
|
||||
- Co-located with related components
|
||||
- Clear naming conventions
|
||||
|
||||
**Code Quality:**
|
||||
- TypeScript for type safety
|
||||
- Consistent prop interfaces
|
||||
- Reusable UI primitives
|
||||
- Minimal prop drilling (use context where appropriate)
|
||||
|
||||
---
|
||||
|
||||
## Component Usage Examples
|
||||
|
||||
### NoteCard
|
||||
```tsx
|
||||
<NoteCard
|
||||
note={note}
|
||||
onPin={() => handleTogglePin(note.id)}
|
||||
onArchive={() => handleToggleArchive(note.id)}
|
||||
onUpdate={(updates) => handleUpdateNote(note.id, updates)}
|
||||
onDelete={() => handleDeleteNote(note.id)}
|
||||
/>
|
||||
```
|
||||
|
||||
### LabelSelector
|
||||
```tsx
|
||||
<LabelSelector
|
||||
availableLabels={labels}
|
||||
selectedLabels={note.labels || []}
|
||||
onChange={(newLabels) => updateNoteLabels(note.id, newLabels)}
|
||||
/>
|
||||
```
|
||||
|
||||
### MasonryGrid
|
||||
```tsx
|
||||
<MasonryGrid
|
||||
items={notes}
|
||||
renderItem={(note) => <NoteCard key={note.id} note={note} />}
|
||||
/>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The Memento application uses a well-organized component architecture with:
|
||||
- **20+ domain components** for notes, labels, auth, and layout
|
||||
- **Radix UI primitives** for accessible, composable UI
|
||||
- **Controlled components** with parent-managed state
|
||||
- **Server actions** for mutations
|
||||
- **No global state library** (Context + hooks instead)
|
||||
- **Drag-and-drop** via @dnd-kit
|
||||
- **Masonry layout** via Muuri
|
||||
- **Responsive design** with Tailwind CSS
|
||||
Reference in New Issue
Block a user