Label
An accessible caption bound to a form control.
Installation
Included in poetry-ui — available as
poetry_label
the moment you've installed Poetry,
with no per-component step. To own the source and edit it, copy it into your app:
bin/rails g poetry:add label
Default
<%# Every control gets a Label wired via for_id - placeholder text is
never the label. %>
<div class="grid w-80 gap-2">
<%= poetry_label(for_id: "label-full-name") { "Full name" } %>
<%= poetry_input(name: "full_name", id: "label-full-name") %>
</div>
Disabled
<%# The label carries peer-disabled: styles - when the control before it
is disabled, the label dims and gets a not-allowed cursor for free. %>
<div class="flex items-center gap-3">
<%= poetry_checkbox(name: "notifications", disabled: true, id: "label-disabled") %>
<%= poetry_label(for_id: "label-disabled") { "Enable notifications" } %>
</div>
Form
<%# Several labels across one form - each control gets its own Label wired
by for_id, whatever the control type (text, email, multiline). %>
<form class="grid w-80 gap-4">
<div class="grid gap-2">
<%= poetry_label(for_id: "label-form-name") { "Name" } %>
<%= poetry_input(name: "name", id: "label-form-name", placeholder: "Jane Doe") %>
</div>
<div class="grid gap-2">
<%= poetry_label(for_id: "label-form-email") { "Email" } %>
<%= poetry_input(name: "email", id: "label-form-email", type: "email", placeholder: "jane@example.com") %>
</div>
<div class="grid gap-2">
<%= poetry_label(for_id: "label-form-message") { "Message" } %>
<%= poetry_textarea(name: "message", id: "label-form-message", rows: 3, placeholder: "How can we help?") %>
</div>
</form>
With checkbox
<%# Inline pair: clicking the label toggles the checkbox via for_id. %>
<div class="flex items-center gap-3">
<%= poetry_checkbox(name: "terms", id: "label-terms") %>
<%= poetry_label(for_id: "label-terms") { "Accept terms and conditions" } %>
</div>
With description
This is the public address teammates use to reach your workspace.
<%# A field grouping: the label names the control via for_id, and a muted
line of help text sits beneath it. The description is caption text, not
a second label - only the Label carries for_id. %>
<div class="grid w-80 gap-2">
<%= poetry_label(for_id: "label-workspace-url") { "Workspace URL" } %>
<%= poetry_input(name: "workspace_url", id: "label-workspace-url", placeholder: "acme") %>
<p class="text-sm text-muted-foreground">
This is the public address teammates use to reach your workspace.
</p>
</div>
API
Poetry::Ui::Label::Component — options are
constructor keywords (the poetry_* helper forwards them);
slots are composed inside the block. Generated from the gem's source documentation.
| Option | Type | Details | Description |
|---|---|---|---|
| for_id: | String | The id of the control this label names; omit it for a group label (the group then points at this label via aria-labelledby). |
Styling
Every part carries a stable data-slot attribute — target
[data-slot=…] from your own CSS to restyle it. State rides
data attributes on the parts below. This contract is verified against rendered DOM in CI.
| Part | Description |
|---|---|
| [data-slot=label] | The <label> element itself - for= rides it (dropped in group mode, where the group names itself via aria-labelledby at this label's id) |