GuideComponentsHooksFunctionsTypesTokensSource code on GitHub
Appearance
Language
Pages
Components

Fields

The fields where the person types or picks something. They are as tall as a button: a field and a button placed side by side line up.

TextField

A one-line text field, pill-shaped, with an icon at the start. It has no visible title: its aria-label names it for screen readers.

A refused field takes aria-invalid: its border, background and text turn to the danger colours. The reason goes right under it, in a StatusLine with tone="error", lined up with the field's icon.

import { TextField } from 'hodi:sdk'
import { Mail } from 'lucide-react'

<TextField
  icon={Mail}
  aria-label="E-mail"
  placeholder="you@example.com"
  value={email}
  onChange={e => setEmail(e.target.value)}
/>
Props?: optional
iconLucideIcon

The icon at the start of the field, a Lucide icon.

aria-labelstring

The field's name, for screen readers.

onClear?() => void

For a search: a round cross shows as soon as the field holds text, and a click on it calls this function.

aria-invalid?boolean

Puts the field in the danger colours, when what was typed was refused.

…InputHTMLAttributes

Everything an <input> accepts: value, onChange, type, placeholder…

PasswordField

A password field, with an eye to show what is typed. For a new password, PasswordRing replaces the padlock and shows its strength, and PasswordGauge goes under the field.

import { PasswordField, PasswordGauge, PasswordRing } from 'hodi:sdk'

<PasswordField
  aria-label="Password"
  value={password}
  onChange={e => setPassword(e.target.value)}
  lead={<PasswordRing password={password} />}
/>
<PasswordGauge password={password} />
Props?: optional
aria-labelstring

The field's name, for screen readers.

icon?LucideIcon

The icon at the start of the field. It is a padlock by default.

invalid?boolean

Puts the field in the danger colours, when the password was refused. The reason goes under it, in a StatusLine, in place of PasswordGauge.

lead?ReactNode

An element in place of the icon, such as a PasswordRing.

…InputHTMLAttributes

Everything an <input> accepts, except type.

PasswordGauge

The line under a new password. It says its strength and what would make it stronger, and goes away as soon as it is strong enough. PasswordRing takes the same prop.

Props?: optional
passwordstring

The password typed, whose strength the line measures.

PinField

A code field, with one box per character. As soon as the last character is typed, the code checks itself, without a button.

import { PinField } from 'hodi:sdk'

<PinField
  label="Code"
  length={6}
  value={code}
  onChange={setCode}
  onComplete={check}
  align="start"
/>
Props?: optional
labelstring

The field's name, for screen readers.

lengthnumber

The number of characters in the code: 8 for the codes of I have a code, 6 for an authenticator app.

valuestring

What is typed so far.

onChange(value: string) => void

Called at each character typed or erased.

onComplete?(value: string) => void

Called when the whole code is typed, to check it.

state?'idle' | 'wrong' | 'right'

wrong turns the boxes red, right turns them green.

align?'center' | 'start'

start lines the boxes up on the left, in a form. center centres them, when the code has its own screen.

masked?boolean

Shows dots instead of the characters.

characters?RegExp

The characters accepted. Only digits by default.

disabled?boolean

The field is greyed out and can't be filled in.

autoFocus?boolean

Puts the cursor in the first box as soon as it shows.

Toggle

The switch, for a setting that turns on or off. In a settings page, it goes at the end of a SettingRow.

import { Toggle } from 'hodi:sdk'

<Toggle
  checked={morning}
  label="Say hello in the morning"
  onChange={setMorning}
/>
Props?: optional
checkedboolean

true when the switch is on.

labelstring

What the switch turns on, for screen readers.

onChange(checked: boolean) => void

Called at each switch, with the new state.

disabled?boolean

The switch is greyed out and doesn't switch.

Checkbox

A checkbox followed by a sentence, for an agreement, such as accepting terms.

import { Checkbox } from 'hodi:sdk'

<Checkbox checked={keep} onChange={setKeep}>Keep my greetings</Checkbox>
Props?: optional
checkedboolean

true when the box is ticked.

onChange(checked: boolean) => void

Called at each click, with the new state.

childrenReactNode

The sentence next to the box.

disabled?boolean

The box is greyed out and can't be ticked.

AgeCheckbox

The I am at least 13 years old box, followed by the text each plugin adds with ageConsent. Every form that creates an account has this box.

import { AgeCheckbox } from 'hodi:sdk'

<AgeCheckbox checked={adult} onChange={setAdult} />
Props?: optional
checkedboolean

true when the box is ticked.

onChange(checked: boolean) => void

Called at each click, with the new state.

Segmented

A choice between a few options, in a pill, such as Light · Dark · System. In a settings page, it is passed to a SettingRow's choice prop.

import { Segmented } from 'hodi:sdk'

<Segmented
  label="Moment"
  value={moment}
  options={[
    { value: 'morning', label: 'Morning' },
    { value: 'noon', label: 'Noon' },
    { value: 'evening', label: 'Evening' }
  ]}
  onChange={setMoment}
/>
Props?: optional
labelstring

The choice's name, for screen readers.

valuestring | number

The value of the chosen option.

options{ value; label; title? }[]

The options, in order. Each has a value and a text; its title shows on hover.

onChange(value) => void

Called when the person picks an option, with its value.

wide?boolean

The choice takes the whole width, shared equally between the options.