Commit 5f369a0b authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Make sure sidebar panels are focused when open, and focus is restored when closed

parent 1b476206
import { Panel } from '@hypothesis/frontend-shared/lib/next'; import { Dialog } from '@hypothesis/frontend-shared/lib/next';
import type { IconComponent } from '@hypothesis/frontend-shared/lib/types'; import type { IconComponent } from '@hypothesis/frontend-shared/lib/types';
import type { ComponentChildren } from 'preact'; import type { ComponentChildren } from 'preact';
import { useCallback, useEffect, useRef } from 'preact/hooks'; import { useCallback, useEffect, useRef } from 'preact/hooks';
...@@ -47,9 +47,7 @@ export default function SidebarPanel({ ...@@ -47,9 +47,7 @@ export default function SidebarPanel({
if (panelIsActive && panelElement.current) { if (panelIsActive && panelElement.current) {
scrollIntoView(panelElement.current); scrollIntoView(panelElement.current);
} }
if (typeof onActiveChanged === 'function') { onActiveChanged?.(panelIsActive);
onActiveChanged(panelIsActive);
}
} }
}, [panelIsActive, onActiveChanged]); }, [panelIsActive, onActiveChanged]);
...@@ -58,12 +56,20 @@ export default function SidebarPanel({ ...@@ -58,12 +56,20 @@ export default function SidebarPanel({
}, [store, panelName]); }, [store, panelName]);
return ( return (
<Slider visible={panelIsActive}> <>
<div ref={panelElement} className="mb-4"> {panelIsActive && (
<Panel title={title} icon={icon} onClose={closePanel}> <Dialog
restoreFocus
ref={panelElement}
classes="mb-4"
title={title}
icon={icon}
onClose={closePanel}
transitionComponent={Slider}
>
{children} {children}
</Panel> </Dialog>
</div> )}
</Slider> </>
); );
} }
...@@ -7,6 +7,9 @@ export type SliderProps = { ...@@ -7,6 +7,9 @@ export type SliderProps = {
/** Whether the content should be visible or not. */ /** Whether the content should be visible or not. */
visible: boolean; visible: boolean;
/** Invoked once the open/close transitions have finished */
onTransitionEnd?: (direction: 'in' | 'out') => void;
}; };
/** /**
...@@ -17,9 +20,13 @@ export type SliderProps = { ...@@ -17,9 +20,13 @@ export type SliderProps = {
* DOM using `display: none` so it does not appear in the keyboard navigation * DOM using `display: none` so it does not appear in the keyboard navigation
* order. * order.
* *
* Currently the only reveal/expand direction supported is top-down. * Currently, the only reveal/expand direction supported is top-down.
*/ */
export default function Slider({ children, visible }: SliderProps) { export default function Slider({
children,
visible,
onTransitionEnd,
}: SliderProps) {
const containerRef = useRef<HTMLDivElement | null>(null); const containerRef = useRef<HTMLDivElement | null>(null);
const [containerHeight, setContainerHeight] = useState(visible ? 'auto' : 0); const [containerHeight, setContainerHeight] = useState(visible ? 'auto' : 0);
...@@ -68,13 +75,15 @@ export default function Slider({ children, visible }: SliderProps) { ...@@ -68,13 +75,15 @@ export default function Slider({ children, visible }: SliderProps) {
const handleTransitionEnd = useCallback(() => { const handleTransitionEnd = useCallback(() => {
if (visible) { if (visible) {
setContainerHeight('auto'); setContainerHeight('auto');
onTransitionEnd?.('in');
} else { } else {
// When the collapse animation completes, stop rendering the content so // When the collapse animation completes, stop rendering the content so
// that the browser has fewer nodes to render and the content is removed // that the browser has fewer nodes to render and the content is removed
// from keyboard navigation. // from keyboard navigation.
setContentVisible(false); setContentVisible(false);
onTransitionEnd?.('out');
} }
}, [setContainerHeight, visible]); }, [setContainerHeight, visible, onTransitionEnd]);
const isFullyVisible = containerHeight === 'auto'; const isFullyVisible = containerHeight === 'auto';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment