From 65eaf362789a32217047b57c831ca3568a201dc4 Mon Sep 17 00:00:00 2001 From: Alvaro Parker Date: Wed, 7 Oct 2026 10:06:11 -0300 Subject: [PATCH] refactor(frontend): retire legacy CSS and isolate visual artwork --- AGENTS.md | 6 +- docs/client/architecture.md | 5 +- docs/client/design.md | 55 +- vocero-api/CHANGELOG.md | 5 + vocero-frontend/README.md | 11 +- vocero-frontend/src/App.tsx | 4 +- .../src/components/SettingsDialogs.tsx | 15 +- vocero-frontend/src/components/VoiceStage.tsx | 49 +- vocero-frontend/src/styles.css | 153 +- vocero-frontend/src/styles/base.css | 128 + vocero-frontend/src/styles/layout.css | 298 - vocero-frontend/src/styles/legacy-theme.css | 4820 ----------------- vocero-frontend/src/styles/markdown.css | 123 + vocero-frontend/src/styles/range.css | 26 + vocero-frontend/src/styles/theme.css | 26 +- vocero-frontend/src/styles/voice-stage.css | 986 ++++ 16 files changed, 1376 insertions(+), 5334 deletions(-) create mode 100644 vocero-frontend/src/styles/base.css delete mode 100644 vocero-frontend/src/styles/layout.css delete mode 100644 vocero-frontend/src/styles/legacy-theme.css create mode 100644 vocero-frontend/src/styles/markdown.css create mode 100644 vocero-frontend/src/styles/range.css create mode 100644 vocero-frontend/src/styles/voice-stage.css diff --git a/AGENTS.md b/AGENTS.md index 7fce268..e363b87 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -167,8 +167,10 @@ evidence; do not bundle them into tooling or structural refactors. `vocero-frontend/src/lib/messages.ts`. User text stays literal, and exports retain raw message text. Keep sanitization and unsafe-link regression coverage when changing it. -- Reuse the existing design tokens, Tailwind integration, and - `vocero-frontend/src/styles/legacy-theme.css`. Verify both light and dark themes, +- Reuse the Tailwind tokens in `vocero-frontend/src/styles/theme.css` and shared + controls in `vocero-frontend/src/components/ui.tsx`. Keep specialized artwork + and sanitized Markdown styles scoped under `vocero-frontend/src/styles/`. + Verify both light and dark themes, narrow screens, keyboard focus, dialog dismissal, and voice-state feedback for UI changes. Preserve intentional `?debug=true` controls and browser audio-permission flows. diff --git a/docs/client/architecture.md b/docs/client/architecture.md index e4fbe48..54584f0 100644 --- a/docs/client/architecture.md +++ b/docs/client/architecture.md @@ -57,8 +57,9 @@ audio. It is not an unconditional byte-for-byte tunnel. | [client.ts](../../vocero-frontend/src/realtime/client.ts) | Realtime protocol, session lifecycle, audio and transcript events | | [components](../../vocero-frontend/src/components) | Chat, caller profile, settings and voice components | | [audio](../../vocero-frontend/src/audio) | TypeScript capture/playback worklets, PCM codec, and visualizer | -| [legacy-theme.css](../../vocero-frontend/src/styles/legacy-theme.css) | Theme tokens, voice artwork and component appearance | -| [layout.css](../../vocero-frontend/src/styles/layout.css) | Shared responsive layout, transcript sizing and reduced-motion behavior | +| [theme.css](../../vocero-frontend/src/styles/theme.css) | Tailwind semantic tokens, configured theme variants and responsive variants | +| [ui.tsx](../../vocero-frontend/src/components/ui.tsx) | Shared Tailwind buttons, fields and dialog controls; layout utilities live with components | +| [styles](../../vocero-frontend/src/styles) | Minimal base defaults, reduced motion, audio artwork, sanitized Markdown, decorative surfaces and native range controls | ## Server routes diff --git a/docs/client/design.md b/docs/client/design.md index 11e4944..ae89e4f 100644 --- a/docs/client/design.md +++ b/docs/client/design.md @@ -1,7 +1,7 @@ # Design language This guide describes the current browser UI. Use -[legacy-theme.css](../../vocero-frontend/src/styles/legacy-theme.css) as the token/selector +[theme.css](../../vocero-frontend/src/styles/theme.css) as the Tailwind token reference and [App.tsx](../../vocero-frontend/src/App.tsx) for the theme-specific structure. Earlier documentation described a monochrome-only dark UI; the current design also uses aurora gradients, glass surfaces, and a separate light theme. @@ -10,8 +10,10 @@ also uses aurora gradients, glass surfaces, and a separate light theme. `S2S_THEME=white` selects the white/blue interface. Empty or `dark` selects the dark aurora interface. The browser sets `html[data-theme]` after configuration -loads; an initial visibility guard prevents the wrong theme flashing on first -paint. Extend the existing theme selectors when adding components. +loads; React renders a loading screen until configuration resolves. Theme values +live under `:root` and `html[data-theme="white"]`, with `@theme inline` exposing +semantic utilities. The `white:` and `dark:` variants follow this attribute, +independently of the browser's preferred color scheme. | Token group | Dark theme values/purpose | |---|---| @@ -20,14 +22,20 @@ paint. Extend the existing theme selectors when adding components. | Text | `--text`, `--text-dim`, `--text-faint` | | Borders | `--border` and `--border-strong` hairlines | | Brand | `--brand: #8b5cf6`, `--brand-2: #ec4899`, `--brand-3: #22d3ee` | -| Radius | `--radius-sm: 10px`, `--radius-md: 16px`, `--radius-lg: 26px`, `--radius-xl: 34px` | +| Radius | `rounded-control: 10px`, `rounded-panel: 16px`, `rounded-card: 26px` (22px in white) | | Shadows | `--shadow-soft`, `--shadow-glow-brand`, `--shadow-glass` | +Use semantic utilities such as `bg-surface`, `bg-surface-raised`, `text-foreground`, +`text-muted`, `border-line`, `rounded-control` and `shadow-panel`. Palette values +are runtime CSS variables; fonts are declared in `@theme`. Keep audio levels and +waveform bands outside the theme token registry. + Prefer existing variables and `color-mix` over new unrelated colors. The dark theme's orb is the strongest visual focus, while gradients and restrained role tints also appear in the surrounding interface. The white theme changes surfaces, typography contrast, controls and chat presentation through its own -selector overrides rather than a second stylesheet. +tokens and explicit component variants. The two voice presentations retain +their separate React markup and scoped artwork. ## Voice state @@ -62,29 +70,40 @@ details out of ordinary user flows. ## Layout and components The page uses a column layout: header, voice stage, always-visible inline -conversation, and sticky footer. The conversation is no longer the old -toggleable right overlay. Preserve space below the latest message so the sticky -footer does not obscure it; chat autoscroll retries after layout/reflow changes. +conversation, and footer. The document scrolls naturally while the transcript +has its own scroll area. New messages preserve the reader's position until they +return to the bottom or use the jump-to-latest action. In the dark theme, the reports sidebar is fixed on the left at desktop widths -of at least 1024px. On smaller screens it becomes an off-canvas panel with a -toggle and backdrop. The white theme hides the sidebar, its toggle, and hint. -The user avatar opens a profile dialog; profile fields collapse from two -columns on narrow screens. Some controls are intentionally gated by `?debug=true`. +of at least 1024px. On smaller screens it becomes a native dialog drawer with a +toggle and backdrop. The white theme omits the sidebar, its toggle, and hint. +The user avatar opens a profile dialog with label/value rows. Some controls are +intentionally gated by `?debug=true`. + +Reuse [ui.tsx](../../vocero-frontend/src/components/ui.tsx) for buttons, icon buttons, +fields and dialog controls. Keep layout utilities with the owning component. +Use complete class names in conditional maps; interpolated utility names cannot +be detected reliably. `compact:` preserves the existing maximum width of 600px; +`short:` covers heights at or below 640px. Other artwork breakpoints remain local. -Use the existing button, icon-button, modal, switch and chat-message classes. The dark theme uses glass bubbles with role tints, borders and restrained glow; -the light theme uses its white/blue message and avatar treatment. Keep required -chat DOM elements intact; optional historical overlay controls may be absent. +the light theme uses its white/blue message and avatar treatment. + +The stylesheet entry point imports Tailwind's theme and utilities without +Preflight. Keep resets explicit in `base.css`; enabling Preflight is a separate +visual change. Custom CSS is reserved for the page background, audio artwork, +sanitized Markdown descendants, decorative masks and native range pseudo-elements. +Do not add model-supplied utility classes to the Markdown sanitizer. ## Motion and accessibility Microphone RMS and assistant audio levels drive the voice visualization. Breathing, glow and decorative gradients should remain subordinate to speech -feedback. `body.booting` suppresses initial transitions; new animation should -respect that state and `prefers-reduced-motion`. +feedback. Preserve the reduced-motion rules in `base.css`: they disable both +CSS animations and the audio-driven transform variables. Their `!important` +declarations intentionally override inline variables written by the audio engine. -For changes, verify both themes, narrow mobile layouts down to 360px, keyboard +For changes, verify both themes, narrow mobile layouts down to 320px, keyboard focus, dialog dismissal, and readable contrast. Prefer touch targets of at least 44px and respect safe-area padding. A CSS guideline is not proof that every existing control already meets the target. diff --git a/vocero-api/CHANGELOG.md b/vocero-api/CHANGELOG.md index 376e5d8..5a6124a 100644 --- a/vocero-api/CHANGELOG.md +++ b/vocero-api/CHANGELOG.md @@ -31,6 +31,11 @@ the implementation at the recorded date; current operating instructions live in ### Changed +- Replace the frontend legacy stylesheet with Tailwind v4 semantic theme tokens, + shared form/dialog controls and component-owned layout utilities. Preserve both + configured themes, responsive layouts, sanitized Markdown and audio-driven + visuals in focused stylesheets, and remove unused historical selectors. + - Renamed the API and browser projects to `vocero-api/` and `vocero-frontend/`. Python uses the `vocero-api` distribution and `vocero_api` import package; npm uses `vocero-frontend`. Updated the launcher, Docker setup, tooling, diff --git a/vocero-frontend/README.md b/vocero-frontend/README.md index 4ad7d9a..cfb55ab 100644 --- a/vocero-frontend/README.md +++ b/vocero-frontend/README.md @@ -131,10 +131,13 @@ Vitest handles Node 26's experimental web storage behavior internally. - `src/lib/`: validated backend contracts, settings, prompt context, profile and report presentation, Markdown sanitization, and conversation exports. - `config/backend-proxy.ts`: the shared HTTP/WebSocket development proxy. -- `src/styles.css`: Tailwind integration and React-specific layout adjustments. -- `src/styles/legacy-theme.css`: the existing visual styles, retained for - fidelity to both the white microphone and dark orb themes. The UI is ported - to React; the full design has not been rewritten as Tailwind utilities. +- `src/styles.css`: Tailwind layer/import entry point. Preflight remains disabled. +- `src/styles/theme.css`: semantic Tailwind tokens and server-selected theme + variants. Use `bg-surface`, `text-foreground`, `border-line`, and related utilities. +- `src/components/ui.tsx`: shared buttons, icon buttons, fields and dialog controls. + Components own their layout, responsive utilities and interaction styling. +- `src/styles/`: minimal element defaults and reduced motion, voice artwork, + sanitized Markdown, decorative surfaces and native range pseudo-elements. The current Spanish interface, local preference keys, session-only RAG, Markdown replies, JSON/TXT exports, optional browser wake word, TALK/TALKFIRST diff --git a/vocero-frontend/src/App.tsx b/vocero-frontend/src/App.tsx index 4fd4200..963d9db 100644 --- a/vocero-frontend/src/App.tsx +++ b/vocero-frontend/src/App.tsx @@ -118,13 +118,13 @@ export default function App() { )}
-
+

Vocero diff --git a/vocero-frontend/src/components/SettingsDialogs.tsx b/vocero-frontend/src/components/SettingsDialogs.tsx index f9abd5c..c6fb07e 100644 --- a/vocero-frontend/src/components/SettingsDialogs.tsx +++ b/vocero-frontend/src/components/SettingsDialogs.tsx @@ -73,10 +73,11 @@ export function SettingsDialog({ state, controller, onClose }: Props) { {settings.noiseGate <= GATE_OFF ? "Desactivada" : `${String(settings.noiseGate)} dB`} -
-
+
+
-
+
Desactivada −3 dB
@@ -151,7 +152,13 @@ function GateMeter({ controller }: { controller: VoiceController }) { 0, Math.min(100, ((20 * Math.log10(level || 0.00001) - GATE_OFF) * 100) / (GATE_MAX - GATE_OFF)), ); - return