Selection changes available options in another control.
<div class="csc csc--fruit" style="--accent:#A8E6C1;">
<div class="csc__field">
<label class="csc__label" for="csc-parent">Category</label>
<select id="csc-parent" class="csc__select" style="border-radius:8px;">
<option>Fruit</option>
<option>Vegetable</option>
<option>Herb</option>
</select>
</div>
<div class="csc__field csc__field--fruit">
<label class="csc__label" for="csc-item-fruit">Item</label>
<select id="csc-item-fruit" class="csc__select" style="border-radius:8px;">
<option>Apple</option>
<option>Pear</option>
<option>Plum</option>
</select>
</div>
<div class="csc__field csc__field--veg">
<label class="csc__label" for="csc-item-veg">Item</label>
<select id="csc-item-veg" class="csc__select" style="border-radius:8px;">
<option>Carrot</option>
<option>Pea</option>
<option>Leek</option>
</select>
</div>
<div class="csc__field csc__field--herb">
<label class="csc__label" for="csc-item-herb">Item</label>
<select id="csc-item-herb" class="csc__select" style="border-radius:8px;">
<option>Basil</option>
<option>Mint</option>
<option>Thyme</option>
</select>
</div>
</div>
<style>
.csc { display: flex; gap: 12px; font: 14px system-ui, sans-serif; color: #241430; max-width: 360px; flex-wrap: wrap; }
.csc__field { flex: 1; min-width: 140px; }
.csc__field--fruit, .csc__field--veg, .csc__field--herb { display: none; }
.csc--fruit .csc__field--fruit, .csc--veg .csc__field--veg, .csc--herb .csc__field--herb { display: block; }
.csc__label { display: block; margin-bottom: 6px; font-weight: 500; }
.csc__select { width: 100%; box-sizing: border-box; padding: 10px 12px; font: inherit; color: #241430; background: #FAF7F2; border: 1.5px solid #24143040; appearance: none; }
.csc__select:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent); }
</style><div class="csc-tw csc-tw--fruit flex gap-3 flex-wrap font-sans text-sm text-[#241430] max-w-[360px]">
<div class="flex-1 min-w-[140px]">
<label class="block mb-1.5 font-medium" for="csc-parent-tw">Category</label>
<select id="csc-parent-tw" style="border-radius:8px;"
class="w-full box-border px-3 py-2.5 bg-[#FAF7F2] border-[1.5px] border-[#24143040] appearance-none focus-visible:outline-none">
<option>Fruit</option>
<option>Vegetable</option>
<option>Herb</option>
</select>
</div>
<div class="csc-tw-item csc-tw-item--fruit flex-1 min-w-[140px] hidden">
<label class="block mb-1.5 font-medium" for="csc-item-fruit-tw">Item</label>
<select id="csc-item-fruit-tw" style="border-radius:8px;"
class="w-full box-border px-3 py-2.5 bg-[#FAF7F2] border-[1.5px] border-[#24143040] appearance-none focus-visible:outline-none">
<option>Apple</option>
<option>Pear</option>
<option>Plum</option>
</select>
</div>
<div class="csc-tw-item csc-tw-item--veg flex-1 min-w-[140px] hidden">
<label class="block mb-1.5 font-medium" for="csc-item-veg-tw">Item</label>
<select id="csc-item-veg-tw" style="border-radius:8px;"
class="w-full box-border px-3 py-2.5 bg-[#FAF7F2] border-[1.5px] border-[#24143040] appearance-none focus-visible:outline-none">
<option>Carrot</option>
<option>Pea</option>
<option>Leek</option>
</select>
</div>
<div class="csc-tw-item csc-tw-item--herb flex-1 min-w-[140px] hidden">
<label class="block mb-1.5 font-medium" for="csc-item-herb-tw">Item</label>
<select id="csc-item-herb-tw" style="border-radius:8px;"
class="w-full box-border px-3 py-2.5 bg-[#FAF7F2] border-[1.5px] border-[#24143040] appearance-none focus-visible:outline-none">
<option>Basil</option>
<option>Mint</option>
<option>Thyme</option>
</select>
</div>
</div>
<style>
.csc-tw--fruit .csc-tw-item--fruit, .csc-tw--veg .csc-tw-item--veg, .csc-tw--herb .csc-tw-item--herb { display: block !important; }
select:focus-visible { border-color: #A8E6C1 !important; }
</style>export function CascadingSelect({
label = "Category",
itemLabel = "Item",
parent = "fruit",
accent = "#A8E6C1",
radius = 8,
}) {
const itemsByParent = {
fruit: ["Apple", "Pear", "Plum"],
veg: ["Carrot", "Pea", "Leek"],
herb: ["Basil", "Mint", "Thyme"],
};
const items = itemsByParent[parent] ?? itemsByParent.fruit;
const selectStyle = {
width: "100%", boxSizing: "border-box", padding: "10px 12px", font: "inherit",
color: "#241430", background: "#FAF7F2", border: "1.5px solid #24143040", borderRadius: radius, appearance: "none",
};
return (
<div style={{ display: "flex", gap: 12, flexWrap: "wrap", fontFamily: "system-ui, sans-serif", fontSize: 14, color: "#241430", maxWidth: 360 }}>
<div style={{ flex: 1, minWidth: 140 }}>
<label htmlFor="csc-parent-r" style={{ display: "block", marginBottom: 6, fontWeight: 500 }}>{label}</label>
<select id="csc-parent-r" style={selectStyle} defaultValue={parent}>
<option value="fruit">Fruit</option>
<option value="veg">Vegetable</option>
<option value="herb">Herb</option>
</select>
</div>
<div style={{ flex: 1, minWidth: 140 }}>
<label htmlFor="csc-item-r" style={{ display: "block", marginBottom: 6, fontWeight: 500 }}>{itemLabel}</label>
<select id="csc-item-r" style={{ ...selectStyle, borderColor: accent }}>
{items.map((item) => <option key={item}>{item}</option>)}
</select>
</div>
</div>
);
}