diff --git a/openless-all/app/scripts/windows-ui-config.test.mjs b/openless-all/app/scripts/windows-ui-config.test.mjs index 873afdbb..4d9ddb61 100644 --- a/openless-all/app/scripts/windows-ui-config.test.mjs +++ b/openless-all/app/scripts/windows-ui-config.test.mjs @@ -55,7 +55,7 @@ if (!/function WindowsResizeHandles\(\)/.test(windowChromeTsx)) { assertMatch( windowChromeTsx, - /const MAC_TITLEBAR_HEIGHT = 30;/, + /const MAC_TITLEBAR_HEIGHT = 28;/, 'macOS titlebar spacer should stay visually compact around the native traffic lights', ); assertMatch( @@ -108,7 +108,7 @@ if (!/export function getCapsuleHostMetrics\(\s*os: OS,\s*translationActive: boo throw new Error('capsule layout should define explicit host metrics separate from the visible pill metrics'); } -if (!/if \(os === 'win'\)\s*\{[\s\S]*?width: 220,[\s\S]*?height: translationActive \? 118 : 84,[\s\S]*?bottomInset: 12,[\s\S]*?badgeGap: 8[\s\S]*?\}/.test(capsuleLayoutTs)) { +if (!/if \(os === 'win'\)\s*\{[\s\S]*?const horizontalInset = 12;[\s\S]*?const pill = getCapsulePillMetrics\(os\);[\s\S]*?width: pill\.width \+ horizontalInset \* 2,[\s\S]*?height: translationActive \? 118 : 84,[\s\S]*?horizontalInset,[\s\S]*?bottomInset: 12,[\s\S]*?badgeGap: 8,[\s\S]*?boxSizing: 'border-box',[\s\S]*?\}/.test(capsuleLayoutTs)) { throw new Error('windows capsule host metrics should leave room for shadow and badge geometry'); } @@ -116,19 +116,23 @@ if (!/const hostMetrics = getCapsuleHostMetrics\(os,\s*translation\);/.test(caps throw new Error('capsule should derive host metrics from the shared layout contract'); } -if (!/justifyContent:\s*os === 'win' \? 'flex-end' : 'center'/.test(capsuleTsx)) { - throw new Error('windows capsule host should anchor the pill to the bottom instead of centering it inside the larger native host window'); +if (!/return\s*\(\s* CapsuleWindowBounds { #[cfg(target_os = "windows")] { + const WINDOWS_CAPSULE_PILL_WIDTH: f64 = 196.0; + const WINDOWS_CAPSULE_SIDE_INSET: f64 = 12.0; CapsuleWindowBounds { - width: 220.0, + // Keep the existing Windows hitbox width, but express it as + // pill width (196) + symmetric 12px side insets for shadow room. + width: WINDOWS_CAPSULE_PILL_WIDTH + WINDOWS_CAPSULE_SIDE_INSET * 2.0, height: if translation_active { 118.0 } else { 84.0 }, bottom_inset: 12.0, } diff --git a/openless-all/app/src/components/Capsule.tsx b/openless-all/app/src/components/Capsule.tsx index 4c669598..6ee474a9 100644 --- a/openless-all/app/src/components/Capsule.tsx +++ b/openless-all/app/src/components/Capsule.tsx @@ -15,9 +15,14 @@ interface AudioBarsProps { function AudioBars({ level }: AudioBarsProps) { const envelope = [0.55, 0.85, 1.0, 0.85, 0.55]; - const base = 4; - const max = 18; + const base = 2; + const max = 24; const voice = Math.min(1, Math.max(0, level)); + const silenceGate = 0.012; + const responseCeiling = 0.34; + const gatedVoice = Math.min(1, Math.max(0, (voice - silenceGate) / (responseCeiling - silenceGate))); + const easedVoice = gatedVoice * gatedVoice * (3 - 2 * gatedVoice); + const visualVoice = Math.pow(easedVoice, 0.42); return (
@@ -110,6 +116,8 @@ interface CircleButtonProps { function CircleButton({ variant, enabled, onClick }: CircleButtonProps) { const { t } = useTranslation(); const isCancel = variant === 'cancel'; + const os = detectOS(); + const useBackdrop = os !== 'win' && isCancel; return (