Component reference
Every component with its import path and prop types, generated from the norns-ui type shims.
Note
Generated from src/types/*.d.ts in @human-synthesis/norns-ui 0.0.13 by scripts/gen-reference.mjs. Do not edit this page by hand; fix the shim in norns-ui and re-run bun run docs:components there.
Every component under components/ is auto-imported by name in .n files when the consumer wires presetUI() into nornsAutoImport (Btn(variant="primary") Save). Components under motion/ are opt-in: import { Reveal } from '@human-synthesis/norns-ui/motion'. Snippet props (children, header, trigger, …) are filled with +snippet('name') blocks in Pug. Every component accepts class and merges it with cn().
Live usage of every component: norns-demo/src/routes/examples/ui/+page.n.
#Components
Accordion · Audio · Autocomplete · Avatar · AvatarGroup · Badge · Banner · Breadcrumbs · Btn · ButtonGroup · Calendar · Card · Carousel · Checkbox · Chip · Collapsible · ColorPicker · ContextMenu · CopyButton · DataTable · DatePicker · DateRangePicker · Dialog · Dropdown · Field · FieldGroup · Form · GradientText · Header · HeroBanner · HierarchicalMenu · Icon · Image · Input · MegaMenu · MultiSelect · NumberInput · OtpField · Pagination · Popover · Progress · ProgressCircular · Radio · RippleButton · ScrollArea · Select · Separator · Sheet · ShinyButton · Skeleton · Stepper · Surface · Switch · Tabs · TagsInput · Textarea · ThemeToggler · Timeline · TimePicker · ToastProvider · ToggleButton · ToggleButtonGroup · Toolbar · Tooltip · Tree · Uploader · Video · Window
#Accordion
@human-synthesis/norns-ui/components/Accordion.n
export type AccordionItem = {
value: string;
title: string;
content?: Snippet;
};
export type AccordionProps = {
items?: AccordionItem[];
multiple?: boolean;
value?: string | string[];
class?: string;
};#Audio
@human-synthesis/norns-ui/components/Audio.n
export type AudioSource = { src: string; type?: string };
export type AudioProps = {
src?: string;
sources?: AudioSource[];
controls?: boolean;
autoplay?: boolean;
loop?: boolean;
muted?: boolean;
preload?: 'none' | 'metadata' | 'auto';
fallback?: string;
class?: string;
};#Autocomplete
@human-synthesis/norns-ui/components/Autocomplete.n
export type ComboboxItem = { value: string; label: string };
export type AutocompleteProps = {
items?: ComboboxItem[];
value?: string;
open?: boolean;
placeholder?: string;
disabled?: boolean;
name?: string;
id?: string;
error?: boolean;
};#Avatar
@human-synthesis/norns-ui/components/Avatar.n
export type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';
export type AvatarProps = {
src?: string;
/** Display name; first + last initial used as fallback when `src` is missing. */
name?: string;
size?: AvatarSize;
class?: string;
};#AvatarGroup
@human-synthesis/norns-ui/components/AvatarGroup.n
export type AvatarGroupItem = { src?: string; name?: string };
export type AvatarGroupProps = {
items?: AvatarGroupItem[];
max?: number;
size?: AvatarSize;
label?: string;
class?: string;
};#Badge
@human-synthesis/norns-ui/components/Badge.n
export type BadgeVariant = 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'info';
export type BadgeSize = 'sm' | 'md';
export type BadgeProps = {
variant?: BadgeVariant;
size?: BadgeSize;
children?: Snippet;
class?: string;
};#Banner
@human-synthesis/norns-ui/components/Banner.n
export type BannerVariant = 'info' | 'success' | 'warning' | 'danger';
export type BannerProps = {
variant?: BannerVariant;
/** Iconify icon name (e.g. `"lucide:alert-triangle"`). */
icon?: string;
actions?: Snippet;
children?: Snippet;
class?: string;
};#Breadcrumbs
@human-synthesis/norns-ui/components/Breadcrumbs.n
export type BreadcrumbItem = {
label: string;
href?: string;
};
export type BreadcrumbsProps = {
items?: BreadcrumbItem[];
separator?: string;
class?: string;
};#Btn
@human-synthesis/norns-ui/components/Btn.n
/**
* Type shim for `Btn.n`. Hand-rolled until we have a proper
* `svelte-package` build over the Civet+Pug source.
*/
export type BtnVariant = 'primary' | 'secondary' | 'ghost' | 'danger' | 'link';
export type BtnSize = 'sm' | 'md' | 'lg';
export type BtnProps = Omit<HTMLButtonAttributes, 'class' | 'children'> & {
variant?: BtnVariant;
size?: BtnSize;
loading?: boolean;
disabled?: boolean;
type?: 'button' | 'submit' | 'reset';
/**
* Convenience: Iconify icon name (e.g. `"lucide:save"`). Renders an
* `<Icon>` in the leading slot. If you also pass a `leading` snippet,
* the snippet wins.
*/
icon?: string;
/** When set, renders as an `<a>` styled like the button. */
href?: string;
target?: string;
rel?: string;
class?: string;
children?: Snippet;
leading?: Snippet;
trailing?: Snippet;
};#ButtonGroup
@human-synthesis/norns-ui/components/ButtonGroup.n
export type ButtonGroupProps = {
orientation?: 'horizontal' | 'vertical';
children?: Snippet;
class?: string;
};#Calendar
@human-synthesis/norns-ui/components/Calendar.n
export type CalendarDateRange = { start: string; end: string };
export type CalendarProps = {
/** ISO YYYY-MM-DD. Bindable. */
value?: string;
/** Range mode. Bindable. Use instead of `value` when `range` is true. */
rangeValue?: CalendarDateRange;
range?: boolean;
/** ISO YYYY-MM-DD inclusive. */
min?: string;
max?: string;
label?: string;
onchange?: (next: string | CalendarDateRange) => void;
class?: string;
};#Card
@human-synthesis/norns-ui/components/Card.n
export type CardProps = {
/** Wrap body in `.card-body` (default true). Set false for full-bleed content. */
padded?: boolean;
/** Apply `.card-interactive` hover/focus treatment. Implicit if `href` is set. */
interactive?: boolean;
/** Renders as `<a>` instead of `<div>` when set. */
href?: string;
target?: string;
rel?: string;
header?: Snippet;
footer?: Snippet;
children?: Snippet;
class?: string;
};#Carousel
@human-synthesis/norns-ui/components/Carousel.n
export type CarouselSlide = {
src?: string;
alt?: string;
[key: string]: unknown;
};
export type CarouselProps = {
slides?: CarouselSlide[];
index?: number;
autoplay?: boolean;
/** Autoplay interval in milliseconds. Default 5000. */
interval?: number;
/** Default aspect ratio applied if no explicit `class="aspect-..."` is passed. */
aspect?: 'video' | 'square' | 'wide' | 'none';
/** Custom slide renderer; receives `(slide, i)` and runs only for slides without `src`. */
children?: Snippet<[CarouselSlide, number]>;
class?: string;
};#Checkbox
@human-synthesis/norns-ui/components/Checkbox.n
export type CheckboxProps = Omit<HTMLInputAttributes, 'class' | 'type' | 'checked'> & {
checked?: boolean;
error?: boolean;
class?: string;
};#Chip
@human-synthesis/norns-ui/components/Chip.n
export type ChipProps = {
icon?: string;
removable?: boolean;
onremove?: (event: MouseEvent) => void;
children?: Snippet;
class?: string;
};#Collapsible
@human-synthesis/norns-ui/components/Collapsible.n
export type CollapsibleProps = {
open?: boolean;
title?: string;
trigger?: Snippet;
children?: Snippet;
onopenchange?: (open: boolean) => void;
class?: string;
};#ColorPicker
@human-synthesis/norns-ui/components/ColorPicker.n
export type ColorPickerProps = {
/** Hex value with leading `#`. Bindable. */
value?: string;
disabled?: boolean;
/** Hide the clipboard-copy button. */
hideCopy?: boolean;
name?: string;
id?: string;
class?: string;
};#ContextMenu
@human-synthesis/norns-ui/components/ContextMenu.n
export type ContextMenuItem = {
label?: string;
icon?: string;
separator?: boolean;
disabled?: boolean;
onSelect?: () => void;
/**
* NOTE: nested submenus are not supported in 0.0.6+ (the property is
* accepted but children are ignored). Re-introduce when the upstream
* design needs them.
*/
children?: ContextMenuItem[];
};
export type ContextMenuProps = {
items?: ContextMenuItem[];
trigger?: Snippet;
triggerClass?: string;
};#CopyButton
@human-synthesis/norns-ui/components/CopyButton.n
export type CopyButtonProps = {
value?: string | number;
variant?: 'primary' | 'secondary' | 'ghost' | 'danger' | 'link';
size?: 'sm' | 'md' | 'lg';
icon?: string;
disabled?: boolean;
label?: string;
oncopy?: (value: string | number) => void;
children?: Snippet;
class?: string;
};#DataTable
@human-synthesis/norns-ui/components/DataTable.n
export type DataTableColumn = {
key: string;
label?: string;
width?: string;
class?: string;
cellClass?: string;
sortable?: boolean;
};
export type DataTableProps = {
columns?: DataTableColumn[];
rows?: Record<string, unknown>[];
striped?: boolean;
dense?: boolean;
stickyHeader?: boolean;
emptyMessage?: string;
/** Currently-sorted column key. Bindable. */
sortKey?: string;
sortDir?: 'asc' | 'desc';
onrowclick?: (row: Record<string, unknown>, index: number) => void;
class?: string;
};#DatePicker
@human-synthesis/norns-ui/components/DatePicker.n
export type DatePickerProps = {
/** ISO date string (YYYY-MM-DD). Bindable. */
value?: string;
/** Whether the popover is open. Bindable. */
open?: boolean;
min?: string;
max?: string;
placeholder?: string;
disabled?: boolean;
/** Close the popover automatically once a date is picked (default true). */
closeOnSelect?: boolean;
/** aria-label override; defaults to "Pick a date". */
label?: string;
name?: string;
id?: string;
error?: boolean;
class?: string;
};#DateRangePicker
@human-synthesis/norns-ui/components/DateRangePicker.n
export type DateRange = { start: string; end: string };
export type DateRangePickerProps = {
value?: DateRange;
/** Whether the popover is open. Bindable. */
open?: boolean;
min?: string;
max?: string;
placeholder?: string;
disabled?: boolean;
class?: string;
};#Dialog
@human-synthesis/norns-ui/components/Dialog.n
export type DialogProps = {
open?: boolean;
title?: string;
description?: string;
hideClose?: boolean;
/** Close on overlay click and Escape. Default true. */
dismissable?: boolean;
/** Used as `aria-label` on the dialog when no `title` is provided. */
ariaLabel?: string;
trigger?: Snippet;
actions?: Snippet;
children?: Snippet;
triggerClass?: string;
overlayClass?: string;
class?: string;
};#Dropdown
@human-synthesis/norns-ui/components/Dropdown.n
export type DropdownItem = {
label?: string;
icon?: string;
separator?: boolean;
disabled?: boolean;
onSelect?: () => void;
};
export type DropdownProps = {
open?: boolean;
side?: 'top' | 'right' | 'bottom' | 'left';
align?: 'start' | 'center' | 'end';
sideOffset?: number;
items?: DropdownItem[];
trigger?: Snippet;
children?: Snippet;
triggerClass?: string;
class?: string;
};#Field
@human-synthesis/norns-ui/components/Field.n
export type FieldProps = {
/** Label text rendered above the control. Used as id-derivation fallback if no `id`/`name` is given. */
label?: string;
/** Helper text shown below the control when there's no error. */
help?: string;
/**
* Explicit error message. Overrides any auto-resolved error from the
* parent `<Form form={...}>` context. Switches the inner control to
* error styling.
*/
error?: string;
/**
* Field name — used to look up an auto-error from the parent `<Form>`
* context (matching `form.errors[*].path[0].key`) and as the default
* id for the inner control. When set, an inner `<Input>` doesn't need
* an explicit `name=` either if it inherits from this Field.
*/
name?: string;
/** Adds a red asterisk after the label. Cosmetic; pair with `required` on the actual input. */
required?: boolean;
/** Explicit id for the control. Otherwise: `name`, then slugified `label`, then undefined. */
id?: string;
/** Optional class merged into the field wrapper. */
class?: string;
/** Snippet that renders the actual control. Children should call `<Input />`, `<Textarea />`, etc. */
children?: Snippet;
};#FieldGroup
@human-synthesis/norns-ui/components/FieldGroup.n
export type FieldGroupProps = {
/** Optional legend text rendered as the fieldset's `<legend>`. */
legend?: string;
class?: string;
children?: Snippet;
};#Form
@human-synthesis/norns-ui/components/Form.n
/**
* The shape returned by `fail(400, { errors, values })` from a SvelteKit
* action — what `+page.server.c`'s `page.actions` produces on validation
* failure (or a manually-constructed equivalent). `errors` is a valibot
* issue list; `values` is the raw form data echoed back for re-rendering.
*/
export type FormActionResult = {
errors?: Array<{ path?: Array<{ key?: string }>; message: string }>;
values?: Record<string, string>;
} | null | undefined;
export type FormProps = Omit<HTMLFormAttributes, 'class' | 'children'> & {
method?: 'GET' | 'POST';
action?: string;
enctype?: 'application/x-www-form-urlencoded' | 'multipart/form-data' | 'text/plain';
/**
* Pass the page's `form` prop here. Form derives a `name → message` errors
* map and exposes it via context so descendant `<Field name="...">` looks
* up its own error automatically.
*/
form?: FormActionResult;
class?: string;
children?: Snippet;
};#GradientText
@human-synthesis/norns-ui/components/GradientText.n
export type GradientTextProps = {
/** Start color. Default `var(--color-primary-500)`. Accepts any CSS color. */
from?: string;
/** End color. Default `var(--color-info-500)`. */
to?: string;
/** Optional middle stop. */
via?: string;
/** Animate the gradient via background-position keyframes. Default true. */
animate?: boolean;
/** Gradient angle in degrees. Default 90. */
angle?: number;
children?: Snippet;
class?: string;
};#Header
@human-synthesis/norns-ui/components/Header.n
export type HeaderProps = {
sticky?: boolean;
brand?: Snippet;
nav?: Snippet;
actions?: Snippet;
class?: string;
};#HeroBanner
@human-synthesis/norns-ui/components/HeroBanner.n
export type HeroBannerProps = {
title: string;
description?: string;
/** Background/decorative image src; rendered with reduced opacity behind the content. */
image?: string;
align?: 'left' | 'center';
/** Apply animated `GradientText` to the title. Default false. */
gradient?: boolean;
actions?: Snippet;
children?: Snippet;
class?: string;
};#HierarchicalMenu
@human-synthesis/norns-ui/components/HierarchicalMenu.n
export type HierarchicalMenuItem = {
label: string;
href?: string;
icon?: string;
description?: string;
children?: HierarchicalMenuItem[];
};
export type HierarchicalMenuProps = {
items?: HierarchicalMenuItem[];
/** aria-label for the <nav> wrapper. */
label?: string;
onSelect?: (item: HierarchicalMenuItem) => void;
class?: string;
};#Icon
@human-synthesis/norns-ui/components/Icon.n
export type IconProps = {
/**
* Iconify icon name in `<set>:<name>` form, e.g. `"lucide:check"` or
* `"mdi:home"`. The `@iconify-json/lucide` package ships with the library;
* other sets can be installed alongside (`@iconify-json/heroicons`, etc.).
*/
name: string;
/**
* Tailwind size utility for the icon, e.g. `"size-4"`, `"size-5"`. Default
* `"size-4"`. Pass any class string accepted by Tailwind.
*/
size?: string;
flip?: 'horizontal' | 'vertical' | 'horizontal,vertical';
rotate?: 90 | 180 | 270 | string;
class?: string;
};#Image
@human-synthesis/norns-ui/components/Image.n
export type ImageProps = {
src: string;
alt?: string;
loading?: 'lazy' | 'eager';
fit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
rounded?: boolean | 'sm' | 'md' | 'lg' | 'full';
width?: number | string;
height?: number | string;
class?: string;
};#Input
@human-synthesis/norns-ui/components/Input.n
export type InputSize = 'sm' | 'md' | 'lg';
export type InputType =
| 'text'
| 'email'
| 'password'
| 'number'
| 'tel'
| 'url'
| 'search'
| 'date'
| 'time'
| 'datetime-local'
| 'month'
| 'week';
export type InputProps = Omit<HTMLInputAttributes, 'class' | 'type' | 'size' | 'value'> & {
value?: string | number;
type?: InputType;
size?: InputSize;
/** Force the error styling regardless of the parent Field's error state. */
error?: boolean;
class?: string;
};#MegaMenu
@human-synthesis/norns-ui/components/MegaMenu.n
export type MegaMenuItem = {
label: string;
href?: string;
icon?: string;
description?: string;
};
export type MegaMenuColumn = {
title?: string;
items: MegaMenuItem[];
};
export type MegaMenuSection = {
label: string;
cols?: 2 | 3 | 4;
columns: MegaMenuColumn[];
};
export type MegaMenuProps = {
sections?: MegaMenuSection[];
/** aria-label for the <nav> wrapper. */
label?: string;
class?: string;
};#MultiSelect
@human-synthesis/norns-ui/components/MultiSelect.n
export type MultiSelectProps = {
items?: ComboboxItem[];
value?: string[];
open?: boolean;
placeholder?: string;
disabled?: boolean;
name?: string;
id?: string;
error?: boolean;
};#NumberInput
@human-synthesis/norns-ui/components/NumberInput.n
export type NumberInputProps = {
value?: number;
min?: number;
max?: number;
stepSize?: number;
disabled?: boolean;
readonly?: boolean;
name?: string;
id?: string;
error?: boolean;
class?: string;
};#OtpField
@human-synthesis/norns-ui/components/OtpField.n
export type OtpFieldProps = {
value?: string;
length?: number;
mask?: boolean;
label?: string;
oncomplete?: (value: string) => void;
class?: string;
};#Pagination
@human-synthesis/norns-ui/components/Pagination.n
export type PaginationProps = {
page?: number;
total?: number;
pageSize?: number;
/** How many pages to show on each side of the current. Default 1. */
siblingCount?: number;
class?: string;
};#Popover
@human-synthesis/norns-ui/components/Popover.n
export type PopoverSide = 'top' | 'right' | 'bottom' | 'left';
export type PopoverAlign = 'start' | 'center' | 'end';
export type PopoverProps = {
open?: boolean;
side?: PopoverSide;
align?: PopoverAlign;
sideOffset?: number;
trigger?: Snippet;
children?: Snippet;
triggerClass?: string;
class?: string;
};#Progress
@human-synthesis/norns-ui/components/Progress.n
export type ProgressVariant = 'primary' | 'success' | 'warning' | 'danger';
export type ProgressProps = {
value?: number;
max?: number;
variant?: ProgressVariant;
indeterminate?: boolean;
class?: string;
};#ProgressCircular
@human-synthesis/norns-ui/components/ProgressCircular.n
export type ProgressCircularSize = 'sm' | 'md' | 'lg';
export type ProgressCircularProps = {
value?: number;
max?: number;
size?: ProgressCircularSize;
indeterminate?: boolean;
class?: string;
};#Radio
@human-synthesis/norns-ui/components/Radio.n
export type RadioProps = Omit<HTMLInputAttributes, 'class' | 'type'> & {
/** Two-way bound shared group value — pass `bind:group={selected}` from parent. */
group?: string;
value?: string;
error?: boolean;
class?: string;
};#RippleButton
@human-synthesis/norns-ui/components/RippleButton.n
export type RippleButtonProps = {
variant?: 'primary' | 'secondary' | 'ghost' | 'danger' | 'link';
size?: 'sm' | 'md' | 'lg';
type?: 'button' | 'submit' | 'reset';
disabled?: boolean;
onclick?: (event: MouseEvent) => void;
icon?: string;
children?: Snippet;
class?: string;
};#ScrollArea
@human-synthesis/norns-ui/components/ScrollArea.n
export type ScrollAreaProps = {
/** Allow horizontal scrolling instead of just vertical. */
horizontal?: boolean;
children?: Snippet;
class?: string;
};#Select
@human-synthesis/norns-ui/components/Select.n
export type SelectProps = Omit<HTMLSelectAttributes, 'class' | 'value' | 'children'> & {
value?: string | number | string[];
error?: boolean;
class?: string;
/** `<option>` children. Pass via Pug body. */
children?: Snippet;
};#Separator
@human-synthesis/norns-ui/components/Separator.n
export type SeparatorProps = {
orientation?: 'horizontal' | 'vertical';
class?: string;
};#Sheet
@human-synthesis/norns-ui/components/Sheet.n
export type SheetSide = 'top' | 'right' | 'bottom' | 'left';
export type SheetProps = {
open?: boolean;
/** `'left'` was previously the default for the now-removed `<Drawer>`. */
side?: SheetSide;
title?: string;
description?: string;
hideClose?: boolean;
dismissable?: boolean;
ariaLabel?: string;
trigger?: Snippet;
actions?: Snippet;
children?: Snippet;
triggerClass?: string;
overlayClass?: string;
class?: string;
};#ShinyButton
@human-synthesis/norns-ui/components/ShinyButton.n
export type ShinyButtonProps = {
variant?: 'primary' | 'secondary' | 'ghost' | 'danger' | 'link';
size?: 'sm' | 'md' | 'lg';
type?: 'button' | 'submit' | 'reset';
disabled?: boolean;
onclick?: (event: MouseEvent) => void;
icon?: string;
children?: Snippet;
class?: string;
};#Skeleton
@human-synthesis/norns-ui/components/Skeleton.n
export type SkeletonVariant = 'rect' | 'text' | 'circle';
export type SkeletonProps = {
variant?: SkeletonVariant;
width?: number | string;
height?: number | string;
class?: string;
};#Stepper
@human-synthesis/norns-ui/components/Stepper.n
export type StepperStep = {
id?: string;
label: string;
complete?: boolean;
current?: boolean;
};
export type StepperProps = {
steps?: StepperStep[];
/** Index of the active step. Steps before are auto-marked complete unless overridden. */
current?: number;
orientation?: 'horizontal' | 'vertical';
class?: string;
};#Surface
@human-synthesis/norns-ui/components/Surface.n
export type SurfaceProps = {
tone?: 'glass';
children?: Snippet;
class?: string;
};#Switch
@human-synthesis/norns-ui/components/Switch.n
export type SwitchProps = Omit<HTMLInputAttributes, 'class' | 'type' | 'checked' | 'role'> & {
checked?: boolean;
error?: boolean;
class?: string;
};#Tabs
@human-synthesis/norns-ui/components/Tabs.n
export type TabsItem = {
value: string;
label: string;
panel?: Snippet;
disabled?: boolean;
};
export type TabsProps = {
value?: string;
items?: TabsItem[];
/** ARIA label for the tablist. Default 'Tabs'. */
label?: string;
class?: string;
};#TagsInput
@human-synthesis/norns-ui/components/TagsInput.n
export type TagsInputProps = {
value?: string[];
max?: number;
placeholder?: string;
commitOnBlur?: boolean;
separators?: string[];
disabled?: boolean;
name?: string;
id?: string;
error?: boolean;
class?: string;
};#Textarea
@human-synthesis/norns-ui/components/Textarea.n
export type TextareaProps = Omit<HTMLTextareaAttributes, 'class' | 'value' | 'rows'> & {
value?: string;
rows?: number;
error?: boolean;
class?: string;
};#ThemeToggler
@human-synthesis/norns-ui/components/ThemeToggler.n
export type ThemeTogglerProps = {
variant?: 'primary' | 'secondary' | 'ghost' | 'danger' | 'link';
size?: 'sm' | 'md' | 'lg';
showLabel?: boolean;
labelLight?: string;
labelDark?: string;
lightIcon?: string;
darkIcon?: string;
/** localStorage key. Default `'norns-theme'`. */
storageKey?: string;
class?: string;
};#Timeline
@human-synthesis/norns-ui/components/Timeline.n
export type TimelineItem = {
time?: string;
title?: string;
description?: string;
icon?: string;
variant?: 'primary' | 'success' | 'warning' | 'danger' | 'info';
};
export type TimelineProps = {
items?: TimelineItem[];
class?: string;
};#TimePicker
@human-synthesis/norns-ui/components/TimePicker.n
export type TimePickerProps = {
/** Time string `HH:MM` (24h regardless of display `hourCycle`). Bindable. */
value?: string;
open?: boolean;
/** Minute increment in the picker (5, 10, 15, 30). Default 5. */
minuteStep?: number;
hourCycle?: 12 | 24;
placeholder?: string;
disabled?: boolean;
label?: string;
name?: string;
id?: string;
error?: boolean;
class?: string;
};#ToastProvider
@human-synthesis/norns-ui/components/ToastProvider.n
export type ToastVariant = 'info' | 'success' | 'warning' | 'error';
export type ToastProviderProps = {
class?: string;
};
export type ToastOpts = {
variant?: ToastVariant;
duration?: number;
};#ToggleButton
@human-synthesis/norns-ui/components/ToggleButton.n
export type ToggleButtonProps = {
pressed?: boolean;
disabled?: boolean;
icon?: string;
/** Any `.btn-*` variant. The toggle visual state is controlled by `data-pressed`. */
variant?: 'primary' | 'secondary' | 'ghost' | 'danger' | 'link';
size?: 'sm' | 'md' | 'lg';
onpressedchange?: (pressed: boolean) => void;
children?: Snippet;
class?: string;
};#ToggleButtonGroup
@human-synthesis/norns-ui/components/ToggleButtonGroup.n
export type ToggleGroupItem = {
value: string;
label?: string;
icon?: string;
iconOnly?: boolean;
disabled?: boolean;
};
export type ToggleButtonGroupProps = {
items?: ToggleGroupItem[];
value?: string | string[] | undefined;
multiple?: boolean;
disabled?: boolean;
label?: string;
class?: string;
};#Toolbar
@human-synthesis/norns-ui/components/Toolbar.n
export type ToolbarProps = {
orientation?: 'horizontal' | 'vertical';
/** Accessible label, used as aria-label. */
label?: string;
children?: Snippet;
class?: string;
};#Tooltip
@human-synthesis/norns-ui/components/Tooltip.n
export type TooltipProps = {
content?: string;
side?: 'top' | 'right' | 'bottom' | 'left';
align?: 'start' | 'center' | 'end';
sideOffset?: number;
delay?: number;
/** Wider, surface-elevated styling for tooltips with markup/multiline content. */
rich?: boolean;
trigger?: Snippet;
children?: Snippet;
triggerClass?: string;
class?: string;
};#Tree
@human-synthesis/norns-ui/components/Tree.n
export type TreeNode = {
id: string | number;
label: string;
icon?: string;
children?: TreeNode[];
};
export type TreeProps = {
items?: TreeNode[];
/** Array of node ids that are expanded. Bindable. */
expanded?: (string | number)[];
/** Currently-selected node id. Bindable. */
selected?: string | number;
class?: string;
};#Uploader
@human-synthesis/norns-ui/components/Uploader.n
export type UploaderProps = {
files?: File[];
multiple?: boolean;
accept?: string;
disabled?: boolean;
placeholder?: string;
helper?: string;
onchange?: (files: File[]) => void;
class?: string;
};#Video
@human-synthesis/norns-ui/components/Video.n
export type VideoSource = { src: string; type?: string };
export type VideoProps = {
src?: string;
sources?: VideoSource[];
controls?: boolean;
autoplay?: boolean;
loop?: boolean;
muted?: boolean;
playsinline?: boolean;
preload?: 'none' | 'metadata' | 'auto';
poster?: string;
fallback?: string;
class?: string;
};#Window
@human-synthesis/norns-ui/components/Window.n
export type WindowProps = {
/** Header title (truncated). */
title?: string;
/** Remove the whole header bar; keeps the rounded shell. */
hideHeader?: boolean;
/** When set, renders a `lucide:x` close button (marked `.nodrag`). */
onClose?: () => void;
/** Fires on double-click over the header bar (e.g. maximise). */
onHeaderDoubleClick?: (event: MouseEvent) => void;
/** Extra header controls, rendered before the close button. */
actions?: Snippet;
children?: Snippet;
/** Classes for the outer shell — pass dimensions here (`w-[520px] h-[380px]`). */
class?: string;
/** Classes for the body section. */
bodyClass?: string;
};#Motion (opt-in)
AnimatedNumber · GradientBackground · LiquidButton · Reveal · Sparkles
#AnimatedNumber
import { AnimatedNumber } from '@human-synthesis/norns-ui/motion'
export type AnimatedNumberProps = {
value: number;
from?: number;
/** Duration in seconds. */
duration?: number;
decimals?: number;
/** Custom number-to-string formatter. */
format?: (n: number) => string;
class?: string;
};#GradientBackground
import { GradientBackground } from '@human-synthesis/norns-ui/motion'
export type GradientBackgroundProps = {
colors?: string[];
/** Loop duration in seconds. Default 18. */
duration?: number;
/** Gradient angle. Default 130. */
angle?: number;
children?: Snippet;
class?: string;
};#LiquidButton
import { LiquidButton } from '@human-synthesis/norns-ui/motion'
export type LiquidButtonProps = {
variant?: 'primary' | 'secondary' | 'ghost' | 'danger' | 'link';
size?: 'sm' | 'md' | 'lg';
type?: 'button' | 'submit' | 'reset';
disabled?: boolean;
onclick?: (event: MouseEvent) => void;
icon?: string;
children?: Snippet;
class?: string;
};#Reveal
import { Reveal } from '@human-synthesis/norns-ui/motion'
export type RevealProps = {
direction?: 'up' | 'down' | 'left' | 'right';
/** Travel distance in pixels. Default 12. */
distance?: number;
/** Animation duration in seconds. Default 0.5. */
duration?: number;
/** Delay before animating, seconds. Default 0. */
delay?: number;
/** Re-trigger on every entry (false) or just the first time (true). Default true. */
once?: boolean;
/** IntersectionObserver threshold (0–1). Default 0.15. */
threshold?: number;
children?: Snippet;
class?: string;
};#Sparkles
import { Sparkles } from '@human-synthesis/norns-ui/motion'
export type SparklesProps = {
density?: number;
colors?: string[];
minSize?: number;
maxSize?: number;
children?: Snippet;
class?: string;
};