# OpenPylon: 15 Improvements Design ## Overview 15 improvements to OpenPylon organized into 5 phases (0-4), designed for incremental delivery. Each phase builds on the previous. You can ship after any phase and have a coherent improvement. ## Decisions - **Phasing**: 4 phases (quick wins first, progressively bigger features) - **Data compatibility**: New fields use Zod `.default()` values. No migration code. Old boards load cleanly. - **Templates storage**: JSON files in `data/templates/` - **Backup storage**: Timestamped files in `data/backups/{boardId}/`, keep last 10 --- ## Phase 0: Data Model Foundation All type/schema changes that later features depend on. Done first so everything builds on a stable base. ### Card type additions ```typescript // Added to Card interface + cardSchema priority: "none" | "low" | "medium" | "high" | "urgent"; // default: "none" comments: Comment[]; // default: [] // New type + schema interface Comment { id: string; text: string; createdAt: string; } ``` ### Column type additions ```typescript // Added to Column interface + columnSchema collapsed: boolean; // default: false wipLimit: number | null; // default: null ``` ### Files touched - `src/types/board.ts` — Add fields to Card, Column interfaces. Add Comment interface. - `src/lib/schemas.ts` — Add Zod fields with defaults to cardSchema, columnSchema. Add commentSchema. --- ## Phase 1: Quick Wins Minimal changes, high value. ~4 files each. ### #8 — Consume defaultColumnWidth Setting In `board-store.ts`, `addColumn` reads `useAppStore.getState().settings.defaultColumnWidth` instead of hardcoding `"standard"`. **Files**: `src/stores/board-store.ts` (1 line change) ### #4 — Due Date Visual Indicators Replace binary overdue/not logic in `CardThumbnail` with 4-tier color system: | Status | Condition | Color | |--------|-----------|-------| | Overdue | past + not today | `pylon-danger` (red) | | Approaching | due within 2 days | amber `oklch(65% 0.15 70)` | | Comfortable | due but >2 days | green `oklch(55% 0.12 145)` | | No date | null | `pylon-text-secondary` (gray) | Helper function `getDueDateStatus(dueDate: string | null)` returns `{ color, label }`. **Files**: `src/components/board/CardThumbnail.tsx` ### #9 — Card Aging Visualization Compute days since `card.updatedAt`. Apply opacity: | Days stale | Opacity | |------------|---------| | 0-7 | 1.0 | | 7-14 | 0.85 | | 14-30 | 0.7 | | 30+ | 0.55 | Applied as inline `opacity` on the card `motion.button`. **Files**: `src/components/board/CardThumbnail.tsx` ### #12 — Open Attachments Add "Open" button to each attachment in `AttachmentSection`. Uses `open()` from `@tauri-apps/plugin-opener` (already registered). **Files**: `src/components/card-detail/AttachmentSection.tsx` --- ## Phase 2: Card Interactions & UI Enhancements 5 features that transform how cards feel to use. ### #2 — Card Priority Levels **Thumbnail indicator**: Colored dot in footer row. Color map: - `none`: hidden - `low`: blue - `medium`: yellow - `high`: orange - `urgent`: red with pulse animation **Detail modal**: Priority picker section in left column (like LabelPicker). Row of 5 clickable chips with colors. **Files**: `CardThumbnail.tsx`, `CardDetailModal.tsx` (new PriorityPicker component inline or separate), `board-store.ts` (no new action needed — `updateCard` handles it) ### #5 — Card Context Menu Wrap `CardThumbnail` in Radix `ContextMenu`. **Menu items**: - Move to → (submenu listing columns except current) - Set priority → (submenu with 5 options) - Duplicate (new card with same fields, `(copy)` suffix, new ID, inserted below original) - Separator - Delete (confirmation dialog) **New store action**: `duplicateCard(cardId): string` — clones card, inserts after original in same column. **Files**: `CardThumbnail.tsx`, `board-store.ts` ### #10 — WIP Limits **Column header display**: Shows `3/5` when wipLimit set. Background tint: - Under limit: normal - At limit: amber tint `oklch(75% 0.08 70 / 15%)` - Over limit: red tint `oklch(70% 0.08 25 / 15%)` **Setting UI**: New "Set WIP Limit" item in ColumnHeader dropdown menu. Preset choices: None / 3 / 5 / 7 / 10 / Custom. **New store action**: `setColumnWipLimit(columnId: string, limit: number | null)` **Files**: `ColumnHeader.tsx`, `KanbanColumn.tsx`, `board-store.ts` ### #3 — Column Collapse/Expand When `collapsed`, render a 40px-wide strip instead of full column: - Vertical text via `writing-mode: vertical-rl; rotate: 180deg` - Card count badge - Click to expand Animate width from full to 40px using existing `animate={{ width }}` on outer `motion.div` with `springs.bouncy`. **New store action**: `toggleColumnCollapse(columnId: string)` **Collapse button**: Added to ColumnHeader dropdown menu + a small chevron icon on the collapsed strip. **Files**: `KanbanColumn.tsx`, `ColumnHeader.tsx`, `board-store.ts` ### #11 — Checklist Item Reordering Wrap checklist `