Components · 22 in 13 files
Every piece. Live.
Each one is drawn from the kit’s current source, in the kit’s own theme. Switch between Grain and Joinery to see both. What you see is what lands in your ui/ folder.
Actions
Button
Use it for the actions of a form or toolbar. The one main action is primary; the rest are secondary or quiet.
size sm
size md
size icon
primary
secondary
quiet
destructive
with an icon
busy
disabled
opens a dialog
intentvariant
primary · secondary · quiet · destructive
default: secondary
sizevariant
sm · md · icon
default: md
typeprop
button · submit
default: button
name, valueprop
text, sent with the form
default: —
disabledprop
true · false
default: false
busyprop
true · false (aria-busy)
default: false
labelprop
text for screen readers; needed with size icon
default: —
commandfor, commandprop
opens a dialog or popover without JavaScript
default: —
iconslot
an Icon before the text
default: —
pressevent
on click
default: —
| Name | Kind | Values | Default |
|---|---|---|---|
| intent | variant | primary · secondary · quiet · destructive | secondary |
| size | variant | sm · md · icon | md |
| type | prop | button · submit | button |
| name, value | prop | text, sent with the form | — |
| disabled | prop | true · false | false |
| busy | prop | true · false (aria-busy) | false |
| label | prop | text for screen readers; needed with size icon | — |
| commandfor, command | prop | opens a dialog or popover without JavaScript | — |
| icon | slot | an Icon before the text | — |
| press | event | on click | — |
- Lives in
- ui/button.ts
- Install
- npx hozu add component ui Button --from official
- With DevTools
- Assets → Hozu UI → Button, then Place it next to the part you selected.
Actions
LinkButton
Use it for a link that should look like a button: “View all orders”, a call to action.
intentvariant
primary · secondary · quiet · destructive
default: secondary
sizevariant
sm · md · icon
default: md
hrefprop
ui.link(route, params) or a full URL
default: required
iconslot
an Icon before the text
default: —
| Name | Kind | Values | Default |
|---|---|---|---|
| intent | variant | primary · secondary · quiet · destructive | secondary |
| size | variant | sm · md · icon | md |
| href | prop | ui.link(route, params) or a full URL | required |
| icon | slot | an Icon before the text | — |
- Lives in
- ui/button.ts
- Install
- npx hozu add component ui LinkButton --from official
- With DevTools
- Assets → Hozu UI → LinkButton, then Place it next to the part you selected.
Forms
Input
Use it for one line of text, an email, a number or a date. Put it in a Field so it has a label.
size sm
size md
size lg
invalid
disabled
type date
sizevariant
sm · md · lg
default: md
nameprop
the form field name
default: required
typeprop
text · email · password · number · search · url · tel · date
default: text
id, value, placeholder, autocompleteprop
text
default: —
required, disabledprop
true · false
default: false
minlength, maxlengthprop
a number
default: —
invalidprop
true · false (aria-invalid)
default: false
describedbyprop
the id of the hint or error
default: —
labelprop
text for screen readers, when no Field labels it
default: —
inputevent
on every keystroke
default: —
| Name | Kind | Values | Default |
|---|---|---|---|
| size | variant | sm · md · lg | md |
| name | prop | the form field name | required |
| type | prop | text · email · password · number · search · url · tel · date | text |
| id, value, placeholder, autocomplete | prop | text | — |
| required, disabled | prop | true · false | false |
| minlength, maxlength | prop | a number | — |
| invalid | prop | true · false (aria-invalid) | false |
| describedby | prop | the id of the hint or error | — |
| label | prop | text for screen readers, when no Field labels it | — |
| input | event | on every keystroke | — |
- Lives in
- ui/input.ts
- Install
- npx hozu add component ui Input --from official
- With DevTools
- Assets → Hozu UI → Input, then Place it next to the part you selected.
Forms
Field
Use it for a labelled control with a hint and an error message that screen readers announce.
with a hint
Shown on invoices.
with an error
Use an address with an @.
forprop
the control’s id
default: required
labelprop
text
default: required
hintprop
text under the control
default: ""
errorprop
text, or null for none
default: null
errorIdprop
the id the control’s describedby points to
default: required
controlslot
an Input, a select, a textarea
default: —
| Name | Kind | Values | Default |
|---|---|---|---|
| for | prop | the control’s id | required |
| label | prop | text | required |
| hint | prop | text under the control | "" |
| error | prop | text, or null for none | null |
| errorId | prop | the id the control’s describedby points to | required |
| control | slot | an Input, a select, a textarea | — |
- Lives in
- ui/field.ts
- Install
- npx hozu add component ui Field --from official
- With DevTools
- Assets → Hozu UI → Field, then Place it next to the part you selected.
Data display
Badge
Use it for a status word next to a row or a title. Its tone is a prop, so it can come from your data.
shape pill · every tone
shape square
shapevariant
pill · square
default: pill
toneprop
neutral · info · success · warning · danger · accent (may come from data)
default: neutral
labelprop
text
default: required
| Name | Kind | Values | Default |
|---|---|---|---|
| shape | variant | pill · square | pill |
| tone | prop | neutral · info · success · warning · danger · accent (may come from data) | neutral |
| label | prop | text | required |
- Lives in
- ui/badge.ts
- Install
- npx hozu add component ui Badge --from official
- With DevTools
- Assets → Hozu UI → Badge, then Place it next to the part you selected.
Data display
Card
Use it for a boxed group with a title: a settings block, a summary, a table with its header.
title, description, actions
Team
3 people
Ada, Grace and Linus can edit every page of this project.
no title
Free plan
3 of 5 projects used.
padvariant
normal · none (for a table inside)
default: normal
titleprop
text; no header when empty
default: ""
descriptionprop
text under the title
default: ""
actionsslot
buttons in the header
default: —
footerslot
a row under the body
default: —
childrencontent
the body
default: —
| Name | Kind | Values | Default |
|---|---|---|---|
| pad | variant | normal · none (for a table inside) | normal |
| title | prop | text; no header when empty | "" |
| description | prop | text under the title | "" |
| actions | slot | buttons in the header | — |
| footer | slot | a row under the body | — |
| children | content | the body | — |
- Lives in
- ui/card.ts
- Install
- npx hozu add component ui Card --from official
- With DevTools
- Assets → Hozu UI → Card, then Place it next to the part you selected.
Data display
Metric
Use it for a number that matters, with a label and how it changed.
trend up
Revenue
$48,210
+12.4%vs last month
trend down
Open orders
27
−3since Monday
flat, no delta
Customers
1,204
labelprop
text
default: required
valueprop
text, e.g. ui.format.number(…)
default: required
deltaprop
text, e.g. +12.4%
default: ""
trendprop
up · down · flat
default: flat
periodprop
text after the delta
default: ""
sparkslot
a small chart under it
default: —
| Name | Kind | Values | Default |
|---|---|---|---|
| label | prop | text | required |
| value | prop | text, e.g. ui.format.number(…) | required |
| delta | prop | text, e.g. +12.4% | "" |
| trend | prop | up · down · flat | flat |
| period | prop | text after the delta | "" |
| spark | slot | a small chart under it | — |
- Lives in
- ui/metric.ts
- Install
- npx hozu add component ui Metric --from official
- With DevTools
- Assets → Hozu UI → Metric, then Place it next to the part you selected.
Data display
Table · Tr · Th · Td
Use it for rows and columns of records. Numbers align to the end; the first column can be strong.
Orders
This week
| Order | Customer | Status | Total |
|---|---|---|---|
| #1042 | Ada Lovelace | Paid | $1,280.00 |
| #1041 | Grace Hopper | Shipped | $342.50 |
| #1040 | Linus Torvalds | Overdue | $96.00 |
headslot (Table)
one Tr of Th
default: —
childrencontent (Table)
Tr rows, usually ui.each
default: —
alignvariant (Th, Td)
start · end (numbers)
default: start
emphasisvariant (Td)
normal · strong · muted
default: normal
| Name | Kind | Values | Default |
|---|---|---|---|
| head | slot (Table) | one Tr of Th | — |
| children | content (Table) | Tr rows, usually ui.each | — |
| align | variant (Th, Td) | start · end (numbers) | start |
| emphasis | variant (Td) | normal · strong · muted | normal |
- Lives in
- ui/table.ts
- Install
- npx hozu add component ui Table --from official
- npx hozu add component ui Tr --from official
- npx hozu add component ui Th --from official
- npx hozu add component ui Td --from official
- With DevTools
- Assets → Hozu UI → Table, then Place it next to the part you selected.
Feedback
Notice
Use it for a short message after an action: “Saved.” As a toast it sits at the bottom right of the window.
inline · tone info
inline · tone danger
placementvariant
toast (fixed, bottom right) · inline
default: toast
messageprop
text
default: required
toneprop
info · danger
default: info
closeLabelprop
text for the close button
default: Dismiss
dismissevent
the close button
default: —
| Name | Kind | Values | Default |
|---|---|---|---|
| placement | variant | toast (fixed, bottom right) · inline | toast |
| message | prop | text | required |
| tone | prop | info · danger | info |
| closeLabel | prop | text for the close button | Dismiss |
| dismiss | event | the close button | — |
- Lives in
- ui/states.ts
- Install
- npx hozu add component ui Notice --from official
- With DevTools
- Assets → Hozu UI → Notice, then Place it next to the part you selected.
Feedback
EmptyState · Problem
Use it for a list with nothing in it yet, and a part of the page that could not load.
EmptyState · size inline
No orders yet
New orders show up here as soon as they are placed.
Problem
Orders could not load
The server did not answer. Try again in a moment.
sizevariant (EmptyState)
inline · page
default: inline
titleprop
text
default: required
bodyprop
text
default: ""
actionslot
what to do next
default: —
| Name | Kind | Values | Default |
|---|---|---|---|
| size | variant (EmptyState) | inline · page | inline |
| title | prop | text | required |
| body | prop | text | "" |
| action | slot | what to do next | — |
- Lives in
- ui/states.ts
- Install
- npx hozu add component ui EmptyState --from official
- npx hozu add component ui Problem --from official
- With DevTools
- Assets → Hozu UI → EmptyState, then Place it next to the part you selected.
Navigation
Pagination
Use it for previous and next pages of a long list, as plain links that work without JavaScript.
first page
a middle page
summaryprop
text, e.g. 1–10 of 42
default: required
prevHref, nextHrefprop
a link, or null when there is none
default: required
prevLabel, nextLabelprop
text
default: Previous, Next
labelprop
the navigation’s name
default: Pagination
| Name | Kind | Values | Default |
|---|---|---|---|
| summary | prop | text, e.g. 1–10 of 42 | required |
| prevHref, nextHref | prop | a link, or null when there is none | required |
| prevLabel, nextLabel | prop | text | Previous, Next |
| label | prop | the navigation’s name | Pagination |
- Lives in
- ui/nav.ts
- Install
- npx hozu add component ui Pagination --from official
- With DevTools
- Assets → Hozu UI → Pagination, then Place it next to the part you selected.
Overlays
Dialog
Use it for a question or a short form on top of the page. A destructive action asks here first.
try it: opens as a modal, no JavaScript needed
sizevariant
sm · md · lg
default: md
idprop
what a button’s commandfor names
default: required
titleprop
text
default: required
descriptionprop
text under the title
default: ""
openprop
bound to the machine: opens as a modal
default: —
footerslot
the buttons
default: —
closeevent
Escape, the backdrop, a close button
default: —
| Name | Kind | Values | Default |
|---|---|---|---|
| size | variant | sm · md · lg | md |
| id | prop | what a button’s commandfor names | required |
| title | prop | text | required |
| description | prop | text under the title | "" |
| open | prop | bound to the machine: opens as a modal | — |
| footer | slot | the buttons | — |
| close | event | Escape, the backdrop, a close button | — |
- Lives in
- ui/dialog.ts
- Install
- npx hozu add component ui Dialog --from official
- With DevTools
- Assets → Hozu UI → Dialog, then Place it next to the part you selected.
Layout
PageHeader
Use it for the top of a page: its title, a line about it, and its main actions.
size app
Orders
Everything placed this month.
size display
Welcome back
Three things need you today.
sizevariant
app · display
default: app
titleprop
the page’s h1
default: required
descriptionprop
text
default: ""
eyebrowslot
above the title, e.g. a Badge
default: —
actionsslot
buttons on the right
default: —
| Name | Kind | Values | Default |
|---|---|---|---|
| size | variant | app · display | app |
| title | prop | the page’s h1 | required |
| description | prop | text | "" |
| eyebrow | slot | above the title, e.g. a Badge | — |
| actions | slot | buttons on the right | — |
- Lives in
- ui/page-header.ts
- Install
- npx hozu add component ui PageHeader --from official
- With DevTools
- Assets → Hozu UI → PageHeader, then Place it next to the part you selected.
Icons
Icon
Use it for an icon in a button, a menu or a list. Lucide’s paths and Hozu’s own, copied as data: no icon library ships.
ui/icons/lucide.ts
- arrowDown
- arrowUp
- check
- chevronDown
- chevronLeft
- chevronRight
- chevronUp
- circleAlert
- download
- ellipsis
- externalLink
- funnel
- inbox
- info
- lock
- menu
- minus
- packageIcon
- pencil
- plus
- search
- trash
- x
ui/icons/hozu.ts
- tenon
- machine
- contract
- request
- island
sizevariant
sm · md
default: sm
dprop
an SVG path from ui/icons/lucide.ts or ui/icons/hozu.ts
default: required
| Name | Kind | Values | Default |
|---|---|---|---|
| size | variant | sm · md | sm |
| d | prop | an SVG path from ui/icons/lucide.ts or ui/icons/hozu.ts | required |
- Lives in
- ui/icon.ts
- Install
- npx hozu add component ui Icon --from official
- With DevTools
- Assets → Hozu UI → Icon, then Place it next to the part you selected.