Autocomplete
An input that suggests options as you type - the text itself is the value.
Installation
Included in poetry-ui — available as
poetry_autocomplete
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 autocomplete
Default
<%# The input IS the value: free text submits as-is; suggestions filter
as you type and selecting one writes the input. Constrained pick
(value must be an item) is Combobox territory. %>
<%= poetry_autocomplete(name: "tag", label: "Search tags", placeholder: "e.g. feature",
class: "w-64") do |auto| %>
<% auto.with_item(label: "feature") %>
<% auto.with_item(label: "fix") %>
<% auto.with_item(label: "docs") %>
<% auto.with_item(label: "refactor") %>
<% auto.with_item(label: "internal") %>
<% end %>
Value override
<%# value: commits canonical text that differs from the shown label -
the label is what filtering matches. %>
<%= poetry_autocomplete(name: "city", label: "City", placeholder: "Where to?",
empty_text: "No matching city.", class: "w-64") do |auto| %>
<% auto.with_item(label: "São Paulo (GRU)", value: "GRU") %>
<% auto.with_item(label: "New York (JFK)", value: "JFK") %>
<% auto.with_item(label: "Tokyo (HND)", value: "HND") %>
<% end %>
API
Poetry::Ui::Autocomplete::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 |
|---|---|---|---|
| empty_text: | String | defaults to "No results." |
The no-matches message; hidden while anything matches. |
| id: | String | Stable DOM id token for the root and list ids. | |
| label: | String | The accessible name (or wire aria-labelledby via html attrs). | |
| name: | String | required | The form param key; the input's text submits under it as-is. |
| open: | Boolean | defaults to false |
Server-renders the suggestion popup open. |
| open_on_focus: | Boolean | defaults to true |
Opens the suggestions on focus; false waits for typing. |
| placeholder: | String | Placeholder text shown while the input is empty. | |
| value: | String | The initial input text. |
Methods
| Method | Description |
|---|---|
| #with_item(label:, value: nil, disabled: false, highlighted: false) | Adds one suggestion to the popup list. |
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=autocomplete] | Root wrapper carrying the controller + popper pair |
| [data-slot=autocomplete-input] | The REAL text input - role=combobox with aria-expanded tracking the popup, the form value itself |
| [data-slot=autocomplete-content] | The popper-positioned popup shell |
| [data-slot=autocomplete-list] | role=listbox holding the options |
| [data-slot=autocomplete-item] | One suggestion - role=option; commit writes its label (or value:) into the input |
| [data-slot=autocomplete-empty] | The no-matches message (hidden while anything matches) |
State attributes
| Part | Attribute | Condition | Values |
|---|---|---|---|
| autocomplete-content | data-open | popup visible | — |
| autocomplete-content | data-closed | popup hidden (the server-rendered default) | — |
| autocomplete-content | data-empty | no item matches the query - the empty state shows | — |
| autocomplete-item | data-label | always - what filtering matches and commit writes | — |
| autocomplete-item | data-value | value: given - overrides the committed text | — |
| autocomplete-item | data-highlighted | the keyboard/pointer highlight | — |
| autocomplete-item | data-disabled | disabled: - skipped by filtering and commit | — |
Wiring
The Stimulus surface each element carries — declared in the component, verified against rendered DOM in CI. Bare actions fire on the element's default event.
| Element | Controller | Wiring |
|---|---|---|
| root | poetry--core--autocomplete | registers · value open_on_focus (if) |
| root | poetry--core--popper | registers |
| input | poetry--core--autocomplete | input on input · focus on focus · blurred on focusout · keydown on keydown · target input |
| input | poetry--core--popper | target anchor |
| content | poetry--core--autocomplete | target content |
| content | poetry--core--popper | target content |
| list | poetry--core--autocomplete | target list |
| empty | poetry--core--autocomplete | target empty |
| item | poetry--core--autocomplete | itemPress on pointerdown · itemEnter on pointerenter |