(Select) add classic variant with placeholder support

- Use FieldVariant enum for variant prop
- Add styled placeholder for classic mode (.c__select__placeholder)
- Label rendered outside wrapper in classic mode
- Compact height in classic mode
- Add unit tests for mono and multi Select
- Add Storybook stories

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Nathan Panchout
2026-01-26 20:07:54 +01:00
parent fb0c8c0f10
commit e94ddc9fd2
9 changed files with 601 additions and 113 deletions

View File

@@ -3,6 +3,81 @@
.c__select { .c__select {
position: relative; position: relative;
&__label {
display: block;
font-size: var(--c--components--forms-labelledbox--classic-label-font-size);
color: var(--c--components--forms-labelledbox--label-color--small);
margin-bottom: var(
--c--components--forms-labelledbox--classic-label-margin-bottom
);
cursor: pointer;
&--disabled {
color: var(
--c--components--forms-labelledbox--label-color--small--disabled
);
cursor: default;
}
}
&--classic {
.c__select__wrapper {
align-items: center;
height: 2.75rem;
}
.c__select__inner {
align-items: center;
&__actions {
top: 0;
}
}
// When not populated, keep flex layout so actions are vertically centered
// alongside the placeholder text (single line).
&.c__select--multiline:not(.c__select--populated) {
.c__select__wrapper {
min-height: 2.75rem;
}
.c__select__inner {
display: flex;
&__actions {
float: none;
height: auto;
top: 0;
order: 2;
}
}
}
// When populated, keep flex layout and use fixed padding instead of
// centering so that the first row of pills stays at a consistent
// vertical position regardless of how many rows wrap below.
&.c__select--multiline.c__select--populated {
.c__select__wrapper {
align-items: flex-start;
min-height: 2.75rem;
padding-top: 9px;
padding-bottom: 0.25rem;
}
.c__select__inner {
display: flex;
align-items: flex-start;
&__actions {
float: none;
height: auto;
top: 0;
order: 2;
}
}
}
}
&__wrapper { &__wrapper {
border-radius: var(--c--components--forms-select--border-radius); border-radius: var(--c--components--forms-select--border-radius);
border-width: var(--c--components--forms-select--border-width); border-width: var(--c--components--forms-select--border-width);
@@ -34,14 +109,16 @@
&:hover { &:hover {
border-radius: var(--c--components--forms-select--border-radius--hover); border-radius: var(--c--components--forms-select--border-radius--hover);
border-color: var(--c--components--forms-select--border-color--hover); border-color: var(--c--components--forms-select--border-color--hover);
box-shadow: 0 0 0 var(--c--components--forms-select--border-width--hover) var(--c--components--forms-select--border-color--hover); box-shadow: 0 0 0 var(--c--components--forms-select--border-width--hover)
var(--c--components--forms-select--border-color--hover);
} }
&:focus-within, &:focus-within,
&--focus { &--focus {
border-radius: var(--c--components--forms-select--border-radius--focus); border-radius: var(--c--components--forms-select--border-radius--focus);
border-color: var(--c--components--forms-select--border-color--focus); border-color: var(--c--components--forms-select--border-color--focus);
box-shadow: 0 0 0 var(--c--components--forms-select--border-width--focus) var(--c--components--forms-select--border-color--focus); box-shadow: 0 0 0 var(--c--components--forms-select--border-width--focus)
var(--c--components--forms-select--border-color--focus);
label { label {
color: var(--c--components--forms-select--label-color--focus); color: var(--c--components--forms-select--label-color--focus);
@@ -49,6 +126,11 @@
} }
} }
&__placeholder {
color: var(--c--components--forms-select--placeholder-color);
font-size: var(--c--components--forms-select--font-size);
}
&__inner { &__inner {
flex-grow: 1; flex-grow: 1;
display: flex; display: flex;
@@ -103,7 +185,9 @@
color: var(--c--contextuals--content--semantic--neutral--secondary); color: var(--c--contextuals--content--semantic--neutral--secondary);
} }
&__separator { &__separator {
background-color: var(--c--contextuals--content--semantic--neutral--tertiary); background-color: var(
--c--contextuals--content--semantic--neutral--tertiary
);
height: 24px; height: 24px;
width: 1px; width: 1px;
} }
@@ -210,7 +294,9 @@
} }
&:hover { &:hover {
border-color: var(--c--contextuals--border--semantic--neutral--tertiary-hover); border-color: var(
--c--contextuals--border--semantic--neutral--tertiary-hover
);
} }
} }

