From dab7cbc9da37c8017b60bb913ec8f0f14d32c2b8 Mon Sep 17 00:00:00 2001 From: Supra4E8C Date: Wed, 30 Sep 2026 21:41:05 +0800 Subject: [PATCH] fix(providers): use shared selects in advanced editors --- src/components/ui/Select.tsx | 9 ++++ .../sheets/forms/ErrorRulesEditor.tsx | 52 +++++++++---------- .../sheets/forms/ModelAdvancedFields.tsx | 27 ++++++---- .../sheets/forms/ProviderBehaviorEditor.tsx | 25 +++++---- .../sheets/forms/RuntimePolicyEditor.tsx | 42 +++++++-------- tests/providerErrorRulesUi.test.ts | 5 +- tests/providerModelOptions.test.ts | 7 ++- tests/providerSelectUi.test.ts | 49 +++++++++++++++++ 8 files changed, 144 insertions(+), 72 deletions(-) create mode 100644 tests/providerSelectUi.test.ts diff --git a/src/components/ui/Select.tsx b/src/components/ui/Select.tsx index 08d845d3..736cf631 100644 --- a/src/components/ui/Select.tsx +++ b/src/components/ui/Select.tsx @@ -7,6 +7,7 @@ import { useRef, useState, type CSSProperties, + type AriaAttributes, } from 'react'; import { createPortal } from 'react-dom'; import { IconChevronDown } from './icons'; @@ -27,6 +28,7 @@ interface SelectProps { ariaLabel?: string; ariaLabelledBy?: string; ariaDescribedBy?: string; + ariaInvalid?: AriaAttributes['aria-invalid']; fullWidth?: boolean; size?: 'sm' | 'md'; id?: string; @@ -86,6 +88,7 @@ export function Select({ ariaLabel, ariaLabelledBy, ariaDescribedBy, + ariaInvalid, fullWidth = true, size = 'md', id, @@ -96,6 +99,7 @@ export function Select({ const [open, setOpen] = useState(false); const [highlightedIndex, setHighlightedIndex] = useState(-1); const wrapRef = useRef(null); + const triggerRef = useRef(null); const dropdownRef = useRef(null); const rafRef = useRef(null); const [dropdownStyle, setDropdownStyle] = useState(null); @@ -191,6 +195,7 @@ export function Select({ onChange(nextOption.value); setOpen(false); setHighlightedIndex(nextIndex); + triggerRef.current?.focus({ preventScroll: true }); }, [onChange, options] ); @@ -250,7 +255,9 @@ export function Select({ case 'Escape': if (!isOpen) return; event.preventDefault(); + event.stopPropagation(); setOpen(false); + triggerRef.current?.focus({ preventScroll: true }); return; case 'Tab': if (isOpen) setOpen(false); @@ -310,6 +317,7 @@ export function Select({ >