AI Input
AI Input is a streamlined input component designed for Active Intelligence experiences, providing consistent styling and enhanced accessibility.
Loading...
Loading...
Overview
Resources
Install
yarn add @camp/ai-inputProps
| Prop | Type | Default | Description |
|---|---|---|---|
onChange † | ChangeEventHandler<HTMLInputElement> | — | |
value † | string | number | readonly string[] | — | |
placeholder | string | — | Placeholder text shown when input is empty. @note Avoid using placeholder when `appearance="inline-edit"`. The inline-edit appearance is designed to display content as static text; placeholder text disrupts this pattern. Consider using a label or default value instead. |
label | string | — | Label text displayed above the input |
invalid | boolean | — | Whether the input is in an invalid/error state |
appearance | "default" | "inline-edit" | default | Appearance variation |
disabled † | boolean | — | |
onBlur † | FocusEventHandler<HTMLInputElement> | — | |
type † | HTMLInputTypeAttribute | — | |
helperText | string | — | Helper text displayed below the input |
id † | string | — | |
themed | boolean | true | Whether the component should adapt to the theme context. When false, forces light theme. |
onKeyDown † | KeyboardEventHandler<HTMLInputElement> | — | |
ref † | LegacyRef<HTMLInputElement> | — | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see {@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs} |
inputSize | "default" | "small" | default | Size of the input. 'small' reduces the padding. |
required | boolean | — | Whether the input field is required; this should only be used when only some fields in a form are required and not the entire form |
action | ReactNode | — | Action element displayed at the end of the input after suffix (e.g., button) |
aria-label † | string | — | Defines a string value that labels the current element. @see aria-labelledby. |
name † | string | — | |
prefix | ReactNode | — | Prefix element displayed at the start of the input (e.g., icon) *Note:* Use small size icons only. |
min † | string | number | — | |
style † | CSSProperties | — | |
textAppearance | TextAppearance | — | Typography style for the input text (uses same appearances as AiText). Only applies when appearance is 'inline-edit'. |
autoFocus † | boolean | — | |
className † | string | — | |
max † | string | number | — | |
onFocus † | FocusEventHandler<HTMLInputElement> | — | |
onKeyPress † | KeyboardEventHandler<HTMLInputElement> | — | @deprecated Use `onKeyUp` or `onKeyDown` instead |
step † | string | number | — | |
tabIndex † | number | — | |
charLimit | number | — | Character limit for the input |
labelProps | LabelHTMLAttributes<HTMLLabelElement> | — | Additional props to spread onto the label element (e.g., from downshift for accessibility) |
suffix | ReactNode | — | Suffix element displayed at the end of the input (e.g., icon) |
textAlign | "left" | "center" | 'left' | Text alignment inside the input. |
Generated from @camp/ai-input@6.14.0 source, ordered by production usage. * required. † standard HTML attribute — all native attributes are supported; only those with production usage are listed.
Usage
Basic usage
The AI Input component provides a consistent input experience with built-in support for labels, validation states, and theming. It forwards native input attributes such as value, onChange, and disabled for controlled usage.
import { useState } from 'react';
import { AiInput } from '@camp/ai-input';
function MyComponent() {
const [value, setValue] = useState('');
return (
<AiInput
label="Input label"
placeholder="Enter text here"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
);
}Best practices
- Use the default appearance for form inputs, search fields, and data entry scenarios
- Use the inline-edit appearance for content that users can edit directly, such as page titles, headings, or descriptions
- Always provide a label for accessibility, even if visually hidden
- Use the
invalidprop to indicate validation errors - Avoid using placeholders with inline-edit appearance; use labels or default values instead
- When using inline-edit with
textAppearance, ensure the typography matches the surrounding content
Content guidelines
✅ DO
- Use clear, descriptive labels that explain what information is expected
- Provide helpful placeholder text for default appearance inputs
- Use inline-edit appearance for content that should feel like editable text
🚫 DON’T
- Use vague labels like 'Input' or 'Field'
- Use placeholder text with inline-edit appearance; use labels or default values instead
- Use inline-edit appearance for form fields that require explicit user action
Variations
Default input
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return <AiInput label="Default input" placeholder="Enter your text here" />;
}Invalid state
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return <AiInput label="Invalid input" placeholder="Enter your text here" invalid={true} />;
}Disabled state
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return <AiInput label="Disabled input" placeholder="This is disabled" disabled={true} />;
}With action
import { AiInput } from '@camp/ai-input';
import { AiButton } from '@camp/ai-button';
function MyComponent() {
return (
<AiInput
label="Input with actions"
placeholder="actions available for this input"
action={
<AiButton appearance="primary" size="medium">
Action
</AiButton>
}
/>
);
}Default appearance
The default appearance provides a standard form input with visible borders and background. This is the default behavior when no appearance prop is specified.
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return (
<AiInput
appearance="default"
label="Default appearance input"
placeholder="Enter your text here"
/>
);
}Helper text
Use the helperText prop to add a helper text to the input.
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return <AiInput label="Label" placeholder="Placeholder" helperText="Helper text" />;
}Character limit
Use the charLimit prop to add a character limit with character counter to the input.
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return <AiInput label="Label" placeholder="Placeholder" charLimit={10} />;
}Inline-edit appearance
The inline-edit appearance creates a seamless editing experience where the input appears as static text until hovered or focused. This is ideal for editing content inline, such as page titles, headings, or descriptions.
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return (
<AiInput appearance="inline-edit" label="Editable title" value="Click to edit this text" />
);
}Inline-edit invalid state
Inline-edit inputs show validation errors with a destructive border when hovered or focused.
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return (
<AiInput
appearance="inline-edit"
label="Invalid title"
value="This content is invalid"
invalid={true}
/>
);
}Inline-edit disabled state
Disabled inline-edit inputs appear as static text and do not respond to hover or focus interactions.
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return (
<AiInput
appearance="inline-edit"
label="Disabled title"
value="Cannot edit this text"
disabled={true}
/>
);
}Inline-edit with text appearance
When using the inline-edit appearance, you can apply typography styles using the textAppearance prop. This allows the input to match surrounding text styles like headings, body text, or labels. The textAppearance prop only applies when appearance="inline-edit".
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return (
<>
{/* Heading styles */}
<AiInput
appearance="inline-edit"
textAppearance="heading-large"
label="Page title"
value="Editable Heading"
/>
{/* Body styles */}
<AiInput
appearance="inline-edit"
textAppearance="body-medium"
label="Description"
value="This is editable body text"
/>
{/* Eyebrow styles */}
<AiInput
appearance="inline-edit"
textAppearance="eyebrow-medium"
label="Category"
value="Featured Article"
/>
</>
);
}Text alignment
Control the text alignment within the input using the textAlign prop. This is useful for centered inputs or when aligning with surrounding content.
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return (
<>
<AiInput label="Left aligned (default)" value="This text is left-aligned" textAlign="left" />
<AiInput label="Center aligned" value="This text is center-aligned" textAlign="center" />
<AiInput
appearance="inline-edit"
textAppearance="heading-large"
label="Centered heading"
value="Big Centered Title"
textAlign="center"
/>
</>
);
}With prefix
Add a prefix element (such as an icon) at the start of the input. Use small size icons only.
import { AiInput } from '@camp/ai-input';
import { SearchSmall } from '@camp/icon';
function MyComponent() {
return (
<AiInput
label="Search input"
placeholder="Search..."
prefix={<SearchSmall fill="icon-decorative" title="Search" />}
/>
);
}With suffix
Add a suffix element (such as an icon) at the end of the input.
import { AiInput } from '@camp/ai-input';
import { CalendarEventSmall } from '@camp/icon';
function MyComponent() {
return (
<AiInput
label="Date selection"
placeholder="Select a date"
suffix={<CalendarEventSmall fill="icon-decorative" title="Calendar" />}
/>
);
}Inline-edit with prefix and suffix
The inline-edit appearance works seamlessly with prefix and suffix elements, maintaining the transparent appearance until hovered or focused.
import { AiInput } from '@camp/ai-input';
import { SearchSmall, CalendarEventSmall } from '@camp/icon';
function MyComponent() {
return (
<>
<AiInput
appearance="inline-edit"
label="Searchable content"
value="Searchable text"
prefix={<SearchSmall fill="icon-decorative" title="Search" />}
/>
<AiInput
appearance="inline-edit"
label="Date selection"
value="2024-01-15"
suffix={<CalendarEventSmall fill="icon-decorative" title="Calendar" />}
/>
<AiInput
appearance="inline-edit"
label="Full featured"
value="With both prefix and suffix"
prefix={<SearchSmall fill="icon-decorative" title="Search" />}
suffix={<CalendarEventSmall fill="icon-decorative" title="Calendar" />}
/>
</>
);
}Sizes
The inputSize prop can be used to control the size of the input. In most cases, the default size should be used. However, you can use the small size when space is limited.
import { AiInput } from '@camp/ai-input';
function MyComponent() {
return <AiInput label="Small input" placeholder="Small input" inputSize="small" />;
}Production Examples
More states from @camp/ai-input's visual test stories, ranked by production
usage. Variations already documented above are not repeated here.
Default Required
import { AiInput } from '@camp/ai-input';
<AiInput label="Required Input" placeholder="Enter text here" required />Inline Edit Default
import { AiInput } from '@camp/ai-input';
<AiInput
appearance="inline-edit"
label="Editable Title"
value="Click to edit this text"
/>Inline Edit Required
import { AiInput } from '@camp/ai-input';
<AiInput
appearance="inline-edit"
label="Required Description"
value="This is a required field that appears as inline text."
required
/>Inline Edit Heading Large
import { AiInput } from '@camp/ai-input';
<AiInput
appearance="inline-edit"
textAppearance="heading-large"
label="Page Title"
value="Editable Heading"
/>Inline Edit Heading X Large
import { AiInput } from '@camp/ai-input';
<AiInput
appearance="inline-edit"
textAppearance="heading-xlarge"
label="Hero Title"
value="Large Display Heading"
/>Inline Edit Body Medium
import { AiInput } from '@camp/ai-input';
<AiInput
appearance="inline-edit"
textAppearance="body-medium"
label="Description"
value="This is editable body text that can be modified inline."
/>23 more variations in Storybook
Accessibility
Keyboard support
- Standard input navigation using
tabkey to focus - All standard text input keyboard interactions supported
- Arrow keys for text cursor navigation within the input
- Screen reader support for labels and validation states