Skip to content

Commit 250c892

Browse files
Merge pull request #1 from muhammadhasnainsaeed/feat/ui-revamp
Feat/UI revamp
2 parents eaa8c8c + 34f37f7 commit 250c892

36 files changed

Lines changed: 3896 additions & 1467 deletions

docs/CHANGELOG.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1350,3 +1350,97 @@ Both factors are now addressed: interim translations trigger for longer sentence
13501350
secrets.
13511351
- Docs updated: `docs/CURRENT_STATE.md` (M10 Phase 4 section + next task),
13521352
this file.
1353+
1354+
## [1.0.1] - 2026-08-31
1355+
1356+
### M11 — shadcn-style UI design-system revamp (UI/design-system only)
1357+
1358+
- Replaced the renderer styles with a cohesive design-token system in
1359+
`src/renderer/styles/App.css`: CSS-variable tokens (`--bg/--panel/--surface/
1360+
--border/--fg*`, semantic `--success/--warning/--destructive/--info/--brand`,
1361+
`--radius-*`, 4/6/8/12/16 spacing scale, type scale, `--font-urdu`). Removed
1362+
ad-hoc hex literals and inconsistent radii.
1363+
- Added hand-rolled shadcn-style primitives in `src/renderer/components/ui/`
1364+
(button, card, badge, label, select, separator, alert, progress) — same
1365+
component API/variants as shadcn but implemented in plain CSS + TSX with
1366+
CSS-variable tokens. **Zero new runtime dependencies** (no Tailwind/Radix/
1367+
shadcn-CLI), honoring the minimal-dependency footprint.
1368+
- Redesigned onboarding into a compact "Get Ready" checklist (Microphone /
1369+
Audio Output / BlackHole rows with status Badges + inline actions; Ready or
1370+
pending banner). Same `setupState.ts` logic.
1371+
- Rebuilt HomeScreen + all panels (Microphone, Translation, TTS, Audio Output,
1372+
Speech Recognition, Pipeline, AudioLevelMeter) into compact shadcn-style
1373+
cards; split the oversized SttPanel monolith into single-purpose panels.
1374+
Compact spacing (buttons 26px, titles 13px) and restrained typography.
1375+
- Accessibility: `role=progressbar`, `role=alert`, `aria-*`, focus states.
1376+
- No business-logic changes: `App.tsx` and `packages/shared/index.ts`
1377+
untouched; provider/session/IPC/audio/BlackHole logic unchanged.
1378+
- Validation: `npm run type-check` clean; `npm test` 60/60; `npm run build`
1379+
OK; `npm run package:dir` OK. CDP-verified dev + packaged (`app.asar`) app:
1380+
all 8 cards render, selects populated, Get Ready "Ready", Start/Stop Meeting
1381+
3-cycle returns to Ready, zero console errors on reload.
1382+
- Docs updated: `docs/CURRENT_STATE.md` (M11 section + files at a glance),
1383+
this file.
1384+
1385+
## [1.1.0] - 2026-09-01
1386+
1387+
### M11 follow-up — Migrate custom shadcn-style UI to real shadcn/ui + Tailwind
1388+
1389+
Replaced the hand-rolled plain-CSS shadcn-style implementation with the actual
1390+
shadcn/ui + Tailwind CSS foundation, preserving the complete M11 UX structure,
1391+
component split, and functional wiring (UI/design-system migration only).
1392+
1393+
- **Tailwind integration** (`tailwind.config.js`, `esbuild.config.js`): added
1394+
Tailwind v3 + `tailwindcss-animate`; renders any CSS via a new Tailwind CLI
1395+
pre-build step in `esbuild.config.js` that compiles
1396+
`src/renderer/styles/globals.css``dist/renderer/tailwind.css`; `index.html`
1397+
now links `tailwind.css` instead of `bundle.css`. esbuild still bundles JS
1398+
(main/preload/renderer) unchanged — no Vite, no new framework.
1399+
- **shadcn/ui**: real shadcn source-style components in
1400+
`src/renderer/components/ui/``button.tsx` (cva + Radix Slot), `card.tsx`,
1401+
`badge.tsx` (cva + extended semantic variants success/warning/info/muted +
1402+
dot), `select.tsx` (Radix Select), `label.tsx` (Radix Label),
1403+
`separator.tsx` (Radix Separator), `alert.tsx` (cva + AlertTitle/
1404+
AlertDescription, extended warning/success variants), `progress.tsx`
1405+
(Radix Progress), `dropdown-menu.tsx` (Radix DropdownMenu), plus
1406+
`lib/utils.ts` (`cn()` via clsx + tailwind-merge). `@/` alias → `src/renderer`
1407+
added in `tsconfig.json` and esbuild.
1408+
- **Theme system** (`components/theme-provider.tsx`): shadcn CSS-variable token
1409+
system (neutral/zinc palette) in `globals.css` `:root` (light) + `.dark`;
1410+
semantic tokens background/foreground/card/popover/primary/secondary/muted/
1411+
accent/destructive/border/input/ring. Theme switching via the standard shadcn
1412+
mode-toggle (`components/theme-selector.tsx`) — icon Button with Sun/Moon +
1413+
DropdownMenu (Light/Dark/System). Persists to `localStorage["ui-theme"]`;
1414+
System follows `prefers-color-scheme` via `matchMedia`, reactive to OS change.
1415+
- **Components migrated** to Tailwind utility classes (no custom CSS classes):
1416+
HomeScreen, SetupPanel, MicrophonePanel, SttPanel, TranslationPanel,
1417+
TtsPanel, AudioOutputPanel, PipelinePanel, AudioLevelMeter. Panels switched
1418+
from native `<select>` to Radix Select; buttons/badges/alerts/progress now
1419+
use the real shadcn components. Compact/neutral/technical Linear-Vercel look
1420+
preserved (h-8 controls, 13px titles).
1421+
- **Removed obsolete design system**: deleted `src/renderer/styles/App.css`
1422+
and the dead legacy stubs `StatusBar.tsx`, `SubtitleDisplay.tsx`,
1423+
`LiveTranslationScreen.tsx`; removed `import "./styles/App.css"` from
1424+
App.tsx. Only app-specific CSS kept in `globals.css` (Urdu RTL/Nastaliq
1425+
transcript, thin scrollbars). One UI system remains.
1426+
- **Dependencies**: added `tailwindcss` (dev), `class-variance-authority`,
1427+
`clsx`, `tailwind-merge`, `tailwindcss-animate`, `@radix-ui/react-slot`,
1428+
`@radix-ui/react-select`, `@radix-ui/react-label`,
1429+
`@radix-ui/react-separator`, `@radix-ui/react-progress`,
1430+
`@radix-ui/react-dropdown-menu`, `lucide-react`. Removed redundant root
1431+
`postcss`/`autoprefixer` (Tailwind bundles them). No UI framework, no
1432+
animation/state libs, no build-tooling change.
1433+
- **No business-logic changes**: STT/Translation/TTS/audio-output providers,
1434+
SessionManager, IPC contracts, mic permission flow, BlackHole detection,
1435+
telemetry, meeting start/stop, audio routing, `PIPELINE_DEBUG` all unchanged.
1436+
`packages/shared/index.ts`, `src/main/*`, `src/preload/*` untouched.
1437+
- **Validation**: `npm run type-check` clean; `npm test` 60/60; `npm run build`
1438+
OK (produces `bundle.js` + `tailwind.css` + `index.html`); `npm run
1439+
package:dir` OK and asar contains all three renderer assets. Packaged-app CDP
1440+
verification (from `app.asar`): all 7 panels render; theme toggle opens menu;
1441+
Light (white bg)/Dark (zinc-950 bg)/System (follows OS) all switch correctly
1442+
and persist (`ui-theme`); output & mic Radix selects enumerate devices
1443+
(incl. BlackHole); Start/Stop Meeting 2-cycle returns Ready; zero console
1444+
errors.
1445+
- Docs updated: `docs/CURRENT_STATE.md` (M11 follow-up section + files at a
1446+
glance), this file.

