Componentradio-group
Radio Group
A set of checkable buttons—known as radio buttons—where no more than one button can be checked at a time.
Preview
A set of checkable buttons—known as radio buttons—where no more than one button can be checked at a time.
@ui.RadioGroup(ui.RadioGroupProps{Name: "option", DefaultValue: "option-one"}) {
<div class="flex items-center space-x-2">
@ui.RadioGroupItem(ui.RadioGroupItemProps{ID: "r1", Name: "option", Value: "option-one", Label: "Option One"})
@ui.Label(ui.LabelProps{For: "r1"}) { Option One }
</div>
<div class="flex items-center space-x-2">
@ui.RadioGroupItem(ui.RadioGroupItemProps{ID: "r2", Name: "option", Value: "option-two", Label: "Option Two"})
@ui.Label(ui.LabelProps{For: "r2"}) { Option Two }
</div>
}Installation
Add this component to your project using the CLI.
templcn add radio-groupUsage
1. Import the component in your Go or templ file:
import "your-module/ui"2. Use the component in your template:
@ui.RadioGroup(ui.RadioGroupProps{Name: "option", DefaultValue: "option-one"}) {
<div class="flex items-center space-x-2">
@ui.RadioGroupItem(ui.RadioGroupItemProps{ID: "r1", Name: "option", Value: "option-one", Label: "Option One"})
@ui.Label(ui.LabelProps{For: "r1"}) { Option One }
</div>
<div class="flex items-center space-x-2">
@ui.RadioGroupItem(ui.RadioGroupItemProps{ID: "r2", Name: "option", Value: "option-two", Label: "Option Two"})
@ui.Label(ui.LabelProps{For: "r2"}) { Option Two }
</div>
}Composition
Use these parts together to build the component.
RadioGroup
├── RadioGroupItem
├── LabelExamples
Named examples and common variations.
Three options
A radio group for plan selection.
@ui.RadioGroup(ui.RadioGroupProps{Name: "plan"}) {
@ui.RadioGroupItem(ui.RadioGroupItemProps{Name: "plan", Value: "starter", Label: "Starter"})
@ui.RadioGroupItem(ui.RadioGroupItemProps{Name: "plan", Value: "pro", Label: "Pro"})
@ui.RadioGroupItem(ui.RadioGroupItemProps{Name: "plan", Value: "enterprise", Label: "Enterprise"})
}API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| Name | string | "" | HTML name shared by all radio inputs. |
| DefaultValue | string | "" | Pre-selected option value. |
| Disabled | bool | false | Disables all options. |
View source
package ui
import (
"context"
"io"
"github.com/a-h/templ"
)
type RadioGroupProps struct {
DOMProps
Name string
Value string
DefaultValue string
Disabled bool
Required bool
}
type radioGroupRenderState struct {
name string
value string
disabled bool
}
type radioGroupRenderStateKey struct{}
func RadioGroup(props RadioGroupProps) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
value := props.Value
if value == "" {
value = props.DefaultValue
}
attrs := attrsFromDOMProps(props.DOMProps, "radio-group", "grid gap-3")
attrs["role"] = "radiogroup"
if props.Name != "" {
attrs["data-name"] = props.Name
}
if value != "" {
attrs["data-value"] = value
}
if props.DefaultValue != "" {
attrs["data-default-value"] = props.DefaultValue
}
if props.Disabled {
attrs["data-disabled"] = "true"
}
if props.Required {
attrs["aria-required"] = "true"
}
ctx = context.WithValue(ctx, radioGroupRenderStateKey{}, radioGroupRenderState{name: props.Name, value: value, disabled: props.Disabled})
return renderElement(ctx, w, "div", attrs, templ.GetChildren(ctx))
})
}
type RadioGroupItemProps struct {
DOMProps
Name string
Value string
Disabled bool
Label string
}
func RadioGroupItem(props RadioGroupItemProps) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
ctx, ownChildren := childrenFromContext(ctx)
className := "flex items-center gap-2 text-sm"
attrs := attrsFromDOMProps(props.DOMProps, "radio-group-item", className)
state, _ := ctx.Value(radioGroupRenderStateKey{}).(radioGroupRenderState)
name := props.Name
if name == "" {
name = state.name
}
disabled := props.Disabled || state.disabled
checked := props.Value != "" && state.value == props.Value
attrs["data-state"] = map[bool]string{true: "checked", false: "unchecked"}[checked]
attrs["aria-checked"] = map[bool]string{true: "true", false: "false"}[checked]
if disabled {
attrs["data-disabled"] = "true"
}
children := templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
inputAttrs := templ.Attributes{
"type": "radio",
"class": "aspect-square size-4 shrink-0 rounded-full border border-input text-primary shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:ring-destructive/40",
"value": props.Value,
}
if name != "" {
inputAttrs["name"] = name
}
if checked {
inputAttrs["checked"] = true
}
if disabled {
inputAttrs["disabled"] = true
}
if err := renderVoidElement(ctx, w, "input", inputAttrs); err != nil {
return err
}
if props.Label != "" {
_, err := io.WriteString(w, templ.EscapeString(props.Label))
return err
}
return renderChildren(ctx, w, ownChildren)
})
return renderElement(ctx, w, "label", attrs, children)
})
}