The example below loads live from Storybook; open it in Storybook to use the controls.
Default
Section titled “Default”TextInput always comes with a visible label. The label is bound to the input, so clicking it focuses the field. The default size is medium (36 px).
import { TextInput } from '@bigbang/ui';
export default function Default() { return <TextInput label="Field label" name="field" className="w-full max-w-80" />;}Help text
Section titled “Help text”description tells what the field expects in more detail than the label can: format, length, where to find the value. Screen readers read it with the field.
Help or instruction text goes here
import { TextInput } from '@bigbang/ui';
export default function WithDescription() { return ( <TextInput label="Field label" description="Help or instruction text goes here" name="field" className="w-full max-w-80" /> );}When error is set, the field is marked invalid: the border turns to the danger colour, the message shows under the help text, and screen readers read it with the field, after the help text. The message says what is wrong and how to fix it. When the message is shown elsewhere, such as in an error summary at the top of the form, set invalid alone: the field is marked invalid without a message under it.
import { TextInput } from '@bigbang/ui';
export default function Invalid() { return ( <TextInput label="Field label" error="Error message goes here" name="field" defaultValue="Value" className="w-full max-w-80" /> );}Required and optional
Section titled “Required and optional”required makes the value required: the input gets the native required attribute, so screen readers say “required”, and the label gets a * with a visually hidden “required”. A form marks the minority: when most fields are required, set necessityIndicator="optional" on every field and the optional ones show “(optional)” instead. Use one convention per form. The marker text comes from the library’s string catalogue in the Provider language.
import { Provider, TextInput } from '@bigbang/ui';
export default function Necessity() { // The Provider reads the library's own strings, such as the necessity marker, in English. return ( <Provider locale="en-GB"> <TextInput label="Field label" name="required-field" required className="w-full max-w-80" /> <TextInput label="Note" name="optional-field" necessityIndicator="optional" className="w-full max-w-80" /> </Provider> );}Start and end content
Section titled “Start and end content”startContent and endContent place content inside the field box, before and after the input: a decorative icon, a currency or unit, or one small action such as copy. Content that only decorates is hidden from screen readers; a unit that matters belongs in the label or the help text too.
import { Icon, TextInput } from '@bigbang/ui';
export default function StartEndContent() { return ( <> <TextInput label="Quantity" name="quantity" inputMode="numeric" endContent="items" className="w-full max-w-80" /> <TextInput label="Field label" name="search" startContent={<Icon name="search" size="sm" />} className="w-full max-w-80" /> </> );}Read-only
Section titled “Read-only”A readOnly field shows a value that cannot be changed here. Unlike a disabled field, it stays focusable, its text can be selected and copied, and its value is submitted with the form.
The value can be copied but not changed.
import { TextInput } from '@bigbang/ui';
export default function ReadOnly() { return ( <TextInput label="Reference number" description="The value can be copied but not changed." name="reference" defaultValue="Value" readOnly className="w-full max-w-80" /> );}There are two sizes. Pick the size by density and device.
- Medium (
md, 36 px): Most places, including desktop forms and filter fields. - Large (
lg, 40 px): Mobile forms. The Button in the same form should be large too.
import { TextInput } from '@bigbang/ui';
export default function Sizes() { return ( <div className="flex w-full max-w-80 flex-col gap-xl"> <TextInput label="Medium" size="md" name="field-md" /> <TextInput label="Large" size="lg" name="field-lg" /> </div> );}Disabled
Section titled “Disabled”A disabled field cannot be edited, does not take focus, and its value is not submitted with the form. Use it for information people need to see but cannot change, and explain why in the help text.
Help or instruction text goes here
import { TextInput } from '@bigbang/ui';
export default function Disabled() { return <TextInput label="Field label" description="Help or instruction text goes here" defaultValue="Value" disabled className="w-full max-w-80" />;}Controlled
Section titled “Controlled”To format the value while typing or tie it to another field, pass value and onValueChange together. This example shows the character count in the help text.
0/20 characters
import { TextInput } from '@bigbang/ui';import { useState } from 'react';
const MAX_LENGTH = 20;
export default function Controlled() { const [value, setValue] = useState(''); return ( <TextInput label="Field label" description={`${value.length}/${MAX_LENGTH} characters`} name="field" value={value} onValueChange={setValue} maxLength={MAX_LENGTH} className="w-full max-w-96" /> );}Light and dark mode
Section titled “Light and dark mode”TextInput takes all its colours from semantic tokens, so light and dark mode need no extra setup.
import { TextInput } from '@bigbang/ui';
export default function Invalid() { return ( <TextInput label="Field label" error="Error message goes here" name="field" defaultValue="Value" className="w-full max-w-80" /> );}