mirror of
https://github.com/PerpetualSoftware/pad.git
synced 2026-09-11 13:28:57 +00:00
4f57a974c7
Phase 3c-i task A (PLAN-2392). The attachment action descriptors carried glyph strings (⇗ ⇩ 🔗 🗑) rendered as MenuItem's text `icon`; this moves them to the shared monochrome SVG icon set so the toolbar the next tasks build renders real, forced-colors-safe icons. - The icon registry (attachments/icons) gains four ACTION icons — action-open, action-download, action-copy-link, action-delete — in the same inline-path, currentColor, stroke-only style as the file-family set, so both render paths (AttachmentIcon.svelte, iconSvg) draw them from one table. New ACTION_ICON_IDS + the IconId union (family ∪ action); a broad isIconId narrow (the family-only isAttachmentIconId stays for MIME→family mapping) so iconSvg renders action ids while keeping its generic fallback for unknown strings. - The action descriptor's `icon` field narrows from string to ActionIconId, and the four glyphs become the ids. AttachmentIcon's `id` widens from string to IconId — an unknown id is now a compile error rather than a silent generic-file fallback. - The details panel renders each action's icon through MenuItem's `iconSnippet` with AttachmentIcon (a per-iteration snippet closing over the row's id), not the text `icon` prop. MenuItem's `.mi-icon` slot centres its content on both axes so the block SVG isn't left-aligned — text/emoji consumers unchanged. - Two stale comments corrected (the "toolbar arrives in phase 3a" note → 3c-i). Falsifiable acceptance: a test asserts every panel action row renders an SVG and none of the four glyph characters survive (fails if the panel passes strings — mutation-verified); a drift-guard asserts the four action ids exist in the registry and render non-empty paths. Out of scope (3c-ii): the delete confirm's own rows. Claude-Session: https://claude.ai/code/session_01WFBYxdBuSZs2tjipATxAZu
Pad Web UI
SvelteKit 2 + Svelte 5 frontend for Pad, compiled to static files and embedded into the Go binary.
Development
npm install
npm run dev # Dev server at localhost:5173 (proxies API to localhost:7777)
npm run build # Production build to build/
npm run check # Type checking with svelte-check
When developing, run the Go backend separately with make dev from the project root.
Building for Production
Do not build in isolation. Always use make build from the project root — this builds the web frontend, then compiles the Go binary with the build output embedded via //go:embed.
Stack
- Svelte 5 with runes (
$state,$derived,$effect) - SvelteKit 2 with
adapter-static(SPA mode) - Tiptap block editor with markdown round-trip
- svelte-dnd-action for drag-and-drop in board/list views
- SSE for real-time updates
- TypeScript throughout
Structure
src/
routes/ SvelteKit pages
+layout.svelte App shell (sidebar + main)
+page.svelte Landing/redirect
[workspace]/
+page.svelte Dashboard (collections, phases, activity)
+layout.svelte SSE connection per workspace
[collection]/
+page.svelte Collection view (board/list)
[collection]/[item]/
+page.svelte Item detail + editor
conventions/ Purpose-built conventions page
playbooks/ Purpose-built playbooks page
settings/ Workspace settings
lib/
api/client.ts HTTP API client
components/
layout/ Sidebar, navigation
editor/ Tiptap editor, raw markdown editor
fields/ FieldEditor, relation picker
items/ ItemCard, ItemDetail
collections/ BoardView, ListView
common/ StatusBadge, badges, modals
search/ CommandPalette
activity/ ActivityFeed
stores/ Svelte 5 reactive stores
workspace.svelte.ts Workspace state
collections.svelte.ts Collection + item state
ui.svelte.ts Sidebar, mobile state
types/index.ts TypeScript types and constants
app.css Global styles and design tokens