View File

@@ -2,6 +2,7 @@ import React, { PropsWithChildren, ReactNode, RefAttributes } from "react";
import { SelectMulti } from ":/components/Forms/Select/multi"; import { SelectMulti } from ":/components/Forms/Select/multi";
import { SelectMono } from ":/components/Forms/Select/mono"; import { SelectMono } from ":/components/Forms/Select/mono";
import { FieldProps } from ":/components/Forms/Field"; import { FieldProps } from ":/components/Forms/Field";
import type { FieldVariant } from ":/components/Forms/types";
export * from ":/components/Forms/Select/mono"; export * from ":/components/Forms/Select/mono";
export * from ":/components/Forms/Select/multi"; export * from ":/components/Forms/Select/multi";
@@ -32,6 +33,8 @@ export type SelectProps = PropsWithChildren &
FieldProps & { FieldProps & {
label: string; label: string;
hideLabel?: boolean; hideLabel?: boolean;
variant?: FieldVariant;
placeholder?: string;
options: Option[]; options: Option[];
searchable?: boolean; searchable?: boolean;
name?: string; name?: string;

View File

@@ -6,6 +6,7 @@ import { Field } from ":/components/Forms/Field";
import { LabelledBox } from ":/components/Forms/LabelledBox"; import { LabelledBox } from ":/components/Forms/LabelledBox";
import { Button } from ":/components/Button"; import { Button } from ":/components/Button";
import { Option, SelectProps } from ":/components/Forms/Select"; import { Option, SelectProps } from ":/components/Forms/Select";
import { ClassicLabel } from ":/components/Forms/ClassicLabel";
import { isOptionWithRender } from ":/components/Forms/Select/utils"; import { isOptionWithRender } from ":/components/Forms/Select/utils";
import { SelectMenu } from ":/components/Forms/Select/select-menu"; import { SelectMenu } from ":/components/Forms/Select/select-menu";
@@ -77,6 +78,8 @@ export const SelectMonoAux = ({
name, name,
label, label,
hideLabel, hideLabel,
variant = "floating",
placeholder,
labelAsPlaceholder, labelAsPlaceholder,
downshiftProps, downshiftProps,
downshiftReturn, downshiftReturn,
@@ -89,6 +92,60 @@ export const SelectMonoAux = ({
const { t } = useCunningham(); const { t } = useCunningham();
const labelProps = downshiftReturn.getLabelProps(); const labelProps = downshiftReturn.getLabelProps();
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const isClassic = variant === "classic";
const showPlaceholder =
isClassic && !downshiftReturn.selectedItem && placeholder;
const selectInner = (
<div className="c__select__inner">
<div className="c__select__inner__value">
{showPlaceholder ? (
<span className="c__select__placeholder">{placeholder}</span>
) : (
children
)}
</div>
<div className="c__select__inner__actions">
{clearable && !disabled && downshiftReturn.selectedItem && (
<>
<Button
variant="tertiary"
color="neutral"
size="nano"
aria-label={t("components.forms.select.clear_button_aria_label")}
className="c__select__inner__actions__clear"
onClick={(e) => {
downshiftReturn.selectItem(null);
e.stopPropagation();
}}
icon={<span className="material-icons">close</span>}
type="button"
/>
<div className="c__select__inner__actions__separator" />
</>
)}
<Button
variant="tertiary"
color="neutral"
size="nano"
className="c__select__inner__actions__open"
icon={
<span
className={classNames("material-icons", {
opened: downshiftReturn.isOpen,
})}
>
arrow_drop_down
</span>
}
disabled={disabled}
type="button"
{...downshiftReturn.toggleButtonProps}
/>
</div>
</div>
);
return ( return (
<> <>
@@ -101,12 +158,24 @@ export const SelectMonoAux = ({
"c__select--" + state, "c__select--" + state,
{ {
"c__select--disabled": disabled, "c__select--disabled": disabled,
"c__select--classic": isClassic,
}, },
)} )}
onBlur={() => onBlur={() =>
onBlur?.({ target: { value: downshiftReturn.selectedItem?.value } }) onBlur?.({ target: { value: downshiftReturn.selectedItem?.value } })
} }
> >
{isClassic && (
<ClassicLabel
label={label}
hideLabel={hideLabel}
disabled={disabled}
className="c__select__label"
disabledClassName="c__select__label--disabled"
htmlFor={labelProps.htmlFor}
id={labelProps.id}
/>
)}
{/* We disabled linting for this specific line because we consider that the onClick props is only used for */} {/* We disabled linting for this specific line because we consider that the onClick props is only used for */}
{/* mouse users, so this do not engender any issue for accessibility. */} {/* mouse users, so this do not engender any issue for accessibility. */}
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */} {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
@@ -124,59 +193,21 @@ export const SelectMonoAux = ({
/> />
)} )}
<LabelledBox {isClassic ? (
label={label} selectInner
hideLabel={hideLabel} ) : (
labelAsPlaceholder={labelAsPlaceholder} <LabelledBox
htmlFor={labelProps.htmlFor} label={label}
labelId={labelProps.id} hideLabel={hideLabel}
disabled={disabled} variant={variant}
> labelAsPlaceholder={labelAsPlaceholder}
<div className="c__select__inner"> htmlFor={labelProps.htmlFor}
<div className="c__select__inner__value">{children}</div> labelId={labelProps.id}
<div className="c__select__inner__actions"> disabled={disabled}
{clearable && !disabled && downshiftReturn.selectedItem && ( >
<> {selectInner}
<Button </LabelledBox>
variant="tertiary" )}
color="neutral"
size="nano"
aria-label={t(
"components.forms.select.clear_button_aria_label",
)}
className="c__select__inner__actions__clear"
onClick={(e) => {
downshiftReturn.selectItem(null);
e.stopPropagation();
}}
icon={<span className="material-icons">close</span>}
type="button"
/>
<div className="c__select__inner__actions__separator" />
</>
)}
<Button
variant="tertiary"
color="neutral"
size="nano"
className="c__select__inner__actions__open"
icon={
<span
className={classNames("material-icons", {
opened: downshiftReturn.isOpen,
})}
>
arrow_drop_down
</span>
}
disabled={disabled}
type="button"
{...downshiftReturn.toggleButtonProps}
/>
</div>
</div>
</LabelledBox>
</div> </div>
</div> </div>
</Field> </Field>

View File

@@ -2133,4 +2133,122 @@ describe("<Select/>", () => {
document.querySelector(".c__field.my-custom-class"), document.querySelector(".c__field.my-custom-class"),
).toBeInTheDocument(); ).toBeInTheDocument();
}); });
describe("classic variant", () => {
it("renders with classic variant", async () => {
render(
<CunninghamProvider>
<Select
label="City"
variant="classic"
options={[
{ label: "Paris", value: "paris" },
{ label: "London", value: "london" },
]}
/>
</CunninghamProvider>,
);
// In classic mode, label is rendered outside the wrapper with its own class
expect(document.querySelector(".c__select__label")).toBeInTheDocument();
expect(document.querySelector(".c__select--classic")).toBeInTheDocument();
});
it("shows placeholder in classic variant when no selection", async () => {
render(
<CunninghamProvider>
<Select
label="City"
variant="classic"
placeholder="Select a city..."
options={[
{ label: "Paris", value: "paris" },
{ label: "London", value: "london" },
]}
/>
</CunninghamProvider>,
);
expect(screen.getByText("Select a city...")).toBeInTheDocument();
expect(
document.querySelector(".c__select__placeholder"),
).toBeInTheDocument();
});
it("hides placeholder after selection in classic variant", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<Select
label="City"
variant="classic"
placeholder="Select a city..."
options={[
{ label: "Paris", value: "paris" },
{ label: "London", value: "london" },
]}
/>
</CunninghamProvider>,
);
// Placeholder should be visible initially
expect(screen.getByText("Select a city...")).toBeInTheDocument();
// Open menu and select an option
const input = screen.getByRole("combobox", { name: "City" });
await user.click(input);
await user.click(screen.getByRole("option", { name: "Paris" }));
// Placeholder should be hidden, value should be shown
expect(screen.queryByText("Select a city...")).not.toBeInTheDocument();
const valueRendered = document.querySelector(".c__select__inner__value");
expect(valueRendered).toHaveTextContent("Paris");
});
it("label is always static in classic variant", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<Select
label="City"
variant="classic"
options={[
{ label: "Paris", value: "paris" },
{ label: "London", value: "london" },
]}
/>
</CunninghamProvider>,
);
const label = screen.getByText("City");
// In classic variant, label is outside the wrapper with c__select__label class
expect(label.classList.contains("c__select__label")).toBe(true);
// Open menu
const input = screen.getByRole("combobox", { name: "City" });
await user.click(input);
// Label should still have the same class
expect(label.classList.contains("c__select__label")).toBe(true);
});
it("defaults to floating variant (no placeholder shown)", () => {
render(
<CunninghamProvider>
<Select
label="City"
placeholder="Select a city..."
options={[
{ label: "Paris", value: "paris" },
{ label: "London", value: "london" },
]}
/>
</CunninghamProvider>,
);
// In floating variant, placeholder prop is ignored
expect(screen.queryByText("Select a city...")).not.toBeInTheDocument();
expect(
document.querySelector(".c__select--classic"),
).not.toBeInTheDocument();
});
});
}); });

