LayerDialog
A second layer slides over the first (add model → review values); Back returns.
function Wizard() {
const [open, setOpen] = useState(false);
const [view, setView] = useState<"pick" | "review" | "custom">("pick");
const [model, setModel] = useState("");
const [custom, setCustom] = useState("");
const m = models.find((x) => x.model === model);
const close = () => {
setOpen(false);
setView("pick");
setCustom("");
};
const add = (id: string) => {
close();
toast.success(`Added ${id}`);
};
const addCustom = () => custom.trim() && add(custom.trim());
const pick = {
title: "Add model",
description: "Pick a model from the models.dev catalogue.",
content: (
<div className="flex flex-col gap-12">
<List
aria-label="Models on models.dev"
density="compact"
items={models.map((x) => ({ id: x.model, textValue: x.model, title: <ModelLabel provider={x.provider} model={x.model} name={x.name} /> }))}
onOpen={(item) => {
setModel(item.id);
setView("review");
}}
/>
<Text variant="small" tone="secondary">
Not on models.dev?{" "}
<Button variant="link" size="sm" onClick={() => setView("custom")}>
Add a custom model
</Button>
</Text>
</div>
),
};
const second = {
review: {
title: `Review ${model}`,
description: "Prices come from models.dev; you can override them.",
content: m && (
<div className="flex flex-col gap-16">
<ModelLabel provider={m.provider} model={m.model} name={m.name} capabilities={m.capabilities} />
<KeyValue
items={[
{ label: "Input", value: `$${m.input} / M` },
{ label: "Output", value: `$${m.output} / M` },
{ label: "Context", value: `${m.context.toLocaleString("en-US")} tokens` },
]}
/>
</div>
),
footer: (
<Button variant="primary" onClick={() => add(model)}>
Add model
</Button>
),
},
custom: {
title: "Add a custom model",
description: "The id the provider knows the model by.",
content: <Input label="Model id" placeholder="acme-internal-1" value={custom} onChange={(e) => setCustom(e.target.value)} />,
footer: (
<Button variant="primary" disabled={!custom.trim()} onClick={addCustom}>
Add model
</Button>
),
},
};
return (
<>
<Button variant="primary" onClick={() => setOpen(true)}>
Add model
</Button>
<LayerDialog
open={open}
onOpenChange={(o) => !o && close()}
layer={view === "pick" ? 0 : 1}
onLayerChange={(l) => l === 0 && setView("pick")}
onSubmit={view === "review" ? () => add(model) : view === "custom" ? addCustom : undefined}
layers={view === "pick" ? [pick] : [pick, second[view]]}
/>
</>
);
}import { LayerDialog } from "@logicplanes/kaeso-ui";Props
defaultOpenbooleanWhether it starts open, when the component keeps its own state.
hideClosebooleanHide the close circle (rare).
inlinebooleanRender without a portal and backdrop, for documentation and state matrices.
layernumberThe visible layer; layers above the first slide over it.
layersDialogLayer[]The layers, each with its title, content and footer; one shows at a time, and the ones below it stay mounted and hidden.
onLayerChange((layer: number) => void)Called with the index of the layer shown.
onOpenChange((open: boolean) => void)Called when it opens or closes.
onSubmit(() => void)⌘/Ctrl+Enter calls this on every layer; pass the action of the layer shown.
openbooleanWhether it is open, when you control it.
size"md" | "sm" | "lg"The dialog's width.
triggerReactElement<unknown, string | JSXElementConstructor<any>>The trigger, a single element.