Reference

# Escape hatches

When field's one-call convenience isn't enough: bare components, wrapped inputs, and the custom-widget recipe.

## The component API

Every control `field` composes is also callable directly, with stable signatures — a bare input, no label/control wrapper, still fully model-bound:

```ruby
f.Input(:name, :primary, :lg)     # bare input, variants stacked
f.Select(:role, choices: roles)   # native <select>
f.Textarea(:bio, :ghost)
f.Checkbox(:terms)
f.Toggle(:notify)
f.Radio(:size, "large")
f.FileInput(:avatar)
f.Hidden(:token)
f.Label(:email)
f.Control(:email, label: "Email") { f.Input(:email) }
```

PascalCase marks the component layer; lowercase `field`/`row`/`group`/ `submit` are the composed verbs. Both apply the model's value, error state, and client-validation data the same way.

## The custom-widget recipe

A bespoke widget — date picker, tag field, remote select — wraps in `Control` and binds through the three public helpers. This is the supported path, not a fork reason:

```ruby
f.Control(:starts_at, label: "Starts") do
  render MyDatePicker.new(
    name: f.field_name(:starts_at),
    id: f.field_id(:starts_at),
    value: f.field_value(:starts_at)
  )
end
```

The control contributes the label, error/hint slot, and layout; your widget owns the input. Errors on the attribute render exactly like any other field's.

## Icons inside the field

`wrapped_input` renders the daisyUI v5 `<label class="input">` pattern — leading content (an icon, a prefix), the bare input, optional trailing content:

```ruby
f.field_object(:search).wrapped_input(:primary) do
  LucideIcon("search", class: "opacity-50")
end
```

Icons default to a bundled inline SVG so the gem is self-contained; see [Configuration](https://phlex-forms.zoolutions.llc/docs/configuration) for the glyphs renderer.

## Specialised controls

- `f.Select(:tags, choices:, searchable: true, multiple: true)` — a choices.js-backed searchable/multi select (needs the `choices.js` peer).
- `f.rich_textarea(:body)` — the rich-text editor binding (ActionText-compatible value handling).
- `f.time_zone_select(:time_zone)` — grouped time zones with a sensible selected default.