Components
PromptComposer
Unstable: where people write to the assistant, a textarea that grows with the text, tools at the start and a send button at the end. Enter sends, Shift+Enter adds a line. Import it from @nizivo/react/unstable/prompt-composer.
Examples
Basic
The composer: attach and dictate at the start, send at the end once there is text.
import type { JSX } from 'react';
import { IconButton } from '@nizivo/react/icon-button';
import { PromptComposer } from '@nizivo/react/unstable/prompt-composer';
/** Stand-ins for `@nizivo/icons` glyphs (Lucide strokes). */
function Paperclip(): JSX.Element {
return (
<svg
viewBox="0 0 24 24"
width="1em"
height="1em"
fill="none"
stroke="currentColor"
strokeWidth={1.92}
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551" />
</svg>
);
}
function Mic(): JSX.Element {
return (
<svg
viewBox="0 0 24 24"
width="1em"
height="1em"
fill="none"
stroke="currentColor"
strokeWidth={1.92}
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M12 19v3" />
<path d="M19 10v2a7 7 0 0 1-14 0v-2" />
<rect x="9" y="2" width="6" height="13" rx="3" />
</svg>
);
}
export function PromptComposerExample(): JSX.Element {
return (
<PromptComposer
style={{ maxInlineSize: 640 }}
labels={{ placeholder: 'Ask Nizivo AI anything…' }}
tools={
<>
<IconButton variant="secondary" size="sm" label="Attach file" icon={<Paperclip />} />
<IconButton variant="secondary" size="sm" label="Dictate" icon={<Mic />} />
</>
}
/>
);
}
Draft
With a draft: the send button is enabled.
import type { JSX } from 'react';
import { PromptComposer } from '@nizivo/react/unstable/prompt-composer';
export function PromptComposerDraftExample(): JSX.Element {
return (
<PromptComposer
style={{ maxInlineSize: 640 }}
defaultValue="Which products sold out last week?"
/>
);
}
Import
import { PromptComposer } from '@nizivo/react/unstable/prompt-composer';
// Once per app (Getting started), after
// @nizivo/tokens/tokens.css and @nizivo/react/css/base.css
import '@nizivo/react/css/prompt-composer.css';Static or interactive
Client. It holds the text and sends on Enter. How to choose.
Text and sending
value, defaultValue and onValueChange hold the text; onSend gets it on Enter or the send
button, unless it is only spaces, and an uncontrolled composer clears after. Shift+Enter adds a
line, and Enter while an input method is composing does neither. pending keeps the send button
disabled while an answer is on its way; the text stays editable. The composer is a <form>, so
name posts the text with it.
Tools
tools sits at the start of the toolbar: IconButtons that attach
or dictate ("Attach file", "Dictate"), a ModelSelector.
Accessibility
The textarea is named by a hidden label ("Message"); the placeholder is a hint, not its name. It
grows with the text, to 12 lines, where the browser has field-sizing. The send button stays
focusable while there is nothing to send, marked aria-disabled.
Props
Client component Renders data-slot="prompt-composer" with the class nz-prompt-composer. Props: PromptComposerProps. Source: src/unstable/prompt-composer/prompt-composer.client.tsx.
| Name | Type | Default | Description |
|---|---|---|---|
defaultValue | string | '' | The text at first (uncontrolled). |
disabled | boolean | – | |
labels | Partial<PromptComposerLabels> | – | |
name | string | – | The textarea's |
onSend | (value: string) => void | – | Enter or the send button, with text that is not only spaces. Uncontrolled, the text clears after. |
onValueChange | (value: string) => void | – | |
pending | boolean | false | An answer is on its way: the send button is disabled; the text stays editable. |
render | RenderProp<PromptComposerState> | – | Must render a |
tools | ReactNode | – | Left of the send button: IconButtons that attach or dictate, a ModelSelector. |
value | string | – | The text (controlled). |
- Also takes every attribute of
<form>exceptchildren,defaultValue,onSubmit;nameis redeclared above. (Omit<ComponentPropsWithRef<"form">, "onSubmit" | "children" | "defaultValue">)
render takes an element, or, in client code, a function of the props and this state (PromptComposerState):
| Name | Type | Default | Description |
|---|---|---|---|
emptyrequired | boolean | – | |
pendingrequired | boolean | – |
Other exports
PromptComposerLabelstypeimport type { PromptComposerLabels } from '@nizivo/react/unstable/prompt-composer'PromptComposer's own strings (§16.4): serialisable, English defaults.
Name Type Default Description labelrequiredstring'Message'The textarea's name.
placeholderrequiredstring'Ask anything…'sendrequiredstring'Send'The send button's name.
PromptComposerPropstypeimport type { PromptComposerProps } from '@nizivo/react/unstable/prompt-composer'The props of
PromptComposer, listed above.PromptComposerStatetypeimport type { PromptComposerState } from '@nizivo/react/unstable/prompt-composer'The render state of
PromptComposer, listed above.
Data attributes and slots
Style parts by class (.nz-<slot>) and state by data attribute. Attribute meanings come from contracts/vocabulary.json.
| Slot | Rendered by | Data attributes |
|---|---|---|
prompt-composer.nz-prompt-composer | PromptComposerroot (takes render) |
|
prompt-composer-input.nz-prompt-composer-input | PromptComposerinner element (CSS only); interactive, focus: self | none |
prompt-composer-send.nz-prompt-composer-send | PromptComposerinner element (CSS only); interactive, focus: self | none |
CSS hooks
Set a hook on the component's class or any ancestor to restyle it without specificity games; leave it unset for the default shown.
This stylesheet reads no public hook.
Layers: nz.components. Classes: .nz-prompt-composer, .nz-prompt-composer-input, .nz-prompt-composer-send, .nz-prompt-composer-toolbar, .nz-prompt-composer-tools.
Tokens this stylesheet reads (23)
--nz-bg-brand, --nz-bg-brand-hover, --nz-bg-disabled, --nz-bg-surface, --nz-border-control, --nz-border-focus, --nz-border-width-default, --nz-border-width-focus, --nz-duration-fast, --nz-easing-standard, --nz-elevation-2, --nz-font-body-l, --nz-radius-full, --nz-radius-xl, --nz-space-1, --nz-space-2, --nz-space-3, --nz-space-4, --nz-space-8, --nz-text-disabled, --nz-text-on-brand, --nz-text-primary, --nz-text-tertiary
Accessibility
These parts are interactive. Each gets the focus outline and touch-action rule from @nizivo/react/css/base.css (the nz.base layer), so the floor survives a restyle:
prompt-composer-input: draws the focus outline itself on keyboard focus.prompt-composer-send: draws the focus outline itself on keyboard focus.
Keyboard
To be written.
ProgressRing
A circular progress indicator in three sizes, exposed as a progressbar or, for a measurement, as a meter.
QuantityStepper
A whole-number quantity, such as a product page's or a cart line's, in Input's box between a minus and a plus button. The input is a native number input; the buttons step it for the pointer and are disabled at the ends of the range.