Skip to content
CodeAtlas UI

Inputs

TextField

Styled text input with label, helper text, error state and leading and trailing slots.

<script>
  import { TextField } from "@codeatlasdev/ui";
  let email = $state("");
</script>

<TextField label="Email" type="email" bind:value={email} />

An error replaces the description and is announced to assistive tech. On touch devices the input text stays at 16px or more so iOS Safari does not zoom on focus. Wrapper components such as MaskedField, MoneyInput and PhoneField forward these props to TextField.

Default

Basic text inputs with a label.

Code
svelte
<script lang="ts">
  import { TextField } from '@codeatlasdev/ui';

  let name = $state('');
  let email = $state('');
</script>

<div class="col">
  <TextField label="Full name" placeholder="Jane Smith" bind:value={name} />
  <TextField label="Email" placeholder="[email protected]" type="email" bind:value={email} />
</div>

<style>
  .col {
    display: flex;
    flex-direction: column;
    gap: var(--ca-space-4);
    width: 100%;
    max-width: 400px;
  }
</style>

With icons

leading and trailing snippets. Interactive trailing content, like a reveal button, must be a real button with its own label.

Code
svelte
<script lang="ts">
  import { TextField } from '@codeatlasdev/ui';
  import { Eye, EyeOff, Search } from '@lucide/svelte';

  let reveal = $state(false);
  let password = $state('');
</script>

<div class="col">
  <TextField label="Search" placeholder="Type to search…">
    {#snippet leading()}<Search size={16} stroke-width={2} />{/snippet}
  </TextField>
  <TextField label="Password" type={reveal ? 'text' : 'password'} placeholder="••••••••" bind:value={password}>
    {#snippet trailing()}
      <button type="button" class="reveal" aria-label={reveal ? 'Hide password' : 'Show password'} aria-pressed={reveal} onclick={() => (reveal = !reveal)}>
        {#if reveal}<EyeOff size={16} stroke-width={2} />{:else}<Eye size={16} stroke-width={2} />{/if}
      </button>
    {/snippet}
  </TextField>
</div>

<style>
  .col {
    display: flex;
    flex-direction: column;
    gap: var(--ca-space-4);
    width: 100%;
    max-width: 400px;
  }

  .reveal {
    display: inline-flex;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    cursor: pointer;
  }
</style>

States

Helper text, error, required, read-only, disabled and the small size.

3–20 characters, letters and underscores only.

Code
svelte
<script lang="ts">
  import { TextField } from '@codeatlasdev/ui';

  let wrong = $state('wrong@');
</script>

<div class="col">
  <TextField label="Username" placeholder="john_doe" description="3–20 characters, letters and underscores only." />
  <TextField label="Email" bind:value={wrong} error="Please enter a valid email address." />
  <TextField label="Company" required />
  <TextField label="Read-only field" value="Cannot edit this" readonly />
  <TextField label="Disabled field" value="Cannot edit this" disabled />
  <TextField label="Small" size="sm" placeholder="Compact height" />
</div>

<style>
  .col {
    display: flex;
    flex-direction: column;
    gap: var(--ca-space-4);
    width: 100%;
    max-width: 400px;
  }
</style>

Props

PropTypeDefaultDescription
labelstring–Label text.
placeholderstring''Input placeholder.
valuestring''Bindable input value.
typestring'text'HTML input type.
errorstring–Validation error message. Puts the field in the error state.
descriptionstring–Non-error hint shown below the field.
helperTextstring–Deprecated alias of description.
disabledbooleanfalseDisables the input.
requiredbooleanfalseMarks the field as required.
readonlybooleanfalseMakes the input read-only.
autocompleteHTMLInputAttributes['autocomplete']–Native autocomplete hint.
namestring–Native name, for form submission.
size'sm' | 'md''md'Field height.
leadingSnippet–Icon or element before the input.
trailingSnippet–Icon or element after the input.
classstring–Extra classes on the root.
oninput(value: string) => void–Called on every keystroke with the new value.
onchange(value: string) => void–Called when the value is committed (blur or Enter).
onblur(e: FocusEvent) => void–Called when the input loses focus.