> ## Documentation Index
> Fetch the complete documentation index at: https://docs.1up.vision/llms.txt
> Use this file to discover all available pages before exploring further.

# Input Components

> Button, TextField, TextArea, NumberField, Toggle, and Dropdown — interactive controls for your extension.

Input components are **interactive** in the editor and control panel. On the **OBS layer**, they render as static display-only text showing their current value (since viewers can't interact with the overlay).

***

## Button

A clickable button with variant styling.

```tsx theme={null}
<Button label="Save" onClick={() => handleSave()} />
<Button label="Reset Score" variant="destructive" onClick={() => setStorage({ ...storage, score: 0 })} />
<Button label="Secondary Action" variant="secondary" onClick={() => {}} />
<Button label="Outline Style" variant="outline" onClick={() => {}} />
```

<ParamField path="label" type="string" required>
  Button text.
</ParamField>

<ParamField path="variant" type="'default' | 'secondary' | 'outline' | 'destructive'" default="default" optional>
  Visual style. Use `"destructive"` for dangerous actions like resets or
  deletes.
</ParamField>

<ParamField path="disabled" type="boolean" default="false" optional>
  Disable the button.
</ParamField>

<ParamField path="onClick" type="() => void" optional>
  Click handler.
</ParamField>

<Warning>
  Buttons don't render at all on the OBS layer — there's no one to click them.
</Warning>

***

## TextField

Single-line text input with an optional label.

```tsx theme={null}
<TextField
  label="Display Name"
  placeholder="Enter a name..."
  value={storage.name ?? ""}
  onChange={(value) => setStorage({ ...storage, name: value })}
/>
```

<ParamField path="label" type="string" optional>
  Label above the input.
</ParamField>

<ParamField path="placeholder" type="string" optional>
  Placeholder text.
</ParamField>

<ParamField path="value" type="string" optional>
  Current value.
</ParamField>

<ParamField path="onChange" type="(value: string) => void" optional>
  Called when the value changes.
</ParamField>

<ParamField path="disabled" type="boolean" default="false" optional>
  Disable editing.
</ParamField>

***

## TextArea

Multi-line text input. Use for longer content like descriptions or messages.

```tsx theme={null}
<TextArea
  label="Description"
  placeholder="Write something..."
  value={storage.description ?? ""}
  rows={4}
  onChange={(value) => setStorage({ ...storage, description: value })}
/>
```

<ParamField path="label" type="string" optional>
  Label above the textarea.
</ParamField>

<ParamField path="placeholder" type="string" optional>
  Placeholder text.
</ParamField>

<ParamField path="value" type="string" optional>
  Current value.
</ParamField>

<ParamField path="onChange" type="(value: string) => void" optional>
  Called when the value changes.
</ParamField>

<ParamField path="rows" type="number" default="3" optional>
  Number of visible rows.
</ParamField>

<ParamField path="disabled" type="boolean" default="false" optional>
  Disable editing.
</ParamField>

***

## NumberField

Numeric input with optional min, max, and step constraints.

```tsx theme={null}
<NumberField
  label="Font Size"
  value={storage.fontSize ?? 16}
  min={8}
  max={72}
  step={1}
  onChange={(value) => setStorage({ ...storage, fontSize: value })}
/>
```

<ParamField path="label" type="string" optional>
  Label above the input.
</ParamField>

<ParamField path="value" type="number" optional>
  Current value.
</ParamField>

<ParamField path="min" type="number" optional>
  Minimum value.
</ParamField>

<ParamField path="max" type="number" optional>
  Maximum value.
</ParamField>

<ParamField path="step" type="number" optional>
  Step increment.
</ParamField>

<ParamField path="onChange" type="(value: number) => void" optional>
  Called when the value changes.
</ParamField>

<ParamField path="disabled" type="boolean" default="false" optional>
  Disable editing.
</ParamField>

***

## Toggle

On/off switch with an optional label.

```tsx theme={null}
<Toggle
  label="Show on stream"
  checked={storage.visible ?? false}
  onChange={(checked) => setStorage({ ...storage, visible: checked })}
/>
```

<ParamField path="label" type="string" optional>
  Label next to the switch.
</ParamField>

<ParamField path="checked" type="boolean" default="false" optional>
  Whether the toggle is on.
</ParamField>

<ParamField path="onChange" type="(checked: boolean) => void" optional>
  Called when toggled.
</ParamField>

<ParamField path="disabled" type="boolean" default="false" optional>
  Disable interaction.
</ParamField>

***

## Dropdown

Select from a list of predefined options.

```tsx theme={null}
<Dropdown
  label="Position"
  value={storage.position ?? "top-left"}
  options={[
    { label: "Top Left", value: "top-left" },
    { label: "Top Right", value: "top-right" },
    { label: "Bottom Left", value: "bottom-left" },
    { label: "Bottom Right", value: "bottom-right" },
  ]}
  onChange={(value) => setStorage({ ...storage, position: value })}
/>
```

<ParamField path="label" type="string" optional>
  Label above the select.
</ParamField>

<ParamField path="value" type="string" optional>
  Currently selected value.
</ParamField>

<ParamField path="options" type="Array<{ label: string; value: string }>" required>
  Available options.
</ParamField>

<ParamField path="onChange" type="(value: string) => void" optional>
  Called when selection changes.
</ParamField>

<ParamField path="disabled" type="boolean" default="false" optional>
  Disable selection.
</ParamField>