docs/CURRENT_STATE.md

Lines changed: 128 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,122 @@ Comparison vs Phase 1 (legacy) and Phase 2 (streaming) digital averages:
591591
- **Signing/notarization**: still NOT done (no Apple Developer identity).
592592
Same BLOCKED status as M10 Phase 3.
593593

594+
### M11 UI — shadcn-style design-system revamp (2026-08-31, complete)
595+
596+
- **Scope**: UI/design-system only. STT, Translation, TTS, Audio Output,
597+
SessionManager, IPC, telemetry, provider logic, audio routing, BlackHole
598+
detection, and meeting functionality are **unchanged**. `App.tsx` and
599+
`packages/shared/index.ts` were not modified — every panel's prop contract
600+
is preserved, so no data-flow wiring changed.
601+
- **Design tokens** (`src/renderer/styles/App.css`, file replaced): `:root`
602+
CSS-variable tokens — `--bg`, `--panel`, `--surface`, `--border`, `--fg*`,
603+
semantic colors (`--success/warning/destructive/info/brand`), `--radius-*`
604+
(4/6/8/10), spacing scale `--sp-*` (4/6/8/12/16), `--font-sans`,
605+
`--font-urdu`, type scale `--text-xs/sm/base/lg`. Layout helpers
606+
(`.stack/.row/.split/.grow`), ui primitive classes (`.btn*/.card*/.badge*`
607+
`.label/.separator*/.select*/.alert*/.progress*/.textbox*`), and
608+
screen-specific classes (`.setup-*/.meeting-stage/.error-text`). Removed all
609+
hard-coded hex colors and the 8/10/12px radius inconsistency.
610+
- **Hand-rolled shadcn-style primitives** (`src/renderer/components/ui/`):
611+
`button.tsx` (variants `default/primary/success/destructive/outline/ghost`,
612+
sizes `sm/md/lg`), `card.tsx`, `badge.tsx` (+`dot`), `label.tsx`,
613+
`select.tsx` (`Select/SelectItem`), `separator.tsx` (h/v),
614+
`alert.tsx` (variants + optional `title`), `progress.tsx`
615+
(`role=progressbar` + `aria-*`). **Zero new runtime dependencies** — no
616+
Tailwind/Radix/shadcn-CLI per the minimal-dependency constraint; the
617+
primitives share the shadcn component API/variants but are plain CSS + TSX
618+
with CSS-variable tokens.
619+
- **Onboarding redesigned** (`SetupPanel.tsx`): compact "Get Ready" card —
620+
three rows (Microphone, Audio Output, BlackHole), each with a step icon,
621+
status Badge (`Ready`/`Action required`/`Checking…`), detail text, and
622+
inline actions; Separators between rows; a "Ready — Press Start Meeting
623+
below." banner (success) when all three pass, or a pending banner
624+
("Complete the required setup") otherwise. Same `setupState.ts` logic, no
625+
data changes.
626+
- **Existing panels rebuilt** into compact shadcn-style cards:
627+
- `HomeScreen.tsx` (rewritten): header (app title + session status Badge
628+
dot), Get Ready card, Meeting Mode card (4 stage Badges STT/Translate/
629+
TTS/Audio + large Start/Stop Meeting button), Separator, then Translation,
630+
Microphone, Text-to-Speech, Audio Output, Speech Recognition cards, then
631+
Pipeline Performance (dev-gated by `PIPELINE_DEBUG`).
632+
- `MicrophonePanel.tsx`: device Select, Input Level (Progress bar),
633+
Start/Stop, warning/destructive Alerts for no-device/denied permission.
634+
- `SttPanel.tsx` (now Speech Recognition only): Urdu RTL transcript textbox,
635+
provider + status Badges, Start/Stop Listening — monolith split.
636+
- `TranslationPanel.tsx`, `TtsPanel.tsx`, `AudioOutputPanel.tsx` (new):
637+
single-purpose compact cards split out of the old `SttPanel`/home.
638+
- `AudioLevelMeter.tsx`: uses Progress.
639+
- `PipelinePanel.tsx`: Card/Badge + inline token styles.
640+
- Dead-but-consistent legacy kept up to date: `StatusBar.tsx`,
641+
`SubtitleDisplay.tsx` (fixed missing Card import),
642+
`LiveTranslationScreen.tsx`.
643+
- **Accessibility**: `role=progressbar`, `role=alert`, `aria-*` on controls,
644+
keyboard focus states, semantic labels/contrast.
645+
- **Functional regression verified** (CDP against dev + packaged app): all
646+
selects (setup output, mic, output) populated; Get Ready → "Ready — Press
647+
Start Meeting below."; Start Meeting → session Active, button → Stop
648+
Meeting, header Badge → Active; ×3 start/stop cycles all return to Ready.
649+
Zero console errors/exceptions on reload. App renders from `app.asar`
650+
identically.
651+
652+
### M11 follow-up — Migrate to real shadcn/ui + Tailwind CSS (2026-09-01, complete)
653+
654+
- **Scope**: UI/design-system migration only. Replaced the previous hand-rolled
655+
plain-CSS shadcn-style implementation with the actual shadcn/ui + Tailwind
656+
CSS foundation. The M11 UX structure, component split, compact layout, and
657+
functional wiring are all preserved — no redesign, no business-logic change
658+
(STT/Translation/TTS/audio-output providers, SessionManager, IPC, mic
659+
permission, BlackHole detection, telemetry, meeting start/stop, audio
660+
routing, `PIPELINE_DEBUG` all untouched; `src/main/*`, `src/preload/*`,
661+
`packages/shared/index.ts` unchanged).
662+
- **Tailwind integration**: `tailwind.config.js` added (Tailwind v3, class dark
663+
mode, zinc/neutral theme tokens, `@/` content scan). `esbuild.config.js` adds
664+
a Tailwind CLI pre-build that compiles `styles/globals.css`
665+
`dist/renderer/tailwind.css`, plus a `@/` alias. `index.html` now links
666+
`tailwind.css` (removed `bundle.css`; App.tsx no longer imports CSS). Main/
667+
preload/renderer esbuild bundling unchanged — no Vite, no new framework.
668+
- **Real shadcn/ui components** (`src/renderer/components/ui/`): `button.tsx`
669+
(cva + Radix Slot), `card.tsx`, `badge.tsx` (cva + semantic variants
670+
success/warning/info/muted + `dot`), `select.tsx` (Radix Select), `label.tsx`
671+
(Radix Label), `separator.tsx` (Radix Separator), `alert.tsx` (cva +
672+
AlertTitle/AlertDescription + warning/success), `progress.tsx` (Radix
673+
Progress), `dropdown-menu.tsx` (Radix DropdownMenu); `lib/utils.ts` `cn()`
674+
(clsx + tailwind-merge). `@/` alias → `src/renderer` in `tsconfig.json` +
675+
esbuild.
676+
- **Theme system** (`components/theme-provider.tsx`, `theme-selector.tsx`):
677+
shadcn CSS-variable token model in `globals.css` (`:root` light + `.dark`
678+
zinc/neutral palette; semantic background/foreground/card/popover/primary/
679+
secondary/muted/accent/destructive/border/input/ring; `--radius`). No
680+
hard-coded colors scattered in components. Theme toggle is the standard shadcn
681+
mode-toggle: icon Button (Sun/Moon) + DropdownMenu → Light/Dark/System.
682+
Persists via `localStorage["ui-theme"]`; System follows
683+
`prefers-color-scheme` reactively via `matchMedia`.
684+
- **Components migrated** to Tailwind utilities (zero custom CSS classes):
685+
HomeScreen, SetupPanel, MicrophonePanel, SttPanel, TranslationPanel,
686+
TtsPanel, AudioOutputPanel, PipelinePanel, AudioLevelMeter. Panels now use
687+
Radix Select (was native `<select>`). Compact/neutral/technical aesthetic
688+
preserved (h-8 controls, 13px titles, no gradients/glass/excess shadows).
689+
- **Obsolete implementation removed**: deleted `styles/App.css` and the dead
690+
legacy stubs `StatusBar.tsx`, `SubtitleDisplay.tsx`, `LiveTranslationScreen
691+
.tsx`; removed `import "./styles/App.css"` from App.tsx. Only app-specific
692+
CSS remains in `globals.css` (Urdu RTL/Nastaliq transcript `.textbox-urdu`,
693+
thin scrollbars). One UI system remains.
694+
- **Dependencies added**: Tailwind v3 (dev); `class-variance-authority`,
695+
`clsx`, `tailwind-merge`, `tailwindcss-animate`, `@radix-ui/react-slot/select/
696+
label/separator/progress/dropdown-menu`, `lucide-react`. Removed redundant
697+
root `postcss`/`autoprefixer`. No UI framework, no animation/state libs, no
698+
build-tooling migration.
699+
- **Accessibility** kept: `role=progressbar`/`role=alert`/`aria-*`,
700+
focus-visible rings, Radix-managed keyboard/interaction for menus & selects.
701+
- **Validation**: `npm run type-check` clean; `npm test` 60/60; `npm run build`
702+
OK (outputs `bundle.js` + `tailwind.css` + `index.html`); `npm run
703+
package:dir` OK and `app.asar` contains all three renderer assets. Packaged
704+
app CDP-verified (from `app.asar`): all 7 panels render; theme toggle opens
705+
menu; Light (white) / Dark (zinc-950) / System (follows OS) all switch and
706+
persist (`ui-theme`) across app restart; mic & output Radix selects enumerate
707+
devices (incl. BlackHole) and fire onSelect; Start/Stop Meeting 2-cycle
708+
returns Ready; zero console errors on reload + interaction.
709+
594710
## What is NOT implemented (intentionally)
595711

