Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: hypothesis/frontend-shared
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 689fa5584a4d4946235b6c02ae364303c6414f8f
Choose a base ref
..
head repository: hypothesis/frontend-shared
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 781ca9037abda7f6afdbaba31bbcfda56fbc3bab
Choose a head ref
Showing with 25 additions and 10 deletions.
  1. +25 −10 src/components/input/SelectNext.tsx
35 changes: 25 additions & 10 deletions src/components/input/SelectNext.tsx
Original file line number Diff line number Diff line change
@@ -111,7 +111,7 @@ function useListboxPositioning(
buttonRef: RefObject<HTMLElement | undefined>,
listboxRef: RefObject<HTMLElement | null>,
listboxOpen: boolean,
nativePopoverSupported: boolean,
asPopover: boolean,
right: boolean,
) {
const [positioningStyles, setPositioningStyles] = useState<
@@ -145,7 +145,7 @@ function useListboxPositioning(
buttonDistanceToBottom < listboxHeight &&
buttonDistanceToTop > buttonDistanceToBottom;

if (!nativePopoverSupported) {
if (!asPopover) {
setPositioningStyles(
shouldListboxDropUp
? { bottom: '100%', marginBottom: LISTBOX_TOGGLE_GAP }
@@ -187,7 +187,7 @@ function useListboxPositioning(
listeners.removeAll();
setPositioningStyles({});
};
}, [buttonRef, listboxRef, listboxOpen, nativePopoverSupported]);
}, [buttonRef, listboxRef, listboxOpen, asPopover, right]);

return positioningStyles;
}
@@ -222,7 +222,20 @@ export type SelectProps<T> = CompositeProps & {
'aria-label'?: string;
'aria-labelledby'?: string;

/** Test seam */
/**
* If this is true and current browser supports it, the listbox will be
* rendered as a native popover.
* Defaults to false.
*
* See https://developer.mozilla.org/en-US/docs/Web/API/Popover_API
*/
listboxAsPopover?: boolean;

/**
* Test seam.
* Used to determine if current browser supports native popovers.
* Defaults to `'popover' in document.body`
*/
nativePopoverSupported?: boolean;
};

@@ -238,6 +251,7 @@ function SelectMain<T>({
listboxClasses,
containerClasses,
right = false,
listboxAsPopover = false,
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledBy,

@@ -247,14 +261,15 @@ function SelectMain<T>({
const wrapperRef = useRef<HTMLDivElement | null>(null);
const listboxRef = useRef<HTMLUListElement | null>(null);
const [listboxOpen, setListboxOpen] = useState(false);
const asPopover = listboxAsPopover && nativePopoverSupported;
const toggleListbox = useCallback(
(open: boolean) => {
setListboxOpen(open);
if (nativePopoverSupported) {
if (asPopover) {
listboxRef.current?.togglePopover(open);
}
},
[nativePopoverSupported],
[asPopover],
);
const closeListbox = useCallback(() => toggleListbox(false), [toggleListbox]);
const listboxId = useId();
@@ -264,7 +279,7 @@ function SelectMain<T>({
buttonRef,
listboxRef,
listboxOpen,
nativePopoverSupported,
asPopover,
right,
);

@@ -285,7 +300,7 @@ function SelectMain<T>({
useArrowKeyNavigation(listboxRef, {
horizontal: false,
loop: false,
autofocus: !nativePopoverSupported,
autofocus: !asPopover,
containerVisible: listboxOpen,
selector: OPTION_SELECTOR,
});
@@ -346,11 +361,11 @@ function SelectMain<T>({
<SelectContext.Provider value={{ selectValue, value }}>
<ul
// @ts-expect-error Popover attribute not yet part of type
popover
popover={asPopover ? true : undefined}
className={classnames(
'absolute z-5 max-h-80 overflow-y-auto',
'rounded border bg-white shadow hover:shadow-md focus-within:shadow-md',
!nativePopoverSupported && {
!asPopover && {
// Hiding instead of unmounting to
// * Ensure screen readers detect button as a listbox handler
// * Listbox size can be computed to correctly drop up or down