Input
A single-line field where users can input and edit text.
Props
text.
off.
goa.
false.
false.
false.
false.
false.
30ch.
1.
0.
left.
default.
1.
Events
Slots
const [open, setOpen] = useState(false);
const [type, setType] = useState<string>();
const [name, setName] = useState<string>();
const [description, setDescription] = useState<string>();<GoabButton type="tertiary" leadingIcon="add" onClick={() => setOpen(true)}>
Add another item
</GoabButton>
<GoabModal
heading="Add a new item"
open={open}
actions={
<GoabButtonGroup alignment="end">
<GoabButton type="tertiary" size="compact" onClick={() => setOpen(false)}>
Cancel
</GoabButton>
<GoabButton type="primary" size="compact" onClick={() => setOpen(false)}>
Save new item
</GoabButton>
</GoabButtonGroup>
}
>
<p>Fill in the information to create a new item</p>
<GoabFormItem label="Type" mt="l">
<GoabDropdown onChange={(e) => setType(e.value)} value={type}>
<GoabDropdownItem value="1" label="Option 1" />
<GoabDropdownItem value="2" label="Option 2" />
</GoabDropdown>
</GoabFormItem>
<GoabFormItem label="Name" mt="l">
<GoabInput
onChange={(e) => setName(e.value)}
value={name}
name="name"
width="100%"
/>
</GoabFormItem>
<GoabFormItem label="Description" mt="l">
<GoabTextarea
name="description"
rows={3}
width="100%"
onChange={(e) => setDescription(e.value)}
value={description}
/>
</GoabFormItem>
</GoabModal>Add a record using a drawer
const [open, setOpen] = useState(false);<GoabButton leadingIcon="add" onClick={() => setOpen(true)}>
Add Record
</GoabButton>
<GoabDrawer
maxSize="492px"
open={open}
heading="Add Record"
position="right"
onClose={() => setOpen(false)}
actions={
<GoabButtonGroup>
<GoabButton type="primary" size="compact" onClick={() => setOpen(false)}>
Add record
</GoabButton>
<GoabButton type="tertiary" size="compact" onClick={() => setOpen(false)}>
Cancel
</GoabButton>
</GoabButtonGroup>
}
>
<GoabFormItem label="Level of education">
<GoabDropdown onChange={() => {}} name="education" value="university">
<GoabDropdownItem value="high-school" label="High School Diploma" />
<GoabDropdownItem value="college" label="College Diploma" />
<GoabDropdownItem value="university" label="University Degree" />
<GoabDropdownItem value="masters" label="Master's Degree" />
<GoabDropdownItem value="doctorate" label="Doctorate" />
</GoabDropdown>
</GoabFormItem>
<GoabFormItem label="Educational institution" mt="l">
<GoabInput name="education" type="text" onChange={() => {}} />
</GoabFormItem>
<GoabFormItem label="Field of study" requirement="optional" mt="l">
<GoabInput name="fieldOfStudy" type="text" onChange={() => {}} />
</GoabFormItem>
<GoabFormItem label="Is the person currently attending?" mt="l">
<GoabRadioGroup name="attendTraining" orientation="horizontal" onChange={() => {}}>
<GoabRadioItem value="yes" label="Yes" />
<GoabRadioItem value="no" label="No" />
</GoabRadioGroup>
</GoabFormItem>
<GoabFormItem label="Start date" mt="l">
<GoabDatePicker onChange={() => {}} value={new Date("2022-09-01")} />
<GoabCheckbox name="startDateApproximate" text="Approximate date" value="y" mt="s" />
</GoabFormItem>
<GoabFormItem label="Credential received?" mt="l">
<GoabRadioGroup name="credentialReceived" orientation="horizontal" onChange={() => {}}>
<GoabRadioItem value="yes" label="Yes" />
<GoabRadioItem value="no" label="No" />
</GoabRadioGroup>
</GoabFormItem>
</GoabDrawer>const [address, setAddress] = useState("");
const [suite, setSuite] = useState("");
const [city, setCity] = useState("");
const [province, setProvince] = useState("");
const [postalCode, setPostalCode] = useState("");<GoabText size="heading-l" mt="none" mb="xl">What is your address?</GoabText>
<GoabFormItem label="Street Address">
<GoabInput
name="address"
type="text"
value={address}
onChange={(e) => setAddress(e.value)}
width="100%"
/>
</GoabFormItem>
<GoabFormItem label="Suite or unit #" mt="l">
<GoabInput
name="suite"
type="text"
value={suite}
onChange={(e) => setSuite(e.value)}
width="100%"
/>
</GoabFormItem>
<GoabFormItem label="City or town" mt="l">
<GoabInput
name="city"
type="text"
value={city}
onChange={(e) => setCity(e.value)}
width="100%"
/>
</GoabFormItem>
<GoabBlock direction="row" gap="l" mt="l">
<GoabFormItem label="Province or territory">
<GoabDropdown
onChange={(e) => setProvince(e.value ?? "")}
name="province"
value={province}
>
<GoabDropdownItem label="Alberta" value="AB" />
<GoabDropdownItem label="British Columbia" value="BC" />
<GoabDropdownItem label="Manitoba" value="MB" />
<GoabDropdownItem label="New Brunswick" value="NB" />
<GoabDropdownItem label="Newfoundland and Labrador" value="NL" />
<GoabDropdownItem label="Northwest Territories" value="NT" />
<GoabDropdownItem label="Nova Scotia" value="NS" />
<GoabDropdownItem label="Nunavut" value="NU" />
<GoabDropdownItem label="Ontario" value="ON" />
<GoabDropdownItem label="Prince Edward Island" value="PE" />
<GoabDropdownItem label="Quebec" value="QC" />
<GoabDropdownItem label="Saskatchewan" value="SK" />
<GoabDropdownItem label="Yukon" value="YT" />
</GoabDropdown>
</GoabFormItem>
<GoabFormItem label="Postal Code">
<GoabInput
name="postalCode"
type="text"
value={postalCode}
onChange={(e) => setPostalCode(e.value)}
width="7ch"
/>
</GoabFormItem>
</GoabBlock>
<GoabButtonGroup alignment="start" mt="2xl">
<GoabButton type="primary" onClick={() => {}}>
Save and continue
</GoabButton>
<GoabButton type="secondary" onClick={() => {}}>
Cancel
</GoabButton>
</GoabButtonGroup>const [bankNumber, setBankNumber] = useState("");
const [transitNumber, setTransitNumber] = useState("");
const [accountNumber, setAccountNumber] = useState("");<GoabText as="h1" size="heading-l" mt="none" mb="m">Direct deposit information</GoabText>
<GoabText as="p" mb="xl">
Find this information on your bank's website or on your personal cheques.
Contact your bank if you can't find this information.
</GoabText>
<form>
<GoabFormItem
label="Bank or Institution number"
helpText="3-4 digits in length"
>
<GoabInput
maxLength={4}
name="bankNumber"
onChange={(e) => setBankNumber(e.value)}
value={bankNumber}
ariaLabel="bankNumber"
width="88px"
/>
</GoabFormItem>
<GoabFormItem
label="Branch or Transit number"
helpText="5 digits in length"
mt="l"
>
<GoabInput
maxLength={5}
name="transitNumber"
onChange={(e) => setTransitNumber(e.value)}
value={transitNumber}
ariaLabel="transitNumber"
width="143px"
/>
</GoabFormItem>
<GoabFormItem
label="Account number"
helpText="3-12 digits in length"
mt="l"
>
<GoabInput
maxLength={12}
name="accountNumber"
value={accountNumber}
onChange={(e) => setAccountNumber(e.value)}
ariaLabel="accountNumber"
/>
</GoabFormItem>
</form>
<GoabDetails heading="Where can I find this information on a personal cheque?" mt="l">
<GoabText as="p" mb="m">
Below is an example of where you can find the required bank information
on a personal cheque.
</GoabText>
<img src="https://design.alberta.ca/images/details-demo.jpg" alt="Cheque example showing bank information locations" />
</GoabDetails>
<GoabButton type="submit" mt="2xl">
Save and continue
</GoabButton>const [bandNo, setBandNo] = useState("");
const [family, setFamily] = useState("");
const [position, setPosition] = useState("");<GoabFormItem label="Indian registration number" labelSize="large">
<GoabBlock gap="m" direction="row">
<GoabFormItem label="Band #" helpText="3 digits">
<GoabInput
onChange={(e) => setBandNo(e.value)}
value={bandNo}
name="bandNo"
width="88px"
maxLength={3}
/>
</GoabFormItem>
<GoabFormItem label="Family" helpText="Up to 5 digits">
<GoabInput
onChange={(e) => setFamily(e.value)}
value={family}
name="family"
width="105px"
maxLength={5}
/>
</GoabFormItem>
<GoabFormItem label="Position" helpText="2 digits">
<GoabInput
onChange={(e) => setPosition(e.value)}
value={position}
name="position"
width="71px"
maxLength={2}
/>
</GoabFormItem>
</GoabBlock>
</GoabFormItem>const [tuitionAmount, setTuitionAmount] = useState("");
const [suppliesAmount, setSuppliesAmount] = useState("");
const [othersAmount, setOthersAmount] = useState("");<GoabFormItem label="Tuition">
<GoabInput
onChange={(e) => setTuitionAmount(e.value)}
value={tuitionAmount}
name="tuitionAmount"
leadingContent="$"
/>
</GoabFormItem>
<GoabFormItem label="Books/Supplies/Instruments" mt="l">
<GoabInput
onChange={(e) => setSuppliesAmount(e.value)}
value={suppliesAmount}
name="suppliesAmount"
leadingContent="$"
/>
</GoabFormItem>
<GoabFormItem label="Other costs" mt="l">
<GoabInput
onChange={(e) => setOthersAmount(e.value)}
value={othersAmount}
name="othersAmount"
leadingContent="$"
/>
</GoabFormItem>Disabled button with a required field
const [inputValue, setInputValue] = useState("");
const handleInputChange = (detail: GoabInputOnChangeDetail) => {
setInputValue(detail.value);
};
const handleConfirm = () => {
// Handle form submission
console.log("Form submitted with:", inputValue);
};
const handleCancel = () => {
// Handle cancellation
setInputValue("");
};<form>
<GoabFormItem label="Name" requirement="required">
<GoabInput
name="input"
type="text"
onChange={handleInputChange}
value={inputValue}
width="100%"
/>
</GoabFormItem>
<GoabButtonGroup alignment="start" mt="xl">
<GoabButton disabled={inputValue.trim() === ""} onClick={handleConfirm}>
Confirm
</GoabButton>
<GoabButton type="secondary" onClick={handleCancel}>
Cancel
</GoabButton>
</GoabButtonGroup>
</form>Dynamically add an item to a dropdown list
type Task = {
value: string;
label: string;
mount: GoabDropdownItemMountType;
};
const DEFAULT_TASKS: Task[] = [
{ label: "Finish Report", value: "finish-report", mount: "append" },
{ label: "Attend Meeting", value: "attend-meeting", mount: "append" },
{ label: "Reply Emails", value: "reply-emails", mount: "append" },
];
const [tasks, setTasks] = useState<Task[]>(DEFAULT_TASKS);
const [newTask, setNewTask] = useState<string>("");
const [mountType, setMountType] = useState<string>("append");
const [selectedTask, setSelectedTask] = useState<string>("");
const [taskError, setTaskError] = useState<boolean>(false);
const [isReset, setIsReset] = useState<boolean>(false);
function onMountTypeChange(value: string | undefined) {
setMountType(value as string);
}
function addTask() {
if (newTask === "") {
setTaskError(true);
return;
}
setTaskError(false);
const task: Task = {
label: newTask,
value: newTask.toLowerCase().replace(" ", "-"),
mount: mountType as GoabDropdownItemMountType,
};
setTasks([...tasks, task]);
setNewTask("");
setIsReset(false);
}
function reset() {
setTasks(DEFAULT_TASKS);
setMountType("append");
setNewTask("");
setSelectedTask("");
setTaskError(false);
setIsReset(true);
}<GoabFormItem
requirement="required"
label="Name of item"
error={taskError ? "Please enter item name" : undefined}
helpText="Add an item to the dropdown list below">
<GoabInput
onChange={(event: GoabInputOnChangeDetail) => setNewTask(event.value)}
name="item"
value={newTask}
/>
</GoabFormItem>
<GoabFormItem mt="l" label="Add to">
<GoabRadioGroup
name="mountType"
onChange={(event: GoabRadioGroupOnChangeDetail) => onMountTypeChange(event.value)}
value={mountType}
orientation="horizontal">
<GoabRadioItem value="prepend" label="Start" />
<GoabRadioItem value="append" label="End" />
</GoabRadioGroup>
</GoabFormItem>
<GoabButtonGroup alignment="start" gap="relaxed" mt="l">
<GoabButton type="primary" onClick={addTask}>
Add new item
</GoabButton>
<GoabButton type="tertiary" onClick={reset}>
Reset list
</GoabButton>
</GoabButtonGroup>
<GoabDivider mt="l" />
<GoabFormItem mt="l" label="All items">
<div style={{ width: isReset ? "320px" : "auto" }}>
<GoabDropdown
key={tasks.length}
onChange={(event: GoabDropdownOnChangeDetail) =>
setSelectedTask(event.value as string)
}
value={selectedTask}
name="selectedTask">
{tasks.map(task => (
<GoabDropdownItem
key={task.value}
value={task.value}
mountType={task.mount}
label={task.label}
/>
))}
</GoabDropdown>
</div>
</GoabFormItem>Filter data in a table
const [typedChips, setTypedChips] = useState<string[]>([]);
const [inputValue, setInputValue] = useState("");
const [inputError, setInputError] = useState("");
const errorEmpty = "Empty filter";
const errorDuplicate = "Enter a unique filter";
const data = useMemo(
() => [
{
status: { type: "information" as GoabBadgeType, text: "In progress" },
name: "Ivan Schmidt",
id: "7838576954",
},
{
status: { type: "success" as GoabBadgeType, text: "Completed" },
name: "Luz Lakin",
id: "8576953364",
},
{
status: { type: "information" as GoabBadgeType, text: "In progress" },
name: "Keith McGlynn",
id: "9846041345",
},
{
status: { type: "success" as GoabBadgeType, text: "Completed" },
name: "Melody Frami",
id: "7385256175",
},
{
status: { type: "important" as GoabBadgeType, text: "Updated" },
name: "Frederick Skiles",
id: "5807570418",
},
{
status: { type: "success" as GoabBadgeType, text: "Completed" },
name: "Dana Pfannerstill",
id: "5736306857",
},
],
[]
);
const [dataFiltered, setDataFiltered] = useState(data);
const handleInputChange = (detail: GoabInputOnChangeDetail) => {
const newValue = detail.value.trim();
setInputValue(newValue);
};
const handleInputKeyPress = (detail: GoabInputOnKeyPressDetail) => {
if (detail.key === "Enter") {
applyFilter();
}
};
const applyFilter = () => {
if (inputValue === "") {
setInputError(errorEmpty);
return;
}
if (typedChips.length > 0 && typedChips.includes(inputValue)) {
setInputError(errorDuplicate);
return;
}
setTypedChips([...typedChips, inputValue]);
setTimeout(() => {
setInputValue("");
}, 0);
setInputError("");
};
const removeTypedChip = (chip: string) => {
setTypedChips(typedChips.filter(c => c !== chip));
setInputError("");
};
const checkNested = useCallback((obj: object, chip: string): boolean => {
return Object.values(obj).some(value =>
typeof value === "object" && value !== null
? checkNested(value, chip)
: typeof value === "string" && value.toLowerCase().includes(chip.toLowerCase())
);
}, []);
const getFilteredData = useCallback(
(typedChips: string[]) => {
if (typedChips.length === 0) {
return data;
}
return data.filter((item: object) =>
typedChips.every(chip => checkNested(item, chip))
);
},
[checkNested, data]
);
useEffect(() => {
setDataFiltered(getFilteredData(typedChips));
}, [getFilteredData, typedChips]);<GoabFormItem id="filterChipInput" error={inputError} mb="m">
<GoabBlock gap="xs" direction="row" alignment="start" width="100%">
<div style={{ flex: 1 }}>
<GoabInput
name="filterChipInput"
aria-labelledby="filterChipInput"
value={inputValue}
leadingIcon="search"
width="100%"
onChange={handleInputChange}
onKeyPress={handleInputKeyPress}
/>
</div>
<GoabButton type="secondary" onClick={applyFilter} leadingIcon="filter">
Filter
</GoabButton>
</GoabBlock>
</GoabFormItem>
{typedChips.length > 0 && (
<div>
<GoabText tag="span" color="secondary" mb="xs" mr="xs">
Filter:
</GoabText>
{typedChips.map((typedChip, index) => (
<GoabFilterChip
key={index}
content={typedChip}
mb="xs"
mr="xs"
onClick={() => removeTypedChip(typedChip)}
/>
))}
<GoabButton type="tertiary" size="compact" mb="xs" onClick={() => setTypedChips([])}>
Clear all
</GoabButton>
</div>
)}
<GoabTable width="full">
<thead>
<tr>
<th>Status</th>
<th>Name</th>
<th className="goa-table-number-header">ID Number</th>
</tr>
</thead>
<tbody>
{dataFiltered.map(item => (
<tr key={item.id}>
<td>
<GoabBadge type={item.status.type} content={item.status.text} icon={false} />
</td>
<td>{item.name}</td>
<td className="goa-table-number-column">{item.id}</td>
</tr>
))}
</tbody>
</GoabTable>
{dataFiltered.length === 0 && data.length > 0 && (
<GoabBlock mt="l" mb="l">
No results found
</GoabBlock>
)}Group related questions together on a question page
const [addressLine1, setAddressLine1] = useState("");
const [addressLine2, setAddressLine2] = useState("");
const [townCity, setTownCity] = useState("");
const [province, setProvince] = useState("");
const [postalCode, setPostalCode] = useState("");<GoabLink leadingIcon="arrow-back" size="small" mb="none">
Back
</GoabLink>
<GoabText as="h2" mt="xl" mb="m">Your address</GoabText>
<GoabText mt="none" mb="xl">This is the home address of the person applying</GoabText>
<GoabFormItem label="Address line 1">
<GoabInput
onChange={(event) => setAddressLine1(event.value)}
value={addressLine1}
name="address-line-1"
ariaLabel="Address line 1"
width="100%"
/>
</GoabFormItem>
<GoabFormItem label="Address line 2" mt="l">
<GoabInput
onChange={(event) => setAddressLine2(event.value)}
value={addressLine2}
name="address-line-2"
ariaLabel="Address line 2"
width="100%"
/>
</GoabFormItem>
<GoabFormItem label="Town or city" mt="l">
<GoabInput
onChange={(event) => setTownCity(event.value)}
value={townCity}
name="town-city"
ariaLabel="Town or city name"
width="460px"
/>
</GoabFormItem>
<GoabFormItem label="Province or territory" mt="l" id="provinceLabel">
<GoabDropdown
onChange={(event) => setProvince(event.value ?? "")}
value={province}
name="province-territory"
ariaLabelledBy="provinceLabel"
>
<GoabDropdownItem value="AB" label="Alberta" />
<GoabDropdownItem value="BC" label="British Columbia" />
<GoabDropdownItem value="MB" label="Manitoba" />
<GoabDropdownItem value="NB" label="New Brunswick" />
<GoabDropdownItem value="NL" label="Newfoundland and Labrador" />
<GoabDropdownItem value="NS" label="Nova Scotia" />
<GoabDropdownItem value="ON" label="Ontario" />
<GoabDropdownItem value="PE" label="Prince Edward Island" />
<GoabDropdownItem value="QC" label="Quebec" />
<GoabDropdownItem value="SK" label="Saskatchewan" />
<GoabDropdownItem value="NT" label="Northwest Territories" />
<GoabDropdownItem value="NU" label="Nunavut" />
<GoabDropdownItem value="YT" label="Yukon" />
</GoabDropdown>
</GoabFormItem>
<GoabFormItem label="Postal code" mt="l">
<GoabInput
onChange={(event) => setPostalCode(event.value)}
value={postalCode}
name="postal-code"
width="105px"
/>
</GoabFormItem>
<GoabButton type="submit" mt="2xl">
Save and continue
</GoabButton>Question page
const [answer, setAnswer] = useState("");
const handleContinue = () => {
console.log("Answer submitted:", answer);
};<GoabLink leadingIcon="arrow-back" size="small" mb="none">
Back
</GoabLink>
<GoabText as="h1" mt="xl" mb="m">What is your email address?</GoabText>
<GoabText mt="none" mb="xl">We'll use this to send you confirmation of your application.</GoabText>
<GoabFormItem label="Email address">
<GoabInput
name="email"
type="email"
value={answer}
onChange={(e) => setAnswer(e.value)}
width="100%"
/>
</GoabFormItem>
<GoabButtonGroup alignment="start" mt="2xl">
<GoabButton type="primary" onClick={handleContinue}>
Continue
</GoabButton>
</GoabButtonGroup>
);
}Reveal input based on a selection
const [contactMethod, setContactMethod] = useState("");
const [checkboxSelection, setCheckboxSelection] = useState<string[]>([]);<GoabFormItem
label="How would you like to be contacted?"
helpText="Select one option"
>
<GoabRadioGroup
name="contactMethod"
value={contactMethod}
onChange={(e) => setContactMethod(e.value)}
>
<GoabRadioItem
value="email"
label="Email"
reveal={
<GoabFormItem label="Email address">
<GoabInput name="email" onChange={() => {}} value="" />
</GoabFormItem>
}
/>
<GoabRadioItem
value="phone"
label="Phone"
reveal={
<GoabFormItem label="Phone number">
<GoabInput name="phoneNumber" onChange={() => {}} value="" />
</GoabFormItem>
}
/>
<GoabRadioItem
value="text"
label="Text message"
reveal={
<GoabFormItem label="Mobile phone number">
<GoabInput name="mobilePhoneNumber" onChange={() => {}} value="" />
</GoabFormItem>
}
/>
</GoabRadioGroup>
</GoabFormItem>
<GoabFormItem label="How would you like to be contacted?" mt="xl">
<GoabCheckboxList
name="contactMethods"
value={checkboxSelection}
onChange={(e) => setCheckboxSelection(e.values || [])}
>
<GoabCheckbox
name="email"
text="Email"
value="email"
reveal={
<GoabFormItem label="Email address">
<GoabInput name="email" onChange={() => {}} value="" />
</GoabFormItem>
}
/>
<GoabCheckbox
name="phone"
text="Phone"
value="phone"
reveal={
<GoabFormItem label="Phone number">
<GoabInput name="phoneNumber" onChange={() => {}} value="" />
</GoabFormItem>
}
/>
<GoabCheckbox
name="text"
text="Text message"
value="text"
reveal={
<GoabFormItem label="Mobile phone number">
<GoabInput name="mobilePhoneNumber" onChange={() => {}} value="" />
</GoabFormItem>
}
/>
</GoabCheckboxList>
</GoabFormItem>Search
const [search, setSearch] = useState("");
const onClick = () => {
console.log("search:", search);
};<form>
<GoabFormItem>
<GoabBlock gap="xs" direction="row">
<GoabInput
type="search"
name="search"
value={search}
onChange={(e) => setSearch(e.value)}
leadingIcon="search"
/>
<GoabButton type="primary" onClick={onClick}>
Search
</GoabButton>
</GoabBlock>
</GoabFormItem>
</form>Show a simple progress indicator on a question page with multiple questions
<GoabLink leadingIcon="arrow-back" size="small" mb="none">
Back
</GoabLink>
<GoabText as="h3" size="body-m" mt="xl" mb="none" color="secondary">Step 1 of 5</GoabText>
<GoabText as="h2" mt="xs" mb="xl">Personal information</GoabText>
<GoabFormItem label="What is your name?">
<GoabInput onChange={() => {}} name="name" ariaLabel="what is your name?" width="50ch" />
</GoabFormItem>
<GoabFormItem label="What is your phone number?" mt="l">
<GoabInput
onChange={() => {}}
name="phone-number"
ariaLabel="what is your phone number?"
leadingContent="+1"
/>
</GoabFormItem>
<GoabFormItem label="What is your home postal code?" mt="l">
<GoabInput
onChange={() => {}}
name="postal-code"
width="14ch"
ariaLabel="what is your home postal code"
/>
</GoabFormItem>
<GoabButton type="submit" mt="2xl">
Save and continue
</GoabButton>Slotted error text in a form item
const [value, setValue] = useState("");
const onChange = (detail: GoabInputOnChangeDetail) => {
setValue(detail.value);
};
const errorMessage = (
<>
<i>This is </i> slotted <b>error text</b>.
</>
);<GoabFormItem label="First name" error={errorMessage}>
<GoabInput onChange={onChange} value={value} name="item" error={true} />
</GoabFormItem>Slotted helper text in a form item
const [value, setValue] = useState("");
const onChange = (detail: GoabInputOnChangeDetail) => {
setValue(detail.value);
};
const helpText = (
<>
<i>This is </i> slotted <b>help text</b>.
</>
);<GoabFormItem label="First name" helpText={helpText}>
<GoabInput onChange={onChange} value={value} name="item" />
</GoabFormItem>Type to create a new filter
const [typedChips, setTypedChips] = useState<string[]>([]);
const [inputValue, setInputValue] = useState("");<GoabFormItem label="Type to create a chip" mb="m">
<GoabInput
name="chipInput"
value={inputValue}
onChange={(e) => setInputValue(e.value.trim())}
onKeyPress={(e) => {
if (e.key === "Enter" && e.value.trim()) {
setTypedChips([...typedChips, e.value.trim()]);
setTimeout(() => setInputValue(""), 0);
} else if (e.key === "Backspace" && !e.value.trim() && typedChips.length > 0) {
setTypedChips(typedChips.slice(0, -1));
}
}}
width="100%"
/>
</GoabFormItem>
<div>
{typedChips.map((chip, index) => (
<GoabFilterChip
key={index}
content={chip}
mb="xs"
mr="xs"
onClick={() => setTypedChips(typedChips.filter((c) => c !== chip))}
/>
))}
</div>States
When you must disable a button or input:
- Provide nearby text explaining what needs to happen first
- Consider showing the element enabled with validation on submit instead
- Use aria-describedby to link the disabled element to explanatory text
Other
The form item automatically associates the label with the input for screen readers, ensuring your form is accessible.
Types
Content
Placeholder text disappears when users start typing, leaving them without context for what the field is asking for.
Always use a visible label above or beside the input field. Placeholder text can provide an example of the expected format, but should never be the only indication of what information is needed.
Sizing
Known input length: Use fixed-width inputs for content with a specific length, such as postal code (7 characters) or year (4 characters).
Unknown input length: If you don’t know how many characters the user will need (like their name), make your text input 100% of the container.
Capture text input from users in forms.
When to use
Use Input when you need users to enter:
- Short text answers (names, email addresses)
- Numbers (phone numbers, quantities)
- Dates and times
- Search queries
When not to use
Don’t use Input when:
- Users need to enter multiple lines of text (use Textarea)
- Users need to select from predefined options (use Dropdown or Radio)
- The input requires complex formatting (consider specialized components)
Types
Input supports multiple HTML input types:
- text - General text entry (default)
- email - Email addresses with validation
- password - Masked password entry
- number - Numeric values with stepper
- date - Date picker
- tel - Phone numbers
- search - Search with clear button
States
- Default - Normal interactive state
- Focused - When the input has keyboard focus
- Error - When validation fails
- Disabled - When input is not available
- Read-only - When showing value without editing