596712
Meeting-app integration, authentication, database, backend server, Python.
@@ -600,9 +716,10 @@ cross-platform ready; not exercised in M10 Phase 3).
600716

601717
## Next task
602718

603-
M10 Phase 3 (production packaging & macOS distribution) and M10 Phase 4
604-
(non-technical install + first-launch onboarding) are complete and documented
605-
above. M10 is fully complete — do not start M11.
719+
M10 Phase 3/4 (production packaging & macOS distribution + non-technical
720+
onboarding), M11 (UI design-system revamp), and the M11 follow-up (real
721+
shadcn/ui + Tailwind migration) are complete and documented. M10, M11, and the
722+
M11 follow-up are fully complete — do not start M12.
606723
Remaining (manual, outside repo code):
607724
1. **upload `docs/demo/demo-v1.0.0.mp4` as a v1.0.0 Release asset**,
608725
2. **sign/notarize + release the built app** when Apple Developer credentials
@@ -630,12 +747,15 @@ src/main/ipc/{audio,audio-output,session,stt,translation,tts,system}.ts
630747
src/preload/index.ts
631748
src/renderer/{App.tsx,index.tsx,index.html}
632749
src/renderer/pages/HomeScreen.tsx
633-
src/renderer/components/{MicrophonePanel,AudioLevelMeter,SttPanel,SetupPanel}.tsx
634-
src/renderer/components/{SubtitleDisplay,StatusBar}.tsx
635-
src/renderer/pages/LiveTranslationScreen.tsx
750+
src/renderer/lib/utils.ts
751+
src/renderer/components/ui/{button,card,badge,label,select,separator,alert,progress,dropdown-menu}.tsx
752+
src/renderer/components/{theme-provider,theme-selector}.tsx
753+
src/renderer/components/{MicrophonePanel,AudioLevelMeter,SetupPanel}.tsx
754+
src/renderer/components/{TranslationPanel,TtsPanel,AudioOutputPanel}.tsx
755+
src/renderer/components/{SttPanel,PipelinePanel}.tsx
636756
src/renderer/setup/{setupState,useSetup}.ts
637757
src/renderer/services/{useMicrophone,useSession,useStt,useTranslation,useTts,useAudioOutput}.ts
638-
src/renderer/styles/App.css
758+
src/renderer/styles/globals.css
639759
src/renderer/types/electron.d.ts
640760
packages/shared/index.ts
641761
tests/tts-dedup.test.ts
@@ -644,6 +764,7 @@ tests/session.test.ts
644764
tests/setup-onboarding.test.ts
645765
scripts/setup-whisper.sh
646766
esbuild.config.js
767+
tailwind.config.js
647768
packaging/entitlements.mac.plist
648769
package.json (includes electron-builder "build" config + package scripts)
649770
tsconfig.json

