Select displays multiple options for a user to pick from in a dropdown menu. User selects one option.
<%= pb_rails("select", props: { id: "select-coffee", label: "Favorite Coffee", name: "coffee", options: [ { value: "1", disabled: true, value_text: "Espresso", }, { value: "2", selected: true, value_text: "Americano", }, { value: "3", disabled: true, value_text: "Cappuccino", }, { value: "4", value_text: "Mocha", }, { value: "5", value_text: "Flat White", }, { value: "6", value_text: "Latte", }, ] }) %>
<%= pb_rails("select", props: { id: "holiday", label: "Favorite Holiday" }) do %> <select name="holiday" id="holiday"> <option value="1">Christmas</option> <option value="2">Thanksgiving</option> <option value="3">Halloween</option> <option value="4">Fourth of July</option> </select> <% end %>
To create a select with non-selectable subheaders, use a Custom Select component to render a native <select> containing <optgroup> elements. The optgroup HTML element groups related options under a non-selectable label in the dropdown.
<%= pb_rails("select", props: { id: "animal", label: "Favorite Animal" }) do %> <select name="animal" id="animal"> <optgroup label="Mammal"> <option value="1">Cat</option> <option value="2">Dog</option> </optgroup> <optgroup label="Amphibian"> <option value="3">Frog</option> <option value="4">Salamander</option> </optgroup> </select> <% end %>
Select w/ Error shows that an option must be selected or is invalid (i.e. when used in a form it signals a user to fix an error).
<%= pb_rails("select", props: { error: raw(pb_rails("icon", props: { icon: "warning" }) + " Please make a valid selection"), id: "select-food-error", label: "Favorite Food", name: "food", options: [ { value: "1", value_text: "Burgers", }, { value: "2", selected: true, value_text: "Pizza", }, { value: "3", value_text: "Tacos", }, { value: "4", value_text: "BBQ", }, ] }) %>
<%= pb_rails("select", props: { id: "select-food-inline-arrow", label: "Favorite Food", name: "food", inline: true, options: [ { value: "1", value_text: "Burgers", }, { value: "2", value_text: "Pizza", }, { value: "3", value_text: "Tacos", }, { value: "4", value_text: "BBQ", }, ], show_arrow: true }) %>
<%= pb_rails("select", props: { id: "select-food-inline-compact", label: "Favorite Food", name: "food", inline: true, compact: true, options: [ { value: "1", value_text: "Burgers", }, { value: "2", value_text: "Pizza", }, { value: "3", value_text: "Tacos", }, { value: "4", value_text: "BBQ", }, ] }) %>
Inspect the element and notice the data-attribute being added to the <select> element
<%= pb_rails("select", props: { id: "select-food-attributes", attributes: { data: { options: "data_attribute" }, }, label: "Favorite Food", name: "food", options: [ { value: "1", value_text: "Burgers", }, { value: "2", selected: true, value_text: "Pizza", }, { value: "3", value_text: "Tacos", }, { value: "4", value_text: "BBQ", }, ] }) %>
The multiple prop enables multiple selections; however, for a better user experience, we recommend our Typeahead kit.
<%= pb_rails("select", props: { id: "select-food-multiple", label: "Favorite Food", name: "food", multiple: true, options: [ { value: "1", value_text: "Burgers", }, { value: "2", selected: true, value_text: "Pizza", }, { value: "3", value_text: "Tacos", }, { value: "4", value_text: "BBQ", }, { value: "4", value_text: "Sushi", }, { value: "4", value_text: "Chinese", }, { value: "4", value_text: "Hot Dogs", }, ] }) %>
Use the input_options / inputOptions prop to pass additional attributes directly to the underlying <select> element instead of the outer wrapper. This is useful for applying data attributes, custom IDs, or other HTML attributes that need to be on the select element itself.
<%= pb_rails("select", props: { label: "Favorite Food", name: "favorite_food", options: [ { value: "pizza", value_text: "Pizza" }, { value: "tacos", value_text: "Tacos" }, { value: "sushi", value_text: "Sushi" } ], input_options: { 'aria-label': "Select your favorite food", class: "custom-select-class", data: { controller: "search", action: "change->search#filter" }, id: "favorite-food-select" } }) %>
The requiredIndicator/required_indicator prop displays a red asterisk (*) next to the label, visually indicating that the field is required. This is purely visual and does not enforce validation.
You can use requiredIndicator/required_indicator with any validation approach: HTML5 validation via the required prop, client-side validation, or backend validation. For this reason, it works independently and doesn't need to be paired with the required prop.
<%= pb_rails("select", props: { id: "select-snacks-required-indicator", label: "Favorite Snacks", name: "food", required_indicator: true, options: [ { value: "1", value_text: "Popcorn", }, { value: "2", selected: true, value_text: "Chips", }, { value: "3", value_text: "Twizzlers", }, { value: "4", value_text: "Cookies", }, ] }) %>
Try to avoid using select when there are limited options to choose from (ie either or questions, yes/no questions, etc).
| Props | Type | Values |
|---|---|---|
align_content |
enum | responsive
|
start
end
center
spaceBetween
spaceAround
spaceEvenly
|
align_items |
enum | responsive
|
start
end
center
|
border_radius |
enum
|
none
xs
sm
md
lg
xl
rounded
|
cursor |
enum
|
auto
default
none
contextMenu
help
pointer
progress
wait
cell
|
dark |
boolean
|
true
false
|
flex |
enum | responsive
|
auto
initial
0
1
2
3
4
5
6
7
8
9
10
11
12
none
|
flex_direction |
enum | responsive
|
row
column
rowReverse
columnReverse
|
flex_wrap |
enum | responsive
|
wrap
nowrap
wrapReverse
|
justify_content |
enum | responsive
|
start
end
center
spaceBetween
spaceAround
spaceEvenly
|
line_height |
enum
|
loosest
looser
loose
normal
tight
tighter
tightest
|
margin_right |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_left |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_top |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_bottom |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_x |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_y |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin |
array
|
none
xxs
xs
sm
md
lg
xl
|
width |
string
|
|
min_width |
string
|
|
max_width |
string
|
|
gap |
string | responsive
|
|
column_gap |
string | responsive
|
|
row_gap |
string | responsive
|
|
number_spacing |
enum
|
tabular
|
order |
enum | responsive
|
none
first
1
2
3
4
5
6
7
8
9
10
11
12
|
overflow_x |
enum
|
scroll
visible
hidden
auto
|
overflow_y |
enum
|
scroll
visible
hidden
auto
|
overflow |
enum
|
scroll
visible
hidden
auto
|
padding_right |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_left |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_top |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_bottom |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_x |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_y |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding |
array
|
none
xxs
xs
sm
md
lg
xl
|
position |
enum
|
relative
absolute
fixed
sticky
static
|
shadow |
enum
|
none
deep
deeper
deepest
|
text_align |
enum | responsive
|
start
end
left
right
center
justify
justifyAll
matchParent
|
truncate |
enum
|
none
1
2
3
4
5
|
vertical_align |
enum | responsive
|
baseline
super
top
middle
bottom
sub
text-top
text-bottom
|
z_index |
enum | responsive
|
1
2
3
4
5
6
7
8
9
10
max
|
top |
enum | object
|
xxs
xs
sm
md
lg
xl
xxl
|
inset |
boolean
|
true
false
|
right |
enum | object
|
xxs
xs
sm
md
lg
xl
xxl
|
bottom |
enum | object
|
xxs
xs
sm
md
lg
xl
xxl
|
left |
enum | object
|
xxs
xs
sm
md
lg
xl
xxl
|
height |
string
|
|
max_height |
string
|
|
min_height |
string
|
|
hover |
object
|
|
group_hover |
boolean
|
true
false
|
| Props | Type | Values | Default |
|---|---|---|---|
blank_selection |
string
|
||
compact |
boolean
|
true
false
|
false
|
disabled |
boolean
|
true
false
|
false
|
error |
string
|
||
include_blank |
string
|
||
inline |
boolean
|
true
false
|
false
|
input_options |
{[key: string]: string | number | boolean | (() => void)}
|
||
label |
string
|
||
multiple |
boolean
|
true
false
|
false
|
name |
string
|
||
on_change |
reactnode
|
||
options |
array
|
||
required |
boolean
|
true
false
|
false
|
required_indicator |
boolean
|
true
false
|
false
|
show_arrow |
boolean
|
true
false
|
false
|
value |
string
|
||
attributes |
string
|
||
onchange |
string
|
||
validation_message |
string
|