diff --git a/.changeset/wicked-cycles-enter.md b/.changeset/wicked-cycles-enter.md
new file mode 100644
index 0000000000..cea5cff371
--- /dev/null
+++ b/.changeset/wicked-cycles-enter.md
@@ -0,0 +1,9 @@
+---
+'@backstage/ui': minor
+---
+
+**BREAKING**: The `SelectProps` interface now accepts a generic type parameter for selection mode.
+
+Added searchable and multiple selection support to Select component. The component now accepts `searchable`, `selectionMode`, and `searchPlaceholder` props to enable filtering and multi-selection modes.
+
+Migration: If you're using `SelectProps` type directly, update from `SelectProps` to `SelectProps<'single' | 'multiple'>`. Component usage remains backward compatible.
diff --git a/docs-ui/src/content/select.mdx b/docs-ui/src/content/select.mdx
index 09a852e871..eb53e9ea35 100644
--- a/docs-ui/src/content/select.mdx
+++ b/docs-ui/src/content/select.mdx
@@ -11,6 +11,9 @@ import {
selectDisabledSnippet,
selectResponsiveSnippet,
selectIconSnippet,
+ selectSearchableSnippet,
+ selectMultipleSnippet,
+ selectSearchableMultipleSnippet,
} from './select.props';
import { PageTitle } from '@/components/PageTitle';
import { Theming } from '@/components/Theming';
@@ -87,6 +90,42 @@ Here's a view when the select is disabled.
code={selectDisabledSnippet}
/>
+### Searchable
+
+Here's a view when the select has searchable filtering.
+
+ }
+ code={selectSearchableSnippet}
+/>
+
+### Multiple Selection
+
+Here's a view when the select allows multiple selections.
+
+ }
+ code={selectMultipleSnippet}
+/>
+
+### Searchable with Multiple Selection
+
+Here's a view when the select combines search and multiple selection.
+
+ }
+ code={selectSearchableMultipleSnippet}
+/>
+
### Responsive
Here's a view when the select is responsive.
diff --git a/docs-ui/src/content/select.props.ts b/docs-ui/src/content/select.props.ts
index a93f448bd8..05f0d895c9 100644
--- a/docs-ui/src/content/select.props.ts
+++ b/docs-ui/src/content/select.props.ts
@@ -23,6 +23,12 @@ export const selectPropDefs: Record = {
values: ['Array<{ value: string, label: string }>'],
required: true,
},
+ selectionMode: {
+ type: 'enum',
+ values: ['single', 'multiple'],
+ default: 'single',
+ responsive: false,
+ },
placeholder: {
type: 'string',
default: 'Select an item',
@@ -34,17 +40,23 @@ export const selectPropDefs: Record = {
responsive: false,
},
value: {
- type: 'string',
+ type: 'enum',
+ values: ['string', 'string[]'],
responsive: false,
+ description:
+ 'Selected value (controlled). String for single selection, array for multiple.',
},
defaultValue: {
- type: 'string',
+ type: 'enum',
+ values: ['string', 'string[]'],
responsive: false,
+ description:
+ 'Initial value (uncontrolled). String for single selection, array for multiple.',
},
size: {
type: 'enum',
values: ['small', 'medium'],
- default: 'medium',
+ default: 'small',
responsive: true,
},
isOpen: {
@@ -57,7 +69,7 @@ export const selectPropDefs: Record = {
},
disabledKeys: {
type: 'enum',
- values: ['string[]'],
+ values: ['Iterable'],
responsive: false,
},
isDisabled: {
@@ -72,14 +84,6 @@ export const selectPropDefs: Record = {
type: 'boolean',
responsive: false,
},
- selectedKey: {
- type: 'string',
- responsive: false,
- },
- defaultSelectedKey: {
- type: 'string',
- responsive: false,
- },
onOpenChange: {
type: 'enum',
values: ['(isOpen: boolean) => void'],
@@ -87,7 +91,19 @@ export const selectPropDefs: Record = {
},
onSelectionChange: {
type: 'enum',
- values: ['(key: Key | null) => void'],
+ values: ['(key: Key | null) => void', '(keys: Selection) => void'],
+ responsive: false,
+ description:
+ 'Handler called when selection changes. Single mode: receives Key | null. Multiple mode: receives Selection.',
+ },
+ searchable: {
+ type: 'boolean',
+ default: 'false',
+ responsive: false,
+ },
+ searchPlaceholder: {
+ type: 'string',
+ default: 'Search...',
responsive: false,
},
...classNamePropDefs,
@@ -151,3 +167,45 @@ export const selectResponsiveSnippet = ` `;
+
+export const selectSearchableSnippet = ` `;
+
+export const selectMultipleSnippet = ` `;
+
+export const selectSearchableMultipleSnippet = ` `;
diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md
index c1e1a309cc..9636b5361c 100644
--- a/packages/ui/report.api.md
+++ b/packages/ui/report.api.md
@@ -664,12 +664,16 @@ export const componentDefinitions: {
readonly root: 'bui-Select';
readonly popover: 'bui-SelectPopover';
readonly trigger: 'bui-SelectTrigger';
+ readonly chevron: 'bui-SelectTriggerChevron';
readonly value: 'bui-SelectValue';
- readonly icon: 'bui-SelectIcon';
readonly list: 'bui-SelectList';
readonly item: 'bui-SelectItem';
readonly itemIndicator: 'bui-SelectItemIndicator';
readonly itemLabel: 'bui-SelectItemLabel';
+ readonly searchWrapper: 'bui-SelectSearchWrapper';
+ readonly search: 'bui-SelectSearch';
+ readonly searchClear: 'bui-SelectSearchClear';
+ readonly noResults: 'bui-SelectNoResults';
};
readonly dataAttributes: {
readonly size: readonly ['small', 'medium'];
@@ -1170,6 +1174,14 @@ export const MenuTrigger: (props: MenuTriggerProps) => JSX_2.Element;
// @public (undocumented)
export interface MenuTriggerProps extends MenuTriggerProps_2 {}
+// @public (undocumented)
+type Option_2 = {
+ value: string;
+ label: string;
+ disabled?: boolean;
+};
+export { Option_2 as Option };
+
// @public (undocumented)
export const Radio: ForwardRefExoticComponent<
RadioProps & RefAttributes
@@ -1214,22 +1226,18 @@ export interface SearchFieldProps
// @public (undocumented)
export const Select: ForwardRefExoticComponent<
- SelectProps & RefAttributes
+ SelectProps<'multiple' | 'single'> & RefAttributes
>;
// @public (undocumented)
-export interface SelectProps
- extends SelectProps_2<{
- name: string;
- value: string;
- }>,
+export interface SelectProps
+ extends SelectProps_2,
Omit {
icon?: ReactNode;
- options?: Array<{
- value: string;
- label: string;
- disabled?: boolean;
- }>;
+ options?: Array;
+ searchable?: boolean;
+ searchPlaceholder?: string;
+ selectionMode?: T;
size?: 'small' | 'medium' | Partial>;
}
diff --git a/packages/ui/src/components/Select/Select.module.css b/packages/ui/src/components/Select/Select.module.css
index d4e201ef3a..a2eb41040e 100644
--- a/packages/ui/src/components/Select/Select.module.css
+++ b/packages/ui/src/components/Select/Select.module.css
@@ -17,6 +17,17 @@
@layer tokens, base, components, utilities;
@layer components {
+ .bui-Select,
+ .bui-SelectPopover {
+ &[data-size='small'] {
+ --select-item-height: 2rem;
+ }
+
+ &[data-size='medium'] {
+ --select-item-height: 2.5rem;
+ }
+ }
+
.bui-SelectPopover {
min-width: var(--trigger-width);
}
@@ -32,30 +43,29 @@
cursor: pointer;
gap: var(--bui-space-2);
width: 100%;
+ height: var(--select-item-height);
+
+ .bui-Select[data-size='small'] & {
+ padding-inline: var(--bui-space-3) 0;
+ }
+
+ .bui-Select[data-size='medium'] & {
+ padding-inline: var(--bui-space-4) 0;
+ }
& svg {
flex-shrink: 0;
color: var(--bui-fg-secondary);
- }
- &[data-size='small'] {
- height: 2rem;
- padding-inline: var(--bui-space-3);
- }
+ .bui-Select[data-size='small'] & {
+ width: 1rem;
+ height: 1rem;
+ }
- &[data-size='medium'] {
- height: 3rem;
- padding-inline: var(--bui-space-4);
- }
-
- &[data-size='small'] svg {
- width: 1rem;
- height: 1rem;
- }
-
- &[data-size='medium'] svg {
- width: 1.25rem;
- height: 1.25rem;
+ .bui-Select[data-size='medium'] & {
+ width: 1.25rem;
+ height: 1.25rem;
+ }
}
&::placeholder {
@@ -63,7 +73,7 @@
}
&:hover {
- transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out;
+ transition: border-color 0.2s ease-in-out;
border-color: var(--bui-border-hover);
}
@@ -72,16 +82,13 @@
outline: 0;
}
- .bui-Select[data-invalid] &,
- &[data-invalid] {
+ .bui-Select[data-invalid] & {
border-color: var(--bui-fg-danger);
- }
- &[data-invalid]:hover {
- border-width: 2px;
- }
- &[data-invalid]:focus-visible {
- border-width: 2px;
+ &:focus-visible,
+ &:hover {
+ outline: 1px solid var(--bui-fg-danger);
+ }
}
&[disabled] {
@@ -89,14 +96,15 @@
border-color: var(--bui-border-disabled);
color: var(--bui-fg-disabled);
}
+ }
- &[disabled] .bui-SelectValue {
- color: var(--bui-fg-disabled);
- }
-
- &[data-popup-open] .bui-SelectIcon {
- transform: rotate(180deg);
- }
+ .bui-SelectTriggerChevron {
+ display: grid;
+ place-content: center;
+ width: var(--select-item-height);
+ height: var(--select-item-height);
+ flex-shrink: 0;
+ flex-grow: 0;
}
.bui-SelectValue {
@@ -128,37 +136,32 @@
}
.bui-SelectItem {
+ box-sizing: border-box;
position: relative;
width: var(--anchor-width);
display: grid;
grid-template-areas: 'icon text';
grid-template-columns: 1rem 1fr;
align-items: center;
- padding-block: var(--bui-space-2);
+ min-height: var(--select-item-height);
+ padding-block: var(--bui-space-1);
padding-left: var(--bui-space-3);
padding-right: var(--bui-space-4);
color: var(--bui-fg-primary);
- border-radius: var(--bui-radius-3);
cursor: pointer;
user-select: none;
font-size: var(--bui-font-size-3);
- gap: var(--bui-space-1);
+ gap: var(--bui-space-2);
outline: none;
- &[data-focused] {
- z-index: 0;
- position: relative;
- color: var(--bui-fg-primary);
- }
-
&[data-focused]::before {
content: '';
- z-index: -1;
position: absolute;
inset-block: 0;
- inset-inline: 0.25rem;
- border-radius: 0.25rem;
- background-color: var(--bui-bg-tint-hover);
+ inset-inline: var(--bui-space-1);
+ border-radius: var(--bui-radius-2);
+ background: var(--bui-bg-surface-2);
+ z-index: -1;
}
&[data-disabled] {
@@ -184,4 +187,73 @@
flex: 1;
grid-area: text;
}
+
+ .bui-SelectSearchWrapper {
+ flex-shrink: 0;
+ margin-bottom: var(--bui-space-1);
+ display: flex;
+ align-items: center;
+ padding-inline: var(--bui-space-3) 0;
+ border-bottom: 1px solid var(--bui-border);
+ }
+
+ .bui-SelectSearch {
+ border: none;
+ background-color: transparent;
+ padding: 0;
+ color: var(--bui-fg-primary);
+ flex: 1;
+ outline: none;
+ font-size: var(--bui-font-size-3);
+ font-family: var(--bui-font-regular);
+ height: var(--select-item-height);
+ line-height: var(--select-item-height);
+
+ &::placeholder {
+ color: var(--bui-fg-secondary);
+ }
+
+ /* Hide native browser clear button */
+ &::-webkit-search-cancel-button,
+ &::-webkit-search-decoration {
+ -webkit-appearance: none;
+ }
+ }
+
+ .bui-SelectSearchClear {
+ flex: 0 0 auto;
+ display: grid;
+ place-content: center;
+ background-color: transparent;
+ border: none;
+ padding: 0;
+ margin: 0;
+ cursor: pointer;
+ color: var(--bui-fg-secondary);
+ transition: color 0.2s ease-in-out;
+ width: var(--select-item-height);
+ height: var(--select-item-height);
+
+ input:placeholder-shown + & {
+ display: none;
+ }
+
+ &:hover {
+ color: var(--bui-fg-primary);
+ }
+
+ & svg {
+ width: 1rem;
+ height: 1rem;
+ }
+ }
+
+ .bui-SelectNoResults {
+ padding-inline: var(--bui-space-3);
+ padding-block: var(--bui-space-2);
+ color: var(--bui-fg-secondary);
+ font-size: var(--bui-font-size-3);
+ font-family: var(--bui-font-regular);
+ font-weight: var(--bui-font-weight-regular);
+ }
}
diff --git a/packages/ui/src/components/Select/Select.stories.tsx b/packages/ui/src/components/Select/Select.stories.tsx
index 6e96e37f08..18263fe710 100644
--- a/packages/ui/src/components/Select/Select.stories.tsx
+++ b/packages/ui/src/components/Select/Select.stories.tsx
@@ -22,6 +22,9 @@ import { RiCloudLine } from '@remixicon/react';
const meta = {
title: 'Backstage UI/Select',
component: Select,
+ args: {
+ style: { width: 300 },
+ },
} satisfies Meta;
export default meta;
@@ -34,6 +37,35 @@ const fontOptions = [
{ value: 'cursive', label: 'Cursive' },
];
+const countries = [
+ { value: 'us', label: 'United States' },
+ { value: 'ca', label: 'Canada' },
+ { value: 'mx', label: 'Mexico' },
+ { value: 'uk', label: 'United Kingdom' },
+ { value: 'fr', label: 'France' },
+ { value: 'de', label: 'Germany' },
+ { value: 'it', label: 'Italy' },
+ { value: 'es', label: 'Spain' },
+ { value: 'jp', label: 'Japan' },
+ { value: 'cn', label: 'China' },
+ { value: 'in', label: 'India' },
+ { value: 'br', label: 'Brazil' },
+ { value: 'au', label: 'Australia' },
+];
+
+const skills = [
+ { value: 'react', label: 'React' },
+ { value: 'typescript', label: 'TypeScript' },
+ { value: 'javascript', label: 'JavaScript' },
+ { value: 'python', label: 'Python' },
+ { value: 'java', label: 'Java' },
+ { value: 'csharp', label: 'C#' },
+ { value: 'go', label: 'Go' },
+ { value: 'rust', label: 'Rust' },
+ { value: 'kotlin', label: 'Kotlin' },
+ { value: 'swift', label: 'Swift' },
+];
+
export const Default: Story = {
args: {
options: fontOptions,
@@ -41,6 +73,38 @@ export const Default: Story = {
},
};
+export const Searchable: Story = {
+ args: {
+ label: 'Country',
+ searchable: true,
+ searchPlaceholder: 'Search countries...',
+ options: countries,
+ },
+};
+
+export const MultipleSelection: Story = {
+ args: {
+ label: 'Select multiple options',
+ selectionMode: 'multiple',
+ options: [
+ { value: 'option1', label: 'Option 1' },
+ { value: 'option2', label: 'Option 2' },
+ { value: 'option3', label: 'Option 3' },
+ { value: 'option4', label: 'Option 4' },
+ ],
+ },
+};
+
+export const SearchableMultiple: Story = {
+ args: {
+ label: 'Skills',
+ searchable: true,
+ selectionMode: 'multiple',
+ searchPlaceholder: 'Filter skills...',
+ options: skills,
+ },
+};
+
export const Preview: Story = {
args: {
label: 'Font Family',
diff --git a/packages/ui/src/components/Select/Select.tsx b/packages/ui/src/components/Select/Select.tsx
index b1fec7dbe7..0b133d07c5 100644
--- a/packages/ui/src/components/Select/Select.tsx
+++ b/packages/ui/src/components/Select/Select.tsx
@@ -15,15 +15,7 @@
*/
import { forwardRef, useEffect } from 'react';
-import {
- Select as AriaSelect,
- SelectValue,
- Button,
- Popover,
- ListBox,
- ListBoxItem,
- Text,
-} from 'react-aria-components';
+import { Select as AriaSelect, Popover } from 'react-aria-components';
import clsx from 'clsx';
import { SelectProps } from './types';
import { useStyles } from '../../hooks/useStyles';
@@ -31,10 +23,14 @@ import { FieldLabel } from '../FieldLabel';
import { FieldError } from '../FieldError';
import styles from './Select.module.css';
import stylesPopover from '../Popover/Popover.module.css';
-import { RiArrowDownSLine, RiCheckLine } from '@remixicon/react';
+import { SelectTrigger } from './SelectTrigger';
+import { SelectContent } from './SelectContent';
/** @public */
-export const Select = forwardRef((props, ref) => {
+export const Select = forwardRef<
+ HTMLDivElement,
+ SelectProps<'single' | 'multiple'>
+>((props, ref) => {
const { classNames: popoverClassNames } = useStyles('Popover');
const { classNames, dataAttributes, cleanedProps } = useStyles('Select', {
size: 'small',
@@ -47,14 +43,13 @@ export const Select = forwardRef((props, ref) => {
label,
description,
options,
- placeholder,
- size,
icon,
+ searchable,
+ searchPlaceholder,
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledBy,
isRequired,
secondaryLabel,
- style,
...rest
} = cleanedProps;
@@ -66,7 +61,6 @@ export const Select = forwardRef((props, ref) => {
}
}, [label, ariaLabel, ariaLabelledBy]);
- // If a secondary label is provided, use it. Otherwise, use 'Required' if the field is required.
const secondaryLabelText = secondaryLabel || (isRequired ? 'Required' : null);
return (
@@ -83,16 +77,7 @@ export const Select = forwardRef((props, ref) => {
secondaryLabel={secondaryLabelText}
description={description}
/>
-
- {icon}
-
-
-
+
((props, ref) => {
classNames.popover,
styles[classNames.popover],
)}
+ {...dataAttributes}
>
-
- {options?.map(option => (
-
-
-
-
-
- {option.label}
-
-
- ))}
-
+
);
diff --git a/packages/ui/src/components/Select/SelectContent.tsx b/packages/ui/src/components/Select/SelectContent.tsx
new file mode 100644
index 0000000000..42070321a3
--- /dev/null
+++ b/packages/ui/src/components/Select/SelectContent.tsx
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2025 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ Input,
+ SearchField,
+ Autocomplete,
+ Button,
+} from 'react-aria-components';
+import { useFilter } from 'react-aria';
+import { RiCloseCircleLine } from '@remixicon/react';
+import clsx from 'clsx';
+import { useStyles } from '../../hooks/useStyles';
+import { SelectListBox } from './SelectListBox';
+import styles from './Select.module.css';
+import type { Option } from './types';
+
+interface SelectContentProps {
+ searchable?: boolean;
+ searchPlaceholder?: string;
+ options?: Array;
+}
+
+export function SelectContent({
+ searchable,
+ searchPlaceholder = 'Search...',
+ options,
+}: SelectContentProps) {
+ const { contains } = useFilter({ sensitivity: 'base' });
+ const { classNames } = useStyles('Select');
+
+ if (!searchable) {
+ return ;
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/ui/src/components/Select/SelectListBox.tsx b/packages/ui/src/components/Select/SelectListBox.tsx
new file mode 100644
index 0000000000..aa050ba766
--- /dev/null
+++ b/packages/ui/src/components/Select/SelectListBox.tsx
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2025 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ListBox, ListBoxItem, Text } from 'react-aria-components';
+import { RiCheckLine } from '@remixicon/react';
+import clsx from 'clsx';
+import { useStyles } from '../../hooks/useStyles';
+import styles from './Select.module.css';
+import type { Option } from './types';
+
+interface SelectListBoxProps {
+ options?: Array ;
+}
+
+const NoResults = () => {
+ const { classNames } = useStyles('Select');
+
+ return (
+
+ No results found.
+
+ );
+};
+
+export function SelectListBox({ options, ...props }: SelectListBoxProps) {
+ const { classNames } = useStyles('Select', props);
+ return (
+ }
+ >
+ {options?.map(option => (
+
+
+
+
+
+ {option.label}
+
+
+ ))}
+
+ );
+}
diff --git a/packages/ui/src/components/Select/SelectTrigger.tsx b/packages/ui/src/components/Select/SelectTrigger.tsx
new file mode 100644
index 0000000000..64604c3c6b
--- /dev/null
+++ b/packages/ui/src/components/Select/SelectTrigger.tsx
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2025 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ReactNode } from 'react';
+import { Button, SelectValue } from 'react-aria-components';
+import { RiArrowDownSLine } from '@remixicon/react';
+import clsx from 'clsx';
+import { useStyles } from '../../hooks/useStyles';
+import styles from './Select.module.css';
+
+interface SelectTriggerProps {
+ icon?: ReactNode;
+}
+
+export function SelectTrigger({ icon }: SelectTriggerProps) {
+ const { classNames } = useStyles('Select');
+
+ return (
+
+ {icon}
+
+
+
+
+
+ );
+}
diff --git a/packages/ui/src/components/Select/types.ts b/packages/ui/src/components/Select/types.ts
index 6051a0e560..436cdeea17 100644
--- a/packages/ui/src/components/Select/types.ts
+++ b/packages/ui/src/components/Select/types.ts
@@ -20,11 +20,11 @@ import type { SelectProps as AriaSelectProps } from 'react-aria-components';
import type { FieldLabelProps } from '../FieldLabel/types';
/** @public */
-export interface SelectProps
- extends AriaSelectProps<{
- name: string;
- value: string;
- }>,
+export type Option = { value: string; label: string; disabled?: boolean };
+
+/** @public */
+export interface SelectProps
+ extends AriaSelectProps,
Omit {
/**
* An icon to render before the input
@@ -33,12 +33,31 @@ export interface SelectProps
/**
* The size of the select field
- * @defaultValue 'medium'
+ * @defaultValue 'small'
*/
size?: 'small' | 'medium' | Partial>;
/**
* The options of the select field
*/
- options?: Array<{ value: string; label: string; disabled?: boolean }>;
+ options?: Array;
+
+ /**
+ * Enable search/filter functionality in the dropdown
+ * @defaultValue false
+ */
+ searchable?: boolean;
+
+ /**
+ * placeholder text for the search input
+ * only used when searchable is true
+ * @defaultvalue 'search...'
+ */
+ searchPlaceholder?: string;
+
+ /**
+ * Selection mode, single or multiple
+ * @defaultvalue 'single'
+ */
+ selectionMode?: T;
}
diff --git a/packages/ui/src/utils/componentDefinitions.ts b/packages/ui/src/utils/componentDefinitions.ts
index 9b18a6feaf..167295c25a 100644
--- a/packages/ui/src/utils/componentDefinitions.ts
+++ b/packages/ui/src/utils/componentDefinitions.ts
@@ -303,12 +303,16 @@ export const componentDefinitions = {
root: 'bui-Select',
popover: 'bui-SelectPopover',
trigger: 'bui-SelectTrigger',
+ chevron: 'bui-SelectTriggerChevron',
value: 'bui-SelectValue',
- icon: 'bui-SelectIcon',
list: 'bui-SelectList',
item: 'bui-SelectItem',
itemIndicator: 'bui-SelectItemIndicator',
itemLabel: 'bui-SelectItemLabel',
+ searchWrapper: 'bui-SelectSearchWrapper',
+ search: 'bui-SelectSearch',
+ searchClear: 'bui-SelectSearchClear',
+ noResults: 'bui-SelectNoResults',
},
dataAttributes: {
size: ['small', 'medium'] as const,