Skip to content

Chips

Edit on GitHub

Chips are compact interactive elements for selecting options or dismissing applied filters.

@volvo-cars/css v2.5.1
Show codeHide code
import { useState } from 'react';
const options = ['Hybrid', 'Electric', 'Petrol'];
export function ChipSelectableSmall() {
const [selected, setSelected] = useState<string[]>([]);
const toggle = (option: string) => {
setSelected((prev) =>
prev.includes(option)
? prev.filter((s) => s !== option)
: [...prev, option],
);
};
return (
<div className="flex gap-8">
{options.map((option) => (
<button
key={option}
type="button"
className="chip-selectable"
data-size="small"
aria-pressed={selected.includes(option)}
onClick={() => toggle(option)}
>
{option}
</button>
))}
</div>
);
}
Show codeHide code
import { useState } from 'react';
const options = ['Hybrid', 'Electric', 'Petrol'];
export function ChipRadio() {
const [selected, setSelected] = useState('Hybrid');
return (
<div role="radiogroup" aria-label="Powertrain" className="flex gap-8">
{options.map((option) => (
<button
key={option}
type="button"
role="radio"
className="chip-selectable"
aria-checked={selected === option}
onClick={() => setSelected(option)}
>
{option}
</button>
))}
</div>
);
}
EX90
EX30
XC90
Show codeHide code
import { IconButton } from '@volvo-cars/react-icons';
import { useState } from 'react';
const initial = ['EX90', 'EX30', 'XC90'];
export function ChipDismissible() {
const [chips, setChips] = useState(initial);
return (
<div
className="flex flex-wrap gap-8"
role="list"
aria-label="Selected models"
>
{chips.map((chip) => (
<div key={chip} role="listitem" className="chip-dismissible">
{chip}
<IconButton
aria-label={`Remove ${chip}`}
slot="dismiss"
variant="clear"
bleed
icon="x"
onClick={() => setChips((prev) => prev.filter((c) => c !== chip))}
/>
</div>
))}
</div>
);
}
EX90
EX30
Show codeHide code
import { IconButton } from '@volvo-cars/react-icons';
import { useState } from 'react';
export function ChipDismissibleLoading() {
const [loading, setLoading] = useState(false);
return (
<div className="flex gap-8">
<div
className="chip-dismissible"
data-loading={loading || undefined}
aria-busy={loading}
>
{loading ? (
<>
<span className="invisible">EX90</span>
<progress className="spinner" aria-label="Loading" />
</>
) : (
'EX90'
)}
<IconButton
aria-label="Remove EX90"
slot="dismiss"
variant="clear"
bleed
icon="x"
onClick={() => {
setLoading(true);
setTimeout(() => setLoading(false), 2000);
}}
/>
</div>
<div className="chip-dismissible">
EX30
<IconButton
aria-label="Remove EX30"
slot="dismiss"
variant="clear"
bleed
icon="x"
/>
</div>
</div>
);
}