Select
Dropdown control for choosing from predefined options.
TailwindCSS
package showcase
import "github.com/axzilla/templui/pkg/components"
templ SelectDefault() {
<div class="w-full max-w-md">
@components.Select(components.SelectProps{
Options: []components.SelectOption{
{Label: "Apple", Value: "apple"},
{Label: "Banana", Value: "banana"},
{Label: "Orange", Value: "orange"},
{Label: "Mango", Value: "mango"},
},
})
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/icons"
"github.com/axzilla/templui/pkg/utils"
)
type SelectProps struct {
ID string // DOM identifier
Name string // Form field name
Placeholder string // Helper text shown when empty
Options []SelectOption // Available choices
Disabled bool // Prevents interaction
HasError bool // Error state styling
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
type SelectOption struct {
Label string // Display text
Value string // Form value
Selected bool // Default selection
Attributes templ.Attributes // Additional HTML attributes
}
// Select renders a styled dropdown selection input
templ Select(props SelectProps) {
<div class={ utils.TwMerge("relative w-full", props.Class) }>
<select
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
disabled?={ props.Disabled }
class={
utils.TwMerge(
// Layout
"peer h-10 w-full px-3 py-2",
// Styling
"rounded-md border border-input bg-background text-sm",
"appearance-none ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Conditional
utils.TwIf("border-destructive ring-destructive", props.HasError),
),
}
{ props.Attributes... }
>
if props.Placeholder != "" {
<option value="" disabled selected hidden>{ props.Placeholder }</option>
}
for _, option := range props.Options {
<option
value={ option.Value }
selected?={ option.Selected }
{ option.Attributes... }
>
{ option.Label }
</option>
}
</select>
<div
class={
utils.TwMerge(
// Layout
"absolute right-3 top-3",
// Styling
"pointer-events-none",
// States
"peer-disabled:opacity-50",
),
}
>
@icons.ChevronDown(icons.IconProps{
Size: "16",
Class: "text-muted-foreground",
})
</div>
</div>
}
Usage
@components.Select(components.SelectProps{...})
Examples
With Placeholder
package showcase
import "github.com/axzilla/templui/pkg/components"
templ SelectWithPlaceholder() {
<div class="w-full max-w-md">
@components.Select(components.SelectProps{
Placeholder: "Pick a fruit",
Options: []components.SelectOption{
{Label: "Apple", Value: "apple"},
{Label: "Banana", Value: "banana"},
{Label: "Orange", Value: "orange"},
{Label: "Mango", Value: "mango"},
},
})
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/icons"
"github.com/axzilla/templui/pkg/utils"
)
type SelectProps struct {
ID string // DOM identifier
Name string // Form field name
Placeholder string // Helper text shown when empty
Options []SelectOption // Available choices
Disabled bool // Prevents interaction
HasError bool // Error state styling
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
type SelectOption struct {
Label string // Display text
Value string // Form value
Selected bool // Default selection
Attributes templ.Attributes // Additional HTML attributes
}
// Select renders a styled dropdown selection input
templ Select(props SelectProps) {
<div class={ utils.TwMerge("relative w-full", props.Class) }>
<select
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
disabled?={ props.Disabled }
class={
utils.TwMerge(
// Layout
"peer h-10 w-full px-3 py-2",
// Styling
"rounded-md border border-input bg-background text-sm",
"appearance-none ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Conditional
utils.TwIf("border-destructive ring-destructive", props.HasError),
),
}
{ props.Attributes... }
>
if props.Placeholder != "" {
<option value="" disabled selected hidden>{ props.Placeholder }</option>
}
for _, option := range props.Options {
<option
value={ option.Value }
selected?={ option.Selected }
{ option.Attributes... }
>
{ option.Label }
</option>
}
</select>
<div
class={
utils.TwMerge(
// Layout
"absolute right-3 top-3",
// Styling
"pointer-events-none",
// States
"peer-disabled:opacity-50",
),
}
>
@icons.ChevronDown(icons.IconProps{
Size: "16",
Class: "text-muted-foreground",
})
</div>
</div>
}
Selected Value
package showcase
import "github.com/axzilla/templui/pkg/components"
templ SelectSelectedValue() {
<div class="w-full max-w-sm">
@components.Select(components.SelectProps{
Options: []components.SelectOption{
{Label: "Apple", Value: "apple"},
{Label: "Banana", Value: "banana", Selected: true},
{Label: "Orange", Value: "orange"},
{Label: "Mango", Value: "mango"},
},
})
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/icons"
"github.com/axzilla/templui/pkg/utils"
)
type SelectProps struct {
ID string // DOM identifier
Name string // Form field name
Placeholder string // Helper text shown when empty
Options []SelectOption // Available choices
Disabled bool // Prevents interaction
HasError bool // Error state styling
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
type SelectOption struct {
Label string // Display text
Value string // Form value
Selected bool // Default selection
Attributes templ.Attributes // Additional HTML attributes
}
// Select renders a styled dropdown selection input
templ Select(props SelectProps) {
<div class={ utils.TwMerge("relative w-full", props.Class) }>
<select
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
disabled?={ props.Disabled }
class={
utils.TwMerge(
// Layout
"peer h-10 w-full px-3 py-2",
// Styling
"rounded-md border border-input bg-background text-sm",
"appearance-none ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Conditional
utils.TwIf("border-destructive ring-destructive", props.HasError),
),
}
{ props.Attributes... }
>
if props.Placeholder != "" {
<option value="" disabled selected hidden>{ props.Placeholder }</option>
}
for _, option := range props.Options {
<option
value={ option.Value }
selected?={ option.Selected }
{ option.Attributes... }
>
{ option.Label }
</option>
}
</select>
<div
class={
utils.TwMerge(
// Layout
"absolute right-3 top-3",
// Styling
"pointer-events-none",
// States
"peer-disabled:opacity-50",
),
}
>
@icons.ChevronDown(icons.IconProps{
Size: "16",
Class: "text-muted-foreground",
})
</div>
</div>
}
With Label
package showcase
import "github.com/axzilla/templui/pkg/components"
templ SelectWithLabel() {
<div class="space-y-2 w-full max-w-sm">
@components.Label(components.LabelProps{
Text: "Choose a Fruit",
For: "fruit-with-label",
})
@components.Select(components.SelectProps{
ID: "fruit-with-label",
Options: []components.SelectOption{
{Label: "Apple", Value: "apple"},
{Label: "Banana", Value: "banana"},
{Label: "Orange", Value: "orange"},
{Label: "Mango", Value: "mango"},
},
})
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/icons"
"github.com/axzilla/templui/pkg/utils"
)
type SelectProps struct {
ID string // DOM identifier
Name string // Form field name
Placeholder string // Helper text shown when empty
Options []SelectOption // Available choices
Disabled bool // Prevents interaction
HasError bool // Error state styling
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
type SelectOption struct {
Label string // Display text
Value string // Form value
Selected bool // Default selection
Attributes templ.Attributes // Additional HTML attributes
}
// Select renders a styled dropdown selection input
templ Select(props SelectProps) {
<div class={ utils.TwMerge("relative w-full", props.Class) }>
<select
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
disabled?={ props.Disabled }
class={
utils.TwMerge(
// Layout
"peer h-10 w-full px-3 py-2",
// Styling
"rounded-md border border-input bg-background text-sm",
"appearance-none ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Conditional
utils.TwIf("border-destructive ring-destructive", props.HasError),
),
}
{ props.Attributes... }
>
if props.Placeholder != "" {
<option value="" disabled selected hidden>{ props.Placeholder }</option>
}
for _, option := range props.Options {
<option
value={ option.Value }
selected?={ option.Selected }
{ option.Attributes... }
>
{ option.Label }
</option>
}
</select>
<div
class={
utils.TwMerge(
// Layout
"absolute right-3 top-3",
// Styling
"pointer-events-none",
// States
"peer-disabled:opacity-50",
),
}
>
@icons.ChevronDown(icons.IconProps{
Size: "16",
Class: "text-muted-foreground",
})
</div>
</div>
}
Disabled
package showcase
import "github.com/axzilla/templui/pkg/components"
templ SelectDisabled() {
<div class="space-y-2 w-full max-w-sm">
@components.FormLabel(components.FormLabelProps{
Text: "Choose a fruit",
For: "select-disabled",
})
@components.Select(components.SelectProps{
ID: "select-disabled",
Disabled: true,
Options: []components.SelectOption{
{Label: "Apple", Value: "1"},
{Label: "Banana", Value: "2"},
},
})
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/icons"
"github.com/axzilla/templui/pkg/utils"
)
type SelectProps struct {
ID string // DOM identifier
Name string // Form field name
Placeholder string // Helper text shown when empty
Options []SelectOption // Available choices
Disabled bool // Prevents interaction
HasError bool // Error state styling
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
type SelectOption struct {
Label string // Display text
Value string // Form value
Selected bool // Default selection
Attributes templ.Attributes // Additional HTML attributes
}
// Select renders a styled dropdown selection input
templ Select(props SelectProps) {
<div class={ utils.TwMerge("relative w-full", props.Class) }>
<select
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
disabled?={ props.Disabled }
class={
utils.TwMerge(
// Layout
"peer h-10 w-full px-3 py-2",
// Styling
"rounded-md border border-input bg-background text-sm",
"appearance-none ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Conditional
utils.TwIf("border-destructive ring-destructive", props.HasError),
),
}
{ props.Attributes... }
>
if props.Placeholder != "" {
<option value="" disabled selected hidden>{ props.Placeholder }</option>
}
for _, option := range props.Options {
<option
value={ option.Value }
selected?={ option.Selected }
{ option.Attributes... }
>
{ option.Label }
</option>
}
</select>
<div
class={
utils.TwMerge(
// Layout
"absolute right-3 top-3",
// Styling
"pointer-events-none",
// States
"peer-disabled:opacity-50",
),
}
>
@icons.ChevronDown(icons.IconProps{
Size: "16",
Class: "text-muted-foreground",
})
</div>
</div>
}
Form
Select your favorite fruit from the dropdown menu.
A fruit selection is required.
package showcase
import "github.com/axzilla/templui/pkg/components"
templ SelectForm() {
<div class="w-full max-w-sm">
@components.FormItem(components.FormItemProps{}) {
@components.Label(components.LabelProps{
Text: "Choose a Fruit",
For: "fruit-form",
})
@components.Select(components.SelectProps{
Name: "fruit",
ID: "fruit-form",
Placeholder: "Pick a fruit",
HasError: true,
Options: []components.SelectOption{
{Label: "Apple", Value: "apple"},
{Label: "Banana", Value: "banana"},
},
})
@components.FormDescription(components.FormDescriptionProps{}) {
Select your favorite fruit from the dropdown menu.
}
@components.FormMessage(components.FormMessageProps{
Type: "error",
Message: "A fruit selection is required.",
})
}
</div>
}
package components
import (
"github.com/axzilla/templui/pkg/icons"
"github.com/axzilla/templui/pkg/utils"
)
type SelectProps struct {
ID string // DOM identifier
Name string // Form field name
Placeholder string // Helper text shown when empty
Options []SelectOption // Available choices
Disabled bool // Prevents interaction
HasError bool // Error state styling
Class string // Additional CSS classes
Attributes templ.Attributes // Additional HTML attributes
}
type SelectOption struct {
Label string // Display text
Value string // Form value
Selected bool // Default selection
Attributes templ.Attributes // Additional HTML attributes
}
// Select renders a styled dropdown selection input
templ Select(props SelectProps) {
<div class={ utils.TwMerge("relative w-full", props.Class) }>
<select
x-ref={ props.ID }
id={ props.ID }
name={ props.Name }
disabled?={ props.Disabled }
class={
utils.TwMerge(
// Layout
"peer h-10 w-full px-3 py-2",
// Styling
"rounded-md border border-input bg-background text-sm",
"appearance-none ring-offset-background",
"placeholder:text-muted-foreground",
// States
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
// Conditional
utils.TwIf("border-destructive ring-destructive", props.HasError),
),
}
{ props.Attributes... }
>
if props.Placeholder != "" {
<option value="" disabled selected hidden>{ props.Placeholder }</option>
}
for _, option := range props.Options {
<option
value={ option.Value }
selected?={ option.Selected }
{ option.Attributes... }
>
{ option.Label }
</option>
}
</select>
<div
class={
utils.TwMerge(
// Layout
"absolute right-3 top-3",
// Styling
"pointer-events-none",
// States
"peer-disabled:opacity-50",
),
}
>
@icons.ChevronDown(icons.IconProps{
Size: "16",
Class: "text-muted-foreground",
})
</div>
</div>
}