x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<form id="some_form_id" data-turbo-frame="example-frame" action="#" accept-charset="UTF-8" method="get"> <div id="looposui-inputs-select_user_id_5793709857" class="grow" data-controller="input-select" data-input-select-input-outlet="#looposui-inputs-select_user_id_5793709857 .lui-inner-input" data-input-select-mode-value="autosubmit" data-input-select-form-value="some_form_id" data-input-select-variant-value="list"> <div class="lui-input-select lui-input-select--autosubmit relative lui-inputs__select lui-input-select--list"> <div data-controller="input" data-input-open-actions-value="true" class="lui-inner-input relative flex gap-2" data-input-original-input-value="user 1" data-input-mode-value="autosubmit" data-input-form-value="some_form_id"> <div class="w-full flex flex-col"> <div class="lui-input-chrome relative w-full"> <span class="lui-input "> <input name="user_id" type="text" value="user 1" placeholder="Selecione um user" class="lui-input__input" mode="autosubmit" form="some_form_id" contentEditable="true" data-input-target="input" data-action="input->input#onChange change->input#onChange" data-input-select-target="textInput" readonly="readonly"> <span class="lui-input__addon-right"> <span class="flex flex-row items-center gap-2"> <i class=" fa-solid fa-xmark cursor-pointer text-gray-400 lui-input-select__clear " data-input-select-target="clearButton" data-action="click->input-select#clear"> </i> <div data-input-select-target="icon"> <div class="lui-icon h-[12px] w-[12px]"> <i class="fa-regular fa-chevron-down lui-icon__icon" style="font-size: 12px; color: #212529;"></i> </div> </div> </span> </span> <span class="lui-input__spinner"> <i class="fa-regular fa-spinner"></i> </span> </span> </div> </div> <span class="lui-inner-input__actions opacity-0 flex items-center gap-1 h-fit" data-input-target="actions"> <span class="lui-button__tooltip-wrapper inline-flex w-fit"> <button class="lui-button lui-button--icon-only lui-button--neutral--secondary lui-button--size-tiny w-fit w-fit relative" data-controller="lui--button" data-input-target="cancel" data-action="click->input#handleClose" type="button" disabled="disabled"> <div class="opacity-100 inline-flex" data-lui--button-target="leadingIcon"> <div class="flex items-center justify-center" style="width: 12px; height: 12px;"><i class="lui-button__icon lui-button__icon--tiny fa-regular fa-xmark" data-lui--button-target="leadingIcon"></i></div> </div> <div class="absolute w-full flex items-center justify-center opacity-0" data-lui--button-target="loadingIcon"> <i class="lui-m_icon animate-spin material-symbols-rounded" style="--lui-micon-size: 12px;"> progress_activity </i> </div> </button></span> <span class="lui-button__tooltip-wrapper inline-flex w-fit"> <button class="lui-button lui-button--icon-only lui-button--neutral--secondary lui-button--size-tiny w-fit w-fit relative" data-controller="lui--button" data-input-target="submit" data-action="click->input#setLoading lui--button#startLoading" form="some_form_id" type="submit" disabled="disabled"> <div class="opacity-100 inline-flex" data-lui--button-target="leadingIcon"> <div class="flex items-center justify-center" style="width: 12px; height: 12px;"><i class="lui-button__icon lui-button__icon--tiny fa-regular fa-check" data-lui--button-target="leadingIcon"></i></div> </div> <div class="absolute w-full flex items-center justify-center opacity-0" data-lui--button-target="loadingIcon"> <i class="lui-m_icon animate-spin material-symbols-rounded" style="--lui-micon-size: 12px;"> progress_activity </i> </div> </button></span> </span> </div> <div data-input-select-target="menu" class="lui-input-select__wrapper"> <div class="lui-input-select__options" role="listbox"> <div class="lui-input-select__option " role="option" data-input-select-target="option" data-text="user 1" data-value="1"> <div class="lui-input-select__option-wrapper"> <div class="lui-input-select__option-text"> <i class="fa-regular fa-user"></i> <span role="text">user 1</span> </div> <i class="fa-regular fa-check " data-input-select-target="check"></i> </div> </div> <div class="lui-input-select__option " role="option" data-input-select-target="option" data-text="user 2" data-value="2"> <div class="lui-input-select__option-wrapper"> <div class="lui-input-select__option-text"> <i class="fa-regular fa-user"></i> <span role="text">user 2</span> </div> <i class="fa-regular fa-check hidden!" data-input-select-target="check"></i> </div> </div> <div class="lui-input-select__option " role="option" data-input-select-target="option" data-text="user 3" data-value="3"> <div class="lui-input-select__option-wrapper"> <div class="lui-input-select__option-text"> <i class="fa-regular fa-user"></i> <span role="text">user 3</span> </div> <i class="fa-regular fa-check hidden!" data-input-select-target="check"></i> </div> </div> </div> </div> </div> <input type="hidden" name="user_id" id="user_id" value="1" form="some_form_id" data-input-select-target="hiddenInput" /> </div></form><div class="mt-6"> Only this frame will be updated: <turbo-frame id="example-frame"> <div> Selected user: </div> <div> 2026-07-04 17:23:27 UTC </div> </turbo-frame></div>Inputs::Select
Description
Related components
| Used Components | Components where is Used |
|---|---|
| Label |
Usage rules
- ✅ Do
- ❌ Don't
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<% if params.key?(:user_id) && params[:simulate_slow_response].present? sleep 2 end%><% form_id = "some_form_id" %><%= form_with url: "#", method: :get, id: form_id, data: { turbo_frame: "example-frame" } do %> <%= lookbook_fields(params.slice(:simulate_slow_response)) %> <%= render LooposUi::Inputs::Select.new( name: "user_id", options: [ { value: 1, text: "user 1", icon: "user" }, { value: 2, text: "user 2", icon: "user" }, { value: 3, text: "user 3", icon: "user" }, ], value: "1", open_actions: true, placeholder: "Selecione um user", mode: :autosubmit, form: form_id, help: params[:help].presence, error: params[:error].presence, open_actions: true, ) %><% end %><div class="mt-6"> Only this frame will be updated: <%= turbo_frame_tag "example-frame" do %> <div> Selected user: <%= params[:user_id] %> </div> <div> <%= Time.current %> </div> <% end %></div>No notes provided.
| Param | Description | Input |
|---|---|---|
|
Simulate slow response, 2 seconds delay |
|
|
|
Helper text below the input |
|
|
|
Validation error message |
|
Inputs::Select
Description
Inputs::Select component is used to render select input fields.
Arguments
Most input components have the following base arguments:
Base Arguments
| Property | Default | Description |
|---|---|---|
model |
nil |
ActiveRecord instance. |
attribute |
nil |
Attribute name of the model. |
name |
nil |
Name of the input field. |
value |
nil |
Pre-selected option. Must have the same value as an exisiting option. |
placeholder |
nil |
Placeholder text. |
error |
nil |
Error message. If model is present, the errors will be extracted for the current attribute |
help |
nil |
Help message. |
appearance |
nil |
Visual modifier. Defaults to mode when omitted. |
readonly |
false |
Renders the selected option text as readonly text. |
custom_readonly |
false |
In readonly mode, renders provided content instead of the plain value. |
open_actions |
false |
Open field in edit mode by default. |
extra_input_attributes |
{} |
Attributes to be added to the input element. |
Select Specific arguments
| Property | Default | Description |
|---|---|---|
options |
nil |
Options for the select field. |
mode |
:inline |
Behavioural mode. Can be :inline, :autosubmit or :form. Controls save/cancel actions and form submission. |
variant |
:list |
Visual variant. :list renders the current dropdown. :grid renders all options as visible buttons. |
include_blank |
false |
Adds a blank option. When a string is passed, it is used as the blank label. In grid mode, blank options are omitted. |
clearable |
true |
Shows the clear button in list mode. |
portal_target |
nil |
CSS selector for the element where the dropdown should be portaled. Falls back to modal containers or document.body. |
form |
nil |
Form id to be submitted when the mode is :autosubmit. Will try to use find closest parent if omitted. |
Options schema
| Property | Description |
|---|---|
value |
Value of the option. |
text |
Label of the option. |
icon |
Icon of the option. Can use the shorthand version fa-regular fa-* will be prepended if missing. |
tooltip |
Optional tooltip text shown next to the option label. |
Modes
mode controls the behavioural integration of the Select within a form:
:inline- On change, cancel/save actions appear. The value is persisted when the user confirms.:autosubmit- On change, the form is submitted immediately. Cancel/save actions are hidden.:form- The value is stored in a hidden input and submitted when the surrounding form is submitted. The developer is responsible for providing the submit button and form.
All modes work with both variant: :list and variant: :grid.
Variants
variant controls the visual presentation of the Select:
:list(default) — The current dropdown behaviour: a readonly text input triggers a Tippy popup with the list of options.:grid— All options are always visible as buttons (LooposUi::Button). The underlying hidden input and form submission contract are identical to thelistvariant.
Slots
No slots available for this component.
⚠️ Important
It's the responsibility of the developer to handle the generation of the form, and handling any
turbo frame updates or form submissions.
The recommendation is to use the form_with helper from Rails, along with a turbo_frame_tag, so only the inline component is updated.