From e4227c7f06891bad81b2bd920f37e9fc0416b2fd Mon Sep 17 00:00:00 2001 From: Isaac Sanchez-Hawkins <266845420+isanchez404@users.noreply.github.com> Date: Fri, 8 May 2026 16:09:35 -0400 Subject: [PATCH] fix(settings): make nav resize keyboard accessible (#1165) Co-authored-by: Isaac Sanchez --- .../ui/src/components/views/SettingsView.tsx | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/packages/ui/src/components/views/SettingsView.tsx b/packages/ui/src/components/views/SettingsView.tsx index 5dd5d282..58206bac 100644 --- a/packages/ui/src/components/views/SettingsView.tsx +++ b/packages/ui/src/components/views/SettingsView.tsx @@ -73,6 +73,11 @@ import { // Same constraints as main sidebar const SETTINGS_NAV_MIN_WIDTH = 176; const SETTINGS_NAV_MAX_WIDTH = 280; +const SETTINGS_NAV_RESIZE_STEP = 8; + +function clampSettingsNavWidth(width: number): number { + return Math.min(SETTINGS_NAV_MAX_WIDTH, Math.max(SETTINGS_NAV_MIN_WIDTH, width)); +} type MobileStage = 'nav' | 'page-sidebar' | 'page-content'; @@ -296,10 +301,7 @@ export const SettingsView: React.FC = ({ onClose, forceMobile if (typeof window === 'undefined') return; const handleResize = () => { if (!hasManuallyResized) { - const proportionalWidth = Math.min( - SETTINGS_NAV_MAX_WIDTH, - Math.max(SETTINGS_NAV_MIN_WIDTH, Math.floor(window.innerWidth * 0.12)) - ); + const proportionalWidth = clampSettingsNavWidth(Math.floor(window.innerWidth * 0.12)); setNavWidth(proportionalWidth); } }; @@ -311,10 +313,7 @@ export const SettingsView: React.FC = ({ onClose, forceMobile if (!isResizing) return; const handlePointerMove = (event: PointerEvent) => { const delta = event.clientX - startXRef.current; - const nextWidth = Math.min( - SETTINGS_NAV_MAX_WIDTH, - Math.max(SETTINGS_NAV_MIN_WIDTH, startWidthRef.current + delta) - ); + const nextWidth = clampSettingsNavWidth(startWidthRef.current + delta); setNavWidth(nextWidth); setHasManuallyResized(true); }; @@ -334,6 +333,32 @@ export const SettingsView: React.FC = ({ onClose, forceMobile event.preventDefault(); }; + const handleResizeKeyDown = (event: React.KeyboardEvent) => { + const step = event.shiftKey ? SETTINGS_NAV_RESIZE_STEP * 4 : SETTINGS_NAV_RESIZE_STEP; + let nextWidth: number; + + switch (event.key) { + case 'ArrowLeft': + nextWidth = navWidth - step; + break; + case 'ArrowRight': + nextWidth = navWidth + step; + break; + case 'Home': + nextWidth = SETTINGS_NAV_MIN_WIDTH; + break; + case 'End': + nextWidth = SETTINGS_NAV_MAX_WIDTH; + break; + default: + return; + } + + event.preventDefault(); + setNavWidth(clampSettingsNavWidth(nextWidth)); + setHasManuallyResized(true); + }; + // Load stores when project changes or when a page becomes active. React.useEffect(() => { if (!isSettingsDialogOpen && !runtimeCtx.isVSCode) { @@ -796,11 +821,17 @@ export const SettingsView: React.FC = ({ onClose, forceMobile