Skip to main content
Urbicon UI

Input

A single-line text field.

Playground

We will never share your email
Intent Style variant
Tier Style variant
<Input
  error=""
  helper="We will never share your email"
  label="Email"
  placeholder="name@example.com"
/>

01 Examples

Search input

Pair clearable with a left search icon. Press Escape or click the clear button to reset.
<Input
  clearable
  bind:value={searchValue}
  placeholder="Search anything..."
  aria-label="Search"
>
  {#snippet leftIcon()}
    <SearchIcon />
  {/snippet}
</Input>

Password with visibility toggle

Giving an icon a click handler turns it into a real button, which then needs its own rightIconAriaLabel or leftIconAriaLabel for a name. A right icon and clearable share the same corner: while the field holds a value, the clear control takes it.
<Input
  type={passwordVisible ? 'text' : 'password'}
  label="Password"
  placeholder="Enter your password"
  bind:value={passwordValue}
  onRightIconClick={() => (passwordVisible = !passwordVisible)}
  rightIconAriaLabel={passwordVisible ? 'Hide password' : 'Show password'}
>
  {#snippet leftIcon()}
    <LockIcon />
  {/snippet}
  {#snippet rightIcon()}
    {#if passwordVisible}
      <EyeOffIcon />
    {:else}
      <EyeIcon />
    {/if}
  {/snippet}
</Input>

Validated in a form

type and required sit on a real input, so the browser checks the address shape and the empty case before the handler runs, while name is what puts the value into the FormData. error covers what only your code knows, an answer from the server for instance, and it overrides helper and any intent for as long as it is set.
We send one confirmation mail and nothing else
<form class="flex flex-col gap-4" onsubmit={handleSignup}>
  <Input
    type="email"
    name="email"
    label="Email"
    placeholder="name@example.com"
    value="ada@example.com"
    error={emailError}
    helper="We send one confirmation mail and nothing else"
    required
  >
    {#snippet leftIcon()}
      <MailIcon />
    {/snippet}
  </Input>
  <Button type="submit" size="sm" class="self-start">Sign up</Button>
  {#if signedUp}
    <p class="text-success text-xs">Address accepted.</p>
  {/if}
</form>

02 Customization

Prominent search bar

The frame belongs to the container slot and the text field to base, so a treatment on the outside goes on the first while the second gives up its own border and ring.
<Input
  tier="commit"
  size="lg"
  clearable
  bind:value={brandedSearch}
  placeholder="Search components, patterns, tokens..."
  aria-label="Search"
  slotClasses={{
    container:
      'shadow-[var(--blocks-shadow-lg)] ring-2 ring-primary/25 focus-within:ring-primary/50 transition-shadow overflow-hidden',
    base: 'border-transparent bg-transparent focus-visible:ring-0'
  }}
>
  {#snippet leftIcon()}
    <SearchIcon />
  {/snippet}
</Input>

A field that reads as the text around it

The bare variant drops the frame, the fill, the padding and the fixed height — size keeps only the type step. It needs context that says it is a field: a placeholder, a rule under the line, a label before it. The one thing it does not drop is the focus indicator: an outline whose colour is --blocks-focus-ring-color, so a product where the accent means something else sets the focus colour once instead of per call site.
Remind me to
<div
  class="text-text-primary border-border-subtle flex items-baseline gap-1 border-b pb-1 text-base"
>
  <span>Remind me to</span>
  <Input
    variant="bare"
    bind:value={bareValue}
    placeholder="write the release note"
    aria-label="Reminder"
    class="flex-1"
  />
</div>

A form where everything is required

The required asterisk is a requiredMark slot, so hiding it once covers the whole app — the GOV.UK convention of marking nothing when every field is required. Use overrides instead of slotClasses when only the required state should change.
<BlocksProvider
  defaults={{
    Input: { slotClasses: { requiredMark: 'hidden' } },
    Select: { overrides: [{ required: true, class: { requiredMark: 'hidden' } }] }
  }}
>
  <SignupForm />
</BlocksProvider>

A treatment every field should share belongs on a BlocksProvider instead, as a defaults entry for Input and the same one for Select and Textarea. See Customization for that and for class, slotClasses, unstyled and preset.

03 Accessibility

Labels and messages

The label links to the field via for/id. helper and error text is announced through aria-describedby, and an error also sets aria-invalid on the input.

Keyboard

Tab focuses the field. On a clearable field that holds a value, Escape clears it and puts focus back in the input, which is also the one case where a field inside a dialog keeps that Escape to itself. An icon with a click handler is a real <button> with its own Tab stop, before the field on the left and after it on the right, and the clear control is another one.

Colour is not the only signal

An intent tints the field's frame and nothing else, so a state carried by it wants helper text saying the same thing in words. An error arrives with its message already attached.

04 API Reference

35 props
35 props
Prop
Type
Default
Description

05 Types

Local type definitions used by this component.

7 types
Name
Kind
Category
Used by
Description

06 Installation

Import

import { Input } from '@urbicon-ui/blocks';