View File

@@ -16,6 +16,12 @@ import { Input } from ":/components/Forms/Input";
export default { export default {
title: "Components/Forms/Select/Mono", title: "Components/Forms/Select/Mono",
component: Select, component: Select,
argTypes: {
variant: {
control: "select",
options: ["floating", "classic"],
},
},
} as Meta<typeof Select>; } as Meta<typeof Select>;
const Template: StoryFn<typeof Select> = (args) => ( const Template: StoryFn<typeof Select> = (args) => (
@@ -303,6 +309,66 @@ export const SearchableCustomRender = {
}, },
}; };
export const ClassicVariant = {
render: Template,
args: {
label: "Select a city",
variant: "classic",
placeholder: "Choose a city...",
options: OPTIONS,
},
};
export const ClassicVariantFilled = {
render: Template,
args: {
label: "Select a city",
variant: "classic",
placeholder: "Choose a city...",
options: OPTIONS,
defaultValue: OPTIONS[4].value,
},
};
export const ClassicVariantSearchable = {
render: Template,
args: {
label: "Select a city",
variant: "classic",
placeholder: "Search for a city...",
options: OPTIONS,
searchable: true,
},
};
export const ClassicVariantDisabled = {
render: Template,
args: {
label: "Select a city",
variant: "classic",
placeholder: "Choose a city...",
options: OPTIONS,
disabled: true,
},
};
export const ClassicVariantError = {
render: Template,
args: {
label: "Select a city",
variant: "classic",
placeholder: "Choose a city...",
options: OPTIONS,
state: "error",
text: "Please select a city",
},
};
export const Ref = () => { export const Ref = () => {
const ref = useRef<SelectHandle>(null); const ref = useRef<SelectHandle>(null);

View File

@@ -10,6 +10,7 @@ import {
getOptionsFilter, getOptionsFilter,
optionToValue, optionToValue,
} from ":/components/Forms/Select/mono-common"; } from ":/components/Forms/Select/mono-common";
import { ClassicLabel } from ":/components/Forms/ClassicLabel";
import { SelectedItems } from ":/components/Forms/Select/multi-selected-items"; import { SelectedItems } from ":/components/Forms/Select/multi-selected-items";
import { SelectMultiMenu } from ":/components/Forms/Select/multi-menu"; import { SelectMultiMenu } from ":/components/Forms/Select/multi-menu";
@@ -64,10 +65,71 @@ export const SelectMultiAux = ({ children, ...props }: SelectMultiAuxProps) => {
const { t } = useCunningham(); const { t } = useCunningham();
const labelProps = props.downshiftReturn.getLabelProps(); const labelProps = props.downshiftReturn.getLabelProps();
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const variant = props.variant ?? "floating";
const isClassic = variant === "classic";
const showPlaceholder =
isClassic && props.selectedItems.length === 0 && props.placeholder;
// We need to remove onBlur from toggleButtonProps because it triggers a menu closing each time // We need to remove onBlur from toggleButtonProps because it triggers a menu closing each time
// we tick a checkbox using the monoline style. // we tick a checkbox using the monoline style.
const { onBlur, ...toggleProps } = props.downshiftReturn.toggleButtonProps; const { onBlur, ...toggleProps } = props.downshiftReturn.toggleButtonProps;
const selectInner = (
<div className="c__select__inner">
<div className="c__select__inner__actions">
{props.clearable &&
!props.disabled &&
props.selectedItems.length > 0 && (
<>
<Button
variant="tertiary"
color="neutral"
size="nano"
aria-label={t(
"components.forms.select.clear_all_button_aria_label",
)}
className="c__select__inner__actions__clear"
onClick={(e) => {
e.stopPropagation();
props.onSelectedItemsChange([]);
}}
icon={<span className="material-icons">close</span>}
type="button"
/>
<div className="c__select__inner__actions__separator" />
</>
)}
<Button
variant="tertiary"
color="neutral"
size="nano"
className="c__select__inner__actions__open"
icon={
<span
className={classNames("material-icons", {
opened: props.downshiftReturn.isOpen,
})}
>
arrow_drop_down
</span>
}
disabled={props.disabled}
type="button"
/>
</div>
<div className="c__select__inner__value">
{showPlaceholder ? (
<span className="c__select__placeholder">{props.placeholder}</span>
) : (
<>
<SelectedItems {...props} />
{children}
</>
)}
</div>
</div>
);
return ( return (
<> <>
<Field {...props}> <Field {...props}>
@@ -83,9 +145,21 @@ export const SelectMultiAux = ({ children, ...props }: SelectMultiAuxProps) => {
"c__select--populated": props.selectedItems.length > 0, "c__select--populated": props.selectedItems.length > 0,
"c__select--monoline": props.monoline, "c__select--monoline": props.monoline,
"c__select--multiline": !props.monoline, "c__select--multiline": !props.monoline,
"c__select--classic": isClassic,
}, },
)} )}
> >
{isClassic && (
<ClassicLabel
label={props.label}
hideLabel={props.hideLabel}
disabled={props.disabled}
className="c__select__label"
disabledClassName="c__select__label--disabled"
htmlFor={labelProps.htmlFor}
id={labelProps.id}
/>
)}
<div <div
className={classNames("c__select__wrapper", { className={classNames("c__select__wrapper", {
"c__select__wrapper--focus": "c__select__wrapper--focus":
@@ -102,62 +176,21 @@ export const SelectMultiAux = ({ children, ...props }: SelectMultiAuxProps) => {
value={optionToValue(selectedItem)} value={optionToValue(selectedItem)}
/> />
))} ))}
<LabelledBox {isClassic ? (
label={props.label} selectInner
labelAsPlaceholder={props.labelAsPlaceholder} ) : (
htmlFor={labelProps.htmlFor} <LabelledBox
labelId={labelProps.id} label={props.label}
hideLabel={props.hideLabel} variant={variant}
disabled={props.disabled} labelAsPlaceholder={props.labelAsPlaceholder}
> htmlFor={labelProps.htmlFor}
<div className="c__select__inner"> labelId={labelProps.id}
<div className="c__select__inner__actions"> hideLabel={props.hideLabel}
{props.clearable && disabled={props.disabled}
!props.disabled && >
props.selectedItems.length > 0 && ( {selectInner}
<> </LabelledBox>
<Button )}
variant="tertiary"
color="neutral"
size="nano"
aria-label={t(
"components.forms.select.clear_all_button_aria_label",
)}
className="c__select__inner__actions__clear"
onClick={(e) => {
e.stopPropagation();
props.onSelectedItemsChange([]);
}}
icon={<span className="material-icons">close</span>}
type="button"
/>
<div className="c__select__inner__actions__separator" />
</>
)}
<Button
variant="tertiary"
color="neutral"
size="nano"
className="c__select__inner__actions__open"
icon={
<span
className={classNames("material-icons", {
opened: props.downshiftReturn.isOpen,
})}
>
arrow_drop_down
</span>
}
disabled={props.disabled}
type="button"
/>
</div>
<div className="c__select__inner__value">
<SelectedItems {...props} />
{children}
</div>
</div>
</LabelledBox>
</div> </div>
</div> </div>
</Field> </Field>

View File

@@ -1895,4 +1895,105 @@ describe("<Select multi={true} />", () => {
document.querySelector(".c__field.my-custom-class"), document.querySelector(".c__field.my-custom-class"),
).toBeInTheDocument(); ).toBeInTheDocument();
}); });
describe("classic variant", () => {
it("renders with classic variant", async () => {
render(
<CunninghamProvider>
<Select
label="Cities"
variant="classic"
multi={true}
options={[
{ label: "Paris", value: "paris" },
{ label: "London", value: "london" },
]}
/>
</CunninghamProvider>,
);
// In classic mode, label is rendered outside the wrapper with its own class
expect(document.querySelector(".c__select__label")).toBeInTheDocument();
expect(document.querySelector(".c__select--classic")).toBeInTheDocument();
});
it("shows placeholder in classic variant when no selection", async () => {
render(
<CunninghamProvider>
<Select
label="Cities"
variant="classic"
placeholder="Select cities..."
multi={true}
options={[
{ label: "Paris", value: "paris" },
{ label: "London", value: "london" },
]}
/>
</CunninghamProvider>,
);
expect(screen.getByText("Select cities...")).toBeInTheDocument();
expect(
document.querySelector(".c__select__placeholder"),
).toBeInTheDocument();
});
it("hides placeholder after selection in classic variant", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<Select
label="Cities"
variant="classic"
placeholder="Select cities..."
multi={true}
options={[
{ label: "Paris", value: "paris" },
{ label: "London", value: "london" },
]}
/>
</CunninghamProvider>,
);
// Placeholder should be visible initially
expect(screen.getByText("Select cities...")).toBeInTheDocument();
// Open menu and select an option
const input = screen.getByRole("combobox", { name: "Cities" });
await user.click(input);
await user.click(screen.getByRole("option", { name: "Paris" }));
// Placeholder should be hidden, selection should be shown
expect(screen.queryByText("Select cities...")).not.toBeInTheDocument();
expectSelectedOptions(["Paris"]);
});
it("label is always static in classic variant", async () => {
const user = userEvent.setup();
render(
<CunninghamProvider>
<Select
label="Cities"
variant="classic"
multi={true}
options={[
{ label: "Paris", value: "paris" },
{ label: "London", value: "london" },
]}
/>
</CunninghamProvider>,
);
const label = screen.getByText("Cities");
// In classic variant, label is outside the wrapper with c__select__label class
expect(label.classList.contains("c__select__label")).toBe(true);
// Open menu
const input = screen.getByRole("combobox", { name: "Cities" });
await user.click(input);
// Label should still have the same class
expect(label.classList.contains("c__select__label")).toBe(true);
});
});
}); });

