Skip to main content

Text Field

Text Field is a form control for entering a single line of text, like naming a project or typing an email address. It pairs the input with a label and can show icons, prefixes, helper text, and error messages.

Import

import { TextField } from '@vortexlabs/vortex';
import type { TextFieldProps } from '@vortexlabs/vortex';

Allied components

Other links

Visible to everyone in your workspace.
<Stack
  width="440px"
  maxWidth="100%"
>
  <TextField.Root
    size="sm"
    variant="outline"
  >
    <TextField.Label>Project name</TextField.Label>
  <TextField.Input name="playground-project" placeholder="Website redesign" />
  <TextField.HelperText>Visible to everyone in your workspace.</TextField.HelperText>
  <TextField.ErrorMessage>Enter a project name.</TextField.ErrorMessage>
  </TextField.Root>
</Stack>

Features

  • Supports outline and fill variants with responsive sizes.
  • Supports start and end icons, affixes, and custom slots.
  • Shows helper text and error messages under the input.
  • Accepts native input types like email and password.
  • Supports controlled and uncontrolled values.

Anatomy

Root links the label, helper text, and error to the input, Label names it, and Input is the field and requires name. HelperText is optional.

<TextField.Root>
  <TextField.Label>Email address</TextField.Label>
  <TextField.Input name="email" />
  <TextField.HelperText>We will use this address for project updates.</TextField.HelperText>
</TextField.Root>

Variants

Text Field has two visual styles: outline and fill. The default is outline.

<TextField.Root variant="outline">
  <TextField.Label>Outline</TextField.Label>
  <TextField.Input name="outline-name" placeholder="Project name" />
</TextField.Root>
<TextField.Root variant="fill">
  <TextField.Label>Fill</TextField.Label>
  <TextField.Input name="fill-name" placeholder="Project name" />
</TextField.Root>

Sizes

Root size scales the input, label, and icons. The default is sm.

<TextField.Root size="sm">
  <TextField.Label>Small</TextField.Label>
  <TextField.Input name="small-name" defaultValue="Website redesign" />
</TextField.Root>
<TextField.Root size="md">
  <TextField.Label>Medium</TextField.Label>
  <TextField.Input name="medium-name" defaultValue="Website redesign" />
</TextField.Root>

Responsive

size also accepts a breakpoint object.

<TextField.Root size={{ xs: "sm", md: "md" }}>
  <TextField.Label>Project name</TextField.Label>
  <TextField.Input name="responsive-name" defaultValue="Website redesign" />
</TextField.Root>

Icons and Affixes

startIcon and endIcon add an icon that focuses the input on click. prefix and suffix add text tied to the value, like a currency. An icon and affix can share a side.

$
AUD
import { Search } from "@vortexlabs/vortex-icons";

<TextField.Root>
  <TextField.Label>Search projects</TextField.Label>
  <TextField.Input name="project-search" startIcon={<Search />} placeholder="Search by name" attributes={{ type: "search" }} />
</TextField.Root>
<TextField.Root>
  <TextField.Label>Budget</TextField.Label>
  <TextField.Input name="budget" prefix="$" suffix="AUD" defaultValue="1200" attributes={{ inputMode: "decimal" }} />
</TextField.Root>

Custom Slots

startSlot and endSlot hold other content, like an action. A slot replaces the icon and affix on its side. This example also controls the value with value and onChange.

16 characters
"use client";

import { Button, TextField } from "@vortexlabs/vortex";
import { useState } from "react";

export const TextFieldClearExample = () => {
  const [value, setValue] = useState("Website redesign");
  return (
    <TextField.Root>
      <TextField.Label>Project name</TextField.Label>
      <TextField.Input
        name="project-name"
        value={value}
        onChange={({ value }) => setValue(value)}
        endSlot={
          <Button size="xs" variant="tertiary" disabled={!value} onClick={() => setValue("")}>
            Clear
          </Button>
        }
      />
      <TextField.HelperText>{value.length} characters</TextField.HelperText>
    </TextField.Root>
  );
};

Multiline

Root multiline lets slot content wrap onto several lines, like a list of tags.

Design

Research

Marketing

Engineering

Support

import { Badge, TextField } from "@vortexlabs/vortex";

<TextField.Root multiline width="320px">
  <TextField.Label>Tags</TextField.Label>
  <TextField.Input
    name="tags"
    placeholder="Add a tag"
    startSlot={["Design", "Research", "Marketing", "Engineering", "Support"].map((tag) => (
      <Badge size="sm" key={tag}>{tag}</Badge>
    ))}
  />
</TextField.Root>

Validation

Root error marks the input invalid and shows TextField.ErrorMessage; helper text stays visible. required only adds native validation, so you decide when to set error.

Use at least three characters.This name is visible to everyone in your workspace.
<TextField.Root error required>
  <TextField.Label>Workspace name</TextField.Label>
  <TextField.Input name="workspace-name" defaultValue="a" attributes={{ minLength: 3 }} />
  <TextField.ErrorMessage>Use at least three characters.</TextField.ErrorMessage>
  <TextField.HelperText>This name is visible to everyone in your workspace.</TextField.HelperText>
</TextField.Root>

Disabled and Read Only

Root disabled blocks editing and focus. readOnly in Input attributes keeps the value focusable and selectable.

<TextField.Root disabled>
  <TextField.Label>Workspace slug</TextField.Label>
  <TextField.Input name="disabled-slug" defaultValue="design-team" />
</TextField.Root>
<TextField.Root>
  <TextField.Label>Workspace ID</TextField.Label>
  <TextField.Input name="workspace-id" defaultValue="ws_12345" attributes={{ readOnly: true }} />
</TextField.Root>

Native Attributes and Width

Input attributes sets native options like type, autoComplete, and minLength; type defaults to text. Root width accepts a CSS length or a breakpoint object.

Use at least eight characters.
<TextField.Root width={{ xs: "100%", md: "24rem" }}>
  <TextField.Label>Password</TextField.Label>
  <TextField.Input name="password" attributes={{ type: "password", autoComplete: "new-password", minLength: 8 }} />
  <TextField.HelperText>Use at least eight characters.</TextField.HelperText>
</TextField.Root>

Accessibility

Key
Description
Tab
Move focus to the input. Disabled fields are skipped.
Include TextField.Label; a placeholder doesn't replace it. Helper text and the error message are linked to the input automatically.