Input
An input takes one line of text, such as a name, an email, or a URL. It is a bare box; wrap it in a
<tk-field label="Email address" helper="We only use this for the receipt"> <tk-input type="email" name="email" autocomplete="email"></tk-input> </tk-field>
Anatomy
| Part | What it is |
|---|---|
tk-input |
the element; one Tab stop |
field part |
the bordered box |
input part |
the native <input> inside |
prefix slot |
optional text or icon before the value |
suffix slot |
optional text or icon after the value |
The label, help text, and error message come from a
Sizes
<tk-input aria-label="Medium input" value="Medium"></tk-input> <tk-input aria-label="Large input" size="large" value="Large"></tk-input>
size |
Height | Padding-inline | Value text |
|---|---|---|---|
medium (default) |
32px | space-8 |
Body Small (14/20) |
large |
36px | space-10 |
Body Medium (16/24) |
- The heights match
mediumandlargebuttons, so a field and its button line up. - There is no
small.size="small"renders asmediumand logs a console warning. - The input fills its container's width. Size the container to the expected answer: a postcode field is postcode-sized.
States
<tk-input aria-label="Workspace URL" value="acme.thykes.com" readonly></tk-input> <tk-input aria-label="Company" value="Acme Inc." disabled></tk-input>
<tk-field label="Email address" required error="Enter an email address, like name@example.com"> <tk-input type="email" name="email" value="ada@"></tk-input> </tk-field>
The box doesn't change on hover. On focus, its border takes the focus color and grows thicker inward, so nothing moves.
readonly: people can focus the input and select or copy its value, but not edit it. It looks like content. Use it for values people may need to read or copy.disabled: the input can't be focused or edited, and it's left out of the form. Preferreadonly, or keep the field active. If a field can't change, say why in the help text.- Error: set
erroron the Field. The message shows under the box, the border turns red, and it stays red while the field has focus. - Required: set
requiredon the Field. It marks the label with an asterisk and makes the input required. Without a Field, setrequiredon the input.
The input doesn't check what people type, apart from the browser's own checks (required,
the type format, maxlength). You decide when to validate and what the error says.
Label, help text, and errors
<tk-field label="Card number" helper="The 16 digits on the front of your card"> <tk-input inputmode="numeric" name="card" autocomplete="cc-number"></tk-input> </tk-field>
<tk-input aria-label="Filter by name"></tk-input>
- Wrap the input in a
Field for a label, help text, or an error. The Field names the input for screen readers. - Inside a Field, set
requiredanddisabledon the Field. The Field overrides them on the input. - Without a visible label, set
aria-label(oraria-labelledby) on the input. Use it only when the purpose is clear from what's around the field. - Every input needs one or the other. A placeholder is never a label.
Prefix and suffix
<tk-field label="Username"> <tk-input name="username"><span slot="prefix">@</span></tk-input> </tk-field> <tk-field label="Workspace address"> <tk-input name="workspace"><span slot="suffix">.thykes.com</span></tk-input> </tk-field>
<tk-field label="Website"> <tk-input type="url" name="website"><tk-icon slot="prefix" name="link"></tk-icon></tk-input> </tk-field>
- Use
prefixfor the kind of value (@, $, an icon) andsuffixfor a unit or domain (USD, .example.com). One short text or one each.tk-icon - Affixes are hidden from screen readers. Don't put information there that the label or help text doesn't also give.
- Affixes are decoration. Don't put buttons in them; there is no clear button, character counter, or show-password toggle.
When to use
- Use an input for free single-line text. It works in native forms: its value submits with the form, and Enter submits the form.
- Use a
Textarea for more than one line. - Use a
Select orCombobox to choose from options. - Use a
Number input for amounts and other numbers, and aSearch field for search.
Content
- Label: name what you're asking for. Short, sentence case, no colon. Put anything essential in the label, not the help text.
- Help text: one short line, such as a format or where to find the value. No links.
- Error: say what happened and how to fix it, in the label's words. For an empty field, give an instruction ("Enter your email address"). For a broken rule, describe it ("Name must be 35 characters or less"). No "please", "sorry", "invalid", or "an error occurred".
- Placeholder: avoid it. It disappears when people type and is too faint to read comfortably. If you use one, keep it short, with no end punctuation, and never essential.
- Required fields: if a form marks them with asterisks, add one line near the top: "* indicates a required field". Better still, ask only what you need.
More in
Do / Don't
| ✅ Do | ❌ Don't |
|---|---|
| Wrap the input in a Field with a label | Leave a bare input with no name |
| Put essential instructions in the label | Put them in the placeholder |
Set required on the Field |
Set required on an input inside a Field |
Use inputmode="numeric" for digits, such as a card number |
Use type="number"; the scroll wheel changes it by accident |
Use readonly for values people can copy |
Use disabled by default |
| Size the field to the expected answer | Stretch a postcode field across the page |
| Write "Enter your email address" | Write "Invalid input" |
Related
Field : the label, help text, and error around an input.Textarea : text entry over several lines.Number input andSearch field : inputs for numbers and search.Button : the submit button beside a field; the heights match.
API
Attributes
| Attribute | Type | Default | What it does |
|---|---|---|---|
value |
string | '' |
the value; submits under name |
type |
text | email | password | tel | url | search |
text |
the native type; there is no number, use inputmode |
name |
string | — | the form field name |
placeholder |
string | — | hint text shown while empty; avoid it |
inputmode |
string | — | the on-screen keyboard, such as numeric or decimal |
autocomplete |
string | — | the autofill purpose, such as email; set it on personal data |
maxlength |
number | — | the most characters allowed; no visible counter |
required |
boolean | false |
the browser blocks submitting while empty; no visible mark |
readonly |
boolean | false |
focusable and copyable, not editable |
disabled |
boolean | false |
not focusable, not editable, left out of the form |
size |
medium | large |
medium |
height 32 / 36px |
Slots
| Slot | Content |
|---|---|
prefix |
text or one tk-icon before the value |
suffix |
text or one tk-icon after the value |
Events
No custom events. Listen for input on every keystroke and change when the value is
committed; read the value property. Resetting the form restores the first value without
firing change.
Methods
focus(): moves focus into the field.
CSS
::part(field): the bordered box.::part(input): the native<input>.
Tokens
| Role | Rest | Focus | Error | Disabled | Read-only |
|---|---|---|---|---|---|
| border | border/subtle |
border/accent/focus |
border/error |
border/disabled |
border/subtle |
| background | surface/default |
surface/default |
surface/default |
surface/disabled |
surface/subtle |
| value text | text/default |
text/default |
text/default |
text/disabled |
text/default |
On focus, the border grows inward by focus/border-inset, in the focus color or, on an
error, in border/error. Placeholder text is text/placeholder; affixes are
text/secondary. Corners are radius-8. The label, help text, and error tokens belong to
the
Accessibility
Built in:
- A native
<input>: Tab reaches it, and autofill, text selection, and the browser's own validation work. - A focus border that is never hidden.
- A composing Field names the input, links the help text and error to it, and marks it invalid on error.
- Affixes are hidden from screen readers.
Your part:
- Give every input a name: a Field label, or
aria-label. - Set
autocompleteon personal data, such as name, email, and address. - Don't put instructions in the placeholder.
- Errors are read when the field gets focus, not as they appear. If you validate the whole form on submit, show a summary at the top, move focus to it, and link each message to its field.
| Key | Action |
|---|---|
Tab |
moves focus to the input; skips it when disabled |
Enter |
submits the form the input is in |
Contrast limits
- Resting border: 1.33:1 in light and 2.00:1 in dark, under the 3:1 minimum; 4.22:1 in high contrast. Give every field a visible label so the border isn't the only cue. Focus and error borders are at least 3:1 in every theme.
- Placeholder: 3.26:1 in light, under 4.5:1 in every theme.
- Disabled text: 2.54:1 in light. Use
readonlyfor values people need to read.