feat(ui): polish the meetings list — icons, accent colors, hover states
Search icon inside the input, Trash2/Download/RotateCcw replacing emoji, tag chips and the selected-item state now use the semantic accent tokens instead of a hardcoded blue hex, and list rows get a hover state + an accent-colored left border when selected.
This commit is contained in:
1 parent
d50342d865
commit
9052d69912
1 file changed
+77
-25
@@ -4,6 +4,7 @@
|
||||
import { recording } from "../stores/recording.svelte";
|
||||
import { api, type MeetingListItem, type SearchHit } from "../api";
|
||||
import { open } from "@tauri-apps/plugin-dialog";
|
||||
import { Search, Trash2, Download, RotateCcw } from "@lucide/svelte";
|
||||
|
||||
let query = $state("");
|
||||
let searchTimer: ReturnType<typeof setTimeout> | undefined;
|
||||
@@ -100,12 +101,15 @@
|
||||
</script>
|
||||
|
||||
<div class="wrap">
|
||||
<input
|
||||
placeholder="Search meetings…"
|
||||
aria-label="Search meetings"
|
||||
bind:value={query}
|
||||
oninput={onSearchInput}
|
||||
/>
|
||||
<div class="search-box">
|
||||
<Search size={15} aria-hidden="true" />
|
||||
<input
|
||||
placeholder="Search meetings…"
|
||||
aria-label="Search meetings"
|
||||
bind:value={query}
|
||||
oninput={onSearchInput}
|
||||
/>
|
||||
</div>
|
||||
<div class="filters">
|
||||
<select aria-label="Filter by tag" bind:value={tagFilter} onchange={onFilterChange}>
|
||||
<option value="">All tags</option>
|
||||
@@ -124,10 +128,12 @@
|
||||
<option value="bundle">bundle</option>
|
||||
</select>
|
||||
<button
|
||||
class="bulk-btn"
|
||||
onclick={bulkExport}
|
||||
disabled={bulkExporting}
|
||||
title="Export every meeting matching the tag/date filters above"
|
||||
>
|
||||
<Download size={13} aria-hidden="true" />
|
||||
{bulkExporting ? "Exporting…" : "Bulk export"}
|
||||
</button>
|
||||
</div>
|
||||
@@ -141,7 +147,7 @@
|
||||
{:else if displayItems.length === 0 && meetings.searchResults !== null}
|
||||
<p class="muted">No matches.</p>
|
||||
{:else if displayItems.length === 0}
|
||||
<p class="muted">No meetings yet. Click ● Record to start.</p>
|
||||
<p class="muted">No meetings yet — click Record above to start.</p>
|
||||
{:else}
|
||||
<ul>
|
||||
{#each displayItems as m (m.id)}
|
||||
@@ -174,16 +180,18 @@
|
||||
</button>
|
||||
<div class="row actions">
|
||||
{#if m.status === "recovering"}
|
||||
<button class="link" onclick={(e) => resumeMeeting(e, m.id)}
|
||||
>Resume transcription</button
|
||||
>
|
||||
<button class="link" onclick={(e) => resumeMeeting(e, m.id)}>
|
||||
<RotateCcw size={12} aria-hidden="true" />
|
||||
Resume transcription
|
||||
</button>
|
||||
{/if}
|
||||
<button
|
||||
class="link danger"
|
||||
onclick={(e) => removeMeeting(e, m.id)}
|
||||
aria-label="Delete meeting"
|
||||
title="Delete meeting"
|
||||
>
|
||||
🗑
|
||||
<Trash2 size={14} aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
@@ -196,11 +204,34 @@
|
||||
.wrap {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
.search-box {
|
||||
position: relative;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.search-box :global(svg) {
|
||||
position: absolute;
|
||||
left: 0.55rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: var(--fg-subtle);
|
||||
pointer-events: none;
|
||||
}
|
||||
.search-box input {
|
||||
padding-left: 1.9rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 0.4rem;
|
||||
padding: 0.45rem 0.6rem;
|
||||
margin-bottom: 0.5rem;
|
||||
box-sizing: border-box;
|
||||
background: var(--bg);
|
||||
color: var(--fg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
input:focus-visible {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
.muted {
|
||||
color: var(--muted);
|
||||
@@ -220,7 +251,7 @@
|
||||
}
|
||||
.filters {
|
||||
display: flex;
|
||||
gap: 0.3rem;
|
||||
gap: 0.35rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.filters select,
|
||||
@@ -228,24 +259,34 @@
|
||||
.filters button {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 0.25rem;
|
||||
padding: 0.3rem;
|
||||
font-size: 0.78rem;
|
||||
background: var(--bg);
|
||||
color: var(--fg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 5px;
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
.bulk-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.3rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.bulk-btn:hover {
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
.tags {
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 0.2rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
.chip {
|
||||
font-size: 0.68rem;
|
||||
padding: 0.05rem 0.35rem;
|
||||
border-radius: 8px;
|
||||
background: color-mix(in srgb, var(--muted) 15%, transparent);
|
||||
color: var(--muted);
|
||||
padding: 0.1rem 0.45rem;
|
||||
border-radius: var(--radius-full);
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent);
|
||||
}
|
||||
ul {
|
||||
list-style: none;
|
||||
@@ -253,11 +294,17 @@
|
||||
margin: 0;
|
||||
}
|
||||
li {
|
||||
padding: 0.5rem 0.4rem;
|
||||
padding: 0.55rem 0.7rem 0.55rem 0.6rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
border-left: 2px solid transparent;
|
||||
transition: background-color 120ms ease-out;
|
||||
}
|
||||
li:hover {
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
li.active {
|
||||
background: color-mix(in srgb, #2563eb 12%, transparent);
|
||||
background: var(--accent-soft);
|
||||
border-left-color: var(--accent);
|
||||
}
|
||||
.item-btn {
|
||||
display: block;
|
||||
@@ -280,11 +327,13 @@
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-weight: 500;
|
||||
}
|
||||
.badge {
|
||||
font-size: 0.65rem;
|
||||
padding: 0.1rem 0.4rem;
|
||||
border-radius: 10px;
|
||||
font-weight: 600;
|
||||
padding: 0.1rem 0.45rem;
|
||||
border-radius: var(--radius-full);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.badge.live {
|
||||
@@ -300,11 +349,14 @@
|
||||
border-color: var(--muted);
|
||||
}
|
||||
.actions {
|
||||
margin-top: 0.2rem;
|
||||
margin-top: 0.3rem;
|
||||
justify-content: flex-end;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
.link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
|
||||
Reference in new issue
Block a user