fix(settings): make nav resize keyboard accessible (#1165)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
This commit is contained in:
committed by
GitHub
co-authored by
Isaac Sanchez
parent
83ea6a70eb
commit
e4227c7f06
@@ -73,6 +73,11 @@ import {
|
|||||||
// Same constraints as main sidebar
|
// Same constraints as main sidebar
|
||||||
const SETTINGS_NAV_MIN_WIDTH = 176;
|
const SETTINGS_NAV_MIN_WIDTH = 176;
|
||||||
const SETTINGS_NAV_MAX_WIDTH = 280;
|
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';
|
type MobileStage = 'nav' | 'page-sidebar' | 'page-content';
|
||||||
|
|
||||||
@@ -296,10 +301,7 @@ export const SettingsView: React.FC<SettingsViewProps> = ({ onClose, forceMobile
|
|||||||
if (typeof window === 'undefined') return;
|
if (typeof window === 'undefined') return;
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
if (!hasManuallyResized) {
|
if (!hasManuallyResized) {
|
||||||
const proportionalWidth = Math.min(
|
const proportionalWidth = clampSettingsNavWidth(Math.floor(window.innerWidth * 0.12));
|
||||||
SETTINGS_NAV_MAX_WIDTH,
|
|
||||||
Math.max(SETTINGS_NAV_MIN_WIDTH, Math.floor(window.innerWidth * 0.12))
|
|
||||||
);
|
|
||||||
setNavWidth(proportionalWidth);
|
setNavWidth(proportionalWidth);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -311,10 +313,7 @@ export const SettingsView: React.FC<SettingsViewProps> = ({ onClose, forceMobile
|
|||||||
if (!isResizing) return;
|
if (!isResizing) return;
|
||||||
const handlePointerMove = (event: PointerEvent) => {
|
const handlePointerMove = (event: PointerEvent) => {
|
||||||
const delta = event.clientX - startXRef.current;
|
const delta = event.clientX - startXRef.current;
|
||||||
const nextWidth = Math.min(
|
const nextWidth = clampSettingsNavWidth(startWidthRef.current + delta);
|
||||||
SETTINGS_NAV_MAX_WIDTH,
|
|
||||||
Math.max(SETTINGS_NAV_MIN_WIDTH, startWidthRef.current + delta)
|
|
||||||
);
|
|
||||||
setNavWidth(nextWidth);
|
setNavWidth(nextWidth);
|
||||||
setHasManuallyResized(true);
|
setHasManuallyResized(true);
|
||||||
};
|
};
|
||||||
@@ -334,6 +333,32 @@ export const SettingsView: React.FC<SettingsViewProps> = ({ onClose, forceMobile
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleResizeKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
|
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.
|
// Load stores when project changes or when a page becomes active.
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!isSettingsDialogOpen && !runtimeCtx.isVSCode) {
|
if (!isSettingsDialogOpen && !runtimeCtx.isVSCode) {
|
||||||
@@ -796,11 +821,17 @@ export const SettingsView: React.FC<SettingsViewProps> = ({ onClose, forceMobile
|
|||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'absolute right-0 top-0 z-20 h-full w-[6px] -mr-[3px] cursor-col-resize',
|
'absolute right-0 top-0 z-20 h-full w-[6px] -mr-[3px] cursor-col-resize',
|
||||||
|
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--interactive-focus-ring)]',
|
||||||
isResizing ? 'bg-primary/30' : 'bg-transparent hover:bg-primary/20'
|
isResizing ? 'bg-primary/30' : 'bg-transparent hover:bg-primary/20'
|
||||||
)}
|
)}
|
||||||
|
tabIndex={0}
|
||||||
onPointerDown={handlePointerDown}
|
onPointerDown={handlePointerDown}
|
||||||
|
onKeyDown={handleResizeKeyDown}
|
||||||
role="separator"
|
role="separator"
|
||||||
aria-orientation="vertical"
|
aria-orientation="vertical"
|
||||||
|
aria-valuemin={SETTINGS_NAV_MIN_WIDTH}
|
||||||
|
aria-valuemax={SETTINGS_NAV_MAX_WIDTH}
|
||||||
|
aria-valuenow={navWidth}
|
||||||
aria-label={t('settings.view.actions.resizeNavigation')}
|
aria-label={t('settings.view.actions.resizeNavigation')}
|
||||||
/>
|
/>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
|
|||||||
Reference in New Issue
Block a user