diff --git a/frontend/package.json b/frontend/package.json
index b5951d5..8d17f4b 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -25,6 +25,7 @@
"@tiptap/vue-3": "^3.0.0",
"d3": "^7",
"dompurify": "^3.1.0",
+ "lucide-vue-next": "^0.469.0",
"marked": "^17.0.0",
"pinia": "^3.0.0",
"vue": "3.5.30",
diff --git a/frontend/src/components/AppHeader.vue b/frontend/src/components/AppHeader.vue
index d824f25..a975ba2 100644
--- a/frontend/src/components/AppHeader.vue
+++ b/frontend/src/components/AppHeader.vue
@@ -7,6 +7,7 @@ import { useAuthStore } from "@/stores/auth";
import { useChatStore } from "@/stores/chat";
import AppLogo from "@/components/AppLogo.vue";
import NotificationBell from "@/components/NotificationBell.vue";
+import { Sun, Moon, Settings } from "lucide-vue-next";
const { theme, toggleTheme } = useTheme();
const { toggleShortcuts } = useShortcuts();
@@ -94,15 +95,13 @@ router.afterEach(() => {
-
+
@@ -137,7 +136,8 @@ router.afterEach(() => {
{{ statusShortLabel }}
-
+
{{ authStore.user?.username }}
diff --git a/frontend/src/components/ChatInputBar.vue b/frontend/src/components/ChatInputBar.vue
index 1d4f4c1..fa33639 100644
--- a/frontend/src/components/ChatInputBar.vue
+++ b/frontend/src/components/ChatInputBar.vue
@@ -10,6 +10,15 @@ import { useChatStore } from '@/stores/chat'
import { useSettingsStore } from '@/stores/settings'
import { useToastStore } from '@/stores/toast'
import type { Note } from '@/types/note'
+import {
+ Paperclip,
+ Volume2,
+ VolumeX,
+ Square,
+ Mic,
+ Loader2,
+ ArrowUp,
+} from 'lucide-vue-next'
const props = withDefaults(defineProps<{
/** Textarea placeholder */
@@ -277,9 +286,7 @@ defineExpose({ focus, prefill })
:disabled="!store.chatReady"
title="Attach a note"
>
-
+
-
-
+
+
@@ -371,12 +374,8 @@ defineExpose({ focus, prefill })
:title="recorder.recording.value ? 'Click to stop (or wait for silence)' : 'Click to speak'"
:aria-label="recorder.recording.value ? 'Stop recording' : 'Start recording'"
>
-
-
+
+
@@ -387,14 +386,14 @@ defineExpose({ focus, prefill })
@click="emit('abort')"
title="Stop generation"
>
-
+
+ >
@@ -484,6 +483,8 @@ defineExpose({ focus, prefill })
z-index: 1;
}
.btn-mic.mic-transcribing { opacity: 0.5; }
+.mic-loader { animation: mic-spin 1s linear infinite; }
+@keyframes mic-spin { to { transform: rotate(360deg); } }
/* Mic wrapper + live amplitude halo. The glow is a filled red disc
absolutely positioned behind the button, scaled/faded by the
diff --git a/frontend/src/components/ChatPanel.vue b/frontend/src/components/ChatPanel.vue
index cf6d2f2..4a34c2d 100644
--- a/frontend/src/components/ChatPanel.vue
+++ b/frontend/src/components/ChatPanel.vue
@@ -6,6 +6,7 @@ import ChatStreamingBubble from '@/components/ChatStreamingBubble.vue'
import ChatInputBar from '@/components/ChatInputBar.vue'
import ToolCallCard from '@/components/ToolCallCard.vue'
import type { Message, ToolCallRecord } from '@/types/chat'
+import { Mic, ChevronDown, X } from 'lucide-vue-next'
const props = withDefaults(defineProps<{
variant: 'full' | 'widget'
@@ -372,7 +373,7 @@ defineExpose({ focus, prefill, send, contextCount, sidebarOpen, toggleContextSid
@@ -391,7 +392,7 @@ defineExpose({ focus, prefill, send, contextCount, sidebarOpen, toggleContextSid
:class="{ collapsed: collapsedSections.has('auto') }"
@click="toggleSection('auto')"
>
-
+
Auto-included
{{ autoInjectedNotes.length }}
@@ -404,7 +405,7 @@ defineExpose({ focus, prefill, send, contextCount, sidebarOpen, toggleContextSid
class="context-note-score"
:class="{ 'score-high': note.score >= 0.75, 'score-medium': note.score >= 0.60 && note.score < 0.75, 'score-low': note.score < 0.60 }"
>{{ Math.round(note.score * 100) }}%
-
+
@@ -414,7 +415,7 @@ defineExpose({ focus, prefill, send, contextCount, sidebarOpen, toggleContextSid
:class="{ collapsed: collapsedSections.has('suggested'), 'context-sidebar-header-gap': autoInjectedNotes.length }"
@click="toggleSection('suggested')"
>
-
+
Suggested
{{ suggestedNotes.length }}
@@ -436,14 +437,14 @@ defineExpose({ focus, prefill, send, contextCount, sidebarOpen, toggleContextSid
:class="{ collapsed: collapsedSections.has('included'), 'context-sidebar-header-gap': autoInjectedNotes.length || suggestedNotes.length }"
@click="toggleSection('included')"
>
-
+
In Context
{{ includedNotes.length }}
diff --git a/frontend/src/components/EventSlideOver.vue b/frontend/src/components/EventSlideOver.vue
index 5ba73a6..e5cd769 100644
--- a/frontend/src/components/EventSlideOver.vue
+++ b/frontend/src/components/EventSlideOver.vue
@@ -1,4 +1,5 @@