Skip to content

Commit 04542b4

Browse files
committed
feat: add matchReferenceWidth to DropdownProps
1 parent 0c0d65c commit 04542b4

1 file changed

Lines changed: 26 additions & 1 deletion

File tree

src/components/Form/Dropdown.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import type {
77
ReactNode,
88
Ref,
99
} from 'react';
10-
import React, { useCallback, useEffect, useMemo, useState } from 'react';
10+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
1111

1212
import { createRovingFocusKeyDownHandler } from '../../a11y/a11yUtils';
1313
import {
@@ -18,6 +18,11 @@ import {
1818
const DEFAULT_DROPDOWN_ITEM_SELECTOR =
1919
'[role="option"]:not(:disabled), [role="menuitem"]:not(:disabled), button:not(:disabled), a:not(:disabled)';
2020

21+
const isEditableTarget = (target: EventTarget | null) =>
22+
target instanceof HTMLInputElement ||
23+
target instanceof HTMLTextAreaElement ||
24+
(target instanceof HTMLElement && target.isContentEditable);
25+
2126
type DropdownContextValue = {
2227
close(): void;
2328
};
@@ -47,6 +52,7 @@ export type DropdownTriggerProps = Pick<
4752

4853
export type DropdownProps = PropsWithChildren<{
4954
className?: string;
55+
matchReferenceWidth?: boolean;
5056
onClose?: () => void;
5157
onOpen?: () => void;
5258
placement?: PopperLikePlacement;
@@ -58,6 +64,7 @@ export type DropdownProps = PropsWithChildren<{
5864
export const Dropdown = ({
5965
children,
6066
className,
67+
matchReferenceWidth = false,
6168
onClose,
6269
onOpen,
6370
placement = 'bottom',
@@ -142,18 +149,32 @@ export const Dropdown = ({
142149
[],
143150
);
144151

152+
const escapeConsumedRef = useRef(false);
153+
145154
const handleKeyDown = useCallback(
146155
(event: React.KeyboardEvent<HTMLElement>) => {
147156
if (event.key === 'Escape') {
148157
event.preventDefault();
158+
event.stopPropagation();
159+
escapeConsumedRef.current = true;
149160
close();
150161
return;
151162
}
163+
if (isEditableTarget(event.target)) {
164+
return;
165+
}
152166
rovingFocusKeyDownHandler(event);
153167
},
154168
[close, rovingFocusKeyDownHandler],
155169
);
156170

171+
const suppressEscapeKeyUp = useCallback((event: React.KeyboardEvent<HTMLElement>) => {
172+
if (event.key === 'Escape' && escapeConsumedRef.current) {
173+
escapeConsumedRef.current = false;
174+
event.stopPropagation();
175+
}
176+
}, []);
177+
157178
const DropdownTriggerComponent = TriggerComponent;
158179

159180
const trigger = DropdownTriggerComponent ? (
@@ -173,10 +194,14 @@ export const Dropdown = ({
173194
className={clsx('str-chat__dropdown__items', className)}
174195
onClick={close}
175196
onKeyDown={handleKeyDown}
197+
onKeyUpCapture={suppressEscapeKeyUp}
176198
ref={setFloatingElement}
177199
role='menu'
178200
style={{
179201
left: x ?? 0,
202+
minWidth: matchReferenceWidth
203+
? resolvedReferenceElement.getBoundingClientRect().width
204+
: undefined,
180205
position: strategy,
181206
top: y ?? 0,
182207
}}

0 commit comments

Comments
 (0)