FormElement
Lightweight wrapper that places an icon addon to the left of a form input, styled with the --cratis-* token layer. Use it to give input fields a leading icon without pulling in PrimeReact's InputGroup chrome.
Purpose
FormElement is a structural primitive — it lays out an icon addon and a child input side by side, with rounded-on-the-left chrome around the addon. It does not render labels, required indicators, or validation messages — those concerns live on the underlying input itself or on the surrounding command form.
Key Features
- Icon addon styled from
--cratis-*tokens (background, border, radius). - Independent of PrimeReact's
p-inputgroup/p-inputgroup-addonclasses — works the same with or without a PrimeReact theme loaded. - Accepts any React node as the icon (PrimeIcons class,
<svg>, third-party icon component, …).
Props
| Prop | Type | Description |
|---|---|---|
icon |
React.ReactNode |
Icon node displayed inside the leading addon. Can be any React node — a PrimeIcons <i className="pi pi-…" />, an <svg>, or a react-icons component. |
children |
React.ReactNode |
The form input rendered to the right of the icon addon (typically an InputText, Dropdown, etc.). |
Basic Usage
import { FormElement } from '@cratis/components';
import { InputText } from 'primereact/inputtext';
function MyForm() {
return (
<FormElement icon={<i className="pi pi-user" />}>
<InputText value={name} onChange={(e) => setName(e.target.value)} />
</FormElement>
);
}
Examples
Email field with envelope icon
<FormElement icon={<i className="pi pi-envelope" />}>
<InputText
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="you@example.com"
/>
</FormElement>
Search field with react-icons
import { FaMagnifyingGlass } from 'react-icons/fa6';
<FormElement icon={<FaMagnifyingGlass />}>
<InputText
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search…"
/>
</FormElement>
Dropdown with category icon
import { FaLayerGroup } from 'react-icons/fa6';
<FormElement icon={<FaLayerGroup />}>
<Dropdown
value={category}
options={categories}
onChange={(e) => setCategory(e.value)}
optionLabel="name"
optionValue="id"
/>
</FormElement>
Styling
The addon's background, border, and radius are driven by the --cratis-* token layer:
| Token | Surface |
|---|---|
--cratis-surface-100 |
Addon background. |
--cratis-surface-border |
Addon border. |
--cratis-text-color-secondary |
Icon color. |
--cratis-border-radius |
Rounded-on-the-left corner radius. |
Override the tokens to retint the addon without forking the component:
:root {
--cratis-surface-100: #1e293b;
--cratis-surface-border: #334155;
--cratis-border-radius: 10px;
}
For per-instance restyling, wrap the FormElement with your own class and target it in CSS:
.brand-form-element .cratis-form-element__addon {
background: var(--brand-accent);
color: var(--brand-on-accent);
}
<div className="brand-form-element">
<FormElement icon={<i className="pi pi-shield" />}>
<InputText … />
</FormElement>
</div>
For full styling control under unstyled mode, the addon classes are stable: cratis-form-element on the row and cratis-form-element__addon on the leading slot.
When to use FormElement vs CommandForm fields
- Use
FormElementfor ad-hoc forms outside of aCommandForm, when you want the icon-addon visual on top of any input you control. - Use CommandForm fields (
InputTextField,NumberField,DropdownField, …) inside aCommandFormorCommandDialog— they bind to a command property, surface validation state, and render the appropriate input type.
See Also
- Styling Overview — the supported styling options and where FormElement fits
- Cratis token reference — every token and the surfaces it tints
- CommandForm Field Types — command-bound field wrappers