diff --git a/TASKS.md b/TASKS.md index f4ae110..2bc0ff8 100644 --- a/TASKS.md +++ b/TASKS.md @@ -1332,6 +1332,10 @@ Detailed comparison and sequencing: [`docs/git-client-1.0-audit.md`](./docs/git- surface-local editing/navigation keys remain fixed and are fully listed in Settings → Keyboard plus the user guide. They are keyboard access, not hidden commands requiring a second binding registry. + - ☑ Windows/Linux commit shortcut polish: the Local Changes commit action + renders `Ctrl` + return as a compact two-key chord while macOS retains its + native `⌘↵` glyph treatment; Linux keeps its own platform identity while + sharing Ctrl-style shortcuts (`CommitBar` + `detectPlatform`, 2026-07-20). - ☑ Status-bar truth pass: branch/ahead/behind plus real derived sync state (up to date, ahead, behind, diverged, or conflicts) and modified/staged counts. Commit signing belongs to `SignatureSummary`; LFS/auth remain system- diff --git a/docs/learnings.md b/docs/learnings.md index 2b6ef39..0c89be9 100644 --- a/docs/learnings.md +++ b/docs/learnings.md @@ -1919,6 +1919,15 @@ state. Surface CSS may size or skin the underlying select, but must size the `.select-control` wrapper too whenever the old select was itself a flex or grid item; otherwise the wrapper, rather than the select, becomes the layout child. +**Linux shares Ctrl shortcuts, not Windows window chrome (2026-07-20).** Keep +Linux as a distinct `Platform` even when shortcut formatting branches only on +macOS versus non-macOS. Collapsing Linux into `win11` makes key labels correct +but incorrectly opts it into Strand's custom Windows caption controls; +collapsing it into `mac` preserves native chrome but emits Command glyphs and +macOS toolbar spacing. Platform detection must identify all three targets, and +individual surfaces may deliberately group Windows and Linux with a non-macOS +predicate. + **Embedding a file document must not change its editing contract (2026-07-20).** Work's tab chrome is presentation context, not an access-control boundary. Existing complete UTF-8 working-tree files remain editable whether the shared diff --git a/ui/src/lib/keys.test.ts b/ui/src/lib/keys.test.ts index a55c0e6..a759450 100644 --- a/ui/src/lib/keys.test.ts +++ b/ui/src/lib/keys.test.ts @@ -127,6 +127,7 @@ describe('formatBinding', () => { expect(formatBinding('Mod+Shift+P', 'win11')).toBe('Ctrl+Shift+P'); expect(formatBinding('Mod+1', 'win11')).toBe('Ctrl+1'); expect(formatBinding('Mod+Enter', 'win11')).toBe('Ctrl+Enter'); + expect(formatBinding('Mod+Enter', 'linux')).toBe('Ctrl+Enter'); }); it('returns empty for an unbound command', () => { diff --git a/ui/src/lib/keys.ts b/ui/src/lib/keys.ts index 26ed332..aa5b817 100644 --- a/ui/src/lib/keys.ts +++ b/ui/src/lib/keys.ts @@ -255,7 +255,7 @@ const WIN_KEY: Record = { * Render a binding for display. macOS uses glyphs joined tight (`⌘⇧P`); other * platforms use words joined with `+` (`Ctrl+Shift+P`). */ -export function formatBinding(binding: string | null, platform: 'mac' | 'win11'): string { +export function formatBinding(binding: string | null, platform: 'mac' | 'win11' | 'linux'): string { if (!binding) return ''; const mac = platform === 'mac'; const mods = mac ? MAC_MOD : WIN_MOD; diff --git a/ui/src/stores/settings.ts b/ui/src/stores/settings.ts index 461d4ba..8b42a3e 100644 --- a/ui/src/stores/settings.ts +++ b/ui/src/stores/settings.ts @@ -12,7 +12,7 @@ export type ThemePref = Theme | 'system'; /** Accent color preset. Each id maps to an OKLCH hue via a `[data-accent]` * block in tokens.css; the registry lives in `lib/theme.ts` (`ACCENT_OPTIONS`). */ export type AccentId = 'amber' | 'rose' | 'magenta' | 'violet' | 'blue' | 'cyan' | 'teal' | 'green'; -export type Platform = 'mac' | 'win11'; +export type Platform = 'mac' | 'win11' | 'linux'; export type Density = 'compact' | 'default' | 'relaxed'; export type DiffMode = 'stacked' | 'split'; export type GraphStyle = 'classic' | 'bold' | 'mono'; @@ -69,10 +69,12 @@ function detectPlatform(): Platform { .__TAURI_OS_PLUGIN_INTERNALS__; if (internals?.os_type === 'windows') return 'win11'; if (internals?.os_type === 'macos') return 'mac'; + if (internals?.os_type === 'linux') return 'linux'; // Fallback for browser mode const ua = navigator.userAgent.toLowerCase(); if (ua.includes('win')) return 'win11'; + if (ua.includes('linux')) return 'linux'; return 'mac'; } diff --git a/ui/src/styles/features.css b/ui/src/styles/features.css index 2965888..00e1b95 100644 --- a/ui/src/styles/features.css +++ b/ui/src/styles/features.css @@ -472,6 +472,44 @@ color: oklch(0 0 0 / 0.6); margin-left: 2px; } +.cb-top .cb-commit .commit-chord { + display: inline-flex; + align-items: center; + gap: 3px; + margin-left: 2px; + color: var(--accent-fg); +} +.cb-top .cb-commit .commit-chord kbd { + display: inline-flex; + align-items: center; + justify-content: center; + height: 19px; + min-width: 26px; + padding: 0 5px; + border: 0; + border-radius: 4px; + background: color-mix(in oklch, var(--accent-fg) 12%, transparent); + box-shadow: + 0 0 0 0.5px color-mix(in oklch, var(--accent-fg) 16%, transparent) inset, + 0 -1px 0 color-mix(in oklch, var(--accent-fg) 28%, transparent) inset; + color: inherit; + font-family: var(--font-mono); + font-size: 9px; + font-weight: 650; + line-height: 1; +} +.cb-top .cb-commit .commit-chord .chord-plus { + font-family: var(--font-mono); + font-size: 8px; + font-weight: 700; + opacity: 0.55; +} +.cb-top .cb-commit .commit-chord .enter-key { + min-width: 21px; + padding: 0; + font-family: var(--font-ui); + font-size: 14px; +} /* Body textarea — content-sized, capped so long messages do not crowd the diff. */ .cb-body { @@ -541,6 +579,9 @@ .cb-top .cb-commit .kbd-inline { display: none; } + .cb-top .cb-commit .commit-chord { + display: none; + } } .lc-col-head { diff --git a/ui/src/views/LocalChanges.tsx b/ui/src/views/LocalChanges.tsx index b7720f8..81bdb2d 100644 --- a/ui/src/views/LocalChanges.tsx +++ b/ui/src/views/LocalChanges.tsx @@ -1757,7 +1757,17 @@ function CommitBar({ canCommit, hasChanges }: { canCommit: boolean; hasChanges: onClick={() => void submit()} > {amend ? 'Amend' : 'Commit'} - {formatBinding('Mod+Enter', platform)} + {platform === 'mac' ? ( + + ) : ( + + )}