([]);
+ const [inputValue, setInputValue] = useState('');
+ const [options, setOptions] = useState(deselectedOptions);
+
+ const updateText = useCallback(
+ (value: string) => {
+ setInputValue(value);
+
+ if (value === '') {
+ setOptions(deselectedOptions);
+ return;
+ }
+
+ const filterRegex = new RegExp(value, 'i');
+ const resultOptions = deselectedOptions.filter((option) =>
+ option.label.match(filterRegex),
+ );
+ setOptions(resultOptions);
+ },
+ [deselectedOptions],
+ );
+
+ const updateSelection = useCallback(
+ (selected: string) => {
+ if (selectedOptions.includes(selected)) {
+ setSelectedOptions(
+ selectedOptions.filter((option) => option !== selected),
+ );
+ } else {
+ setSelectedOptions([...selectedOptions, selected]);
+ }
+
+ updateText('');
+ },
+ [selectedOptions, updateText],
+ );
+
+ const removeTag = useCallback(
+ (tag: string) => () => {
+ const options = [...selectedOptions];
+ options.splice(options.indexOf(tag), 1);
+ setSelectedOptions(options);
+ },
+ [selectedOptions],
+ );
+
+ const tagsMarkup = selectedOptions.map((option) => (
+
+ {option}
+
+ ));
+
+ const optionsMarkup =
+ options.length > 0
+ ? options.map((option) => {
+ const {label, value} = option;
+
+ return (
+
+ {label}
+
+ );
+ })
+ : null;
+
+ return (
+
+
+ }
+ >
+ {optionsMarkup ? (
+ {optionsMarkup}
+ ) : null}
+
+
+ {tagsMarkup}
+
+ );
+}
diff --git a/polaris-react/playground/components/Select/Select.module.scss b/polaris-react/playground/components/Select/Select.module.scss
new file mode 100644
index 00000000000..cd505a817a1
--- /dev/null
+++ b/polaris-react/playground/components/Select/Select.module.scss
@@ -0,0 +1,31 @@
+.Select {
+ padding: calc(var(--p-space-200) + var(--p-space-050)) var(--p-space-200)
+ var(--p-space-200) var(--p-space-300);
+ border-radius: var(--p-border-radius-200);
+ border: var(--p-border-width-0165) solid var(--p-color-input-border);
+ background-color: var(--Color-input-bg-surface);
+ width: 100%;
+
+ &:focus:not(:active) {
+ outline: var(--p-border-width-050) solid var(--p-color-border-focus);
+ outline-offset: var(--p-border-width-025);
+ }
+
+ &:hover {
+ border-color: var(--p-color-input-border-hover);
+ background-color: var(--Color-input-bg-surface-hover);
+
+ svg {
+ fill: var(--p-color-icon-hover);
+ }
+ }
+
+ &:active {
+ border-color: var(--p-color-input-border-active);
+ background-color: var(--Color-input-bg-surface-active);
+
+ svg {
+ fill: var(--p-color-icon-active);
+ }
+ }
+}
diff --git a/polaris-react/playground/components/Select/Select.tsx b/polaris-react/playground/components/Select/Select.tsx
new file mode 100644
index 00000000000..649223f4ec9
--- /dev/null
+++ b/polaris-react/playground/components/Select/Select.tsx
@@ -0,0 +1,67 @@
+import React from 'react';
+import {SelectMinor} from '@shopify/polaris-icons';
+
+import type {OptionListProps} from '../../../src';
+import {
+ BlockStack,
+ Icon,
+ Text,
+ InlineGrid,
+ UnstyledButton,
+ Popover,
+} from '../../../src';
+import {Options} from '../Options/Options';
+
+import styles from './Select.module.scss';
+
+interface Props {
+ title: string;
+ defaultSelected?: string[];
+}
+
+export function Select({
+ title,
+ defaultSelected,
+ options,
+}: Props & Pick) {
+ const [active, setActive] = React.useState(false);
+ // const [selected, setSelected] = React.useState(defaultSelected ?? []);
+
+ const firstSelected = options?.find(
+ (option) => option.value === defaultSelected?.[0],
+ )?.label;
+
+ const activator = (
+ setActive((active) => !active)}
+ className={styles.Select}
+ >
+
+
+
+ {title}
+
+ {defaultSelected?.length && (
+
+ {firstSelected}
+
+ )}
+
+
+
+
+ );
+
+ return (
+ setActive(false)}
+ // TODO: Allow coverage of activator
+ // preferredAlignment="cover"
+ activator={activator}
+ >
+
+
+ );
+}
diff --git a/polaris-react/playground/components/index.ts b/polaris-react/playground/components/index.ts
new file mode 100644
index 00000000000..a153daafaf3
--- /dev/null
+++ b/polaris-react/playground/components/index.ts
@@ -0,0 +1,2 @@
+export * from './Select/Select';
+export * from './Options/Options';
diff --git a/polaris-react/src/components/Combobox/Combobox.tsx b/polaris-react/src/components/Combobox/Combobox.tsx
index cdda0c4efc4..ca92dd43c8f 100644
--- a/polaris-react/src/components/Combobox/Combobox.tsx
+++ b/polaris-react/src/components/Combobox/Combobox.tsx
@@ -14,6 +14,8 @@ import type {
ComboboxListboxType,
ComboboxListboxOptionType,
} from '../../utilities/combobox';
+import {BlockStack} from '../BlockStack';
+import {Box} from '../Box';
import styles from './Combobox.module.scss';
import {TextField} from './components';
@@ -31,6 +33,7 @@ export interface ComboboxProps {
willLoadMoreOptions?: boolean;
/** Height to set on the Popover Pane. */
height?: string;
+ persistent?: boolean;
/** Callback fired when the bottom of the lisbox is reached. Use to lazy load when listbox option data is paginated. */
onScrolledToBottom?(): void;
/** Callback fired when the popover closes */
@@ -44,6 +47,7 @@ export function Combobox({
preferredPosition = 'below',
willLoadMoreOptions,
height,
+ persistent,
onScrolledToBottom,
onClose,
}: ComboboxProps) {
@@ -148,7 +152,23 @@ export function Combobox({
],
);
- return (
+ return persistent ? (
+ <>
+
+
+ {activator}
+
+
+
+
+
+ {children}
+
+
+ >
+ ) : (