SelectionIndicator
A small marker that stays invisible, while still reserving its own layout slot.
View code
<div mix={[vstack({ gap: 1, align: "stretch" }), on<HTMLDivElement, "change">("change", readOrder)]}>
<Header id="preview-sort-heading">Sort packages by</Header>
<div role="group" aria-labelledby="preview-sort-heading" mix={[vstack({ gap: 0, align: "stretch" })]}>
{orders.map((order) => (
<label
key={order.value}
mix={[
hstack({ gap: 2, align: "center" }),
p(2),
css({ cursor: "pointer", borderRadius: "var(--ui-radius-md)" }),
]}
>
<SelectionIndicator aria-selected={order.value === selected ? "true" : "false"}>
<CheckIcon />
</SelectionIndicator>
<input
type="radio"
name="preview-order"
value={order.value}
checked={order.value === selected}
mix={[ariaChecked(), visuallyHidden()]}
/>
{order.label}
</label>
))}
</div>
<Text>Nothing shifts sideways as the marker moves.</Text>
</div>Installation
An ordinary dependency: install it, import the theme once, and import the component where it is used.
npm add @sdxc/uiimport "@sdxc/ui/theme.css";Usage
import { SelectionIndicator } from "@sdxc/ui";Renders a marker that stays present in the layout at all times but only
becomes visible once its host carries aria-selected="true" or a truthy
aria-current, so sibling content never reflows on selection change.
Examples
<Tabs.Trigger id="billing" aria-selected={activeTab === "billing"}>
{t("settings.tabs.billing")}
<SelectionIndicator
aria-selected={activeTab === "billing"}
mix={css({ position: "absolute", insetBlockEnd: "0", insetInline: "0", blockSize: "2px" })}
/>
</Tabs.Trigger>Props
Read from the component's own types, so every prop, every default and every allowed value is listed.
Also accepts everything in TagProps<"div">.