esbuild.config.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,31 @@
11
const esbuild = require('esbuild');
22
const fs = require('fs');
33
const path = require('path');
4+
const { execSync } = require('child_process');
45

56
const watch = process.argv.includes('--watch');
67

8+
const root = __dirname;
9+
710
function copyIndexHtml() {
8-
const src = path.join(__dirname, 'src/renderer/index.html');
9-
const destDir = path.join(__dirname, 'dist/renderer');
11+
const src = path.join(root, 'src/renderer/index.html');
12+
const destDir = path.join(root, 'dist/renderer');
1013
fs.mkdirSync(destDir, { recursive: true });
1114
fs.copyFileSync(src, path.join(destDir, 'index.html'));
1215
}
1316

17+
/** Compile Tailwind CSS (globals.css -> dist/renderer/tailwind.css). */
18+
function buildTailwind() {
19+
const input = path.join(root, 'src/renderer/styles/globals.css');
20+
const outDir = path.join(root, 'dist/renderer');
21+
fs.mkdirSync(outDir, { recursive: true });
22+
const output = path.join(outDir, 'tailwind.css');
23+
const binary = path.join(root, 'node_modules/.bin/tailwindcss');
24+
execSync(`"${binary}" -c "${path.join(root, 'tailwind.config.js')}" -i "${input}" -o "${output}" ${watch ? '--watch' : '--minify'}`, {
25+
stdio: 'inherit',
26+
});
27+
}
28+
1429
/** @type {import('esbuild').BuildOptions} */
1530
const commonConfig = {
1631
bundle: true,
@@ -47,6 +62,9 @@ async function build() {
4762
loader: {
4863
'.css': 'css',
4964
},
65+
alias: {
66+
'@': path.join(root, 'src/renderer'),
67+
},
5068
define: {
5169
'process.env.NODE_ENV': watch ? '"development"' : '"production"',
5270
},
@@ -55,12 +73,14 @@ async function build() {
5573
copyIndexHtml();
5674

5775
if (watch) {
76+
buildTailwind();
5877
await Promise.all([
5978
mainCtx.watch(),
6079
preloadCtx.watch(),
6180
rendererCtx.watch(),
6281
]);
6382
} else {
83+
buildTailwind();
6484
await Promise.all([
6585
mainCtx.rebuild(),
6686
preloadCtx.rebuild(),

0 commit comments

Comments
 (0)