From f758927848f89d2b821fe8eb954cdf6afa5be8a2 Mon Sep 17 00:00:00 2001 From: Hiro Date: Mon, 30 Mar 2026 23:47:17 +0000 Subject: [PATCH] Phase 3: Graph View, Backlinks UI, Quick Switcher, Dark Mode, Export Features: - GraphView.vue: SVG-based force-directed graph visualization for projects - QuickSwitcher.vue: Cmd+K modal with fuzzy search via /search API - Dark Mode: Theme toggle in Header, persisted in localStorage, system pref support - Backlinks UI: Incoming and outgoing links in DocumentView - Export: Document (markdown/JSON) and Project (ZIP/JSON) export with download - New composables: useTheme.ts for dark/light/system theme management - New store methods: fetchBacklinks, fetchOutgoingLinks, search, exportDocument, fetchProjectGraph, exportProject - TypeScript types for all Phase 3 API responses --- src/App.vue | 7 + src/components/common/GraphView.vue | 419 ++++++++++++++++++++++++ src/components/common/QuickSwitcher.vue | 360 ++++++++++++++++++++ src/components/layout/Header.vue | 61 +++- src/composables/useApi.ts | 3 +- src/composables/useTheme.ts | 76 +++++ src/stores/documents.ts | 57 +++- src/stores/projects.ts | 27 +- src/types/index.ts | 97 ++++++ src/views/DocumentView.vue | 312 +++++++++++++++++- src/views/ProjectView.vue | 154 +++++++++ 11 files changed, 1563 insertions(+), 10 deletions(-) create mode 100644 src/components/common/GraphView.vue create mode 100644 src/components/common/QuickSwitcher.vue create mode 100644 src/composables/useTheme.ts diff --git a/src/App.vue b/src/App.vue index fe45f3c..91f3223 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,5 +1,12 @@ @@ -244,6 +348,13 @@ async function createDocument() { color: var(--text-secondary); } +.project__actions { + display: flex; + justify-content: center; + gap: 0.75rem; + margin-top: 1.5rem; +} + /* Form styles */ .form__field { margin-bottom: 1.25rem; @@ -282,4 +393,47 @@ async function createDocument() { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1); } + +/* Export Modal Styles */ +.export-formats { + display: flex; + gap: 0.75rem; +} + +.export-format { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5rem; + padding: 1.25rem 1rem; + background: var(--bg-secondary); + border: 2px solid var(--border); + border-radius: 10px; + cursor: pointer; + transition: all 0.15s; + color: var(--text-secondary); +} + +.export-format:hover { + border-color: var(--accent); + color: var(--text-primary); +} + +.export-format--selected { + border-color: var(--accent); + background: rgba(99, 102, 241, 0.08); + color: var(--accent); +} + +.export-format span { + font-size: 0.9375rem; + font-weight: 600; + color: var(--text-primary); +} + +.export-format small { + font-size: 0.75rem; + color: var(--text-secondary); +}