From 8b3fb4bad4f736e84b5808d342dc8a614e8c7f34 Mon Sep 17 00:00:00 2001 From: jialecl Date: Tue, 25 Aug 2026 10:17:52 +0200 Subject: [PATCH] Select refactored to use the popover component --- packages/lib/src/select/Listbox.tsx | 139 +++++++-------- packages/lib/src/select/Select.tsx | 258 +++++++++++++--------------- 2 files changed, 192 insertions(+), 205 deletions(-) diff --git a/packages/lib/src/select/Listbox.tsx b/packages/lib/src/select/Listbox.tsx index 86fa7608a..0d2a151d8 100644 --- a/packages/lib/src/select/Listbox.tsx +++ b/packages/lib/src/select/Listbox.tsx @@ -8,6 +8,7 @@ import scrollbarStyles from "../styles/scroll"; import { FlattenedItem, ListboxProps, ListOptionGroupType, ListOptionType } from "./types"; import CheckboxContext from "../checkbox/CheckboxContext"; import { Virtuoso, VirtuosoHandle } from "react-virtuoso"; +import DxcBleed from "../bleed/Bleed"; const ListboxContainer = styled.div<{ height?: ListboxProps["virtualizedHeight"]; @@ -15,11 +16,6 @@ const ListboxContainer = styled.div<{ box-sizing: border-box; max-height: 304px; height: ${(props) => (props.height ? props.height : undefined)}; - padding: var(--spacing-padding-xxs) var(--spacing-padding-none); - background-color: var(--color-bg-neutral-lightest); - border: var(--border-width-s) var(--border-style-default) var(--border-color-neutral-medium); - border-radius: var(--border-radius-s); - box-shadow: var(--shadow-200); color: var(--color-fg-neutral-dark); font-family: var(--typography-font-family); font-size: var(--typography-label-m); @@ -219,54 +215,57 @@ const VirtualizedListbox = ({ }; return ( - { - event.stopPropagation(); - }} - onMouseDown={(event) => { - event.preventDefault(); - }} - style={styles} - > - item.type === "option" && item.option.value === currentValue) ?? - 0, - align: "center", - behavior: "auto", - } - : 0 - } - itemContent={(index) => renderItem(index)} - components={{ - List: forwardRef((props, ref) => ( -
- )), - Header: () => - isSearchEmpty ? ( - - - {translatedLabels.select.noMatchesErrorMessage} - - ) : null, + + { + event.stopPropagation(); + }} + onMouseDown={(event) => { + event.preventDefault(); }} - /> - + style={styles} + > + item.type === "option" && item.option.value === currentValue + ) ?? 0, + align: "center", + behavior: "auto", + } + : 0 + } + itemContent={(index) => renderItem(index)} + components={{ + List: forwardRef((props, ref) => ( +
+ )), + Header: () => + isSearchEmpty ? ( + + + {translatedLabels.select.noMatchesErrorMessage} + + ) : null, + }} + /> + + ); }; @@ -435,23 +434,25 @@ const NonVirtualizedListbox = ({ }, [visualFocusIndex]); return ( - { - event.stopPropagation(); - }} - onMouseDown={(event) => { - event.preventDefault(); - }} - ref={listboxRef} - role="listbox" - style={styles} - > - {getFirstItem()} - {options.map(mapOptionFunc)} - + + { + event.stopPropagation(); + }} + onMouseDown={(event) => { + event.preventDefault(); + }} + ref={listboxRef} + role="listbox" + style={styles} + > + {getFirstItem()} + {options.map(mapOptionFunc)} + + ); }; diff --git a/packages/lib/src/select/Select.tsx b/packages/lib/src/select/Select.tsx index 0544cfb84..b8546ff34 100644 --- a/packages/lib/src/select/Select.tsx +++ b/packages/lib/src/select/Select.tsx @@ -1,4 +1,3 @@ -import * as Popover from "@radix-ui/react-popover"; import { ChangeEvent, FocusEvent, @@ -7,7 +6,6 @@ import { MouseEvent, useCallback, useContext, - useEffect, useId, useMemo, useRef, @@ -42,6 +40,7 @@ import ErrorMessage from "../styles/forms/ErrorMessage"; import HelperText from "../styles/forms/HelperText"; import Label from "../styles/forms/Label"; import inputStylesByState from "../styles/forms/inputStylesByState"; +import DxcPopover from "../popover/Popover"; const SelectContainer = styled.div<{ margin: SelectPropsType["margin"]; @@ -211,10 +210,6 @@ const DxcSelect = forwardRef( const [isOpen, changeIsOpen] = useState(false); const [searchValue, setSearchValue] = useState(""); const [visualFocusIndex, changeVisualFocusIndex] = useState(-1); - const [portalContainer, setPortalContainer] = useState(null); - useEffect(() => { - setPortalContainer(document?.getElementById(`${id}-portal`)); - }, []); const selectRef = useRef(null); const selectSearchInputRef = useRef(null); @@ -508,143 +503,134 @@ const DxcSelect = forwardRef( {helperText} )} - - - + } + isOpen={isOpen} + onOpenAutoFocus={(event) => { + // Avoid select to lose focus when the list is opened + event.preventDefault(); + }} + onCloseAutoFocus={(event) => { + // Avoid select to lose focus when the list is closed + event.preventDefault(); + }} + asChild + > + + {searchable && ( + )} - - - - - {portalContainer && ( - - { - // Avoid select to lose focus when the list is closed - event.preventDefault(); - }} - onOpenAutoFocus={(event) => { - // Avoid select to lose focus when the list is opened - event.preventDefault(); - }} - sideOffset={4} - style={{ zIndex: "var(--z-dropdown)" }} - > - + {getSelectedOptionLabel(placeholder, selectedOption)} + + )} + + + + {searchable && searchValue.length > 0 && ( + - - - )} - + )} + + + + {!disabled && typeof error === "string" && } - -
); }