Examples
Select Label Composition
Select trigger composition with static field label plus selected value.
Example Files
Each file is copyable and downloadable.
import "@nake-ui/theme-vanilla/styles.css";
import { bindSelect } from "@nake-ui/adapter-vanilla";
interface AspectOption {
id: string;
label: string;
}
const ASPECT_OPTIONS: readonly AspectOption[] = [
{ id: "16:9", label: "16:9" },
{ id: "9:16", label: "9:16" },
{ id: "1:1", label: "1:1" }
];
const REGISTRATIONS = ASPECT_OPTIONS.map((option) => ({
id: option.id,
value: option.id,
label: option.label
}));
export function mountSelectLabelComposition(root: HTMLElement): () => void {
root.innerHTML = `
<div data-ui="select">
<button type="button" data-slot="trigger" aria-label="Select canvas aspect ratio">
<span>Aspect</span>
<span aria-hidden="true">: </span>
<span data-slot="value">16:9</span>
<span aria-hidden="true"> v</span>
</button>
<input type="hidden" data-slot="hidden-input" name="editor-aspect" />
<div data-slot="content" hidden style="display: none; pointer-events: none;">
${ASPECT_OPTIONS.map(
(option) =>
`<button type="button" data-slot="option" data-demo-id="${option.id}" data-demo-label="${option.label}">${option.label}</button>`
).join("\n")}
</div>
</div>
`;
const trigger = root.querySelector<HTMLElement>("[data-slot='trigger']");
const valueNode = root.querySelector<HTMLElement>("[data-slot='value']");
const content = root.querySelector<HTMLElement>("[data-slot='content']");
const hiddenInput = root.querySelector<HTMLInputElement>("[data-slot='hidden-input']");
const optionElements = Array.from(
root.querySelectorAll<HTMLElement>("[data-slot='option'][data-demo-id]")
);
if (!trigger || !valueNode || !content || !hiddenInput) {
return () => {};
}
const optionNodes: Record<string, HTMLElement> = {};
for (const optionElement of optionElements) {
const id = optionElement.dataset.demoId;
if (!id) {
continue;
}
optionNodes[id] = optionElement;
}
const binding = bindSelect(
{
trigger,
content,
options: optionNodes,
hiddenInput
},
REGISTRATIONS,
{
id: "docs-select-label-composition-controller",
name: "editor-aspect",
defaultValue: "16:9",
onValueChange(nextValue) {
if (nextValue === null) {
valueNode.textContent = "16:9";
return;
}
valueNode.textContent = optionNodes[nextValue]?.dataset.demoLabel ?? nextValue;
}
}
);
return () => {
binding.destroy();
};
}