View File

@@ -16,6 +16,12 @@ import { Input } from ":/components/Forms/Input";
export default { export default {
title: "Components/Forms/Select/Multi", title: "Components/Forms/Select/Multi",
component: Select, component: Select,
argTypes: {
variant: {
control: "select",
options: ["floating", "classic"],
},
},
} as Meta<typeof Select>; } as Meta<typeof Select>;
const Template: StoryFn<typeof Select> = (args) => { const Template: StoryFn<typeof Select> = (args) => {
@@ -73,6 +79,49 @@ export const Monoline = {
}, },
}; };
export const ClassicVariant = {
render: Template,
args: {
label: "Select cities",
variant: "classic",
placeholder: "Choose cities...",
options: OPTIONS,
},
};
export const ClassicVariantFilled = {
render: Template,
args: {
label: "Select cities",
variant: "classic",
placeholder: "Choose cities...",
options: OPTIONS,
defaultValue: [OPTIONS[4].value, OPTIONS[2].value],
},
};
export const ClassicVariantSearchable = {
render: Template,
args: {
label: "Select cities",
variant: "classic",
placeholder: "Search for cities...",
options: OPTIONS,
searchable: true,
},
};
export const ClassicVariantDisabled = {
render: Template,
args: {
label: "Select cities",
variant: "classic",
placeholder: "Choose cities...",
options: OPTIONS,
disabled: true,
},
};
export const WithText = { export const WithText = {
render: Template, render: Template,
args: { args: {

View File

@@ -33,4 +33,5 @@ export const tokens = (defaults: DefaultTokens) => ({
"multi-pill-border-radius": "2px", "multi-pill-border-radius": "2px",
"multi-pill-max-width": "68%", "multi-pill-max-width": "68%",
"multi-pill-font-size": defaults.globals.font.sizes.md, "multi-pill-font-size": defaults.globals.font.sizes.md,
"placeholder-color": defaults.contextuals.content.semantic.neutral.secondary,
}); });