Note TextField extends props from HTMLInputElement on web. On mobile, it extends TextInputProps from react-native.
Default composition of Inputs.
<VStack gap={3}>
<TextInput
label="API Access Token"
placeholder="HaeJiWplJohn6W42eCq0Qqft0"
end={
<Box paddingX={2}>
<Link variant="caption" color="primary" to="">
COPY
</Link>
</Box>
}
/>
<VStack>
<Text as="p">Use the compact variant when space is tight.</Text>
<TextInput
compact
type="number"
step="0.01"
label="Amount"
placeholder="8293323.23"
suffix="USD"
/>
</VStack>
</VStack>
Accessible Text Inputs
TextInput comes with an accessibilityLabel prop. If no accessibilityLabel is passed, it will use the label as the accessibilityLabel. If you want an accessibilityLabel that differs from the Label, you can set this prop.
Here, since no accessibilityLabel is passed, the accessibilityLabel will be "Email".
<TextInput label="Email" />
Example of passing an accessibilityLabel. For web, this will set aria-label="Enter a Coinbase Email" under the hood
<TextInput accessibilityLabel="Enter a Coinbase Email" label="Email" />
Accessibility tipLike any component system, much of the responsibility for building accessible UIs is in your hands as the consumer to properly implement the component composition. We'll do our best to provide sane fallbacks, but here are the biggest gotchas for TextInputs you can watch out for.
aria-* attr overrides
Any time you use variant='negative', we assume you're showing an error state. If for some reason this is not the case, you will want to use aria-invalid={false} to override the default configuration.
It's also advised you always format helperText with Error: ${errorMessage}. We'd do that for you, but i18n isn't baked into CDS. Take a look at the example below:
<VStack gap={4}>
<TextInput
label="Text Input rendered in an errored state"
placeholder="Enter a color"
helperText="Error: Your favorite color is not orange"
variant="negative"
/>
<TextInput
label="Text Input that's red but not in an errored state"
placeholder="Enter a color"
helperText="You like red?"
variant="negative"
aria-invalid={false}
/>
</VStack>
Placeholder Text
<TextInput label="Label" placeholder="Placeholder" />
Borderless
For borderless TextInput usage, prefer adding a focus border with focusedBorderWidth.
If you need a fully borderless input (including focus), use that pattern with a TypeAhead
composition.
<VStack gap={2} padding={2}>
<TextInput
label="Borderless TextInput"
placeholder="placeholder"
helperText="When bordered is false, focus border styling is disabled by default."
bordered={false}
/>
<TextInput
label="Borderless TextInput (with focus border)"
placeholder="placeholder"
helperText="Set focusedBorderWidth to opt into a focus border style."
bordered={false}
focusedBorderWidth={200}
/>
</VStack>
Helper Text
Default Sentiment
<VStack gap={3}>
<VStack>
<Text as="p" font="headline">
Default sentiment
</Text>
<TextInput
label="Campaign title"
placeholder="Title"
helperText="This won't be displayed to user"
/>
</VStack>
<VStack>
<Text as="p" font="headline">
Positive sentiment
</Text>
<TextInput
label="Address"
helperText="Valid BTC address"
variant="positive"
placeholder="HaeJiWplJohn6W42eCq0Qqft0"
end={<InputIcon active color="fgPositive" name="visible" />}
/>
</VStack>
<VStack>
<Text as="p" font="headline">
Negative Sentiment
</Text>
<TextInput
label="Address"
helperText="Invalid BTC address"
variant="negative"
placeholder="HaeJiWplJohn6W42eCq0Qqft0"
end={<InputIcon active color="fgNegative" name="visible" />}
/>
</VStack>
</VStack>
Color Surge Enabled
<VStack gap={3}>
<TextInput
label="Default Color Surge"
placeholder="Focus me"
helperText="This won't be displayed to user"
enableColorSurge
/>
<TextInput
label="Positive Color Surge"
placeholder="Focus me"
helperText="Valid BTC address"
variant="positive"
enableColorSurge
/>
<TextInput
label="Negative Color Surge"
placeholder="Focus me"
helperText="Invalid BTC address"
variant="negative"
enableColorSurge
/>
</VStack>
Content Alignment
<VStack gap={3}>
<VStack>
<Text as="p">
<strong>Left aligned (default): </strong>
</Text>
<TextInput label="City/town" placeholder="Oakland" />
</VStack>
<VStack>
<Text as="p">Right aligned (with compact):</Text>
<TextInput
label="Limit price"
compact
align="end"
type="number"
step="0.01"
placeholder="29.3"
suffix="USD"
/>
</VStack>
</VStack>
Label Variants
TextInput supports two label variants: outside (default) and inside. Note that the compact prop, when set to true, will override label variant preference.
WarningWhen using the inside label variant, you should always include a placeholder prop.
<VStack gap={3}>
<VStack>
<Text as="p">
<strong>Outside label (default):</strong>
</Text>
<TextInput label="Email Address" placeholder="Enter your email" />
</VStack>
<VStack>
<Text as="p">
<strong>Inside label:</strong>
</Text>
<TextInput label="Email Address" labelVariant="inside" placeholder="Enter your email" />
</VStack>
<VStack>
<Text as="p">
<strong>Inside label (with start content):</strong>
</Text>
<TextInput
label="Search"
labelVariant="inside"
start={<InputIconButton name="search" />}
placeholder="Search for anything"
/>
</VStack>
<VStack>
<Text as="p">
<strong>Inside label (with end content):</strong>
</Text>
<TextInput
label="Password"
labelVariant="inside"
type="password"
end={<InputIconButton name="visible" />}
placeholder="Enter your password"
/>
</VStack>
</VStack>
Custom Label
You can pass a ReactNode to labelNode to render a custom label. If you want to include a tooltip, ensure the touch target is at least 24x24 for accessibility compliance.
<VStack gap={2}>
<TextInput
accessibilityLabel="Display name"
id="display-name-input"
labelNode={
<HStack alignItems="center">
<InputLabel htmlFor="display-name-input">Display name</InputLabel>
{}
<Tooltip content="This will be visible to other users.">
<Icon active color="fg" name="info" padding={0.75} size="xs" tabIndex={0} />
</Tooltip>
</HStack>
}
placeholder="Satoshi Nakamoto"
/>
<TextInput
accessibilityLabel="Amount"
compact
labelNode={
<InputLabel>
<HStack alignItems="center" gap={0.5}>
Amount
<Text color="fgNegative" font="label1">
*
</Text>
</HStack>
</InputLabel>
}
placeholder="0.00"
suffix="USD"
/>
<TextInput
accessibilityLabel="Bio"
id="bio-input"
labelVariant="inside"
labelNode={
<InputLabel htmlFor="bio-input" paddingY={0}>
<HStack alignItems="center" gap={1}>
Bio
<Text color="fgMuted" font="legal">
(optional)
</Text>
</HStack>
</InputLabel>
}
placeholder="Tell us about yourself"
/>
<TextInput
accessibilityLabel="Notes"
id="notes-input"
labelVariant="inside"
labelNode={
<InputLabel htmlFor="notes-input" paddingY={0}>
Notes
</InputLabel>
}
placeholder="Add a note"
start={<InputIcon name="pencil" />}
/>
</VStack>
StartContent & EndContent