@@ -825,29 +826,37 @@ export function RecordingsWorkspace(props: RecordingsWorkspaceProps) {
filtered.map((item) => (
{
event.preventDefault();
openContextMenu(item, event.clientX, event.clientY);
}}
>
- props.onSelect(item.id)}>
-
- {item.transcription?.status === "completed" ? : }
-
+ props.onSelect(item.id)}
+ onDoubleClick={() => toggleQuickPlayback(item)}
+ onKeyDown={(event) => {
+ if (event.key !== " ") return;
+ event.preventDefault();
+ toggleQuickPlayback(item);
+ }}
+ >
{item.title}
-
+
{new Date(item.createdAt).toLocaleDateString("zh-CN", {
month: "short",
day: "numeric",
})}
- {" · "}{formatDuration(item.durationMs)}{" · "}{formatSize(item.sizeBytes)}
+ {" · "}{formatDuration(item.durationMs)}{" · "}
+
+
+ {item.transcription ? transcriptionLabel(item.transcription) : "未转写"}
+ {item.transcription ? transcriptionProgressSuffix(item.transcription) : ""}
+
-
- {item.transcription ? transcriptionLabel(item.transcription) : "未转写"}
- {item.transcription ? transcriptionProgressSuffix(item.transcription) : ""}
-
@@ -1193,7 +1202,6 @@ export function RecordingsWorkspace(props: RecordingsWorkspaceProps) {
}}
/>
- 本地录音;仅在转写或手动生成 AI 文档时连接所选服务
>
)}
diff --git a/src/recording-detail.css b/src/recording-detail.css
index 78c0808..04faa57 100644
--- a/src/recording-detail.css
+++ b/src/recording-detail.css
@@ -3,11 +3,12 @@
.library-workspace { grid-template-columns: 280px minmax(0, 1fr); }
.library-workspace.is-focused { grid-template-columns: minmax(0, 1fr); }
.library-workspace [hidden] { display: none !important; }
-.library-workspace .history-pane { padding: var(--space-4) var(--space-3) 0; }
-.library-workspace .history-header { align-items: center; gap: var(--space-2); }
+.library-workspace .history-pane { padding: var(--space-3) var(--space-2) 0; }
+.library-workspace .history-header { align-items: center; gap: var(--space-2); padding: 0 var(--space-1-5) var(--space-3); }
.library-workspace .history-header .eyebrow { display: none; }
.library-workspace .history-header-actions { gap: var(--space-1); }
-.library-workspace .history-item { padding-inline: var(--space-2); }
+.library-workspace .history-search { min-height: var(--control-height-large); margin-bottom: var(--space-2); padding-block: var(--space-1-5); border-radius: var(--radius-medium); }
+.library-workspace .history-item { padding-inline: var(--space-1); }
.library-workspace .transcript-pane { padding: 0; overflow: hidden; }
.library-workspace .recording-active-banner { flex: 0 0 auto; margin: var(--space-2) var(--space-4) 0; }
.library-workspace .record-detail-header { flex: 0 0 auto; align-items: center; margin: 0; padding: var(--space-3) var(--space-5); gap: var(--space-3); }
@@ -31,8 +32,7 @@
.library-workspace .transcription-version-select { min-width: 0; max-width: 190px; }
.library-workspace .transcription-version-select > span { display: none; }
.library-workspace .transcription-progress, .library-workspace .transcript-error { flex: 0 0 auto; margin: var(--space-2) var(--space-4); }
-.library-workspace .unified-player { flex: 0 0 auto; margin: 0; padding: var(--space-2) var(--space-4) 0; border: 0; border-top: 1px solid var(--color-border-subtle); border-radius: 0; background: var(--color-surface-primary); }
-.record-privacy-note { flex: 0 0 auto; padding: var(--space-1) var(--space-5) var(--space-2); color: var(--color-text-secondary); font-size: var(--font-size-caption); line-height: var(--line-height-caption); }
+.library-workspace .unified-player { flex: 0 0 auto; margin: 0; padding: var(--space-2) var(--space-4); border: 0; border-top: 1px solid var(--color-border-subtle); border-radius: 0; background: var(--color-surface-primary); }
.ai-documents-layout { min-height: 0; min-width: 0; display: flex; flex-direction: column; margin: 0; border: 0; border-radius: 0; overflow: visible; }
.ai-document-preview { flex: 1 1 0; }
.ai-document-toolbar { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-5); border-block: 1px solid var(--color-border-subtle); background: var(--color-surface-primary); }
diff --git a/src/styles.css b/src/styles.css
index 6f71e7b..2c829b9 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -506,6 +506,10 @@ body.capture-prompt-body {
.history-header { display: flex; align-items: end; justify-content: space-between; padding: 0 var(--space-1-5) var(--space-4); }
.history-header h1 { font-size: var(--font-size-subtitle); line-height: var(--line-height-subtitle); }
.history-header-actions { display: flex; align-items: center; gap: var(--space-2); }
+.history-count {
+ min-width: max-content; color: var(--color-text-muted); font-size: var(--font-size-caption); line-height: var(--line-height-caption);
+ font-weight: var(--font-weight-semibold); font-variant-numeric: tabular-nums;
+}
.import-audio-button { white-space: nowrap; }
.history-search {
display: flex; align-items: center; gap: var(--space-2); margin: 0 var(--space-1) var(--space-3); padding: var(--space-2) var(--space-3);
@@ -549,31 +553,62 @@ body.capture-prompt-body {
}
.history-list {
flex: 1 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto;
- overscroll-behavior: contain; scrollbar-gutter: stable; padding: 0 var(--space-1) var(--space-5);
-}
+ overscroll-behavior: contain; padding: 0 var(--space-1) var(--space-5);
+ scrollbar-width: thin; scrollbar-color: var(--color-border-default) transparent;
+}
+.history-list::-webkit-scrollbar { width: var(--space-1-5); }
+.history-list::-webkit-scrollbar-track { background: transparent; }
+.history-list::-webkit-scrollbar-thumb { border-radius: var(--radius-round); background: var(--color-border-default); }
+.history-list:hover::-webkit-scrollbar-thumb { background: var(--color-icon-muted); }
+.history-list::-webkit-scrollbar-button { display: none; }
.history-item {
- width: 100%; display: grid; grid-template-columns: minmax(0,1fr) 30px; align-items: center;
- margin-bottom: var(--space-1); padding: var(--space-1); border: 1px solid transparent; border-radius: var(--radius-large); background: transparent;
+ position: relative;
+ width: 100%; display: grid; grid-template-columns: minmax(0,1fr) var(--control-height-compact); align-items: center;
+ margin: 0; padding: 0 var(--space-1); border: 0; border-radius: var(--radius-medium); background: transparent;
+ transition: background-color var(--motion-duration-fast) var(--motion-easing-standard);
+}
+.history-item::after {
+ content: ""; position: absolute; right: var(--space-3); bottom: 0; left: var(--space-3); height: 1px;
+ background: var(--color-border-subtle); pointer-events: none;
+}
+.history-item::before {
+ content: ""; position: absolute; top: 50%; left: var(--space-0-5); width: var(--space-0-5); height: var(--space-6);
+ border-radius: var(--radius-round); background: var(--color-control-primary); opacity: 0; transform: translateY(-50%) scaleY(.6);
+ transition: opacity var(--motion-duration-fast) var(--motion-easing-standard), transform var(--motion-duration-fast) var(--motion-easing-standard);
}
.history-item:hover { background: var(--color-surface-hover-translucent); }
-.history-item.selected { border-color: var(--color-border-subtle); background: var(--color-surface-raised); box-shadow: var(--shadow-sm); }
-.history-item.menu-target { border-color: var(--color-border-default); background: var(--color-surface-raised); }
+.history-item.selected { background: var(--color-surface-brand); }
+.history-item.menu-target { background: var(--color-surface-brand-strong); }
+.history-item:is(:hover, .selected, .menu-target)::after { opacity: 0; }
+.history-item.selected::before { opacity: 1; transform: translateY(-50%) scaleY(1); }
.history-select {
- min-width: 0; display: flex; align-items: flex-start; gap: var(--space-2-5); padding: var(--space-2) var(--space-1-5);
+ min-width: 0; display: flex; align-items: center; padding: var(--space-2-5) var(--space-3);
border: 0; text-align: left; background: transparent; cursor: pointer;
}
-.history-quick-play {
- width: 28px; height: 28px; display: grid; place-items: center; border: 0; border-radius: 50%;
- color: var(--color-text-success); background: var(--color-surface-brand); cursor: pointer;
-}
-.history-quick-play:hover { color: var(--color-text-inverse); background: var(--color-control-primary); }
-.history-item-icon {
- width: 29px; height: 29px; display: grid; place-items: center; flex: 0 0 auto;
- border-radius: var(--radius-medium); color: var(--color-text-info); background: var(--color-surface-brand);
+.history-select:focus-visible {
+ outline: 0; border-radius: var(--radius-medium); box-shadow: var(--shadow-focus-compact);
}
-.history-item-main { min-width: 0; display: grid; gap: var(--space-1); }
+.history-quick-play {
+ width: var(--control-height-compact); height: var(--control-height-compact); display: grid; place-items: center;
+ border: 0; border-radius: var(--radius-round); color: var(--color-icon-primary); background: var(--color-surface-raised); box-shadow: var(--shadow-xs); cursor: pointer;
+ opacity: 0; visibility: hidden;
+ transition: color var(--motion-duration-fast) var(--motion-easing-standard), background-color var(--motion-duration-fast) var(--motion-easing-standard), opacity var(--motion-duration-fast) var(--motion-easing-standard), transform var(--motion-duration-fast) var(--motion-easing-standard);
+}
+.history-item:is(:hover, :focus-within, .selected, .is-playing, .menu-target) .history-quick-play {
+ opacity: 1; visibility: visible;
+}
+.history-quick-play:hover { color: var(--color-text-primary); background: var(--color-surface-sunken); }
+.history-quick-play:focus-visible { outline: 0; box-shadow: var(--shadow-focus-compact); }
+.history-quick-play:active { transform: scale(.97); }
+.history-item.is-playing .history-quick-play { color: var(--color-text-inverse); background: var(--color-control-primary); }
+.history-item-main { min-width: 0; display: grid; gap: var(--space-0-5); }
.history-item-main strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--font-size-body); line-height: var(--line-height-body); }
-.history-item-main small { color: var(--color-text-subtle); font-size: var(--font-size-caption); line-height: var(--line-height-caption); }
+.history-item-main small { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--color-text-subtle); font-size: var(--font-size-caption); line-height: var(--line-height-caption); font-variant-numeric: tabular-nums; }
+.history-transcription-status { display: inline-flex; align-items: center; gap: var(--space-1); color: var(--color-text-muted); font-weight: var(--font-weight-medium); }
+.history-status-dot { width: var(--space-1-5); height: var(--space-1-5); flex: 0 0 auto; border-radius: var(--radius-round); background: currentColor; }
+.history-transcription-status.status-completed { color: var(--color-text-success); background: transparent; }
+.history-transcription-status:is(.status-queued, .status-preparing, .status-transcribing) { color: var(--color-text-info); background: transparent; }
+.history-transcription-status:is(.status-failed, .status-interrupted, .status-cancelled) { color: var(--color-text-danger); background: transparent; }
.transcription-badge {
width: max-content; display: inline-flex; align-items: center; padding: var(--space-0-5) var(--space-2);
border-radius: var(--radius-round); color: var(--color-text-muted); background: var(--color-surface-hover); font-size: var(--font-size-caption); line-height: var(--line-height-caption); font-weight: var(--font-weight-semibold);
@@ -581,6 +616,10 @@ body.capture-prompt-body {
.status-completed { color: var(--color-text-success); background: var(--color-surface-success); }
.status-queued, .status-preparing, .status-transcribing { color: var(--color-text-info); background: var(--color-surface-info); }
.status-failed, .status-interrupted, .status-cancelled { color: var(--color-text-danger); background: var(--color-surface-danger); }
+@media (forced-colors: active) {
+ .history-list { scrollbar-color: auto; }
+ .history-item.selected { outline: 1px solid Highlight; outline-offset: -1px; }
+}
.history-empty { display: grid; place-items: center; gap: var(--space-2); padding: var(--space-14) var(--space-4); color: var(--color-text-subtle); }
.history-empty strong { font-size: var(--font-size-body); line-height: var(--line-height-body); color: var(--color-text-secondary); }.history-empty span { font-size: var(--font-size-caption); line-height: var(--line-height-caption); }
.transcript-pane {
From 8f70b3eeb069a74204c6b32488f28a8500a99074 Mon Sep 17 00:00:00 2001
From: Kelvin Poon <35914355+kwp-lab@users.noreply.github.com>
Date: Wed, 16 Sep 2026 15:31:43 +0800
Subject: [PATCH 2/2] feat: polish recording library for 0.11.0
---
CHANGELOG.md | 17 +++--
README.md | 2 +-
README.zh-CN.md | 2 +-
THIRD_PARTY_NOTICES.txt | 2 +-
bom.cyclonedx.json | 4 +-
docs/design-system.md | 31 +++++----
package-lock.json | 4 +-
package.json | 2 +-
src-tauri/Cargo.lock | 2 +-
src-tauri/Cargo.toml | 2 +-
src-tauri/tauri.conf.json | 2 +-
src/components/RecordingsWorkspace.test.tsx | 9 ++-
src/components/RecordingsWorkspace.tsx | 17 ++---
src/design-tokens.css | 70 ++++++++++-----------
src/styles.css | 45 +++++++------
15 files changed, 120 insertions(+), 91 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa3a85c..024eab1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,17 @@ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.ht
## [Unreleased]
+## [0.11.0] - 2026-09-16
+
+### Changed
+
+- Refined the recording library into compact two-line rows with regular-weight
+ truncated titles, trailing semantic status badges, flatter selection,
+ subtle inset separators, quieter progressive quick-play actions, a narrow
+ scrollbar, and playback controls free of the redundant persistent
+ network-use reminder. Refreshed the shared neutral palette to cleaner white
+ and cool-neutral surfaces with stronger secondary-text legibility.
+
## [0.10.0] - 2026-09-15
### Added
@@ -22,9 +33,6 @@ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.ht
### Changed
-- Refined the recording library into compact two-line rows with flatter
- selection, quieter progressive quick-play actions, a narrow scrollbar, and
- playback controls free of the redundant persistent network-use reminder.
- Simplified the AI document toolbar with bounded document/version selectors,
icon-only revision and copy actions, generation details in the overflow menu,
and one generation dialog for both new templates and new versions of an
@@ -398,7 +406,8 @@ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.ht
- Added GitHub Actions workflows for continuous integration and tagged Windows releases.
- Added English and Simplified Chinese README documentation.
-[Unreleased]: https://github.com/kwp-lab/nota/compare/v0.10.0...HEAD
+[Unreleased]: https://github.com/kwp-lab/nota/compare/v0.11.0...HEAD
+[0.11.0]: https://github.com/kwp-lab/nota/compare/v0.10.0...v0.11.0
[0.10.0]: https://github.com/kwp-lab/nota/compare/v0.9.0...v0.10.0
[0.9.0]: https://github.com/kwp-lab/nota/compare/v0.8.0...v0.9.0
[0.8.0]: https://github.com/kwp-lab/nota/compare/v0.7.0...v0.8.0
diff --git a/README.md b/README.md
index d253d06..3aff6bd 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@
-
+
diff --git a/README.zh-CN.md b/README.zh-CN.md
index a2d450d..4c91f00 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -19,7 +19,7 @@
-
+
diff --git a/THIRD_PARTY_NOTICES.txt b/THIRD_PARTY_NOTICES.txt
index b129cac..899a904 100644
--- a/THIRD_PARTY_NOTICES.txt
+++ b/THIRD_PARTY_NOTICES.txt
@@ -4242,7 +4242,7 @@ developed by Chen Jiaju, licensed under the MIT License and the Apache License 2
-------------------------------------------------------------------------------
MIT License (MIT)
Used by:
-- nota 0.10.0
+- nota 0.11.0
- brotli-decompressor 5.0.3
- cargo_toml 0.22.3
- dpi 0.1.2
diff --git a/bom.cyclonedx.json b/bom.cyclonedx.json
index 691cdcc..f7694e6 100644
--- a/bom.cyclonedx.json
+++ b/bom.cyclonedx.json
@@ -1,14 +1,14 @@
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
- "serialNumber": "urn:uuid:2e51a386-9432-4a50-a3c3-0e7d998d7106",
+ "serialNumber": "urn:uuid:30a8310e-8b01-43a9-a4ca-542abf91333f",
"version": 1,
"metadata": {
"component": {
"type": "application",
"bom-ref": "pkg:github/kwp-lab/nota",
"name": "Nota",
- "version": "0.10.0",
+ "version": "0.11.0",
"licenses": [
{
"license": {
diff --git a/docs/design-system.md b/docs/design-system.md
index e86a37f..01665de 100644
--- a/docs/design-system.md
+++ b/docs/design-system.md
@@ -11,7 +11,7 @@ It is intentionally separate from marketing artwork and release assets.
## Product Character
Nota should feel calm, trustworthy, local, and precise. The visual language
-uses warm neutral surfaces and a restrained jade accent so recording state and
+uses clean neutral surfaces and a restrained jade accent so recording state and
meeting content remain more prominent than decoration. Interfaces should feel
native to Windows 11 without impersonating a Microsoft product.
@@ -226,17 +226,24 @@ The compact title, detail tabs, contextual toolbar, reading region, and native
audio player follow DOM order. The list and reading region scroll independently;
the outer detail pane must not scroll. Playback remains mounted across tabs.
The recording list uses compact two-line rows rather than individual cards. A
-row contains the recording title followed by date, duration, and transcription
-state on one metadata line; file size remains available in the selected
-recording header instead of being repeated throughout the list. Status uses a
-compact semantic dot plus text, not a pill or a second leading icon. Subtle
-inset dividers establish row rhythm, while the selected row adds a short jade
-selection marker and flat brand surface. The quick-play action appears for
-hover, keyboard focus, selection, or active playback, and Space toggles
-playback for the focused row. Its circular raised surface distinguishes the
-row action from the selection target without returning to a second permanent
-icon column. The list scrollbar uses a narrow neutral thumb on a transparent
-track while retaining a visible high-contrast fallback.
+row contains a regular-weight, single-line recording title followed by a
+two-ended metadata line: date and duration stay at the leading edge, while a
+compact semantic transcription badge aligns to the trailing edge. Long titles
+truncate with an ellipsis without displacing the fixed quick-play action; the
+full title remains available to assistive technology and on pointer hover. File
+size remains available in the selected recording header instead of being
+repeated throughout the list. Status badges use Caption text, a small radius,
+semantic foreground/surface colors, and a subtle border instead of relying on
+text color alone. Quiet inter-row spacing, comfortable vertical padding, and
+subtle inset hairline separators establish rhythm without turning rows into
+individual cards or restoring a permanent leading icon. Separators sit between
+rows and disappear when a row is hovered, selected, or owns an open context
+menu so the interactive surface reads as one unit. The selected row uses a
+flat brand surface. The quick-play action appears for hover, keyboard focus,
+selection, or active playback, and Space toggles playback for the focused row.
+Its compact trailing slot remains reserved so row content does not shift when
+the action appears. The list scrollbar uses a narrow neutral thumb on a
+transparent track while retaining a visible high-contrast fallback.
AI documents use shared select styling for document/version selection instead
of a permanent nested document sidebar. The document selector may grow to a
diff --git a/package-lock.json b/package-lock.json
index 0370a83..6306c66 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "nota",
- "version": "0.10.0",
+ "version": "0.11.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "nota",
- "version": "0.10.0",
+ "version": "0.11.0",
"license": "MIT",
"dependencies": {
"@radix-ui/react-select": "^2.3.7",
diff --git a/package.json b/package.json
index fcef732..a3970cd 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "nota",
"private": true,
- "version": "0.10.0",
+ "version": "0.11.0",
"license": "MIT",
"repository": {
"type": "git",
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index 74bea21..07e3b70 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -2299,7 +2299,7 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]]
name = "nota"
-version = "0.10.0"
+version = "0.11.0"
dependencies = [
"anyhow",
"arboard",
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index ec3990d..4c5e060 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "nota"
-version = "0.10.0"
+version = "0.11.0"
description = "A private, local-first Windows meeting recorder"
authors = ["Nota Contributors"]
license = "MIT"
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index df2ab66..16bd508 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Nota",
- "version": "0.10.0",
+ "version": "0.11.0",
"identifier": "com.local.meetingnote",
"build": {
"beforeDevCommand": "npm run dev:web",
diff --git a/src/components/RecordingsWorkspace.test.tsx b/src/components/RecordingsWorkspace.test.tsx
index 80c61eb..efec842 100644
--- a/src/components/RecordingsWorkspace.test.tsx
+++ b/src/components/RecordingsWorkspace.test.tsx
@@ -322,10 +322,17 @@ describe("RecordingsWorkspace", () => {
const list = screen.getByLabelText("录音列表");
const row = within(list).getByText("产品周会").closest("article")!;
const metadata = row.querySelector(".history-item-meta");
+ const title = within(row).getByText("产品周会");
+ const status = within(row).getByText("已转写");
expect(screen.getByLabelText("2 条录音")).toHaveTextContent("2 条");
expect(row.querySelector(".history-item-icon")).toBeNull();
- expect(row.querySelector(".history-status-dot")).toBeInTheDocument();
+ expect(row.querySelector(".history-status-dot")).toBeNull();
+ expect(title).toHaveClass("history-item-title");
+ expect(title).toHaveAttribute("title", "产品周会");
+ expect(metadata?.firstElementChild).toHaveClass("history-item-facts");
+ expect(metadata?.lastElementChild).toBe(status);
+ expect(status).toHaveClass("transcription-badge", "history-transcription-status", "status-completed");
expect(metadata).toHaveTextContent("1:02");
expect(metadata).toHaveTextContent("已转写");
expect(within(list).queryByText("1.0 MB")).not.toBeInTheDocument();
diff --git a/src/components/RecordingsWorkspace.tsx b/src/components/RecordingsWorkspace.tsx
index 0ef1f5a..b41ffe7 100644
--- a/src/components/RecordingsWorkspace.tsx
+++ b/src/components/RecordingsWorkspace.tsx
@@ -845,15 +845,16 @@ export function RecordingsWorkspace(props: RecordingsWorkspaceProps) {
}}
>
- {item.title}
+ {item.title}
- {new Date(item.createdAt).toLocaleDateString("zh-CN", {
- month: "short",
- day: "numeric",
- })}
- {" · "}{formatDuration(item.durationMs)}{" · "}
-
-
+
+ {new Date(item.createdAt).toLocaleDateString("zh-CN", {
+ month: "short",
+ day: "numeric",
+ })}
+ {" · "}{formatDuration(item.durationMs)}
+
+
{item.transcription ? transcriptionLabel(item.transcription) : "未转写"}
{item.transcription ? transcriptionProgressSuffix(item.transcription) : ""}
diff --git a/src/design-tokens.css b/src/design-tokens.css
index ec62cbd..fae4d90 100644
--- a/src/design-tokens.css
+++ b/src/design-tokens.css
@@ -23,15 +23,15 @@
--font-weight-semibold: 600;
--font-weight-bold: 700;
- /* Nota's warm-neutral, calm-jade semantic color system. */
- --color-text-primary: #242726;
- --color-text-secondary: #59615d;
- --color-text-muted: #737a76;
- --color-text-subtle: #858a86;
- --color-text-disabled: #999d99;
+ /* Nota's clean-neutral, calm-jade semantic color system. */
+ --color-text-primary: #2b302e;
+ --color-text-secondary: #4f5954;
+ --color-text-muted: #626c67;
+ --color-text-subtle: #66706b;
+ --color-text-disabled: #8d9590;
--color-text-inverse: #ffffff;
- --color-text-brand: #285f58;
- --color-text-success: #2d675e;
+ --color-text-brand: #245e55;
+ --color-text-success: #285f57;
--color-text-info: #3d6875;
--color-text-warning: #80621e;
--color-text-danger: #a23e3e;
@@ -45,45 +45,45 @@
--color-syntax-null: var(--color-text-muted);
--color-syntax-punctuation: var(--color-text-secondary);
- --color-surface-canvas: #f4f3ef;
- --color-surface-primary: #fbfaf7;
+ --color-surface-canvas: #f4f6f4;
+ --color-surface-primary: #ffffff;
--color-surface-raised: #ffffff;
- --color-surface-subtle: #f1f0ec;
- --color-surface-sunken: #efeee9;
- --color-surface-hover: #ebeae5;
- --color-surface-brand: #e4eeeb;
- --color-surface-brand-strong: #dce9e6;
- --color-surface-success: #dfebe7;
- --color-surface-info: #deebef;
- --color-surface-warning: #f5eedf;
- --color-surface-danger: #f2e3df;
+ --color-surface-subtle: #f7f8f6;
+ --color-surface-sunken: #eef1ee;
+ --color-surface-hover: #e9eeea;
+ --color-surface-brand: #e1eeea;
+ --color-surface-brand-strong: #d8e9e4;
+ --color-surface-success: #deede8;
+ --color-surface-info: #e2edf0;
+ --color-surface-warning: #f7f1e4;
+ --color-surface-danger: #f4e7e3;
--color-surface-tooltip: #26312e;
- --color-border-default: #d8d7d1;
- --color-border-subtle: #e5e4df;
- --color-border-strong: #bed2cc;
- --color-border-danger: #e7cfca;
+ --color-border-default: #dce1dd;
+ --color-border-subtle: #e7ebe8;
+ --color-border-strong: #b8d3cb;
+ --color-border-danger: #e5ccc5;
--color-border-inverse: #ffffff;
- --color-focus-ring: #4d7f77;
+ --color-focus-ring: #477a72;
- --color-control-primary: #285f58;
- --color-control-primary-hover: #214f49;
+ --color-control-primary: #245e55;
+ --color-control-primary-hover: #1f514a;
--color-control-secondary: #ffffff;
--color-control-danger: #a23e3e;
- --color-icon-primary: #59615d;
- --color-icon-muted: #737a76;
- --color-icon-brand: #39786e;
- --color-brand-accent: #4b8178;
- --color-brand-accent-soft: #72a49b;
+ --color-icon-primary: #56615c;
+ --color-icon-muted: #66706b;
+ --color-icon-brand: #34766b;
+ --color-brand-accent: #468078;
+ --color-brand-accent-soft: #70a49b;
--color-status-recording: #c84f45;
--color-status-paused: #bd8b35;
--color-status-warning-accent: #d99a42;
/* Translucent surfaces and effect colors. */
- --color-surface-app-chrome: rgba(248, 247, 243, 0.92);
- --color-surface-app-chrome-soft: rgba(248, 247, 243, 0.88);
- --color-surface-glass: rgba(255, 254, 251, 0.98);
- --color-surface-hover-translucent: rgba(255, 255, 255, 0.55);
+ --color-surface-app-chrome: rgba(247, 249, 247, 0.92);
+ --color-surface-app-chrome-soft: rgba(247, 249, 247, 0.88);
+ --color-surface-glass: rgba(255, 255, 255, 0.98);
+ --color-surface-hover-translucent: rgba(255, 255, 255, 0.62);
--color-surface-selected-translucent: rgba(255, 255, 255, 0.72);
--color-border-inverse-subtle: rgba(255, 255, 255, 0.09);
--color-fill-inverse-subtle: rgba(255, 255, 255, 0.18);
diff --git a/src/styles.css b/src/styles.css
index 2c829b9..7149bfa 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -452,7 +452,7 @@ body.capture-prompt-body {
.app-sidebar {
position: relative; z-index: 10; display: flex; flex-direction: column; align-items: stretch;
gap: var(--space-2); min-height: 100vh; padding: var(--space-4) var(--space-2-5) var(--space-3); border-right: 1px solid var(--color-border-default);
- background: var(--color-surface-hover);
+ background: var(--color-surface-sunken);
}
.sidebar-brand {
width: 42px; height: 42px; display: grid; place-items: center; align-self: center;
@@ -552,7 +552,7 @@ body.capture-prompt-body {
.audio-import-progress.indeterminate i { animation: none; }
}
.history-list {
- flex: 1 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto;
+ flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: var(--space-1); overflow-x: hidden; overflow-y: auto;
overscroll-behavior: contain; padding: 0 var(--space-1) var(--space-5);
scrollbar-width: thin; scrollbar-color: var(--color-border-default) transparent;
}
@@ -568,19 +568,14 @@ body.capture-prompt-body {
transition: background-color var(--motion-duration-fast) var(--motion-easing-standard);
}
.history-item::after {
- content: ""; position: absolute; right: var(--space-3); bottom: 0; left: var(--space-3); height: 1px;
- background: var(--color-border-subtle); pointer-events: none;
-}
-.history-item::before {
- content: ""; position: absolute; top: 50%; left: var(--space-0-5); width: var(--space-0-5); height: var(--space-6);
- border-radius: var(--radius-round); background: var(--color-control-primary); opacity: 0; transform: translateY(-50%) scaleY(.6);
- transition: opacity var(--motion-duration-fast) var(--motion-easing-standard), transform var(--motion-duration-fast) var(--motion-easing-standard);
+ content: ""; position: absolute; right: var(--space-1); bottom: calc(-1 * var(--space-0-5)); left: var(--space-3); height: 1px;
+ background: var(--color-border-default); pointer-events: none;
+ transition: opacity var(--motion-duration-fast) var(--motion-easing-standard);
}
+.history-item:last-child::after, .history-item:is(:hover, .selected, .menu-target)::after { opacity: 0; }
.history-item:hover { background: var(--color-surface-hover-translucent); }
.history-item.selected { background: var(--color-surface-brand); }
.history-item.menu-target { background: var(--color-surface-brand-strong); }
-.history-item:is(:hover, .selected, .menu-target)::after { opacity: 0; }
-.history-item.selected::before { opacity: 1; transform: translateY(-50%) scaleY(1); }
.history-select {
min-width: 0; display: flex; align-items: center; padding: var(--space-2-5) var(--space-3);
border: 0; text-align: left; background: transparent; cursor: pointer;
@@ -590,25 +585,27 @@ body.capture-prompt-body {
}
.history-quick-play {
width: var(--control-height-compact); height: var(--control-height-compact); display: grid; place-items: center;
- border: 0; border-radius: var(--radius-round); color: var(--color-icon-primary); background: var(--color-surface-raised); box-shadow: var(--shadow-xs); cursor: pointer;
+ border: 0; border-radius: var(--radius-small); color: var(--color-icon-primary); background: transparent; cursor: pointer;
opacity: 0; visibility: hidden;
transition: color var(--motion-duration-fast) var(--motion-easing-standard), background-color var(--motion-duration-fast) var(--motion-easing-standard), opacity var(--motion-duration-fast) var(--motion-easing-standard), transform var(--motion-duration-fast) var(--motion-easing-standard);
}
.history-item:is(:hover, :focus-within, .selected, .is-playing, .menu-target) .history-quick-play {
opacity: 1; visibility: visible;
}
-.history-quick-play:hover { color: var(--color-text-primary); background: var(--color-surface-sunken); }
+.history-quick-play:hover { color: var(--color-text-primary); background: var(--color-surface-raised); }
.history-quick-play:focus-visible { outline: 0; box-shadow: var(--shadow-focus-compact); }
.history-quick-play:active { transform: scale(.97); }
.history-item.is-playing .history-quick-play { color: var(--color-text-inverse); background: var(--color-control-primary); }
.history-item-main { min-width: 0; display: grid; gap: var(--space-0-5); }
-.history-item-main strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--font-size-body); line-height: var(--line-height-body); }
-.history-item-main small { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--color-text-subtle); font-size: var(--font-size-caption); line-height: var(--line-height-caption); font-variant-numeric: tabular-nums; }
-.history-transcription-status { display: inline-flex; align-items: center; gap: var(--space-1); color: var(--color-text-muted); font-weight: var(--font-weight-medium); }
-.history-status-dot { width: var(--space-1-5); height: var(--space-1-5); flex: 0 0 auto; border-radius: var(--radius-round); background: currentColor; }
-.history-transcription-status.status-completed { color: var(--color-text-success); background: transparent; }
-.history-transcription-status:is(.status-queued, .status-preparing, .status-transcribing) { color: var(--color-text-info); background: transparent; }
-.history-transcription-status:is(.status-failed, .status-interrupted, .status-cancelled) { color: var(--color-text-danger); background: transparent; }
+.history-item-title {
+ display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
+ color: var(--color-text-primary); font-size: var(--font-size-body); line-height: var(--line-height-body); font-weight: var(--font-weight-regular);
+}
+.history-item-meta {
+ min-width: 0; display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
+ color: var(--color-text-subtle); font-size: var(--font-size-caption); line-height: var(--line-height-caption); font-variant-numeric: tabular-nums;
+}
+.history-item-facts { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.transcription-badge {
width: max-content; display: inline-flex; align-items: center; padding: var(--space-0-5) var(--space-2);
border-radius: var(--radius-round); color: var(--color-text-muted); background: var(--color-surface-hover); font-size: var(--font-size-caption); line-height: var(--line-height-caption); font-weight: var(--font-weight-semibold);
@@ -616,9 +613,17 @@ body.capture-prompt-body {
.status-completed { color: var(--color-text-success); background: var(--color-surface-success); }
.status-queued, .status-preparing, .status-transcribing { color: var(--color-text-info); background: var(--color-surface-info); }
.status-failed, .status-interrupted, .status-cancelled { color: var(--color-text-danger); background: var(--color-surface-danger); }
+.history-transcription-status {
+ width: auto; max-width: 50%; min-width: 0; min-height: var(--line-height-caption); flex: 0 1 auto; justify-content: center;
+ overflow: hidden; padding: 0 var(--space-1-5); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-small);
+ font-weight: var(--font-weight-medium); line-height: 1; text-overflow: ellipsis; white-space: nowrap;
+}
+.history-transcription-status.status-completed { border-color: var(--color-border-strong); }
+.history-transcription-status:is(.status-failed, .status-interrupted, .status-cancelled) { border-color: var(--color-border-danger); }
@media (forced-colors: active) {
.history-list { scrollbar-color: auto; }
.history-item.selected { outline: 1px solid Highlight; outline-offset: -1px; }
+ .history-transcription-status { border-color: currentColor; }
}
.history-empty { display: grid; place-items: center; gap: var(--space-2); padding: var(--space-14) var(--space-4); color: var(--color-text-subtle); }
.history-empty strong { font-size: var(--font-size-body); line-height: var(--line-height-body); color: var(--color-text-secondary); }.history-empty span { font-size: var(--font-size-caption); line-height: var(--line-height-caption); }