Files
sigpro-ui/docs/demo.md
2026-05-09 19:23:54 +02:00

1120 lines
23 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SigPro Demo Atomic Components
---
## Accordion
<div id="demo-accordion"></div>
```js
const accName = "demo-acc";
mount(
div({ class: "space-y-2" }, [
Accordion({ class: "collapse-arrow bg-base-100 border border-base-300" }, [
AccordionRadio({ name: accName, checked: true }),
AccordionTitle({}, "What is SigPro?"),
AccordionContent({}, "A lightweight UI library built on DaisyUI and a finegrained reactivity system."),
]),
Accordion({ class: "collapse-arrow bg-base-100 border border-base-300" }, [
AccordionRadio({ name: accName }),
AccordionTitle({}, "Why use it?"),
AccordionContent({}, "No build step, minimal boilerplate, and all components are just functions."),
]),
Accordion({ class: "collapse-arrow bg-base-100 border border-base-300" }, [
AccordionRadio({ name: accName }),
AccordionTitle({}, "Browser support?"),
AccordionContent({}, "All modern browsers that support ES2020+"),
]),
]),
"#demo-accordion"
);
```
---
## Alert
<div id="demo-alert"></div>
```js
mount(
Alert({ class: "alert-info" }, [
Icon({}, "icon-[lucide--info]"),
span({}, "You have 2 new messages"),
]),
"#demo-alert"
);
```
---
## Autocomplete
<div id="demo-autocomplete"></div>
```js
const fruitQuery = $("");
const fruitResults = $([]);
const fruits = ["Apple", "Banana", "Orange", "Mango", "Carrot", "Broccoli", "Spinach", "Potato"];
Filter(fruitQuery, fruits, fruitResults);
const colorQuery = $("");
const colorResults = $([]);
const colors = ["Red", "Blue", "Green", "Yellow", "Black", "White", "Purple", "Cyan"];
Filter(colorQuery, colors, colorResults);
const autocompleteCombo = (query, results, placeholder) =>
Combo({ class: "p-2 bg-base-100 rounded-box shadow-xl max-h-60 overflow-y-auto border border-base-300 z-50" },
LabelInput({}, [
Icon({}, "icon-[lucide--search]"),
Input({ placeholder, value: query, oninput: (e) => query(e.target.value) })
]),
{ content: Menu({ class: "flex-col flex-nowrap w-full p-0" },
each(results, (item) =>
MenuItem({ label: item, onclick: () => { query(item); hide() } })
)
)}
);
mount(
div({ class: "flex flex-col gap-10" }, [
div({}, [
h3({ class: "font-bold mb-2" }, "Fruits:"),
autocompleteCombo(fruitQuery, fruitResults, "Search fruit..."),
span({ class: "text-xs" }, () => `Signal: ${fruitQuery()}`),
]),
div({}, [
h3({ class: "font-bold mb-2" }, "Colors:"),
autocompleteCombo(colorQuery, colorResults, "Search color..."),
span({ class: "text-xs" }, () => `Signal: ${colorQuery()}`),
]),
]),
"#demo-autocomplete"
);
```
---
## Avatar & AvatarGroup
<div id="demo-avatar"></div>
```js
mount(
div({ class: "flex flex-col gap-4" }, [
Avatar({ class: "w-24 rounded-full" },
img({ src: "https://img.daisyui.com/images/profile/demo/kenobee@192.webp" })
),
AvatarGroup({}, [
Avatar({ class: "w-12" }, img({ src: "https://img.daisyui.com/images/profile/demo/kenobee@192.webp" })),
Avatar({ class: "w-12" }, img({ src: "https://img.daisyui.com/images/profile/demo/anakeen@192.webp" })),
Avatar({ class: "w-12" }, img({ src: "https://img.daisyui.com/images/profile/demo/kenobee@192.webp" })),
]),
]),
"#demo-avatar"
);
```
---
## Badge
<div id="demo-badge"></div>
```js
mount(
div({ class: "flex gap-2" }, [
Badge({}, "New"),
Badge({ class: "badge-outline" }, "Sale"),
Badge({ class: "badge-error" }, "Deleted"),
]),
"#demo-badge"
);
```
---
## Breadcrumbs
<div id="demo-breadcrumbs"></div>
```js
mount(
Breadcrumbs({}, [
ul({}, [
li({}, a({ href: "#" }, "Home")),
li({}, a({ href: "#" }, "Docs")),
li({}, span({ class: "font-bold" }, "Components")),
]),
]),
"#demo-breadcrumbs"
);
```
---
## Button
<div id="demo-button"></div>
```js
const count = $(0);
mount(
div({ class: "flex gap-2 items-center" }, [
Button({ class: "btn-primary", onclick: () => count(count() + 1) },
() => `Clicked ${count()} times`
),
Button({ class: "btn-outline", disabled: true }, "Disabled"),
]),
"#demo-button"
);
```
---
## Calendar
<div id="demo-calendar"></div>
```js
const calendarRange = $({ start: "2026-04-01", end: "2026-04-15", startHour: 9, endHour: 18 });
mount(
Calendar({
value: calendarRange,
range: true,
hour: true,
onChange: (val) => console.log("Range:", val),
}),
"#demo-calendar"
);
```
---
## Card, CardTitle, CardBody & CardActions
<div id="demo-card"></div>
```js
mount(
Card({ class: "w-80 bg-base-100 shadow-xl" }, [
CardBody({}, [
CardTitle({}, "Card Title"),
p({}, "This is a card with title, body and actions."),
CardActions({ class: "justify-end" }, [
Button({ class: "btn-primary btn-sm" }, "Buy"),
]),
]),
]),
"#demo-card"
);
```
---
## Carousel & CarouselItem
<div id="demo-carousel"></div>
```js
mount(
Carousel({ class: "carousel-vertical rounded-box h-96" }, [
CarouselItem({ class: "h-full" },
img({ src: "https://img.daisyui.com/images/stock/photo-1559703248-dcaaec9fab78.webp" })
),
CarouselItem({ class: "h-full" },
img({ src: "https://img.daisyui.com/images/stock/photo-1565098772267-60af42b81ef2.webp" })
),
CarouselItem({ class: "h-full" },
img({ src: "https://img.daisyui.com/images/stock/photo-1572635148818-ef6fd45eb394.webp" })
),
]),
"#demo-carousel"
);
```
---
## Chat, ChatImage, ChatHeader, ChatBubble & ChatFooter
<div id="demo-chat"></div>
```js
mount(
div({ class: "flex flex-col gap-4" }, [
Chat({ class: "chat-start" }, [
ChatImage({}, img({ src: "https://img.daisyui.com/images/profile/demo/kenobee@192.webp", alt: "Obi-Wan" })),
ChatHeader({}, ["Obi-Wan Kenobi", time({ class: "text-xs opacity-50" }, "12:45")]),
ChatBubble({}, "You were the Chosen One!"),
ChatFooter({ class: "opacity-50" }, "Delivered"),
]),
Chat({ class: "chat-end" }, [
ChatImage({}, img({ src: "https://img.daisyui.com/images/profile/demo/anakeen@192.webp", alt: "Anakin" })),
ChatHeader({}, ["Anakin", time({ class: "text-xs opacity-50" }, "12:46")]),
ChatBubble({}, "I hate you!"),
ChatFooter({ class: "opacity-50" }, "Seen at 12:46"),
]),
]),
"#demo-chat"
);
```
---
## Checkbox
<div id="demo-checkbox"></div>
```js
const checked = $(false);
mount(
div({ class: "flex items-center gap-2" }, [
Checkbox({ checked, onchange: (e) => checked(e.target.checked) }),
span({}, () => `Accept terms (${checked() ? "Yes" : "No"})`),
]),
"#demo-checkbox"
);
```
---
## Colorpicker & ColorPalette
<div id="demo-colorpicker"></div>
```js
const color = $("#000000");
mount(
div({ class: "flex flex-col gap-4" }, [
Combo({ class: "p-0" },
LabelInput({ class: "flex items-center gap-2 cursor-pointer" }, [
div({ class: "size-5 rounded-sm", style: () => `background-color: ${color() || "#000"}` }),
span({ class: () => `grow text-left truncate ${!color() ? "opacity-50" : ""}` }, () => color() || "Pick a color"),
() => color() ? span({ class: "btn-ghost btn-xs btn-circle -mr-2", onmousedown: (e) => { e.stopPropagation(); color(null); } }, Icon({}, "icon-[lucide--x]")) : null
]),
{ content: ColorPalette({ value: color, onchange: (c) => { color(c); hide(); } }) }
),
p({}, () => `Selected: ${color()}`),
]),
"#demo-colorpicker"
);
```
---
## Datepicker
<div id="demo-datepicker"></div>
```js
const dateRange = $(null);
const displayRange = $(() => {
const v = dateRange();
if (!v) return "";
if (typeof v === "string") return v;
if (v.start && v.end) return `${v.start} - ${v.end}`;
if (v.start) return `${v.start}...`;
return "";
});
mount(
Combo({ class: "p-0" },
LabelInput({ class: "flex items-center gap-2 cursor-pointer" }, [
Icon({}, "icon-[lucide--calendar]"),
span({ class: () => `grow text-left truncate ${!displayRange() ? "opacity-50" : ""}` }, () => displayRange() || "Select date range"),
() => displayRange() ? span({ class: "btn-ghost btn-xs btn-circle -mr-2", onmousedown: (e) => { e.stopPropagation(); dateRange(null); } }, Icon({}, "icon-[lucide--x]")) : null
]),
{ content: Calendar({ value: dateRange, range: true, hour: true, onChange: (v) => { dateRange(v); if (v?.end) hide(); } }) }
),
"#demo-datepicker"
);
```
---
## Divider
<div id="demo-divider"></div>
```js
mount(
div({ class: "flex flex-col gap-2" }, [
p({ class: "card bg-base-300 rounded-box grid h-20 place-items-center" }, "Above"),
Divider({}, "OR"),
p({ class: "card bg-base-300 rounded-box grid h-20 place-items-center" }, "Below"),
]),
"#demo-divider"
);
```
---
## Drawer
<div id="demo-drawer"></div>
```js
const leftOpen = $(false);
const rightOpen = $(false);
mount(
Drawer({ class: () => leftOpen() ? "drawer-open" : "" }, [
DrawerToggle({ id: "left-drawer", checked: leftOpen }),
DrawerContent({}, [
Drawer({ class: () => `drawer-end ${rightOpen() ? "drawer-open" : ""}` }, [
DrawerToggle({ id: "right-drawer", checked: rightOpen }),
DrawerContent({}, [
div({ class: "p-4" }, [
h3({ class: "text-lg font-bold" }, "Central Panel"),
label({ for: "left-drawer", class: "btn" }, "Open Left"),
label({ for: "right-drawer", class: "btn ml-2" }, "Open Right"),
p({}, "Main Content..."),
]),
]),
DrawerSide({}, [
DrawerOverlay({ for: "right-drawer" }),
div({ class: "min-h-full bg-base-200 w-60 p-4" }, h4({ class: "font-semibold" }, "Right Menu")),
]),
]),
]),
DrawerSide({}, [
DrawerOverlay({ for: "left-drawer" }),
div({ class: "min-h-full bg-base-200 w-60 p-4" }, h4({ class: "font-semibold" }, "Left Menu")),
]),
]),
"#demo-drawer"
);
```
---
## Dropdown, DropdownButton & DropdownContent
<div id="demo-dropdown"></div>
```js
mount(
div({ class: "flex gap-4" }, [
Dropdown({}, [
DropdownButton({}, "Options"),
DropdownContent({ class: "menu bg-base-100 rounded-box w-52 p-2 shadow" }, [
Menu({}, [
MenuItem({ label: "Edit", onclick: () => hide() }),
MenuItem({ label: "Delete", onclick: () => hide() }),
MenuItem({ label: "Archive", onclick: () => hide() }),
]),
]),
]),
Dropdown({ class: "dropdown-bottom dropdown-end" }, [
DropdownButton({}, "More"),
DropdownContent({ class: "menu bg-base-100 rounded-box w-40 p-2 shadow" },
Menu({}, [
MenuItem({ label: "Profile", onclick: (e) => { e.preventDefault(); hide(); } }),
MenuItem({ label: "Logout", onclick: (e) => { e.preventDefault(); hide(); } }),
])
),
]),
]),
"#demo-dropdown"
);
```
---
## Fab
<div id="demo-fab"></div>
```js
mount(
Fab({ icon: "R", class: "btn-lg btn-circle btn-secondary" }, [
Button({}, "C"),
Button({}, "B"),
Button({}, "A"),
]),
"#demo-fab"
);
```
---
## Fieldset
<div id="demo-fieldset"></div>
```js
mount(
div({ class: "flex gap-4" }, [
Fieldset({ class: "bg-base-200 border-base-300 rounded-box w-xs border gap-3 p-4", label: "Personal Info" }, [
LabelFloating({}, [
span({}, "Name"),
Input({ placeholder: "", value: $("") }),
]),
LabelFloating({}, [
span({}, "Country"),
Select({}, [
SelectOption({}, "Spain"),
SelectOption({}, "France"),
SelectOption({}, "Italy"),
]),
]),
]),
Fieldset({ class: "bg-base-200 p-4 rounded-box", label: "Any content" }, [
div({}, "Any content"),
]),
]),
"#demo-fieldset"
);
```
---
## Fileinput
<div id="demo-fileinput"></div>
```js
const files = $([]);
const drag = $(false);
const error = $(null);
const maxMB = 5;
const processFiles = (fileList) => {
const arr = [...fileList];
if (arr.some(f => f.size > maxMB * (1 << 20))) return error(`Max ${maxMB}MB`);
error(null);
files([...files(), ...arr]);
};
mount(
div({ class: "w-full" }, [
FileDrag({
drag: drag(),
ondrag: (v) => drag(v),
ondrop: processFiles
}, [
div({ class: "flex items-center gap-3 w-full text-sm opacity-70" }, [
Icon({}, "icon-[lucide--upload]"),
span({ class: "grow truncate" }, "Upload files"),
span({ class: "text-[10px] opacity-40" }, maxMB + "MB"),
]),
FileInput({ onchange: processFiles }),
]),
() => error() && FileError({ message: error() }),
() => files().length > 0 && FilePreview({
files: files(),
onremove: (i) => files(files().filter((_, j) => j !== i))
}),
]),
"#demo-fileinput"
);
```
---
## Icon
<div id="demo-icon"></div>
```js
mount(
div({ class: "flex gap-4 text-xl" }, [
Icon({}, "icon-[lucide--home]"),
Icon({}, "icon-[lucide--settings]"),
"❤️",
]),
"#demo-icon"
);
```
---
## Indicator
<div id="demo-indicator"></div>
```js
mount(
Indicator({ value: "3" }, [
Button({ class: "btn-circle" }, Icon({}, "icon-[lucide--bell]")),
]),
"#demo-indicator"
);
```
---
## Input
<div id="demo-input"></div>
```js
const username = $("");
const password = $("");
mount(
div({ class: "flex flex-col gap-4 w-80" }, [
LabelFloating({}, [
span({}, "Username"),
div({ class: "input" }, [
Icon({}, "icon-[lucide--user]"),
Input({ class: "grow border-none", placeholder: "", value: username }),
]),
]),
LabelFloating({}, [
span({}, "Password"),
div({ class: "input" }, [
Icon({}, "icon-[lucide--lock]"),
InputPass({ class: "grow border-none", placeholder: "", value: password }),
]),
]),
]),
"#demo-input"
);
```
---
## Kbd
<div id="demo-kbd"></div>
```js
mount(
p({}, ["Press ", Kbd({}, "Ctrl"), " + ", Kbd({}, "S"), " to save"]),
"#demo-kbd"
);
```
---
## List & ListRows
<div id="demo-list"></div>
```js
const people = $([
{ name: "Alice", online: true },
{ name: "Bob", online: false },
]);
mount(
div({ class: "flex flex-col gap-4" }, [
List({ class: "bg-base-100 rounded-box shadow-md" }, [
each(people, (p) =>
li({ class: "list-row" }, [
Badge({ class: p.online ? "badge-success" : "badge-ghost" }),
p.name,
])
),
]),
Divider({}, "OR"),
List({ class: "bg-base-100 rounded-box shadow-md" }, [
ListRows({
items: people,
render: (p) => [
Badge({ class: p.online ? "badge-success" : "badge-ghost" }),
p.name,
],
}),
]),
]),
"#demo-list"
);
```
---
## Loading
<div id="demo-loading"></div>
```js
mount(Loading({ class: "loading-lg text-primary" }), "#demo-loading");
```
---
## Menu
<div id="demo-menu"></div>
```js
mount(
Menu({ class: "w-56 bg-base-200 rounded-box" }, [
MenuItem({ label: "Dashboard", onclick: () => hide() }),
li({}, details({ open: true }, [
summary({}, "Settings"),
Menu({}, [
MenuItem({ label: "Profile", onclick: () => hide() }),
MenuItem({ label: "Account", onclick: () => hide() }),
]),
])),
MenuItem({ label: "Logout", onclick: () => alert("Logout") }),
]),
"#demo-menu"
);
```
---
## Modal
<div id="demo-modal"></div>
```js
const modalRef = { current: null };
mount(
div({}, [
Button({ class: "btn", onclick: () => modalRef.current?.showModal() }, "Open modal"),
Modal({ ref: (el) => modalRef.current = el }, [
ModalBox({}, [
h3({ class: "text-lg font-bold" }, "Congratulations!"),
p({ class: "py-4" }, "You have successfully created a reactive DaisyUI modal with SigPro."),
ModalAction({}, [
form({ method: "dialog" }, [
Button({}, "Close"),
]),
]),
]),
ModalBackdrop(),
]),
]),
"#demo-modal"
);
```
---
## Navbar
<div id="demo-navbar"></div>
```js
mount(
Navbar({ class: "bg-base-300 rounded-box" }, [
div({ class: "flex-1" }, a({ class: "btn btn-ghost text-xl" }, "SigPro")),
div({ class: "flex-none" }, Button({ class: "btn-square btn-ghost" }, Icon({}, "icon-[lucide--menu]"))),
]),
"#demo-navbar"
);
```
---
## Progress
<div id="demo-progress"></div>
```js
const progressVal = $(35);
mount(
div({ class: "flex flex-col gap-2" }, [
span({}, () => `${progressVal()}%`),
Progress({ value: progressVal, max: 100, class: "w-56" }),
]),
"#demo-progress"
);
```
---
## Radial Progress
<div id="demo-radial"></div>
```js
const radialVal = $(70);
mount(
Radial({ value: radialVal, class: "text-primary" }, () => `${radialVal()}%`),
"#demo-radial"
);
```
---
## Radio
<div id="demo-radio"></div>
```js
const option = $("a");
mount(
div({ class: "flex gap-4" }, [
label({ class: "flex items-center gap-2" }, [
Radio({ name: "demo-radio", value: "a", checked: () => option() === "a", onchange: () => option("a") }),
"Option A",
]),
label({ class: "flex items-center gap-2" }, [
Radio({ name: "demo-radio", value: "b", checked: () => option() === "b", onchange: () => option("b") }),
"Option B",
]),
]),
"#demo-radio"
);
```
---
## Range
<div id="demo-range"></div>
```js
const rangeValue = $(25);
mount(
div({ class: "flex flex-col gap-2 w-60" }, [
Range({ min: 0, max: 100, value: rangeValue, class: "range-sm" }),
span({}, () => `Value: ${rangeValue()}`),
]),
"#demo-range"
);
```
---
## Rating & RatingItems
<div id="demo-rating"></div>
```js
const stars = $(3);
mount(
Rating({}, [
RatingItems({ count: 5, value: stars, name: "demo-rating", class: "mask-star-2" }),
]),
"#demo-rating"
);
```
---
## Select
<div id="demo-select"></div>
```js
const choice = $("css");
mount(
LabelFloating({}, [
span({}, "Tech"),
LabelSelect({}, [
Select({ value: choice, onchange: (e) => choice(e.target.value) }, [
SelectOption({ value: "" }, "Pick a language"),
SelectOption({ value: "html" }, "HTML"),
SelectOption({ value: "css" }, "CSS"),
SelectOption({ value: "js" }, "JavaScript"),
]),
]),
]),
"#demo-select"
);
```
---
## Skeleton & SkeletonText
<div id="demo-skeleton"></div>
```js
mount(
div({ class: "flex flex-col gap-4 w-52" }, [
Skeleton({ class: "h-32" }),
SkeletonText({ class: "h-4" }),
SkeletonText({ class: "h-4 w-3/4" }),
]),
"#demo-skeleton"
);
```
---
## Stack
<div id="demo-stack"></div>
```js
mount(
Stack({ class: "w-48" }, [
img({ src: "https://img.daisyui.com/images/stock/photo-1572635148818-ef6fd45eb394.webp", class: "rounded-box" }),
img({ src: "https://img.daisyui.com/images/stock/photo-1565098772267-60af42b81ef2.webp", class: "rounded-box" }),
img({ src: "https://img.daisyui.com/images/stock/photo-1559703248-dcaaec9fab78.webp", class: "rounded-box" }),
]),
"#demo-stack"
);
```
---
## Stats & Stat
<div id="demo-stats"></div>
```js
mount(
Stats({ class: "w-full" }, [
Stat({}, [
StatTitle({}, "Downloads"),
StatValue({}, "1,200"),
StatDesc({}, "↑ 21% from last month"),
]),
Stat({}, [
StatTitle({}, "New Users"),
StatValue({}, "450"),
StatDesc({}, "↑ 14% from last month"),
]),
Stat({}, [
StatTitle({}, "Revenue"),
StatValue({}, "$89k"),
StatDesc({}, "↓ 1% from last month"),
]),
]),
"#demo-stats"
);
```
---
## Steps & Step
<div id="demo-steps"></div>
```js
mount(
Steps({ class: "steps-horizontal w-full" }, [
Step({ dataContent: "1", class: "step-primary" }, "Register"),
Step({ dataContent: "2", class: "step-primary" }, "Choose plan"),
Step({ dataContent: "3" }, "Purchase"),
Step({ dataContent: "4" }, "Enjoy"),
]),
"#demo-steps"
);
```
---
## Swap (Toggle)
<div id="demo-swap"></div>
```js
const isDark = $(false);
mount(
Swap({ class: "text-2xl" }, [
SwapToggle({ value: isDark, class: "swap-rotate" }),
SwapOn({}, Icon({}, "icon-[lucide--moon]")),
SwapOff({}, Icon({}, "icon-[lucide--sun]")),
]),
"#demo-swap"
);
```
---
## Table
<div id="demo-table"></div>
```js
const tableData = $([
{ id: 1, name: "Alice", role: "Admin" },
{ id: 2, name: "Bob", role: "User" },
{ id: 3, name: "Charlie", role: "User" },
]);
mount(
Table({ class: "w-full" }, [
TableHead({}, TableRow({}, [
TableTh({}, "Name"),
TableTh({}, "Role"),
TableTh({}, "Action"),
])),
TableBody({},
each(tableData, (item) =>
TableRow({}, [
TableTd({ class: "font-bold" }, item.name),
TableTd({}, item.role),
TableTd({}, Button({ class: "btn-xs", onclick: () => alert(`Edit ${item.name}`) }, "Edit")),
])
)
),
]),
"#demo-table"
);
```
---
## Tabs
<div id="demo-tabs"></div>
```js
const tabsSignal = $([
{ label: "Tab A", content: "Content of tab A", open: true },
{ label: "Tab B", content: "Content of tab B", closable: true },
{ label: "Tab C", content: "Content of tab C" },
]);
mount(
Tabs({ class: "tabs-box" },
each(tabsSignal, (tab, i) =>
Tab({
name: "demo-tabs",
label: tab.label,
content: tab.content,
checked: tab.open || false,
tabs: tabsSignal,
index: i,
closable: tab.closable || false,
})
)
),
"#demo-tabs"
);
```
---
## Textarea
<div id="demo-textarea"></div>
```js
const bio = $("");
mount(
Textarea({ class: "w-80", placeholder: "Write something...", value: bio }),
"#demo-textarea"
);
```
---
## Textrotate
<div id="demo-textrotate"></div>
```js
mount(
Textrotate({ class: "text-2xl font-bold" }, [
span({}, "Hello"),
span({}, "Bonjour"),
span({}, "Hola"),
]),
"#demo-textrotate"
);
```
---
## Timeline
<div id="demo-timeline"></div>
```js
mount(
Timeline({ class: "timeline-vertical" }, [
li({}, [
div({ class: "timeline-start" }, "2024"),
div({ class: "timeline-middle" }, Icon({}, "icon-[lucide--check]")),
div({ class: "timeline-end timeline-box" }, "Project started"),
]),
li({}, [
div({ class: "timeline-start" }, "2025"),
div({ class: "timeline-middle" }, Icon({}, "icon-[lucide--clock]")),
div({ class: "timeline-end timeline-box" }, "First prototype"),
]),
]),
"#demo-timeline"
);
```
---
## Toast
<div id="demo-toast"></div>
```js
mount(
div({ class: "flex flex-wrap gap-2" }, [
Button({ class: "btn", onclick: () => Toast("File saved!") }, "Simple"),
Button({ class: "btn", onclick: () => Toast("Error!", "alert-error", 5000) }, "Error (5s)"),
Button({
class: "btn",
onclick: () =>
Toast(
div({ class: "flex items-center gap-2" }, [
Icon({}, "icon-[lucide--check]"),
span({}, "Report generated"),
]),
"alert-success"
),
}, "With icon"),
Button({
class: "btn",
onclick: () =>
Toast(
div({ class: "flex flex-col" }, [
strong({}, "ATTENTION!"),
span({}, "Error saving!"),
button({ class: "btn btn-xs mt-1", onclick: () => console.log("Retry") }, "Retry"),
]),
"alert-warning",
7000
),
}, "Complex"),
]),
"#demo-toast"
);
```
---
## Toggle
<div id="demo-toggle"></div>
```js
const toggleActive = $(false);
mount(
Toggle({
checked: toggleActive,
onchange: (e) => toggleActive(e.target.checked),
class: "toggle-primary",
}),
"#demo-toggle"
);
```
---
## Tooltip
<div id="demo-tooltip"></div>
```js
mount(
Tooltip({ tip: "Save changes", class: "tooltip-right tooltip-primary" },
Button({ class: "btn" }, "Save")
),
"#demo-tooltip"
);
```