Skip to main content
Form components provide accessible, styled inputs for user interaction.

Input

A text input component with icon and reset functionality.

Usage

import { Input } from "@/components/form/Input";
import { faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons";

function SearchForm() {
  const [query, setQuery] = useState("");
  
  return (
    <Input
      value={query}
      onChange={setQuery}
      icon={faMagnifyingGlass}
      resettable={true}
      inputProps={{
        placeholder: "Search anime...",
        autoComplete: "off"
      }}
    />
  );
}

Props

value
string
required
Current input value
onChange
(value: string) => void
required
Callback when value changes
resettable
boolean
default:"false"
Shows reset button (X) when value is not empty
icon
IconDefinition
FontAwesome icon to display at the start of input
inputProps
ComponentPropsWithRef<'input'>
Additional props passed to the underlying input element

Styling

padding
string
default:"0.5rem 1rem"
Input padding
border-radius
string
default:"2rem"
Rounded corners for pill shape
background-color
string
Uses theme.colors["solid-on-card"]

Focus State

From /src/components/form/Input.tsx:24:
&:focus-within {
  box-shadow: ${theme.shadows.low};
  
  // Dark theme focus ring
  box-shadow: 0 0 0 2px ${theme.colors["text-primary"]};
}

Source

Defined in /src/components/form/Input.tsx:52

TextArea

A multi-line text input with vertical resizing.

Usage

import { TextArea } from "@/components/form/TextArea";

function CommentForm() {
  return (
    <TextArea
      placeholder="Enter your comment..."
      rows={4}
    />
  );
}

Props

TextArea extends the standard HTML textarea element and accepts all standard textarea attributes.

Styling

padding
string
default:"8px 16px"
Internal padding
border-radius
string
default:"8px"
Corner radius
resize
string
default:"vertical"
Only allow vertical resizing
background-color
string
Uses theme.colors["solid-on-card"]
scrollbar-color
string
Custom scrollbar colors: theme.colors["gray-800"] on transparent

Source

Defined in /src/components/form/TextArea.tsx:6

Switch

A toggle switch built with Radix UI Switch primitive.

Usage

import Switch from "@/components/form/Switch";

function Settings() {
  const [enabled, setEnabled] = useState(false);
  
  return (
    <label>
      <Switch 
        isChecked={enabled}
        onCheckedChange={setEnabled}
      />
      <span>Enable notifications</span>
    </label>
  );
}

Props

isChecked
boolean
required
Current checked state
onCheckedChange
(isChecked: boolean) => void
required
Callback when checked state changes
Also accepts all RadixSwitch.SwitchProps.

Styling

width
string
default:"50px"
Switch width
height
string
default:"25px"
Switch height
background-color
string
Uses theme.colors["solid-on-card"] when unchecked

Switch States

From /src/components/form/Switch.tsx:26:
const StyledSwitchThumb = styled(RadixSwitch.Thumb)`
  width: 25px;
  height: 25px;
  background-color: ${theme.colors["text-disabled"]};
  
  &[data-state="checked"] {
    transform: translateX(25px);
    background-color: ${theme.colors["text-primary"]};
  }
`;

Source

Defined in /src/components/form/Switch.tsx:48

Slider

A range slider built with Radix UI Slider primitive.

Usage

import { Slider } from "@/components/slider/Slider";

function VolumeControl() {
  const [volume, setVolume] = useState(0.5);
  
  return (
    <Slider
      value={[volume]}
      onValueChange={([value]) => setVolume(value)}
      min={0}
      max={1}
      step={0.01}
    />
  );
}

Props

value
number[]
Current slider value(s)
onValueChange
(value: number[]) => void
Callback when value changes
min
number
Minimum value
max
number
Maximum value
step
number
Step increment
Also accepts all RadixSlider.SliderProps.

Styling

width
string
default:"100px"
Slider width
height
string
default:"20px"
Touch target height

Example from VolumeControl

From /src/components/video-player/VolumeControl.tsx:47:
<StyledSlider
  value={[volume]}
  onValueChange={([volume]) => { 
    setVolume(volume); 
    setMuted(false); 
  }}
  min={0}
  max={1}
  step={0.01}
/>

Source

Defined in /src/components/slider/Slider.tsx:53

Form Composition

Combining form components:
import { Column } from "@/components/box/Flex";
import { Input } from "@/components/form/Input";
import { TextArea } from "@/components/form/TextArea";
import Switch from "@/components/form/Switch";
import { Button } from "@/components/button/Button";

function PlaylistForm() {
  return (
    <Column style={{ "--gap": "16px" }}>
      <Input
        value={name}
        onChange={setName}
        inputProps={{ placeholder: "Playlist name" }}
      />
      
      <TextArea
        placeholder="Description"
        rows={3}
      />
      
      <label>
        <Switch isChecked={isPublic} onCheckedChange={setIsPublic} />
        Make playlist public
      </label>
      
      <Button variant="primary">Save Playlist</Button>
    </Column>
  );
}

Accessibility

  • All inputs support keyboard navigation
  • Focus states use theme colors
  • Radix UI primitives include ARIA attributes
  • Custom scrollbar styles maintain accessibility

Build docs developers (and LLMs) love