feat(design): surface phase PR 1 — Lucide icon migration + scale enforcement
Replaces every hand-inlined SVG in the chrome (60 across 15 files) with Lucide components. Snaps icon sizes to the doc's 16/24 scale — all icons in this pass land at 16. AppLogo wordmark stays as the legitimate "custom app icon" exception per the doc; GraphView's <svg> mount point for D3 stays as well. Replaces emoji-as-icons in clear button-affordance cases with their Lucide equivalents: ✕ → X (close/dismiss buttons across 8 files), ✓ → Check (ProjectView task-advance button), 🎤 → Mic (ChatPanel voice CTA), 📎 → Paperclip (ChatView context toggle), ↑ → ArrowUp (ChatInputBar Send), × → X (ChatPanel context-note remove), ☀/☾ → Sun/Moon (AppHeader theme toggle). Inline emoji punctuation in textual confirmation copy ("Saved ✓", "Created ✓", `done: "✓"` status maps, `'✓' : '📄'` interpolations) is left for surface-phase voice/tone touchups — replacing requires structural template changes and is best done per-component. Stroke weight stays at Lucide's default 2px; tightening to the doc's 1.5/1 is deferred per the surface-phase spec (option ii: drop-in + scale enforcement). Adds lucide-vue-next ^0.469.0 to frontend/package.json. Docker rebuild handles the install. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import TiptapEditor from "@/components/TiptapEditor.vue";
|
||||
import TagInput from "@/components/TagInput.vue";
|
||||
import MarkdownToolbar from "@/components/MarkdownToolbar.vue";
|
||||
import WordCount from "@/components/WordCount.vue";
|
||||
import { Trash2, X } from "lucide-vue-next";
|
||||
|
||||
const props = defineProps<{
|
||||
projectId: number;
|
||||
@@ -316,7 +317,7 @@ defineExpose({ reload: loadProjectNotes });
|
||||
<button class="btn-confirm" :disabled="creatingNote || !newNoteTitle.trim()" @click="createNote">
|
||||
{{ creatingNote ? '…' : '+' }}
|
||||
</button>
|
||||
<button class="btn-cancel" aria-label="Cancel new note" @click="cancelNewNote">✕</button>
|
||||
<button class="btn-cancel" aria-label="Cancel new note" @click="cancelNewNote"><X :size="16" /></button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="rail-title">Notes</span>
|
||||
@@ -332,7 +333,7 @@ defineExpose({ reload: loadProjectNotes });
|
||||
type="search"
|
||||
aria-label="Search notes"
|
||||
/>
|
||||
<button v-if="searchQuery" class="btn-search-clear" aria-label="Clear search" @click="searchQuery = ''">✕</button>
|
||||
<button v-if="searchQuery" class="btn-search-clear" aria-label="Clear search" @click="searchQuery = ''"><X :size="16" /></button>
|
||||
</div>
|
||||
|
||||
<div v-if="listLoading" class="rail-state">Loading…</div>
|
||||
@@ -360,10 +361,10 @@ defineExpose({ reload: loadProjectNotes });
|
||||
<button class="btn-confirm-delete" :disabled="pendingDelete === note.id" @click="requestDelete(note.id, $event)">
|
||||
{{ pendingDelete === note.id ? '…' : 'Delete?' }}
|
||||
</button>
|
||||
<button class="btn-cancel-delete" aria-label="Cancel delete" @click="cancelDelete($event)">✕</button>
|
||||
<button class="btn-cancel-delete" aria-label="Cancel delete" @click="cancelDelete($event)"><X :size="16" /></button>
|
||||
</template>
|
||||
<button v-else class="btn-delete" title="Delete note" @click="requestDelete(note.id, $event)">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/></svg>
|
||||
<Trash2 :size="16" />
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
@@ -416,7 +417,7 @@ defineExpose({ reload: loadProjectNotes });
|
||||
:class="['btn-tag-suggestion', { applied: tagSuggestions.appliedTags.value.has(tag) }]"
|
||||
@click="tagSuggestions.applyTagSuggestion(tag)"
|
||||
>#{{ tag }}{{ tagSuggestions.appliedTags.value.has(tag) ? ' ✓' : '' }}</button>
|
||||
<button class="btn-dismiss-suggestions" aria-label="Dismiss tag suggestions" @click="tagSuggestions.dismissTagSuggestions()">✕</button>
|
||||
<button class="btn-dismiss-suggestions" aria-label="Dismiss tag suggestions" @click="tagSuggestions.dismissTagSuggestions()"><X :size="16" /></button>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-row">
|
||||
@@ -429,7 +430,7 @@ defineExpose({ reload: loadProjectNotes });
|
||||
<button class="btn-chip-link" @click="applyLink(s)">[[{{ s.title }}]]</button>
|
||||
</span>
|
||||
<button class="btn-link-all" @click="applyAllLinks" title="Link all suggestions">All</button>
|
||||
<button class="btn-dismiss-suggestions" aria-label="Dismiss link suggestions" @click="linkSuggestions = []">✕</button>
|
||||
<button class="btn-dismiss-suggestions" aria-label="Dismiss link suggestions" @click="linkSuggestions = []"><X :size="16" /></button>
|
||||
</div>
|
||||
|
||||
<div class="editor-area" @keydown.ctrl.s.prevent="saveNote" @keydown.ctrl.e.prevent="editorRef?.editor?.commands.focus()">
|
||||
|
||||
Reference in New Issue
Block a user