@uiForm
uiForm is a collection of components that make it easy to create forms.
.CheckboxInput
A checkbox selects one value, bound to a boolean or an array state path.
Usage
@uiForm.CheckboxInput(uiForm.CheckboxInputSettings{
Label: "Accept the terms",
TwoWayStatePath: "hasAcceptedTerms",
// OptionalFields
InputName: "hasAcceptedTerms",
})Alpine.js Parent State (x-data)
<div x-data="{hasAcceptedTerms: false}"></div>
<div x-data="{selectedFruits: ['apple']}"></div>Live Example
A bound checkbox and the select-all pattern with an indeterminate parent.
Boolean state
Value:
Indeterminate state
Values:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Shapes
Shapes
Shape rounds the checkbox frame: square, rounded, or circular.
Usage
@uiForm.CheckboxInput(uiForm.CheckboxInputSettings{
Label: "Accept the terms",
TwoWayStatePath: "hasAcceptedTerms",
// OptionalFields
Shape: uiForm.CheckboxInputShapeRounded,
})Sizes
Sizes
Size scales the checkbox and its label: xs, sm, md, lg, or xl.
Usage
@uiForm.CheckboxInput(uiForm.CheckboxInputSettings{
Label: "Accept the terms",
TwoWayStatePath: "hasAcceptedTerms",
// OptionalFields
Size: uiForm.CheckboxInputSizeMd,
})Label Position
Label Position
LabelPosition places the label on the left or the right of the checkbox.
Usage
@uiForm.CheckboxInput(uiForm.CheckboxInputSettings{
Label: "Accept the terms",
TwoWayStatePath: "hasAcceptedTerms",
// OptionalFields
LabelPosition: uiForm.CheckboxInputLabelPositionLeft,
})States
States
IsChecked starts the box checked, IsDisabled blocks edits, and IsRequired marks the field as required. IsDisabledOneWayStatePath blocks edits from Alpine state, and TextCase transforms the label.
Usage
@uiForm.CheckboxInput(uiForm.CheckboxInputSettings{
Label: "Accept the terms",
// OptionalFields
IsChecked: true,
IsDisabled: false,
IsRequired: false,
IsDisabledOneWayStatePath: "!isCheckboxExampleEnabled",
TextCase: uiToolset.TextCaseUpper,
})Array and Indeterminate Binding
Array and Indeterminate Binding
Value binds one array item to each checkbox. IndeterminateOneWayStatePath, IsCheckedOneWayStatePath, and OnChangeFunc drive a select-all parent. InputName includes the bound state in form submission.
Usage
@uiForm.CheckboxInput(uiForm.CheckboxInputSettings{
Label: "Select all",
InputName: "selectedFruits",
IndeterminateOneWayStatePath: "selectedFruits.length > 0 && selectedFruits.length < fruitOptions.length",
IsCheckedOneWayStatePath: "selectedFruits.length === fruitOptions.length",
OnChangeFunc: "selectedFruits = selectedFruits.length === fruitOptions.length ? [] : [...fruitOptions]",
})
@uiForm.CheckboxInput(uiForm.CheckboxInputSettings{
Label: "Apple",
InputName: "selectedFruits",
TwoWayStatePath: "selectedFruits",
Value: "apple",
})Values:
Error States
Error States
IsInvalid shows the error style and ErrorMessage explains it. ErrorColor paints the error style, IsInvalidOneWayStatePath drives the error from Alpine state, and ErrorMessageOneWayStatePath prints the message from it.
Usage
@uiForm.CheckboxInput(uiForm.CheckboxInputSettings{
Label: "Accept the terms",
// OptionalFields
InputId: "checkbox-demo-terms",
IsInvalid: true,
ErrorMessage: "You must accept the terms to continue.",
ErrorColor: "orange-500",
IsInvalidOneWayStatePath: "!hasAcceptedTerms",
ErrorMessageOneWayStatePath: "errorMessage",
})Checked Colors
Checked Colors
CheckedColor paints the filled box and UncheckedColor paints the empty box. FocusRingColor colors the focus ring, and TextColor colors the label.
Usage
@uiForm.CheckboxInput(uiForm.CheckboxInputSettings{
Label: "Primary",
// OptionalFields
IsChecked: true,
CheckedColor: "primary-500",
UncheckedColor: "neutral-500",
FocusRingColor: "primary-500",
TextColor: "neutral-50",
}).InlineRadioGroup
An inline radio group displays a set of radio options in a horizontal layout.
Usage
@uiForm.InlineRadioGroup(uiForm.InlineRadioGroupSettings{
Label: "Select an option",
InputSettings: []uiForm.RadioInputSettings{
{
Label: "Option 1",
StateValue: "option1",
TwoWayStatePath: "groupSelection",
InputId: "groupOption1",
InputName: "group1",
},
},
// OptionalFields
TwoWayStatePath: "groupSelection",
})Alpine.js Parent State (x-data)
<div x-data="{groupSelection: 'option2'}"></div>Live Example
A horizontal radio group bound to one shared Alpine state path.
Value:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Sizes
Sizes
Each radio carries its own Size, so the group can scale per option. TextCase transforms the legend and the labels, and InputName includes the selected value in form submission.
Usage
@uiForm.InlineRadioGroup(uiForm.InlineRadioGroupSettings{
Label: "Select an option",
InputSettings: []uiForm.RadioInputSettings{
{
Label: "Option 1",
StateValue: "option1",
TwoWayStatePath: "groupSizeSelection",
InputId: "groupOption1",
InputName: "groupSizes",
Size: uiForm.RadioInputSizeSm,
TextCase: uiToolset.TextCaseUpper,
},
},
// OptionalFields
TwoWayStatePath: "groupSizeSelection",
InputName: "groupSizeSelection",
TextCase: uiToolset.TextCaseUpper,
}).InputField
An input field is a basic form element that allows users to enter text.
Usage
@uiForm.InputField(uiForm.InputFieldSettings{
InputType: uiForm.InputTypeText,
InputName: "name",
Label: "Name",
// OptionalFields
TwoWayStatePath: "name",
})Alpine.js Parent State (x-data)
<div x-data="{name: ''}"></div>Live Example
A labeled text field bound to Alpine state.
Value:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Value & Read-Only
Value & Read-Only
Value seeds the field content. IsReadOnly shows the value without accepting edits. IsRequired marks the field as required.
Usage
@uiForm.InputField(uiForm.InputFieldSettings{
InputType: uiForm.InputTypeText,
InputName: "name",
Label: "Name",
// OptionalFields
Value: "Lorem ipsum dolor sit amet.",
IsReadOnly: true,
IsRequired: true,
})Number Constraints
Number Constraints
InputTypeNumber with InputNumberMin, InputNumberMax, and InputNumberStep bounds the accepted value.
Usage
@uiForm.InputField(uiForm.InputFieldSettings{
InputType: uiForm.InputTypeNumber,
InputName: "name",
Label: "Name",
// OptionalFields
TwoWayStatePath: "name",
InputNumberMin: "0",
InputNumberMax: "100",
InputNumberStep: ".1",
})Affixes
Affixes
AffixLeftValue and AffixRightValue render fixed text on either side of the input. AffixLeftStatePath and AffixRightStatePath read the affix text from Alpine state.
Usage
@uiForm.InputField(uiForm.InputFieldSettings{
InputType: uiForm.InputTypeText,
InputName: "name",
Label: "Name",
// OptionalFields
TwoWayStatePath: "name",
AffixLeftValue: "goinfinite.net/",
AffixLeftStatePath: "leftAffix",
AffixRightValue: ".jpg",
AffixRightStatePath: "rightAffix",
})Icon Left
Icon Left
IconLeft renders a Phosphor icon inside the field before the input.
Usage
@uiForm.InputField(uiForm.InputFieldSettings{
InputType: uiForm.InputTypeText,
InputName: "name",
Label: "Name",
// OptionalFields
TwoWayStatePath: "name",
IconLeft: "ph-magnifying-glass",
})Affix Width
Affix Width
AffixLeftWidthPercent and AffixRightWidthPercent fix an affix to a percentage of the field width. Without them, an affix caps at half the width.
Usage
@uiForm.InputField(uiForm.InputFieldSettings{
InputType: uiForm.InputTypeText,
InputName: "domain",
Label: "Domain",
// OptionalFields
TwoWayStatePath: "domain",
AffixLeftValue: "goinfinite.net/",
AffixLeftWidthPercent: 40,
})Sizes
Sizes
Size scales the input, its affixes, and the floating label. It accepts xs, sm, md (the default), lg, or xl.
Usage
@uiForm.InputField(uiForm.InputFieldSettings{
InputType: uiForm.InputTypeText,
InputName: "name",
Label: "Name",
// OptionalFields
Size: uiForm.InputFieldSizeLg,
})Label Case
Label Case
TextCase transforms the floating label and the placeholder. It accepts uiToolset.TextCaseNone (the default, as typed), TextCaseLower, TextCaseUpper, or TextCaseCapitalize.
Usage
@uiForm.InputField(uiForm.InputFieldSettings{
InputType: uiForm.InputTypeText,
InputName: "name",
Label: "Network Interface",
// OptionalFields
TextCase: uiToolset.TextCaseUpper,
})Hints
Hints
HintValue explains the field. HintDisplay shows it as a description below the field or as a tooltip. HintStatePath reads the hint text from Alpine state. The HintDisplayTooltip fields shape the tooltip surface.
Usage
@uiForm.InputField(uiForm.InputFieldSettings{
InputType: uiForm.InputTypeText,
InputName: "name",
Label: "Name",
// OptionalFields
TwoWayStatePath: "name",
HintValue: "This is a helpful hint.",
HintStatePath: "hintText",
HintDisplay: uiForm.InputHintDisplayTooltip,
HintDisplayTooltipBackgroundColor: "violet-950/95",
HintDisplayTooltipMinWidthClass: "min-w-40",
HintDisplayTooltipMaxWidthClass: "max-w-64",
HintDisplayTooltipMinHeightClass: "min-h-10",
HintDisplayTooltipMaxHeightClass: "max-h-24",
})Hint Icon Styles
Hint Icon Styles
HintIconStyle renders the hint trigger as an icon or as a boxed tooltip.
Usage
@uiForm.InputField(uiForm.InputFieldSettings{
InputType: uiForm.InputTypeText,
InputName: "name",
Label: "Name",
// OptionalFields
TwoWayStatePath: "name",
HintValue: "This is a helpful hint.",
HintDisplay: uiForm.InputHintDisplayTooltip,
HintIconStyle: uiForm.InputHintIconStyleBoxed,
}).MultiSelectInput
A multi-select input allows users to select multiple options from a dropdown list.
Usage
@uiForm.MultiSelectInput(uiForm.MultiSelectInputSettings{
InputName: "countries",
Label: "Countries",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "countries",
})Alpine.js Parent State (x-data)
<div x-data="{countries: ['Brazil']}"></div>Live Example
A multi-select bound to an Alpine array, with flat option labels.
Values:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
LabelValueOptions
LabelValueOptions
LabelValueOptions send a stored Value while showing a human Label. The bound state holds the selected Values.
Usage
@uiForm.MultiSelectInput(uiForm.MultiSelectInputSettings{
InputName: "countries",
Label: "Countries",
// OptionalFields
LabelValueOptions: []uiForm.SelectLabelValueOption{
{Label: "Argentina", Value: "AR"},
{Label: "Brazil", Value: "BR"},
{Label: "Chile", Value: "CL"},
},
TwoWayStatePath: "countries",
})Alpine.js Parent State (x-data)
<div x-data="{countries: ['BR']}"></div>HTML Option Labels
HTML Option Labels
LabelHtml replaces the plain option label with custom markup in the dropdown.
Usage
@uiForm.MultiSelectInput(uiForm.MultiSelectInputSettings{
InputName: "countriesWithHtml",
Label: "Countries",
// OptionalFields
LabelValueOptions: []uiForm.SelectLabelValueOption{
{Label: "Argentina", LabelHtml: MultiSelectInputDemoOption1(), Value: "AR"},
{Label: "Brazil", LabelHtml: MultiSelectInputDemoOption2(), Value: "BR"},
{Label: "Chile", LabelHtml: MultiSelectInputDemoOption3(), Value: "CL"},
},
TwoWayStatePath: "countries",
})Alpine.js Parent State (x-data)
<div x-data="{countries: ['BR']}"></div>Click the dropdown to see the HTML labels.
Hints
Hints
HintValue explains the field. HintDisplay shows it as a description below the field or as a tooltip. HintStatePath reads the hint text from Alpine state. The HintDisplayTooltip fields shape the tooltip surface.
Usage
@uiForm.MultiSelectInput(uiForm.MultiSelectInputSettings{
InputName: "countriesHint",
Label: "Countries",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "countries",
HintValue: "This is a helpful hint.",
HintStatePath: "hintText",
HintDisplay: uiForm.InputHintDisplayTooltip,
HintDisplayTooltipBackgroundColor: "violet-950/95",
HintDisplayTooltipMinWidthClass: "min-w-40",
HintDisplayTooltipMaxWidthClass: "max-w-64",
HintDisplayTooltipMinHeightClass: "min-h-10",
HintDisplayTooltipMaxHeightClass: "max-h-24",
})Hint Icon Styles
Hint Icon Styles
HintIconStyle renders the hint trigger as an icon or as a boxed tooltip.
Usage
@uiForm.MultiSelectInput(uiForm.MultiSelectInputSettings{
InputName: "countriesHintBoxed",
Label: "Countries",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "countries",
HintValue: "This is a helpful hint.",
HintDisplay: uiForm.InputHintDisplayTooltip,
HintIconStyle: uiForm.InputHintIconStyleBoxed,
})Required
Required
IsRequired marks the field as required.
Usage
@uiForm.MultiSelectInput(uiForm.MultiSelectInputSettings{
InputName: "countriesRequired",
Label: "Countries",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "countries",
IsRequired: true,
})OnChangeFunc
OnChangeFunc
OnChangeFunc runs when a selection changes and when the field is cleared.
Usage
@uiForm.MultiSelectInput(uiForm.MultiSelectInputSettings{
InputName: "countriesChange",
Label: "Countries",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "countries",
OnChangeFunc: "onCountryChange()",
})Alpine.js Parent State (x-data)
<div x-data="{countries: ['BR'], changeCount: 0, onCountryChange() { this.changeCount++ }}"></div>Toggle an option or clear the field to see the function run.
Change count:
Dropdown Background
Dropdown Background
DropdownBackgroundColor sets the dropdown surface color. It accepts a Tailwind token.
Usage
@uiForm.MultiSelectInput(uiForm.MultiSelectInputSettings{
InputName: "countriesDropdown",
Label: "Countries",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "countries",
DropdownBackgroundColor: "emerald-900",
})Open the dropdown to see the background color.
Text Case
Text Case
TextCase transforms the field label. It accepts uiToolset.TextCaseNone (the default, as typed), TextCaseLower, TextCaseUpper, or TextCaseCapitalize.
Usage
@uiForm.MultiSelectInput(uiForm.MultiSelectInputSettings{
InputName: "countriesTextCase",
Label: "Countries",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "countries",
TextCase: uiToolset.TextCaseUpper,
}).RadioInput
A radio input allows users to select one option from a set of options.
Usage
@uiForm.RadioInput(uiForm.RadioInputSettings{
Label: "Option 1",
StateValue: "option1",
TwoWayStatePath: "selectedOption",
InputId: "radioOption1",
InputName: "options",
})Alpine.js Parent State (x-data)
<div x-data="{selectedOption: 'option2'}"></div>Live Example
A radio group bound to one shared Alpine state path.
Value:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Sizes
Sizes
Size scales the radio and its label: xs, sm, md, lg, or xl. TextCase transforms the label, and InputName names the radio in the form.
Usage
@uiForm.RadioInput(uiForm.RadioInputSettings{
Label: "Option 1",
StateValue: "option1",
TwoWayStatePath: "selectedOption",
// OptionalFields
InputName: "options",
Size: uiForm.RadioInputSizeMd,
TextCase: uiToolset.TextCaseUpper,
}).SelectInput
A select input allows users to select one option from a dropdown list.
Usage
@uiForm.SelectInput(uiForm.SelectInputSettings{
InputName: "country",
Label: "Country",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile", "Côte d'Ivoire"},
TwoWayStatePath: "country",
ShouldIncludeBlankOption: true,
})Alpine.js Parent State (x-data)
<div x-data="{country: 'Brazil'}"></div>Live Example
A select bound to Alpine state, with a blank option and flat option labels.
Value:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
LabelValueOptions
LabelValueOptions
LabelValueOptions send a stored Value while showing a human Label. The bound state holds the Value.
Usage
@uiForm.SelectInput(uiForm.SelectInputSettings{
InputName: "countryCode",
Label: "Country",
// OptionalFields
LabelValueOptions: []uiForm.SelectLabelValueOption{
{Label: "Argentina", Value: "AR"},
{Label: "Brazil", Value: "BR"},
{Label: "Chile", Value: "CL"},
},
TwoWayStatePath: "country",
ShouldIncludeBlankOption: true,
})Alpine.js Parent State (x-data)
<div x-data="{country: 'BR'}"></div>HTML Option Labels
HTML Option Labels
LabelHtml replaces the plain option label with custom markup in the dropdown.
Usage
@uiForm.SelectInput(uiForm.SelectInputSettings{
InputName: "countryWithHtml",
Label: "Country",
// OptionalFields
LabelValueOptions: []uiForm.SelectLabelValueOption{
{Label: "Argentina", LabelHtml: SelectInputDemoOption1(), Value: "AR"},
{Label: "Brazil", LabelHtml: SelectInputDemoOption2(), Value: "BR"},
{Label: "Chile", LabelHtml: SelectInputDemoOption3(), Value: "CL"},
},
TwoWayStatePath: "country",
ShouldIncludeBlankOption: true,
})Alpine.js Parent State (x-data)
<div x-data="{country: 'BR'}"></div>Click the dropdown to see the HTML labels.
Hints
Hints
HintValue explains the field. HintDisplay shows it as a description below the field or as a tooltip. HintStatePath reads the hint text from Alpine state. The HintDisplayTooltip fields shape the tooltip surface.
Usage
@uiForm.SelectInput(uiForm.SelectInputSettings{
InputName: "countryHint",
Label: "Country",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "country",
ShouldIncludeBlankOption: true,
HintValue: "This is a helpful hint.",
HintStatePath: "hintText",
HintDisplay: uiForm.InputHintDisplayTooltip,
HintDisplayTooltipBackgroundColor: "violet-950/95",
HintDisplayTooltipMinWidthClass: "min-w-40",
HintDisplayTooltipMaxWidthClass: "max-w-64",
HintDisplayTooltipMinHeightClass: "min-h-10",
HintDisplayTooltipMaxHeightClass: "max-h-24",
})Hint Icon Styles
Hint Icon Styles
HintIconStyle renders the hint trigger as an icon or as a boxed tooltip.
Usage
@uiForm.SelectInput(uiForm.SelectInputSettings{
InputName: "countryHintBoxed",
Label: "Country",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "country",
HintValue: "This is a helpful hint.",
HintDisplay: uiForm.InputHintDisplayTooltip,
HintIconStyle: uiForm.InputHintIconStyleBoxed,
})OnChangeFunc
OnChangeFunc
OnChangeFunc runs when the selection changes and when the field is cleared.
Usage
@uiForm.SelectInput(uiForm.SelectInputSettings{
InputName: "countryChange",
Label: "Country",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "country",
ShouldIncludeBlankOption: true,
OnChangeFunc: "onCountryChange()",
})Alpine.js Parent State (x-data)
<div x-data="{country: 'Brazil', changeCount: 0, onCountryChange() { this.changeCount++ }}"></div>The function runs when the selection changes. Clear the field to see it run again.
Change count:
Sizes
Sizes
Size scales the select trigger and its label: xs, sm, md (the default), lg, or xl.
Usage
@uiForm.SelectInput(uiForm.SelectInputSettings{
InputName: "countrySize",
Label: "Country",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
Size: uiForm.SelectInputSizeLg,
})Text Case
Text Case
TextCase transforms the field label. It accepts uiToolset.TextCaseNone (the default, as typed), TextCaseLower, TextCaseUpper, or TextCaseCapitalize.
Usage
@uiForm.SelectInput(uiForm.SelectInputSettings{
InputName: "countryCase",
Label: "Country",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TextCase: uiToolset.TextCaseUpper,
})Dropdown Background
Dropdown Background
DropdownBackgroundColor sets the dropdown surface color. It accepts a Tailwind token.
Usage
@uiForm.SelectInput(uiForm.SelectInputSettings{
InputName: "countryDropdown",
Label: "Country",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "countryDropdown",
DropdownBackgroundColor: "emerald-900",
})Open the dropdown to see the background color.
Required
Required
IsRequired marks the field as required.
Usage
@uiForm.SelectInput(uiForm.SelectInputSettings{
InputName: "countryRequired",
Label: "Country",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "country",
ShouldIncludeBlankOption: true,
IsRequired: true,
})Disabled Binding
Disabled Binding
IsDisabledOneWayStatePath disables the select from Alpine state.
Usage
@uiForm.SelectInput(uiForm.SelectInputSettings{
InputName: "countryDisabled",
Label: "Country",
// OptionalFields
FlatOptions: []string{"Argentina", "Brazil", "Chile"},
TwoWayStatePath: "country",
ShouldIncludeBlankOption: true,
IsDisabledOneWayStatePath: "isDisabled",
})Alpine.js Parent State (x-data)
<div x-data="{country: 'Brazil', isDisabled: true}"></div>.TextArea
A textarea is a form element that allows users to enter multiple lines of text.
Usage
@uiForm.TextArea(uiForm.TextAreaSettings{
InputName: "description",
Label: "Description",
// OptionalFields
TwoWayStatePath: "description",
})Alpine.js Parent State (x-data)
<div x-data="{description: ''}"></div>Live Example
A labeled textarea bound to Alpine state.
Value:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Value & Read-Only
Value & Read-Only
Value seeds the field content. IsReadOnly shows the value without accepting edits.
Usage
@uiForm.TextArea(uiForm.TextAreaSettings{
InputName: "description",
Label: "Description",
// OptionalFields
Value: "Lorem ipsum dolor sit amet.",
IsReadOnly: true,
})Code Mode
Code Mode
IsCode switches the field to a monospace editor styled for source code.
Usage
@uiForm.TextArea(uiForm.TextAreaSettings{
InputName: "snippet",
Label: "Snippet",
// OptionalFields
TwoWayStatePath: "snippet",
IsCode: true,
})Hints
Hints
HintValue explains the field. HintDisplay shows it as a description below the field or as a tooltip. The HintDisplayTooltip fields shape the tooltip surface.
Usage
@uiForm.TextArea(uiForm.TextAreaSettings{
InputName: "description",
Label: "Description",
// OptionalFields
TwoWayStatePath: "description",
HintValue: "This is a helpful hint.",
HintDisplay: uiForm.InputHintDisplayTooltip,
HintDisplayTooltipBackgroundColor: "violet-950/95",
HintDisplayTooltipMinWidthClass: "min-w-40",
HintDisplayTooltipMaxWidthClass: "max-w-64",
HintDisplayTooltipMinHeightClass: "min-h-10",
HintDisplayTooltipMaxHeightClass: "max-h-24",
})Hint State Path
Hint State Path
HintStatePath reads the hint text from Alpine state, so the hint updates as the state changes.
Usage
@uiForm.TextArea(uiForm.TextAreaSettings{
InputName: "description",
Label: "Description",
// OptionalFields
TwoWayStatePath: "description",
HintStatePath: "hintText",
HintDisplay: uiForm.InputHintDisplayTooltip,
})Sizes
Sizes
Size scales the textarea height and font: xs, sm, md (the default), lg, or xl.
Usage
@uiForm.TextArea(uiForm.TextAreaSettings{
InputName: "description",
Label: "Description",
// OptionalFields
TwoWayStatePath: "description",
Size: uiForm.TextAreaSizeLg,
})Text Case
Text Case
TextCase transforms the label and the placeholder. It accepts uiToolset.TextCaseNone (the default, as typed), TextCaseLower, TextCaseUpper, or TextCaseCapitalize.
Usage
@uiForm.TextArea(uiForm.TextAreaSettings{
InputName: "description",
Label: "Description",
// OptionalFields
TwoWayStatePath: "description",
TextCase: uiToolset.TextCaseUpper,
})Required
Required
IsRequired marks the field as required.
Usage
@uiForm.TextArea(uiForm.TextAreaSettings{
InputName: "description",
Label: "Description",
// OptionalFields
TwoWayStatePath: "description",
IsRequired: true,
}).ToggleSwitch
A switch toggles a boolean state or adds and removes a custom value from an array.
Usage
@uiForm.ToggleSwitch(uiForm.ToggleSwitchSettings{
Label: "Enable notifications",
TwoWayStatePath: "isNotificationsEnabled",
// OptionalFields
InputName: "notificationsEnabled",
})Alpine.js Parent State (x-data)
<div x-data="{isNotificationsEnabled: false}"></div>
<div x-data="{selectedChannels: ['email']}"></div>Live Example
The two binding modes: a boolean toggle and channel switches bound to an array.
Boolean state
Value:
Array state
Values:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Sizes
Sizes
Size scales the track, thumb, and label: xs, sm, md, lg, or xl.
Usage
@uiForm.ToggleSwitch(uiForm.ToggleSwitchSettings{
Label: "Enable notifications",
TwoWayStatePath: "isNotificationsEnabled",
// OptionalFields
Size: uiForm.ToggleSwitchSizeMd,
})Label Position
Label Position
LabelPosition places the label on the left or the right of the switch. TextCase transforms the label.
Usage
@uiForm.ToggleSwitch(uiForm.ToggleSwitchSettings{
Label: "Enable notifications",
TwoWayStatePath: "isNotificationsEnabled",
// OptionalFields
LabelPosition: uiForm.ToggleSwitchLabelPositionLeft,
TextCase: uiToolset.TextCaseUpper,
})Color Variants
Color Variants
Track, thumb, border, text, and focus colors accept Tailwind color tokens.
Usage
@uiForm.ToggleSwitch(uiForm.ToggleSwitchSettings{
Label: "Emerald accent",
TwoWayStatePath: "emeraldEnabled",
// OptionalFields
TrackBackgroundColor: "emerald-900/40",
TrackCheckedBackgroundColor: "emerald-500",
ThumbBackgroundColor: "amber-300",
ThumbBorderColor: "amber-500",
TextColor: "amber-100",
FocusRingColor: "emerald-500/50",
})Required & Disabled
Required & Disabled
IsRequired marks the switch as required. IsDisabled blocks edits.
Usage
@uiForm.ToggleSwitch(uiForm.ToggleSwitchSettings{
Label: "Enable notifications",
TwoWayStatePath: "isNotificationsEnabled",
// OptionalFields
IsRequired: true,
IsDisabled: false,
})Custom Values
Custom Values
CustomValue turns the switch into an array toggle: it adds the value when checked and removes it when unchecked. InputName includes the selection in form submission.
Usage
@uiForm.ToggleSwitch(uiForm.ToggleSwitchSettings{
Label: "Email notifications",
TwoWayStatePath: "selectedChannels",
InputName: "channels",
// OptionalFields
CustomValue: "email",
})Values:
@uiDisplay
uiDisplay is a collection of components for displaying content.
.Accordion
An accordion is a vertically stacked list of items that can be expanded or collapsed to reveal content.
Usage
@uiDisplay.Accordion(uiDisplay.AccordionSettings{
Items: []uiDisplay.AccordionItemSettings{
{Title: "Section 1", Content: AccordionDemoSection1()},
{Title: "Section 2", Content: AccordionDemoSection2()},
{Title: "Section 3", Content: AccordionDemoSection3()},
},
})Live Example
Three titled sections, each holding its own content.
Section 1
This is the content for section 1. You can put any content here.
Section 2
This is the content for section 2. You can put any content here.
Section 3
This is the content for section 3. You can put any content here.
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Item Icons
Item Icons
Icon renders a Phosphor icon beside the item title.
Usage
@uiDisplay.Accordion(uiDisplay.AccordionSettings{
Items: []uiDisplay.AccordionItemSettings{
{Title: "Section 1", Content: AccordionDemoSection1(), Icon: "ph-info"},
{Title: "Section 2", Content: AccordionDemoSection2(), Icon: "ph-warning"},
},
})Section 1
This is the content for section 1. You can put any content here.
Section 2
This is the content for section 2. You can put any content here.
Section 3
This is the content for section 3. You can put any content here.
Surface & Padding
Surface & Padding
Background, open background, content background, title color, border, and radius style the item surface. PaddingSize and ContentPaddingSize scale the paddings.
Usage
@uiDisplay.Accordion(uiDisplay.AccordionSettings{
Items: []uiDisplay.AccordionItemSettings{
{Title: "Section 1", Content: AccordionDemoSection1()},
},
// OptionalFields
BackgroundColor: "primary-900/40",
OpenBackgroundColor: "primary-800/60",
ContentBackgroundColor: "primary-950",
TitleColor: "primary-100",
BorderColor: "primary-500/30",
BorderRadius: uiDisplay.AccordionBorderRadiusXl,
PaddingSize: uiDisplay.AccordionPaddingSizeLg,
ContentPaddingSize: uiDisplay.AccordionPaddingSizeXl,
})Section 1
This is the content for section 1. You can put any content here.
Section 2
This is the content for section 2. You can put any content here.
Single Open
Single Open
IsSingleOpen keeps one item open at a time. Opening a section closes the section that was open.
Usage
@uiDisplay.Accordion(uiDisplay.AccordionSettings{
Items: []uiDisplay.AccordionItemSettings{
{Title: "Section 1", Content: AccordionDemoSection1()},
{Title: "Section 2", Content: AccordionDemoSection2()},
{Title: "Section 3", Content: AccordionDemoSection3()},
},
// OptionalFields
IsSingleOpen: true,
})Section 1
This is the content for section 1. You can put any content here.
Section 2
This is the content for section 2. You can put any content here.
Section 3
This is the content for section 3. You can put any content here.
Text Case
Text Case
TextCase transforms the item titles. It accepts uiToolset.TextCaseNone (the default, as typed), TextCaseLower, TextCaseUpper, or TextCaseCapitalize.
Usage
@uiDisplay.Accordion(uiDisplay.AccordionSettings{
Items: []uiDisplay.AccordionItemSettings{
{Title: "Section 1", Content: AccordionDemoSection1()},
{Title: "Section 2", Content: AccordionDemoSection2()},
},
// OptionalFields
TextCase: uiToolset.TextCaseUpper,
})Section 1
This is the content for section 1. You can put any content here.
Section 2
This is the content for section 2. You can put any content here.
.Alert
An alert is a notification component that displays important information to users.
Usage
@uiDisplay.Alert(uiDisplay.AlertSettings{
Title: "Alert Title",
Description: "This is an alert message.",
Variation: uiDisplay.AlertVariationInfo,
Size: uiDisplay.AlertSizeMd,
IsCloseable: true,
})Live Example
The four tone variations: success, warning, error, and info.
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Sizes
Sizes
Size scales the alert padding and type: xs, sm, md, lg, or xl. MaxWidth caps the width with a Tailwind size token.
Usage
@uiDisplay.Alert(uiDisplay.AlertSettings{
Title: "Alert Title",
Description: "This is an alert message.",
Variation: uiDisplay.AlertVariationInfo,
Size: uiDisplay.AlertSizeMd,
MaxWidth: "md",
})Content Html Slot
Content Html Slot
ContentHtml replaces the plain description with a templ component of your own.
Usage
@uiDisplay.Alert(uiDisplay.AlertSettings{
Title: "Deploy finished",
// OptionalFields
ContentHtml: AlertDemoCustomContent(),
})Deploy finished on edge-03. Wire in any templ component here.
Icons
Icons
TitleLeftIcon replaces the variation icon on the left. TitleRightIcon adds an icon on the right. The TwoWayStatePath variants bind the icon classes to Alpine state.
Usage
@uiDisplay.Alert(uiDisplay.AlertSettings{
Title: "Rocket deploy",
Description: "TitleLeftIcon and TitleRightIcon frame the content.",
TitleLeftIcon: "ph-rocket-launch",
TitleRightIcon: "ph-arrow-right",
})Close & Timeout
Close & Timeout
IsCloseable adds the dismiss button and OnCloseFunc runs when it is pressed. DisplayTimeoutSeconds auto-dismisses the alert and runs OnTimeoutFunc.
Usage
@uiDisplay.Alert(uiDisplay.AlertSettings{
Title: "Alert Title",
Description: "This is an alert message.",
// OptionalFields
IsCloseable: true,
OnCloseFunc: "alertClosed = true",
DisplayTimeoutSeconds: 8,
OnTimeoutFunc: "alertTimedOut = true",
})Closed: · Timed out:
Custom Surface
Custom Surface
Background, text, ring, radius, shadow, and close-icon colors accept Tailwind tokens. TextTitleColor and TextDescriptionColor style the title and description separately. Gradient backgrounds work too.
Usage
@uiDisplay.Alert(uiDisplay.AlertSettings{
Title: "Alert Title",
Description: "This is an alert message.",
// OptionalFields
BackgroundColor: "cyan-500/20",
TextColor: "cyan-100",
TextTitleColor: "cyan-50",
TextDescriptionColor: "cyan-200",
RingThickness: uiDisplay.AlertRingThicknessLg,
RingColor: "cyan-400",
ShadowSize: uiDisplay.AlertShadowSizeXl,
BorderRadius: uiDisplay.AlertBorderRadiusLg,
CloseIconBackgroundColor: "cyan-500/30",
CloseIconTextColor: "white",
})State-Bound Content
State-Bound Content
TitleOneWayStatePath, DescriptionOneWayStatePath, and IsCloseableOneWayStatePath drive the alert from Alpine state.
Usage
@uiDisplay.Alert(uiDisplay.AlertSettings{
Title: "Dynamic Content Alert",
TitleOneWayStatePath: "alertTitle",
DescriptionOneWayStatePath: "alertMessage",
Variation: uiDisplay.AlertVariationInfo,
// OptionalFields
IsCloseableOneWayStatePath: "isAlertCloseable",
}).CloakLoading (pre-Alpine/HTMX)
A cloak loading screen that appears only before the JavaScript libraries are loaded to prevent FOUC (Flash of Unstyled Content).
Usage
@uiDisplay.CloakLoading(uiDisplay.CloakLoadingSettings{})Set colors as rgb(a), hex, or hsl(a) values: they are used in the inline style.Live Example
Since the demo is already loaded with Alpine.js, the CloakLoading component will behave like a regular loading overlay. In a real application, this would be the first thing that appears when the page starts loading.
The page content will be covered by the cloak loading screen when triggered.
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Custom Text
Custom Text
TextMessage replaces the default loading label. TextColor and TextSize style it. Set colors as rgb(a), hex, or hsl(a) values: they are used in an inline style.
Usage
@uiDisplay.CloakLoading(uiDisplay.CloakLoadingSettings{
// OptionalFields
BackgroundColor: "rgb(30, 58, 138)",
TextMessage: "Please wait...",
TextColor: "rgb(255, 255, 255)",
TextSize: uiDisplay.CloakLoadingTextSizeLg,
})The cloak screen covers this content when triggered.
Icon & Animation
Icon & Animation
Icon replaces the spinner. IconSize scales it. IconAnimationName spins or pulses it over IconAnimationDurationSeconds.
Usage
@uiDisplay.CloakLoading(uiDisplay.CloakLoadingSettings{
// OptionalFields
Icon: "ph-hourglass",
IconSize: uiDisplay.CloakLoadingIconSizeMd,
IconColor: "rgb(110, 231, 183)",
IconAnimationName: uiDisplay.CloakLoadingAnimationNamePulse,
IconAnimationDurationSeconds: "2",
})The cloak screen covers this content when triggered.
Hide Delay
Hide Delay
HideDelaySeconds keeps the cloak on screen for a moment after the libraries load, so the hand-off does not flash. It defaults to 1 second.
Usage
@uiDisplay.CloakLoading(uiDisplay.CloakLoadingSettings{
// OptionalFields
HideDelaySeconds: "3",
})The cloak screen covers this content when triggered.
.ConfirmationDialog
Confirmation dialog presets: confirm, warning, critical, and delete. Each preset supplies its icon, tone, and confirmation copy. Delete and critical gate the confirm action behind typing the target name.
Usage
@uiDisplay.DeleteDialog(uiDisplay.ConfirmationDialogSettings{
IsVisibleTwoWayStatePath: "isDeleteDialogVisible",
OnConfirmFunc: "deleteRecord()",
// OptionalFields
TargetNameStatePath: "demoTargetName",
TargetIdStatePath: "demoTargetId",
WidthPercent: 32,
MinHeightPercent: 42,
})Alpine.js Parent State (x-data)
<div x-data="{
isDeleteDialogVisible: false,
demoTargetName: 'primary-database',
demoTargetId: '42',
}"></div>Live Example
The four presets against one target. Delete and critical require typing the target name.
Target: (id: ) · Confirmed: nothing yet
Presets
Confirm Action
Are you sure you want to proceed with # ?
This action needs your confirmation.
Warning
Are you sure you want to proceed with # ?
Review the effects before you continue.
Critical Action
Are you sure you want to proceed with # ?
This action cannot be undone.
Delete
Are you sure you want to delete # ?
This process cannot be undone. This will permanently delete the element(s).
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Type-to-Confirm
Type-to-Confirm
IsTypeToConfirmEnabled gates the confirm button behind a typed match. The first dialog matches the TypeToConfirmExpectedValue phrase; the second matches the bound TargetNameStatePath and TargetIdStatePath. TypeToConfirmValueTwoWayStatePath binds the typed value to your own Alpine state. The delete and critical presets enable this by default.
Usage
@uiDisplay.ConfirmDialog(uiDisplay.ConfirmationDialogSettings{
IsVisibleTwoWayStatePath: "isTypeToConfirmVisible",
OnConfirmFunc: "runAction()",
// OptionalFields
IsTypeToConfirmEnabled: true,
TypeToConfirmExpectedValue: "proceed",
TypeToConfirmValueTwoWayStatePath: "typedConfirmationValue",
// Or match the bound target name and id
TargetNameStatePath: "demoTargetName",
TargetIdStatePath: "demoTargetId",
})Confirmed:
Typed Prompt
Are you sure you want to proceed?
This action needs your confirmation.
Target Prompt
Are you sure you want to proceed with # ?
This action needs your confirmation.
Uncloseable
Uncloseable
IsUncloseable hides the close button and ignores backdrop clicks. CancelFunc still closes the dialog from its cancel button.
Usage
@uiDisplay.ConfirmDialog(uiDisplay.ConfirmationDialogSettings{
IsVisibleTwoWayStatePath: "isUncloseableVisible",
OnConfirmFunc: "runAction()",
// OptionalFields
IsUncloseable: true,
CancelFunc: "isUncloseableVisible = false",
})Uncloseable Prompt
Are you sure you want to proceed?
This action needs your confirmation.
Button Labels & Icons
Button Labels & Icons
ConfirmButtonLabel, ConfirmButtonIcon, and CancelButtonLabel override the preset copy. CancelFunc runs when the cancel button is pressed.
Usage
@uiDisplay.ConfirmDialog(uiDisplay.ConfirmationDialogSettings{
IsVisibleTwoWayStatePath: "isLabelsVisible",
OnConfirmFunc: "runAction()",
// OptionalFields
HeaderTitle: "Purge Records",
ConfirmButtonLabel: "Purge Everything",
ConfirmButtonIcon: "ph-fire",
CancelButtonLabel: "Keep It",
})Confirmed:
Purge Records
Are you sure you want to proceed?
This action needs your confirmation.
Custom Message & Header
Custom Message & Header
Message sets the note under the question. MessageContent replaces the whole question block, so it wins when both are set. HeaderContent replaces the icon and title block. Size sets the dialog width.
Usage
@uiDisplay.ConfirmDialog(uiDisplay.ConfirmationDialogSettings{
IsVisibleTwoWayStatePath: "isSlotsVisible",
OnConfirmFunc: "runAction()",
// OptionalFields
Message: "This action cannot be undone.",
MessageContent: ConfirmationDialogDemoCustomMessage(),
HeaderContent: ConfirmationDialogDemoCustomHeader(),
Size: uiDisplay.ConfirmationDialogSizeLg,
})Confirmed:
Maintenance window
Drain the edge pool?
Billing impact
Removing this record stops the metered plan at the end of the cycle. Invoices already issued stay open.
Icon On Left
Icon On Left
HeaderIconPosition defaults to Top, which centers the icon above the title. HeaderIconPositionLeft places it beside the title. HeaderIcon swaps the preset icon. HeaderIconColor, HeaderIconBackgroundColor, HeaderIconBorderRadius, and HeaderIconPaddingSize shape it. HeaderSize scales the title and icon.
Usage
@uiDisplay.WarningDialog(uiDisplay.ConfirmationDialogSettings{
IsVisibleTwoWayStatePath: "isIconPositionVisible",
OnConfirmFunc: "runAction()",
// OptionalFields
HeaderIcon: "ph-rocket-launch",
HeaderIconPosition: uiDisplay.HeaderIconPositionLeft,
HeaderIconColor: "sky-300",
HeaderIconBackgroundColor: "sky-500/20",
HeaderIconBorderRadius: uiDisplay.HeaderIconBorderRadiusSm,
HeaderIconPaddingSize: uiDisplay.HeaderIconPaddingSizeSm,
HeaderSize: uiDisplay.HeaderSizeMd,
})Icon Beside Title
Are you sure you want to proceed?
Review the effects before you continue.
Header Text Styling
Header Text Styling
HeaderSubHeading adds a line under the title. HeaderTitleColor, HeaderSubHeadingColor, and TextColor color the title, the sub-heading, and the block text. HeaderTitleOneWayStatePath and HeaderSubHeadingOneWayStatePath bind both lines to Alpine state. TextCase transforms the text.
Usage
@uiDisplay.ConfirmDialog(uiDisplay.ConfirmationDialogSettings{
IsVisibleTwoWayStatePath: "isHeaderTextVisible",
OnConfirmFunc: "runAction()",
// OptionalFields
HeaderTitle: "Reindex Storage",
HeaderTitleColor: "amber-300",
HeaderTitleOneWayStatePath: "headerTextTitle",
HeaderSubHeading: "Runs in the background",
HeaderSubHeadingColor: "emerald-300",
HeaderSubHeadingOneWayStatePath: "headerTextSubHeading",
TextCase: uiToolset.TextCaseUpper,
TextColor: "neutral-200",
})Reindex Storage
Runs in the background
Are you sure you want to proceed?
This action needs your confirmation.
Sizing Bounds
Sizing Bounds
HeightPercent fixes the dialog height instead of matching the content. MinWidthPercent and MaxWidthPercent clamp the width. MaxHeightPercent caps the height.
Usage
@uiDisplay.ConfirmDialog(uiDisplay.ConfirmationDialogSettings{
IsVisibleTwoWayStatePath: "isSizingVisible",
OnConfirmFunc: "runAction()",
// OptionalFields
HeightPercent: 50,
MinWidthPercent: 60,
MaxWidthPercent: 70,
MaxHeightPercent: 40,
})Bounded Dialog
Are you sure you want to proceed?
This action needs your confirmation.
Header Actions
Header Actions
ActionsContent renders custom controls at the end of the dialog header. The close button stays at the top right.
Usage
@uiDisplay.ConfirmDialog(uiDisplay.ConfirmationDialogSettings{
IsVisibleTwoWayStatePath: "isActionsVisible",
OnConfirmFunc: "runAction()",
// OptionalFields
ActionsContent: ConfirmationDialogDemoHeaderActions(),
})Review Changes
Are you sure you want to proceed?
This action needs your confirmation.
.LoadingOverlay (htmx-ready)
A loading overlay displays a loading indicator over content to show that an operation is in progress.
Usage
@uiDisplay.LoadingOverlay(uiDisplay.LoadingOverlaySettings{
IsLoadingOneWayStatePath: "isLoading",
})Alpine.js Parent State (x-data)
<div x-data="{isLoading: false}"></div>Live Example
An overlay driven by one boolean state path. Trigger it to cover the content below.
The page content will be covered by the loading overlay when triggered.
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Icon & Animation
Icon & Animation
Icon replaces the spinner. IconSize scales it. AnimationName spins or pulses it over AnimationDurationSeconds.
Usage
@uiDisplay.LoadingOverlay(uiDisplay.LoadingOverlaySettings{
IsLoadingOneWayStatePath: "isLoading",
// OptionalFields
Icon: "ph-compass-rose",
IconSize: uiDisplay.LoadingOverlayIconSizeMd,
AnimationName: uiDisplay.LoadingOverlayAnimationNameSpin,
AnimationDurationSeconds: "2",
})The overlay covers this content while it loads.
Background Color
Background Color
BackgroundColor paints the veil over the content.
Usage
@uiDisplay.LoadingOverlay(uiDisplay.LoadingOverlaySettings{
IsLoadingOneWayStatePath: "isLoading",
// OptionalFields
BackgroundColor: "neutral-900/80",
})The overlay covers this content while it loads.
.Modal
A modal is a dialog box that appears on top of the main content to display additional information or request user input.
Usage
@uiDisplay.Modal(uiDisplay.ModalSettings{
MiddleContent: ModalDemoContent(),
// OptionalFields
Title: "Modal Title",
InitialSize: uiDisplay.ModalSizeMd,
IsVisibleTwoWayStatePath: "isModalVisible",
})Alpine.js Parent State (x-data)
<div x-data="{
isModalVisible: false,
modalSize: 'md',
modalTitle: 'Interactive Modal'
}"></div>Live Example
The interactive modal: size presets, resize controls, a state-bound title, and a close callback.
Basic Modal
Different Sizes
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Uncloseable
Uncloseable
IsUncloseable hides the close button and ignores backdrop clicks. Your content closes the modal through its own state path.
Usage
@uiDisplay.Modal(uiDisplay.ModalSettings{
MiddleContent: UncloseableModalDemoContent(),
Title: "Uncloseable Modal",
// OptionalFields
IsUncloseable: true,
IsVisibleTwoWayStatePath: "isUncloseableModalVisible",
})Uncloseable Modal
This modal hides the close button and ignores backdrop clicks. Use the button below to close it.
Unresizable & OnResize
Unresizable & OnResize
IsUnresizable hides the resize buttons. OnResizeFunc runs every time the user resizes a closeable modal through those buttons.
Usage
@uiDisplay.Modal(uiDisplay.ModalSettings{
MiddleContent: ModalDemoContent(),
Title: "Fixed Size Modal",
// OptionalFields
IsUnresizable: true,
OnResizeFunc: "resizeCount = resizeCount + 1",
})OnResizeFunc calls:
Fixed Size Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Resize-Tracked Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Header & Footer Slots
Header & Footer Slots
HeaderContent replaces the title bar. FooterContent renders under the body for actions. Set Title or TitleOneWayStatePath as well to keep an accessible name when the header is custom.
Usage
@uiDisplay.Modal(uiDisplay.ModalSettings{
MiddleContent: ModalDemoContent(),
// OptionalFields
HeaderContent: ModalDemoHeader(),
FooterContent: ModalDemoFooter(),
TitleOneWayStatePath: "slotsModalTitle",
IsVisibleTwoWayStatePath: "isSlotsModalVisible",
})Slots Modal
Custom Header Slot
betaThis is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Custom Surface
Custom Surface
Backdrop, background, ring, radius, shadow, and text colors accept Tailwind tokens.
Usage
@uiDisplay.Modal(uiDisplay.ModalSettings{
MiddleContent: ModalDemoContent(),
Title: "Blue Backdrop Modal",
// OptionalFields
BackdropColor: "blue-900/60",
BackgroundColor: "primary-900",
TextColor: "neutral-100",
ShadowSize: uiDisplay.ModalShadowSizeXl,
RingColor: "primary-500",
RingThickness: "md",
BorderRadius: "lg",
IsVisibleTwoWayStatePath: "isBlueBackdropModalVisible",
})Background Colors
Backdrop Colors
Ring Variations
Border Radius
Dark Background Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Primary Background Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Secondary Background Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Blue Backdrop Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Red Backdrop Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Primary Ring Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Emerald Ring Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Red Ring Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Thin Violet Ring Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Square Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Small Radius Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Large Radius Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Extra Large Radius Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Near-Full Size
Near-Full Size
ModalSizeXxl spans about 90% of the viewport in both directions. Tall content like a terminal session is its usual partner.
Usage
@uiDisplay.Modal(uiDisplay.ModalSettings{
MiddleContent: TerminalModalDemoContent(),
Title: "WebTerminal Modal",
// OptionalFields
InitialSize: uiDisplay.ModalSizeXxl,
IsVisibleTwoWayStatePath: "isTerminalModalVisible",
})WebTerminal Modal
agent@opencode:~$ run --task "ship the feature"
planning the change across 4 files...
applying edits (12 hunks, 3 packages)
agent@opencode:~$ tests/tests.sh fast
go test ./src/... ok · playwright 18 passed
agent@opencode:~$
Custom Dimensions
Custom Dimensions
WidthPercent and HeightPercent replace the width and height of InitialSize; InitialSize keeps its padding and header scale. The Min and Max fields clamp each axis. Pinning both axes retires the resize controls. IsMiddleContentScrollDisabled pins the body for embedded apps like a terminal. ShouldHeightMatchContent sizes the height to the content.
Usage
@uiDisplay.Modal(uiDisplay.ModalSettings{
MiddleContent: TerminalModalDemoContent(),
Title: "Pinned Dimensions Modal",
// OptionalFields
InitialSize: uiDisplay.ModalSizeMd,
WidthPercent: 70,
HeightPercent: 45,
MinWidthPercent: 50,
MaxWidthPercent: 90,
MinHeightPercent: 30,
MaxHeightPercent: 60,
IsMiddleContentScrollDisabled: true,
IsVisibleTwoWayStatePath: "isPinnedDimensionsModalVisible",
})
@uiDisplay.Modal(uiDisplay.ModalSettings{
MiddleContent: ModalDemoContent(),
Title: "Content Height Modal",
// OptionalFields
InitialSize: uiDisplay.ModalSizeMd,
ShouldHeightMatchContent: true,
IsVisibleTwoWayStatePath: "isContentHeightModalVisible",
})Pinned Dimensions Modal
agent@opencode:~$ run --task "ship the feature"
planning the change across 4 files...
applying edits (12 hunks, 3 packages)
agent@opencode:~$ tests/tests.sh fast
go test ./src/... ok · playwright 18 passed
agent@opencode:~$
Content Height Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
Size Slice
Size Slice
PossibleSizes is the ordered set of sizes and InitialSize is its first entry; entries below it are dropped. Enlarge steps up the set, reduce steps back down, and each control hides when it would do nothing.
Usage
@uiDisplay.Modal(uiDisplay.ModalSettings{
MiddleContent: ModalDemoContent(),
Title: "Size Slice Modal",
// OptionalFields
InitialSize: uiDisplay.ModalSizeMd,
PossibleSizes: []string{uiDisplay.ModalSizeMd, uiDisplay.ModalSizeLg, uiDisplay.ModalSizeXl},
IsVisibleTwoWayStatePath: "isSizeSliceModalVisible",
})Size Slice Modal
This is the modal content area. You can put any content here including forms, images, or other components.
Features:
- Click outside to close (when closeable)
- Use the close button in the header
- Resize using the + and - buttons
- Responsive design for different screen sizes
.Sidebar
A sidebar is a vertical navigation component that can contain various types of content.
Usage
@uiStructural.Sidebar(uiStructural.SidebarSettings{
MiddleContent: SidebarDemoMiddle(),
// OptionalFields
HeaderContent: SidebarDemoHeader(),
FooterContent: SidebarDemoFooter(),
IsVisibleTwoWayStatePath: "isVisible",
IsCollapsedTwoWayStatePath: "isCollapsed",
})Alpine.js Parent State (x-data)
<div x-data="{
isVisible: true,
isCollapsed: false,
}"></div>Live Example
An app shell with header, middle, and footer content. Collapse it or hide it from the controls.
Controls
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Attachment Modes
Attachment Modes
inline keeps the sidebar in the page flow. fixed pins it to the viewport while the rest of the page scrolls. Set AttachmentMode directly, or use AttachmentModeTwoWayStatePath to switch at runtime.
Usage
@uiStructural.Sidebar(uiStructural.SidebarSettings{
MiddleContent: SidebarDemoMiddle(),
// OptionalFields
HeaderContent: SidebarDemoHeader(),
FooterContent: SidebarDemoFooter(),
AttachmentMode: uiStructural.SidebarAttachmentModeInline,
AttachmentModeTwoWayStatePath: "attachmentMode",
})AttachmentMode
Off-Canvas
Off-Canvas
IsOffCanvas overlays the sidebar on the content instead of pushing it. Pair it with IsVisibleTwoWayStatePath for a drawer.
Usage
@uiStructural.Sidebar(uiStructural.SidebarSettings{
MiddleContent: SidebarDemoMiddle(),
// OptionalFields
HeaderContent: SidebarDemoHeader(),
FooterContent: SidebarDemoFooter(),
IsOffCanvas: true,
IsOffCanvasTwoWayStatePath: "isOffCanvas",
IsVisibleTwoWayStatePath: "isVisible",
})OffCanvas
Side
Side
Side attaches the sidebar to the left or right edge. Set Side directly to pin it, or use SideTwoWayStatePath to switch at runtime.
Usage
@uiStructural.Sidebar(uiStructural.SidebarSettings{
MiddleContent: SidebarDemoMiddle(),
// OptionalFields
HeaderContent: SidebarDemoHeader(),
FooterContent: SidebarDemoFooter(),
SideTwoWayStatePath: "side",
})
@uiStructural.Sidebar(uiStructural.SidebarSettings{
MiddleContent: SidebarDemoMiddle(),
// OptionalFields
HeaderContent: SidebarDemoHeader(),
FooterContent: SidebarDemoFooter(),
Side: uiStructural.SidebarSideRight,
})Side
Width & Background
Width & Background
Width accepts a Tailwind width class. BackgroundColor accepts a Tailwind background class, opacity included. The second preview sets IsCollapsed: true with a matching Width for a static collapsed sidebar.
Usage
@uiStructural.Sidebar(uiStructural.SidebarSettings{
MiddleContent: SidebarDemoMiddle(),
// OptionalFields
HeaderContent: SidebarDemoHeader(),
FooterContent: SidebarDemoFooter(),
Width: "w-46",
BackgroundColor: "bg-primary-900/80",
})
@uiStructural.Sidebar(uiStructural.SidebarSettings{
MiddleContent: SidebarDemoMiddle(),
// OptionalFields
HeaderContent: SidebarDemoHeader(),
FooterContent: SidebarDemoFooter(),
Width: "w-16",
IsCollapsed: true,
}).Tag
A tag is a small label that can be used to categorize or identify content.
Usage
@uiDisplay.Tag(uiDisplay.TagSettings{
OuterLeftIcon: "ph-info",
OuterLeftLabel: "Info",
InnerLabel: "Warning",
})Live Example
The common shapes: an outer label with an inner label, and an outer label with a bound inner value.
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Sizes
Sizes
Size scales the outer and inner segments: tiny, xs, sm, md, lg, or xl.
Usage
@uiDisplay.Tag(uiDisplay.TagSettings{
OuterLeftIcon: "ph-info",
OuterLeftLabel: "Info",
InnerIcon: "ph-warning",
InnerLabel: "Warning",
// OptionalFields
Size: uiDisplay.TagSizeSm,
})Radii
Radii
OuterRadius rounds the outer segment and InnerRadius rounds the inner one: none, xs, sm, md, lg, xl, or full.
Usage
@uiDisplay.Tag(uiDisplay.TagSettings{
OuterLeftIcon: "ph-info",
OuterLeftLabel: "Info",
InnerIcon: "ph-warning",
InnerLabel: "Warning",
// OptionalFields
OuterRadius: uiDisplay.TagRadiusMd,
InnerRadius: uiDisplay.TagRadiusMd,
})Outer Ring Colors
Outer Ring Colors
OuterRingColor outlines the outer segment. OuterRingThickness sets the outline width. Pair it with a transparent OuterBackgroundColor for an outlined tag.
Usage
@uiDisplay.Tag(uiDisplay.TagSettings{
OuterLeftIcon: "ph-info",
OuterLeftLabel: "Info",
// OptionalFields
OuterRingColor: "emerald-500",
OuterRingThickness: uiDisplay.TagRingThicknessLg,
OuterBackgroundColor: "transparent",
OuterTextColor: "neutral-50",
})Outer Background Colors
Outer Background Colors
OuterBackgroundColor fills the outer segment. OuterTextColor paints its label and icon.
Usage
@uiDisplay.Tag(uiDisplay.TagSettings{
OuterLeftIcon: "ph-info",
OuterLeftLabel: "Info",
// OptionalFields
OuterBackgroundColor: "emerald-500",
OuterTextColor: "neutral-50",
})Inner Colors
Inner Colors
InnerBackgroundColor and InnerTextColor style the inner segment only.
Usage
@uiDisplay.Tag(uiDisplay.TagSettings{
OuterLeftIcon: "ph-info",
OuterLeftLabel: "Info",
InnerIcon: "ph-warning",
InnerLabel: "Warning",
// OptionalFields
InnerBackgroundColor: "emerald-500",
InnerTextColor: "neutral-50",
})Side Element Actions
Side Element Actions
OuterLeftOnClickFunc and OuterRightOnClickFunc run on the outer side labels. OuterLeftLabelOneWayStatePath and OuterRightLabelOneWayStatePath bind the side labels to Alpine state. InnerLabelOneWayStatePath and InnerValueOneWayStatePath mirror Alpine state into the inner segment.
Usage
@uiDisplay.Tag(uiDisplay.TagSettings{
OuterLeftIcon: "ph-plus",
OuterLeftLabel: "Add",
OuterLeftOnClickFunc: "clickCount++",
OuterRightIcon: "ph-minus",
OuterRightLabel: "Remove",
OuterRightOnClickFunc: "if(clickCount > 0) clickCount--",
InnerIcon: "ph-hash",
InnerLabelOneWayStatePath: "clickCount",
})
@uiDisplay.Tag(uiDisplay.TagSettings{
OuterLeftIcon: "ph-pencil",
OuterLeftLabelOneWayStatePath: "leftActionLabel",
OuterRightIcon: "ph-pencil",
OuterRightLabelOneWayStatePath: "rightActionLabel",
})Count:
Removable Tags
Removable Tags
OnRemoveFunc renders a remove button on the tag. RemoveButtonLabel names it for screen readers.
Usage
@uiDisplay.Tag(uiDisplay.TagSettings{
OuterLeftLabel: "Status: running",
// OptionalFields
OnRemoveFunc: "showTag = false",
RemoveButtonLabel: "Remove status filter",
})Text Case
Text Case
TextCase transforms the tag labels. It accepts uiToolset.TextCaseNone (the default, as typed), TextCaseLower, TextCaseUpper, or TextCaseCapitalize.
Usage
@uiDisplay.Tag(uiDisplay.TagSettings{
OuterLeftLabel: "Info",
InnerLabel: "Warning",
// OptionalFields
TextCase: uiToolset.TextCaseUpper,
}).Toast
A toast is a temporary notification displayed to provide feedback to users.
Usage
@uiDisplay.Toast(uiDisplay.ToastSettings{
// OptionalFields
AutoDismissSeconds: 6,
BackgroundColor: "neutral-800",
TextColor: "neutral-50",
Size: uiDisplay.ToastSizeMd,
RingThickness: uiDisplay.ToastRingThicknessMd,
RingColor: "neutral-500",
Radius: uiDisplay.ToastRadiusMd,
})
@uiControl.Button(uiControl.ButtonSettings{
OnClickFunc: "$store.toast.displayToast('Saved!', 'success')",
})Live Example
One toast mount serves every message. Trigger the success, warning, and error tones below.
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
API Response Toasts
API Response Toasts
displayToastWithApiResponse reads an Infinite API envelope and picks the tone from the status code: 207 is a partial success, 400 and above is an error, anything else is a success.
Usage
$store.toast.displayToastWithApiResponse(apiResponse, httpStatusCode)
$store.toast.displayToastWithApiResponse({readableMessage: "Server rebuilt"}, 200)Mount Settings
Mount Settings
AutoDismissSeconds sets how long each toast stays up; it defaults to 10 seconds. Background, text, ring, and radius accept Tailwind tokens. Mount one Toast per page: the mount configures the shared toast store.
Usage
@uiDisplay.Toast(uiDisplay.ToastSettings{
// OptionalFields
AutoDismissSeconds: 6,
BackgroundColor: "neutral-800",
TextColor: "neutral-50",
Size: uiDisplay.ToastSizeMd,
RingThickness: uiDisplay.ToastRingThicknessMd,
RingColor: "neutral-500",
Radius: uiDisplay.ToastRadiusMd,
})The live example above already mounts a styled toast with a 6 second auto-dismiss. Every button on this page uses that mount.
@uiControl
uiControl is a collection of components for controlling content.
.Button
A button is a clickable element that can be used to trigger an action.
Usage
@uiControl.Button(uiControl.ButtonSettings{
Label: "Click me",
IconLeft: "ph-info",
OnClickFunc: "alert('Button clicked!')",
})Live Example
The action buttons an app reaches for: a primary action, a quiet secondary, and a destructive one.
New Record clicks:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Sizes
Sizes
Size scales the button and its type: xs, sm, md, lg, or xl.
Usage
@uiControl.Button(uiControl.ButtonSettings{
Label: "Button",
// OptionalFields
Size: uiControl.ButtonSizeMd,
})Shapes
Shapes
Shape rounds the button frame: square, rounded, or circular.
Usage
@uiControl.Button(uiControl.ButtonSettings{
Label: "Button",
// OptionalFields
Shape: uiControl.ButtonShapeRounded,
})Icons
Icons
IconLeft and IconRight flank the label with Phosphor icons. IconLeftOneWayStatePath and IconRightOneWayStatePath bind the icon class to Alpine state.
Usage
@uiControl.Button(uiControl.ButtonSettings{
Label: "Info",
// OptionalFields
IconLeft: "ph-info",
IconLeftOneWayStatePath: "leftIconClass",
IconRight: "ph-arrow-right",
IconRightOneWayStatePath: "rightIconClass",
})Colors
Colors
Background and text colors accept Tailwind tokens. The Hover variants paint the hover state.
Usage
@uiControl.Button(uiControl.ButtonSettings{
Label: "Save",
// OptionalFields
BackgroundColor: "emerald-500",
BackgroundColorHover: "emerald-600",
TextColor: "neutral-50",
TextColorHover: "neutral-50",
})Rings
Rings
RingColor and RingThickness outline the button. The Hover variants paint the hover ring.
Usage
@uiControl.Button(uiControl.ButtonSettings{
Label: "Red Ring",
// OptionalFields
BackgroundColor: "red-500/10",
BackgroundColorHover: "red-500/20",
RingColor: "red-500",
RingColorHover: "red-400",
RingThickness: uiControl.ButtonRingThicknessMd,
})Tooltips
Tooltips
TooltipContent renders a tooltip on hover. TooltipPosition places it on any side. TooltipBackgroundColor, TooltipTextColor, TooltipRingColor, and TooltipRingThickness style the surface. The Min and Max width and height classes set its size limits. TooltipContentHtml accepts a component, and TooltipContentOneWayStatePath binds live text.
Usage
@uiControl.Button(uiControl.ButtonSettings{
Label: "Top Tooltip",
// OptionalFields
TooltipContent: "This tooltip appears on top",
TooltipPosition: uiToolset.TooltipPositionTop,
TooltipBackgroundColor: "violet-950/95",
TooltipTextColor: "violet-100",
TooltipRingColor: "violet-500",
TooltipRingThickness: uiControl.ButtonRingThicknessMd,
TooltipMinWidthClass: "min-w-48",
TooltipMaxWidthClass: "max-w-72",
TooltipMinHeightClass: "min-h-12",
TooltipMaxHeightClass: "max-h-32",
})Disabled Binding
Disabled Binding
IsDisabledOneWayStatePath disables the button from Alpine state. IsDisabled disables it outright. IsVisibleOneWayStatePath hides it from Alpine state, and OnClickPreventDefault calls preventDefault before the click handler.
Usage
@uiControl.Button(uiControl.ButtonSettings{
Label: "Click Me",
// OptionalFields
OnClickFunc: "clickCount++",
OnClickPreventDefault: true,
IsDisabled: true,
IsDisabledOneWayStatePath: "shouldDisable",
IsVisibleOneWayStatePath: "isVisible",
})Count:
Full-Width & Submit
Full-Width & Submit
IsFullWidth stretches the button to its container. IsSubmit renders a submit input for forms.
Usage
@uiControl.Button(uiControl.ButtonSettings{
Label: "Save",
// OptionalFields
IsFullWidth: true,
IsSubmit: true,
})Text Case
Text Case
TextCase transforms the button label. It accepts uiToolset.TextCaseNone (the default, as typed), TextCaseLower, TextCaseUpper, or TextCaseCapitalize.
Usage
@uiControl.Button(uiControl.ButtonSettings{
Label: "New Record",
TextCase: uiToolset.TextCaseUpper,
}).RangeSlider
A range slider allows users to select a value from a range by dragging a thumb along a track.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbValueTwoWayStatePath: "sliderValue",
// OptionalFields
TrackStartValue: "0",
TrackEndValue: "100",
})Alpine.js Parent State (x-data)
<div x-data="{sliderValue: 50}"></div>Live Example
A slider bound to one numeric Alpine state path. Drag the thumb or use the arrow keys.
Value:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Sizes
Sizes
Size scales the track, thumb, and labels: xs, sm, md, lg, or xl.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbValueTwoWayStatePath: "sliderValue",
// OptionalFields
Size: uiControl.RangeSliderSizeMd,
})Thumb Shapes
Thumb Shapes
ThumbShape draws the thumb as circular, rounded, square, or pipe.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbValueTwoWayStatePath: "sliderValue",
// OptionalFields
ThumbShape: uiControl.RangeSliderThumbShapeCircular,
})Thumb Colors & Icons
Thumb Colors & Icons
Thumb background and text colors accept Tailwind tokens. ThumbLabel prints static text on the thumb, ThumbLabelIcon stamps an icon on it, and ThumbLabelOneWayStatePath prints live state on it.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbValueTwoWayStatePath: "sliderValue",
// OptionalFields
ThumbBackgroundColor: "emerald-500",
ThumbTextColor: "neutral-50",
ThumbLabel: "A",
ThumbLabelIcon: "ph-check",
ThumbLabelOneWayStatePath: "sliderValue",
})Value Bubble
Value Bubble
ThumbValueBubbleEnabled shows the live value above or below the thumb. The default display mode always shows it; ThumbValueBubbleDisplayModeHover shows it only while the slider is hovered or dragged. Bubble colors, size, shape, ring, and position style it.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbValueTwoWayStatePath: "sliderValue",
// OptionalFields
ThumbValueBubbleEnabled: true,
ThumbValueBubbleDisplayMode: uiControl.RangeSliderThumbValueBubbleDisplayModeHover,
ThumbValueBubblePosition: uiControl.RangeSliderThumbValueBubblePositionTop,
ThumbValueBubbleBackgroundColor: "red-500",
ThumbValueBubbleTextColor: "neutral-50",
ThumbValueBubbleSize: uiControl.RangeSliderThumbValueBubbleSizeLg,
ThumbValueBubbleShape: uiControl.RangeSliderThumbValueBubbleShapeRounded,
ThumbValueBubbleRingColor: "violet-500",
ThumbValueBubbleRingThickness: uiControl.RangeSliderThumbValueBubbleRingThicknessXl,
})Track Labels
Track Labels
Track start and end labels print the range bounds from static values or Alpine state. Their position moves the labels above or below the track, and their icons mark each bound.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbValueTwoWayStatePath: "sliderValue",
TrackStartValueOneWayStatePath: "rangeStart",
TrackEndValueOneWayStatePath: "rangeEnd",
// OptionalFields
TrackStartValueLabelEnabled: true,
TrackStartValueLabelPosition: uiControl.RangeSliderTrackValueLabelPositionTop,
TrackStartValueLabelIcon: "ph-arrow-left",
TrackEndValueLabelEnabled: true,
TrackEndValueLabelPosition: uiControl.RangeSliderTrackValueLabelPositionTop,
TrackEndValueLabelIcon: "ph-arrow-right",
})Track Colors & Icons
Track Colors & Icons
Track background colors paint a solid or gradient track, and TrackFillColor paints the filled span. Label text colors and icons mark the bounds.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbValueTwoWayStatePath: "sliderValue",
TrackStartValue: "0",
TrackEndValue: "100",
// OptionalFields
TrackBackgroundColor: "neutral-50/15",
TrackBackgroundColorFrom: "red-500",
TrackBackgroundColorVia: "emerald-500",
TrackBackgroundColorTo: "cyan-500",
TrackFillColor: "sky-500",
TrackFillColorVia: "yellow-500",
TrackStartValueLabelTextColor: "red-500",
TrackEndValueLabelTextColor: "cyan-500",
})Steps & Ticks
Steps & Ticks
TrackSteps snaps the thumb to increments. TrackTicksEnabled draws tick marks every TrackTickStep.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbValueTwoWayStatePath: "sliderValue",
// OptionalFields
TrackSteps: "20",
TrackTicksEnabled: true,
TrackTickStep: "25",
})Track Tooltip
Track Tooltip
TrackTooltipEnabled previews the value under the pointer as it moves along the track. The preview snaps to TrackSteps and clamps to the track bounds. TrackTooltipRingColor and TrackTooltipRingThickness outline it.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbValueTwoWayStatePath: "sliderValue",
// OptionalFields
TrackTooltipEnabled: true,
TrackTooltipPosition: uiControl.RangeSliderTrackTooltipPositionTop,
TrackTooltipBackgroundColor: "primary-500",
TrackTooltipTextColor: "neutral-50",
TrackTooltipRingColor: "primary-200",
TrackTooltipRingThickness: uiControl.RangeSliderTrackTooltipRingThicknessMd,
})Dual-Thumb Mode
Dual-Thumb Mode
ThumbDualValueModeEnabled turns the slider into a range picker. Each thumb binds its own state path and aria label. The upper thumb takes its own colors, labels, icons, and bubble styling.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbDualValueModeEnabled: true,
ThumbValueTwoWayStatePath: "lowerValue",
ThumbAriaLabel: "Minimum price",
ThumbUpperValueTwoWayStatePath: "upperValue",
ThumbUpperAriaLabel: "Maximum price",
ThumbUpperTextColor: "neutral-50",
ThumbUpperLabel: "Max",
ThumbUpperLabelIcon: "ph-arrow-up",
ThumbUpperLabelOneWayStatePath: "upperValue",
ThumbValueBubbleEnabled: true,
ThumbUpperValueBubbleEnabled: true,
ThumbValueBubbleRingColor: "emerald-200",
ThumbValueBubbleRingThickness: uiControl.RangeSliderThumbValueBubbleRingThicknessSm,
ThumbUpperValueBubbleDisplayMode: uiControl.RangeSliderThumbValueBubbleDisplayModeHover,
ThumbUpperValueBubbleTextColor: "neutral-50",
ThumbUpperValueBubbleRingColor: "red-700",
ThumbUpperValueBubbleRingThickness: uiControl.RangeSliderThumbValueBubbleRingThicknessLg,
ThumbUpperValueBubbleSize: uiControl.RangeSliderThumbValueBubbleSizeLg,
TrackStartValue: "0",
TrackEndValue: "100",
})Price Range: $ - $
Static Thumb Values
Static Thumb Values
ThumbValue places one thumb without binding Alpine state. In dual mode ThumbUpperValue places the upper thumb.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbDualValueModeEnabled: true,
ThumbValue: "25",
ThumbUpperValue: "75",
// OptionalFields
TrackStartValue: "0",
TrackEndValue: "100",
})Initial State Normalization
Initial State Normalization
ShouldNormalizeInitialState orders crossed thumbs and pulls out-of-range values back into the track on load. Without it the thumbs start where the state says.
Usage
@uiControl.RangeSlider(uiControl.RangeSliderSettings{
ThumbDualValueModeEnabled: true,
ThumbValueTwoWayStatePath: "lowerValue",
ThumbUpperValueTwoWayStatePath: "upperValue",
// OptionalFields
ShouldNormalizeInitialState: true,
TrackStartValue: "0",
TrackEndValue: "100",
})Normalized Range: $ - $, Overflow Range: $ - $, Slider:
Raw Range: $ - $
@uiStructural
uiStructural is a collection of components for navigating and displaying structured data.
.Card
A card is a surface container with an optional page-style heading (header title, icon, sub-heading) and customizable edges, shadow, ring, and padding.
Usage
@uiStructural.Card(uiStructural.CardSettings{
MiddleContent: CardDemoBody(),
// OptionalFields
HeaderTitle: "Card Title",
HeaderSubHeading: "Card sub-heading",
HeaderIcon: "ph-cube",
})Live Example
The complete card: header with icon and sub-heading, a body, and a footer with actions.
Default Card
Rounded edges and an icon heading
Cards group related content on a surface. This body is the MiddleContent, so the card only styles the container and the optional heading.
Card footer content sits below the body.
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Surface & Edges
Surface & Edges
Background, text, radius, shadow, ring, and padding accept Tailwind tokens.
Usage
@uiStructural.Card(uiStructural.CardSettings{
MiddleContent: CardDemoBody(),
// OptionalFields
BackgroundColor: "primary-900/60",
TextColor: "neutral-50",
PaddingSize: uiStructural.CardPaddingSizeLg,
BorderRadius: uiStructural.CardBorderRadiusNone,
ShadowSize: uiStructural.CardShadowSizeLg,
RingColor: "primary-500",
RingThickness: uiStructural.CardRingThicknessMd,
HeaderSubHeading: "Custom background, text, and ring",
ActionsContent: CardDemoActions(),
})Tinted Card
Custom background, text, and ring
Cards group related content on a surface. This body is the MiddleContent, so the card only styles the container and the optional heading.
Square Card
Cards group related content on a surface. This body is the MiddleContent, so the card only styles the container and the optional heading.
Header Icon Styles
Header Icon Styles
HeaderIcon stamps a Phosphor icon in the header. Position, color, background, radius, and padding size style it.
Usage
@uiStructural.Card(uiStructural.CardSettings{
MiddleContent: CardDemoBody(),
// OptionalFields
HeaderIcon: "ph-cube",
HeaderIconPosition: uiDisplay.HeaderIconPositionLeft,
HeaderIconColor: "primary-100",
HeaderIconBackgroundColor: "primary-500/30",
HeaderIconBorderRadius: uiDisplay.HeaderIconBorderRadiusLg,
HeaderIconPaddingSize: uiDisplay.HeaderIconPaddingSizeMd,
})Icon on Top
Cards group related content on a surface. This body is the MiddleContent, so the card only styles the container and the optional heading.
Icon on Left
Cards group related content on a surface. This body is the MiddleContent, so the card only styles the container and the optional heading.
Content Gap
Content Gap
GapSize sets the space between the header, body, and footer. The default CardGapSizeMd renders gap-3.
Usage
@uiStructural.Card(uiStructural.CardSettings{
MiddleContent: CardDemoBody(),
FooterContent: CardDemoFooter(),
// OptionalFields
HeaderTitle: "Tight Gap",
GapSize: uiStructural.CardGapSizeSm,
})Tight Gap
Cards group related content on a surface. This body is the MiddleContent, so the card only styles the container and the optional heading.
Card footer content sits below the body.
Loose Gap
Cards group related content on a surface. This body is the MiddleContent, so the card only styles the container and the optional heading.
Card footer content sits below the body.
Content-Only Card
Content-Only Card
With no header settings the card is a bare surface around MiddleContent.
Usage
@uiStructural.Card(uiStructural.CardSettings{
MiddleContent: CardDemoContentOnlyBody(),
})Content-only card body without a heading block above it.
State-Bound Header
State-Bound Header
HeaderTitleOneWayStatePath and HeaderSubHeadingOneWayStatePath drive the header text from Alpine state.
Usage
@uiStructural.Card(uiStructural.CardSettings{
MiddleContent: CardDemoBody(),
// OptionalFields
HeaderTitle: "Card Title",
HeaderTitleOneWayStatePath: "cardTitle",
HeaderSubHeadingOneWayStatePath: "cardSubHeading",
})Live Title
Cards group related content on a surface. This body is the MiddleContent, so the card only styles the container and the optional heading.
Custom Header Slot
Custom Header Slot
HeaderContent replaces the standard header block with your own component.
Usage
@uiStructural.Card(uiStructural.CardSettings{
MiddleContent: CardDemoBody(),
// OptionalFields
HeaderContent: CardDemoCustomHeader(),
})Cards group related content on a surface. This body is the MiddleContent, so the card only styles the container and the optional heading.
Header Styling
Header Styling
HeaderSize scales the title and sub-heading. HeaderTitleColor and HeaderSubHeadingColor tint them. TextCase transforms both.
Usage
@uiStructural.Card(uiStructural.CardSettings{
MiddleContent: CardDemoBody(),
// OptionalFields
HeaderTitle: "Styled Header",
HeaderSubHeading: "Sized, tinted, and uppercased",
HeaderSize: uiDisplay.HeaderSizeLg,
HeaderTitleColor: "amber-300",
HeaderSubHeadingColor: "amber-200/70",
TextCase: uiToolset.TextCaseUpper,
})Styled Header
Sized, tinted, and uppercased
Cards group related content on a surface. This body is the MiddleContent, so the card only styles the container and the optional heading.
.Carousel
A carousel slides a window of items inside a server page. The window holds a configurable count per view that follows Tailwind's named breakpoints. Prev and next arrows, dot indicators, and swipe move the window. This demo serves one page of fixed records, and the filter bar and search box do not narrow them.
Usage
@uiStructural.Carousel(uiStructural.CarouselSettings[Record]{
ItemRenderer: func(record Record) templ.Component { return CarouselDemoItem(record) },
Items: records,
QueryUrlTemplate: "/records?page={pageNumber}&itemsPerPage={itemsPerPage}",
// OptionalFields
ItemsPerView: uiStructural.CarouselItemsPerViewSettings{Base: 1, Sm: 2, Lg: 3},
IsSwipeEnabled: true,
})Live Example
Six items on one page, three per view on a wide window. Slide the window with the arrows, the dots, or a drag. Resize the browser to watch the count drop to two, then one.
Handles the public API traffic for the primary region and drains connections during rolling deploys.
Runs the nightly batch jobs, the reporting pipeline, and the weekly archive export.
Hosts the internal dashboard, the metrics collector, and the alerting rules engine.
Serves the static assets, the image resizing service, and the signed download links.
Runs the message queue workers, the retry scheduler, and the dead letter processor.
Handles the public API traffic for the primary region and drains connections during rolling deploys.
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Styling
Surface, Arrows, Dots, and Item Styling
The carousel paints its own surface (background, radius, padding, gap, ring, shadow, text color), its arrows (position, shape, size, colors), its dots (position, size, colors), and the item wrapper (background, radius, padding, ring, shadow). The plain item renderer here carries no card of its own, so the item styling comes from the carousel.
Usage
@uiStructural.Carousel(uiStructural.CarouselSettings[Record]{
ItemRenderer: func(record Record) templ.Component { return CarouselDemoPlainItem(record) },
Items: records,
// OptionalFields
BackgroundColor: "neutral-800/50",
BorderRadius: uiStructural.CarouselBorderRadiusXl,
PaddingSize: uiStructural.CarouselPaddingSizeLg,
GapSize: uiStructural.CarouselGapSizeLg,
RingColor: "secondary-500/30",
RingThickness: uiStructural.CarouselRingThicknessMd,
ShadowSize: uiStructural.CarouselShadowSizeLg,
TextColor: "neutral-100",
ArrowsPosition: uiStructural.CarouselArrowsPositionInside,
ArrowsShape: uiStructural.CarouselArrowsShapeRounded,
ArrowsSize: uiStructural.CarouselArrowsSizeLg,
ArrowsBackgroundColor: "secondary-500/20",
ArrowsIconColor: "secondary-100",
DotsPosition: uiStructural.CarouselDotsPositionTop,
DotsActiveColor: "secondary-500",
DotsInactiveColor: "neutral-50/20",
DotsSize: uiStructural.CarouselDotsSizeLg,
ItemBackgroundColor: "neutral-50/5",
ItemBorderRadius: uiStructural.CarouselBorderRadiusLg,
ItemPaddingSize: uiStructural.CarouselPaddingSizeMd,
ItemRingColor: "neutral-50/10",
ItemRingThickness: uiStructural.CarouselRingThicknessXs,
ItemShadowSize: uiStructural.CarouselShadowSizeMd,
})Handles the public API traffic for the primary region and drains connections during rolling deploys.
Runs the nightly batch jobs, the reporting pipeline, and the weekly archive export.
Hosts the internal dashboard, the metrics collector, and the alerting rules engine.
Serves the static assets, the image resizing service, and the signed download links.
Runs the message queue workers, the retry scheduler, and the dead letter processor.
Handles the public API traffic for the primary region and drains connections during rolling deploys.
Autoplay
Autoplay
IsAutoplay advances the window on a timer. IsAutoplayPausedOnHover stops the timer while the pointer is over the carousel and resumes it when the pointer leaves.
Usage
@uiStructural.Carousel(uiStructural.CarouselSettings[Record]{
ItemRenderer: func(record Record) templ.Component { return CarouselDemoItem(record) },
Items: records,
// OptionalFields
IsAutoplay: true,
IsAutoplayPausedOnHover: true,
AutoplayIntervalMs: 3000,
})Handles the public API traffic for the primary region and drains connections during rolling deploys.
Runs the nightly batch jobs, the reporting pipeline, and the weekly archive export.
Hosts the internal dashboard, the metrics collector, and the alerting rules engine.
Serves the static assets, the image resizing service, and the signed download links.
Runs the message queue workers, the retry scheduler, and the dead letter processor.
Handles the public API traffic for the primary region and drains connections during rolling deploys.
Server Pagination
Server Pagination
This demo pages the server chunk from the query URL. It serves fixed fragments keyed by page and page size, so only page and page size change the records. The filter bar and search box keep their values across a refresh, but they do not narrow these records. The search box sits below the track here through SearchBoxPosition.
Usage
@uiStructural.Carousel(uiStructural.CarouselSettings[Record]{
ItemRenderer: func(record Record) templ.Component { return CarouselDemoItem(record) },
Items: records,
QueryUrlTemplate: "/records?page={pageNumber}&itemsPerPage={itemsPerPage}&search={search}",
// OptionalFields
Filters: filters,
ItemsPerPage: 6,
SearchBoxPosition: uiStructural.CarouselSearchBoxPositionBottom,
})Handles the public API traffic for the primary region and drains connections during rolling deploys.
Runs the nightly batch jobs, the reporting pipeline, and the weekly archive export.
Hosts the internal dashboard, the metrics collector, and the alerting rules engine.
Serves the static assets, the image resizing service, and the signed download links.
Runs the message queue workers, the retry scheduler, and the dead letter processor.
Handles the public API traffic for the primary region and drains connections during rolling deploys.
Item Tooltips
Item Tooltips
CarouselItemTooltip wraps one item and shows its tooltip on hover or on focus inside the item. Position places the tooltip, the colors and ring style its surface, and the width and height classes cap its size. The tooltip renders in a fixed layer on the document body, so the track viewport, a scroll container, and a modal cannot clip it. The card clamps its description to two lines; the tooltip carries the full text. The button opens the same carousel inside a modal.
Usage
templ CarouselTooltipDemoItem(record Record) {
@uiStructural.CarouselItemTooltip(uiStructural.CarouselItemTooltipSettings{
Content: record.Description,
BackgroundColor: "primary-900/95",
Position: uiToolset.TooltipPositionBottom,
RingColor: "primary-500/40",
RingThickness: uiStructural.CarouselRingThicknessXs,
TextColor: "primary-100",
MinWidthClass: "min-w-64",
MaxWidthClass: "max-w-72",
MinHeightClass: "min-h-16",
MaxHeightClass: "max-h-32",
// ContentHtml accepts a component instead of plain text.
}) {
// The item markup, with a clamped description.
}
}Handles the public API traffic for the primary region and drains connections during rolling deploys.
Runs the nightly batch jobs, the reporting pipeline, and the weekly archive export.
Hosts the internal dashboard, the metrics collector, and the alerting rules engine.
Serves the static assets, the image resizing service, and the signed download links.
Runs the message queue workers, the retry scheduler, and the dead letter processor.
Handles the public API traffic for the primary region and drains connections during rolling deploys.
Carousel in a modal
Handles the public API traffic for the primary region and drains connections during rolling deploys.
Runs the nightly batch jobs, the reporting pipeline, and the weekly archive export.
Hosts the internal dashboard, the metrics collector, and the alerting rules engine.
Serves the static assets, the image resizing service, and the signed download links.
Runs the message queue workers, the retry scheduler, and the dead letter processor.
Handles the public API traffic for the primary region and drains connections during rolling deploys.
.DataTable
A data table renders rows from column definitions with sorting, selection, filters, search, and pagination. Every change refreshes the table from the server through the URL template. The examples below cover the full settings surface.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: columns,
Rows: records,
QueryUrlTemplate: "/records?page={pageNumber}&sort={sortKey}&direction={sortDirection}&search={search}",
// OptionalFields
Filters: filters,
RowIdResolver: func(record Record) string { return record.Id },
RefreshOnEvents: []string{"refresh:records-table"},
RefreshDebounceMs: 300,
MaxVisibleRows: 4,
InitialSortKey: "name",
InitialSortDirection: uiStructural.DataTableSortDirectionAsc,
})Live Example
The complete server-driven table: filters, search, sorting, selection, bulk and header actions, and pagination.
| | Status | |||
|---|---|---|---|---|
| alpha | running | 2 | 2026-09-01 | |
| bravo | running | 4 | 2026-09-02 | |
| charlie | stopped | 1 | 2026-09-03 | |
| delta | running | 8 | 2026-09-04 | |
| echo | running | 2 | 2026-09-05 |
Advanced Examples
The panels below hold static tables. They send no requests, so you can inspect the layout and the configuration without a server. Open a panel to see the settings and the rendered result.
Column Configuration
Column Configuration
A column sets its alignment, width, and sortability. WidthPercent shares the row width, MaxWidthClass caps a long cell, and MinWidthClass holds a floor. A column with a SortKey renders a sort button; InitialSortKey and InitialSortDirection seed the active sort indicator.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: []uiStructural.DataTableColumnSettings[Record]{
{Label: "Name", SortKey: "name", WidthPercent: 20, CellRenderer: nameCell},
{Label: "Description", MaxWidthClass: "max-w-72 truncate", CellRenderer: descriptionCell},
{Label: "Status", Alignment: uiStructural.TextAlignmentCenter, WidthPercent: 15, CellRenderer: statusCell},
{Label: "CPU cores", SortKey: "cpuCores", Alignment: uiStructural.TextAlignmentRight, WidthPercent: 12, CellRenderer: cpuCell},
{Label: "Created at", MinWidthClass: "min-w-28", CellRenderer: createdAtCell},
},
Rows: records,
// OptionalFields
InitialSortKey: "name",
InitialSortDirection: uiStructural.DataTableSortDirectionAsc,
})| Description | Status | Created at | ||
|---|---|---|---|---|
| alpha | Handles the public API traffic for the primary region and drains connections during rolling deploys. | running | 2 | 2026-09-01 |
| bravo | Runs the nightly batch jobs, the reporting pipeline, and the weekly archive export. | running | 4 | 2026-09-02 |
| charlie | Hosts the internal dashboard, the metrics collector, and the alerting rules engine. | stopped | 1 | 2026-09-03 |
| delta | Serves the static assets, the image resizing service, and the signed download links. | running | 8 | 2026-09-04 |
Rows Configuration
Rows Configuration
RowIdResolver adds the selection column and identifies each row. RowLabelResolver names the row checkbox for screen readers. CheckboxShape, CheckboxSize, CheckboxCheckedColor, and CheckboxUncheckedColor change the selection checkbox. Select a row to see the colors change.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: columns,
Rows: records,
RowIdResolver: func(record Record) string { return record.Id },
RowLabelResolver: func(record Record) string { return record.Name },
CheckboxShape: uiForm.CheckboxInputShapeRounded,
CheckboxSize: uiForm.CheckboxInputSizeSm,
CheckboxCheckedColor: "emerald-500",
CheckboxUncheckedColor: "sky-500",
})| | Name | Status | CPU cores |
|---|---|---|---|
| alpha | running | 2 | |
| bravo | running | 4 | |
| charlie | stopped | 1 | |
| delta | running | 8 |
Filters
Filters
Each filter renders an editor and an active chip. InitialFilterValues seeds the starting values. FilterDropdownBackgroundColor paints the dropdown panel. A filter change updates the chips and the filter values.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: columns,
Rows: records,
Filters: filters,
FilterDropdownBackgroundColor: "neutral-800",
InitialFilterValues: map[string]any{"status": "running"},
})| Name | Status | CPU cores |
|---|---|---|
| alpha | running | 2 |
| bravo | running | 4 |
| charlie | stopped | 1 |
| delta | running | 8 |
| echo | running | 2 |
Search Box
Search Box
The table renders a default search box when the query template carries the search placeholder. The box stretches to the available space by default; IsSearchBoxCompact fixes it to a narrow width so SearchBoxAlignment can place it left, center, or right. InitialSearchQuery seeds the starting text. Pass SearchBox to replace the default box with any component that binds to searchQuery.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: columns,
Rows: records,
QueryUrlTemplate: "/records?search={search}",
// OptionalFields
InitialSearchQuery: "alpha",
IsSearchBoxCompact: true,
SearchBoxAlignment: uiStructural.HorizontalAlignmentCenter,
// Or replace the default box
SearchBox: CustomSearchBox(),
})Default box, compact and centered
| Name | Status | CPU cores |
|---|---|---|
| alpha | running | 2 |
| bravo | running | 4 |
| charlie | stopped | 1 |
| delta | running | 8 |
| echo | running | 2 |
Custom SearchBox, full width
| Name | Status | CPU cores |
|---|---|---|
| alpha | running | 2 |
| bravo | running | 4 |
| charlie | stopped | 1 |
| delta | running | 8 |
| echo | running | 2 |
Header Actions
Header Actions
HeaderActions renders in the toolbar. The button here dispatches an event the panel counts.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: columns,
Rows: records,
HeaderActions: uiControl.Button(uiControl.ButtonSettings{
Label: "Sync",
IconLeft: "ph-arrows-clockwise",
OnClickFunc: "$dispatch('demo:header-action')",
Size: uiControl.ButtonSizeSm,
}),
})| Name | Status | CPU cores |
|---|---|---|
| alpha | running | 2 |
| bravo | running | 4 |
| charlie | stopped | 1 |
| delta | running | 8 |
Header action clicks:
Bulk Actions
Bulk Actions
BulkActions renders in the toolbar only while at least one row is selected. Select a row to reveal the action.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: columns,
Rows: records,
RowIdResolver: func(record Record) string { return record.Id },
BulkActions: uiControl.Button(uiControl.ButtonSettings{
Label: "Archive",
IconLeft: "ph-archive",
OnClickFunc: "selectedRowIds = []",
Size: uiControl.ButtonSizeSm,
BackgroundColor: "red-500/20",
TextColor: "red-200",
}),
})| | Name | Status | CPU cores |
|---|---|---|---|
| alpha | running | 2 | |
| bravo | running | 4 | |
| charlie | stopped | 1 | |
| delta | running | 8 |
Row and Column Styling
Row and Column Styling
HeaderClass paints the header row. IsStriped adds a zebra stripe. CellClass styles one column, and RowClassResolver styles each row from its data. A cell component that sets its own color overrides the row color.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: []uiStructural.DataTableColumnSettings[Record]{
{Label: "Name", CellClass: "font-bold", CellRenderer: nameCell},
{Label: "Status", CellRenderer: statusCell},
{Label: "CPU cores", Alignment: uiStructural.TextAlignmentRight, CellRenderer: cpuCell},
},
Rows: records,
// OptionalFields
HeaderClass: "bg-neutral-50/5",
IsStriped: true,
RowClassResolver: func(record Record) string {
if record.Status != "running" {
return "text-neutral-400"
}
return ""
},
})| Name | Status | CPU cores |
|---|---|---|
| alpha | running | 2 |
| bravo | running | 4 |
| charlie | stopped | 1 |
| delta | running | 8 |
Density and Header Text Case
Density and Header Text Case
Density changes the cell padding. TextCase changes the header capitalization. Both tables use the same columns and rows. The last column holds an icon button with a tooltip.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: columns,
Rows: records,
Density: uiStructural.DataTableDensityDense,
TextCase: uiToolset.TextCaseUpper,
})Comfortable (default), headers as typed
| Name | Status | CPU cores | Actions |
|---|---|---|---|
| alpha | running | 2 | |
| bravo | running | 4 | |
| charlie | stopped | 1 |
Dense with uppercase headers
| Name | Status | CPU cores | Actions |
|---|---|---|---|
| alpha | running | 2 | |
| bravo | running | 4 | |
| charlie | stopped | 1 |
Static Header
Static Header
The header pins to the top of the scroll viewport by default; IsHeaderStatic lets it scroll away with the body. MinWidthClass and MaxWidthClass size the table surface. MinHeightClass and MaxHeightClass size the scroll viewport. MaxVisibleRows measures the header and the tallest row and caps the viewport to that row count instead; the live table above uses it.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: columns,
Rows: records,
IsHeaderStatic: true,
MinWidthClass: "min-w-96",
MaxWidthClass: "max-w-2xl",
MinHeightClass: "min-h-24",
MaxHeightClass: "max-h-40",
})| Name | Status | CPU cores |
|---|---|---|
| alpha | running | 2 |
| bravo | running | 4 |
| charlie | stopped | 1 |
| delta | running | 8 |
| echo | running | 2 |
| foxtrot | stopped | 16 |
| golf | running | 2 |
| hotel | running | 4 |
| india | stopped | 1 |
| juliett | running | 8 |
| kilo | running | 2 |
| lima | stopped | 16 |
| mike | running | 2 |
| november | running | 4 |
| oscar | stopped | 1 |
| papa | running | 8 |
| quebec | running | 2 |
| romeo | stopped | 16 |
| sierra | running | 2 |
| tango | running | 4 |
| uniform | stopped | 1 |
| victor | running | 8 |
| whiskey | running | 2 |
| xray | stopped | 16 |
| yankee | running | 2 |
Pagination Display
Pagination Display
Page numbers are zero-based by default; ShouldUseOneBasedPageDisplay shifts the labels to start at 1. IsPaginationHiddenWhenSinglePage hides the page controls when a single page holds every row. PaginationAriaLabel names the footer navigation for screen readers.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: columns,
Rows: records,
// OptionalFields
ShouldUseOneBasedPageDisplay: true,
IsPaginationHiddenWhenSinglePage: true,
PaginationAriaLabel: "Servers",
})One-based labels
| Name | Status | CPU cores |
|---|---|---|
| alpha | running | 2 |
| bravo | running | 4 |
| charlie | stopped | 1 |
| delta | running | 8 |
Hidden on a single page
Empty States
Empty States
With no rows the table renders the EmptyState slot. Without the slot it renders the default message.
Usage
@uiStructural.DataTable(uiStructural.DataTableSettings[Record]{
Columns: columns,
Rows: nil,
EmptyState: DataTableDemoEmptyState(),
})Custom EmptyState
| Name | Status | CPU cores |
|---|---|---|
No servers yet Create a server to see it listed here. | ||
Default empty state
| Name | Status | CPU cores |
|---|---|---|
| No records found. | ||
.FilterBar
A filter bar renders one editor per declared filter and shows the active filters as removable chips.
Usage
@uiStructural.FilterBar(uiStructural.FilterBarSettings{
Filters: []uiStructural.FilterSettings{
{Key: "name", Label: "Name", Kind: uiStructural.FilterKindTextContains},
{Key: "status", Label: "Status", Kind: uiStructural.FilterKindEnumSelect, Options: statusOptions},
{Key: "cpu", Label: "CPU", Kind: uiStructural.FilterKindNumberRange},
},
ValuesTwoWayStatePath: "filterValues",
// OptionalFields
OnChangeFunc: "changeCount = changeCount + 1",
})Live Example
All three filter kinds at once: text contains, enum select, and number range, with removable chips.
Values: · OnChangeFunc calls:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Query Param Names
Query Param Names
QueryParamName renames the filter in the DataTable URL template. Without it the filter Key is the parameter name.
Usage
@uiStructural.FilterBar(uiStructural.FilterBarSettings{
Filters: []uiStructural.FilterSettings{
{
Key: "environment",
Label: "Environment",
Kind: uiStructural.FilterKindEnumSelect,
Options: buildDemoEnvironmentOptions(),
QueryParamName: "recordEnvironment",
},
},
ValuesTwoWayStatePath: "filterValues",
})Enum Radio Group Prefix
Enum Radio Group Prefix
EnumSelectRadioGroupNamePrefix namespaces the generated radio inputs of enum selects, so two filter bars on one page do not collide.
Usage
@uiStructural.FilterBar(uiStructural.FilterBarSettings{
Filters: []uiStructural.FilterSettings{
{Key: "region", Label: "Region", Kind: uiStructural.FilterKindEnumSelect, Options: buildDemoRegionOptions()},
},
ValuesTwoWayStatePath: "filterValues",
// OptionalFields
EnumSelectRadioGroupNamePrefix: "myForm",
})Dropdown Background
Dropdown Background
DropdownBackgroundColor paints the enum select dropdown with a Tailwind background token. DataTable forwards it as FilterDropdownBackgroundColor.
Usage
@uiStructural.FilterBar(uiStructural.FilterBarSettings{
Filters: []uiStructural.FilterSettings{
{Key: "status", Label: "Status", Kind: uiStructural.FilterKindEnumSelect, Options: statusOptions},
},
ValuesTwoWayStatePath: "filterValues",
// OptionalFields
DropdownBackgroundColor: "primary-500/95",
})Multi-Value Filter
Multi-Value Filter
FilterKindMultiEnumSelect holds an array of selected values under one key. The chip lists every value, and the DataTable URL repeats the parameter once per value.
Usage
@uiStructural.FilterBar(uiStructural.FilterBarSettings{
Filters: []uiStructural.FilterSettings{
{Key: "status", Label: "Status", Kind: uiStructural.FilterKindMultiEnumSelect, Options: statusOptions},
},
ValuesTwoWayStatePath: "filterValues",
})Date Range Filter
Date Range Filter
FilterKindDateRange renders a min and a max date input. The active chip shows the selected span, and clearing the chip resets both dates.
Usage
@uiStructural.FilterBar(uiStructural.FilterBarSettings{
Filters: []uiStructural.FilterSettings{
{Key: "createdAt", Label: "Created", Kind: uiStructural.FilterKindDateRange},
},
ValuesTwoWayStatePath: "filterValues",
})Values:
Change Callback
Change Callback
OnChangeFunc runs on every filter edit and on chip removal. It can drive a fetch or update local state.
Usage
@uiStructural.FilterBar(uiStructural.FilterBarSettings{
Filters: []uiStructural.FilterSettings{
{Key: "name", Label: "Name", Kind: uiStructural.FilterKindTextContains},
},
ValuesTwoWayStatePath: "filterValues",
// OptionalFields
OnChangeFunc: "changeCount = changeCount + 1",
})OnChangeFunc calls:
.Pagination
Pagination splits records into pages and lets the user move between them.
Usage
@uiStructural.Pagination(uiStructural.PaginationSettings{
PageNumberTwoWayStatePath: "pageNumber",
ItemsPerPageTwoWayStatePath: "itemsPerPage",
ItemsTotal: 240,
// OptionalFields
PagesTotal: 24,
OnChangeFunc: "changeCount = changeCount + 1",
})Live Example
Page navigation and a page-size select bound to Alpine state.
pageNumber: · itemsPerPage: · OnChangeFunc calls:
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Page-Size Choices
Page-Size Choices
ItemsPerPageSizeChoices replaces the default page-size options in the select.
Usage
@uiStructural.Pagination(uiStructural.PaginationSettings{
PageNumberTwoWayStatePath: "pageNumber",
ItemsPerPageTwoWayStatePath: "itemsPerPage",
ItemsTotal: 240,
// OptionalFields
PagesTotal: 48,
ItemsPerPageSizeChoices: []uint{5, 10, 25},
})Disabled Binding
Disabled Binding
IsDisabledOneWayStatePath greys out the controls while a request is in flight.
Usage
@uiStructural.Pagination(uiStructural.PaginationSettings{
PageNumberTwoWayStatePath: "pageNumber",
ItemsPerPageTwoWayStatePath: "itemsPerPage",
ItemsTotal: 240,
// OptionalFields
PagesTotal: 24,
IsDisabledOneWayStatePath: "isPaginationDisabled",
})Hidden On Single Page
Hidden On Single Page
IsHiddenWhenSinglePage hides only the page-number controls while the records fit on one page. The readout and the items-per-page select stay visible, and the controls return when a smaller page size needs more pages.
Usage
@uiStructural.Pagination(uiStructural.PaginationSettings{
PageNumberTwoWayStatePath: "pageNumber",
ItemsPerPageTwoWayStatePath: "itemsPerPage",
ItemsTotal: 10,
// OptionalFields
PagesTotal: 1,
IsHiddenWhenSinglePage: true,
})One page: only the readout and page size
Two pages: pagination shows
One-Based Labels
One-Based Labels
ShouldUseOneBasedPageDisplay keeps the 0-based state and labels the pages from 1. Without it, the first page is 0.
Usage
@uiStructural.Pagination(uiStructural.PaginationSettings{
PageNumberTwoWayStatePath: "pageNumber",
ItemsPerPageTwoWayStatePath: "itemsPerPage",
ItemsTotal: 240,
// OptionalFields
PagesTotal: 24,
ShouldUseOneBasedPageDisplay: true,
})Change Callback
Change Callback
OnChangeFunc runs after a page change or a page-size change. It can drive a fetch or update local state.
Usage
@uiStructural.Pagination(uiStructural.PaginationSettings{
PageNumberTwoWayStatePath: "pageNumber",
ItemsPerPageTwoWayStatePath: "itemsPerPage",
ItemsTotal: 240,
// OptionalFields
PagesTotal: 24,
OnChangeFunc: "changeCount = changeCount + 1",
})OnChangeFunc calls:
.Tabs
Tabs split content into a header row and matching panels. Each tab carries a label, a value, and an optional icon and badge count. The selected value binds to an Alpine state path, and the panels switch with x-show.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Icon: "ph-gear", Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", Icon: "ph-shield-check", BadgeCount: 3, Content: TabsDemoSecurityPanel()},
{Label: "Advanced", Value: "advanced", Icon: "ph-sliders", Content: TabsDemoAdvancedPanel()},
},
SelectedValueTwoWayStatePath: "selectedTab",
})Alpine.js Parent State (x-data)
<div x-data="{
selectedTab: 'general',
}"></div>Live Example
Horizontal tabs with icons and a badge. Click a tab, or use the arrow keys, Home, and End.
General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Advanced
Danger zone and developer options. Arrow keys, Home, and End move between the tabs.
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Vertical
Vertical
Orientation renders the tab list as a column beside the panels, for sidebar-style layouts. Up and Down arrows move between the tabs.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Icon: "ph-gear", Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", Icon: "ph-shield-check", Content: TabsDemoSecurityPanel()},
{Label: "Advanced", Value: "advanced", Icon: "ph-sliders", Content: TabsDemoAdvancedPanel()},
},
SelectedValueTwoWayStatePath: "selectedSettingsTab",
// OptionalFields
Orientation: uiStructural.TabOrientationVertical,
})General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Advanced
Danger zone and developer options. Arrow keys, Home, and End move between the tabs.
Right Side
Right Side
Side places the vertical tab list on the right side of the panels, for layouts that read better with the navigation on the right. Up and Down arrows still move between the tabs.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Icon: "ph-gear", Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", Icon: "ph-shield-check", Content: TabsDemoSecurityPanel()},
{Label: "Advanced", Value: "advanced", Icon: "ph-sliders", Content: TabsDemoAdvancedPanel()},
},
SelectedValueTwoWayStatePath: "selectedRightSideTab",
// OptionalFields
Orientation: uiStructural.TabOrientationVertical,
Side: uiStructural.TabSideRight,
})General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Advanced
Danger zone and developer options. Arrow keys, Home, and End move between the tabs.
Vertical Alignment
Vertical Alignment
Alignment aligns the vertical tab list with the tab content. It accepts TabAlignmentTop (the default), TabAlignmentCenter, and TabAlignmentBottom, and only applies with TabOrientationVertical.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Icon: "ph-gear", Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", Icon: "ph-shield-check", Content: TabsDemoSecurityPanel()},
{Label: "Advanced", Value: "advanced", Icon: "ph-sliders", Content: TabsDemoAdvancedPanel()},
},
SelectedValueTwoWayStatePath: "selectedAlignmentTab",
// OptionalFields
Orientation: uiStructural.TabOrientationVertical,
Alignment: uiStructural.TabAlignmentCenter,
})General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Advanced
Danger zone and developer options. Arrow keys, Home, and End move between the tabs.
Icon Position
Icon Position
IconPosition places the icon above the label instead of beside it. The default, TabIconPositionLeft, keeps the icon on the left.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Icon: "ph-gear", IconPosition: uiStructural.TabIconPositionTop, Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", Icon: "ph-shield-check", IconPosition: uiStructural.TabIconPositionTop, Content: TabsDemoSecurityPanel()},
{Label: "Advanced", Value: "advanced", Icon: "ph-sliders", IconPosition: uiStructural.TabIconPositionTop, Content: TabsDemoAdvancedPanel()},
},
SelectedValueTwoWayStatePath: "selectedIconTab",
})General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Advanced
Danger zone and developer options. Arrow keys, Home, and End move between the tabs.
Border Radius
Border Radius
BorderRadius rounds the tab edges. It accepts TabBorderRadiusNone through TabBorderRadiusXl, and the default is TabBorderRadiusMd.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Icon: "ph-gear", Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", Icon: "ph-shield-check", Content: TabsDemoSecurityPanel()},
{Label: "Advanced", Value: "advanced", Icon: "ph-sliders", Content: TabsDemoAdvancedPanel()},
},
SelectedValueTwoWayStatePath: "selectedRadiusTab",
// OptionalFields
BorderRadius: uiStructural.TabBorderRadiusXl,
})General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Advanced
Danger zone and developer options. Arrow keys, Home, and End move between the tabs.
Surface Customization
Surface Customization
BackgroundColor paints the tab list. BorderRadius rounds the tab edges. GapSize and PaddingSize space and inset the tabs. RingColor and RingThickness frame the list. ShadowSize adds a shadow. TextCase transforms the labels. TextColor tints the unselected tab labels.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Icon: "ph-gear", Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", Icon: "ph-shield-check", Content: TabsDemoSecurityPanel()},
{Label: "Advanced", Value: "advanced", Icon: "ph-sliders", Content: TabsDemoAdvancedPanel()},
},
SelectedValueTwoWayStatePath: "selectedSurfaceTab",
// OptionalFields
BackgroundColor: "neutral-50/5",
BorderRadius: uiStructural.TabBorderRadiusNone,
GapSize: uiStructural.TabGapSizeLg,
PaddingSize: uiStructural.TabPaddingSizeXs,
RingColor: "neutral-50/10",
RingThickness: uiStructural.TabRingThicknessMd,
ShadowSize: uiStructural.TabShadowSizeMd,
TextCase: uiToolset.TextCaseUpper,
TextColor: "neutral-50/60",
})General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Advanced
Danger zone and developer options. Arrow keys, Home, and End move between the tabs.
Content Surface
Content Surface
The Content fields style the panel area: ContentBackgroundColor, ContentPaddingSize, ContentBorderRadius, ContentRingColor, ContentRingThickness, ContentShadowSize, and ContentTextColor. ContentPaddingSize replaces the default inset that separates the content from the tab list.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Icon: "ph-gear", Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", Icon: "ph-shield-check", Content: TabsDemoSecurityPanel()},
{Label: "Advanced", Value: "advanced", Icon: "ph-sliders", Content: TabsDemoAdvancedPanel()},
},
SelectedValueTwoWayStatePath: "selectedContentTab",
// OptionalFields
ContentBackgroundColor: "neutral-50/5",
ContentBorderRadius: uiStructural.TabBorderRadiusMd,
ContentPaddingSize: uiStructural.TabPaddingSizeMd,
ContentRingColor: "neutral-50/10",
ContentRingThickness: uiStructural.TabRingThicknessMd,
ContentShadowSize: uiStructural.TabShadowSizeMd,
ContentTextColor: "neutral-50/70",
})General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Advanced
Danger zone and developer options. Arrow keys, Home, and End move between the tabs.
Badge Counts
Badge Counts
BadgeCount renders a static count, and BadgeCountOneWayStatePath renders a live count that hides itself at zero. BadgeBackgroundColor, BadgeTextColor, BadgeRingColor, BadgeRingThickness, and BadgeBorderRadius style the badge.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", BadgeCount: 3, Content: TabsDemoSecurityPanel()},
{Label: "Notifications", Value: "notifications", BadgeCountOneWayStatePath: "alertCount", BadgeBackgroundColor: "red-500/20", BadgeBorderRadius: uiStructural.TabBorderRadiusLg, BadgeRingColor: "red-500/50", BadgeRingThickness: uiStructural.TabRingThicknessSm, BadgeTextColor: "red-50", Content: TabsDemoNotificationsPanel()},
},
SelectedValueTwoWayStatePath: "selectedBadgeTab",
})General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Notifications
Email, push, and in-app notification preferences.
Deep Linking
Deep Linking
IsUrlHashSynced reads the URL hash on load and on every hash change, so a link to #security opens the Security tab. Clicking a tab writes the hash.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", Content: TabsDemoSecurityPanel()},
{Label: "Advanced", Value: "advanced", Content: TabsDemoAdvancedPanel()},
},
SelectedValueTwoWayStatePath: "selectedDeepLinkTab",
// OptionalFields
IsUrlHashSynced: true,
})General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Advanced
Danger zone and developer options. Arrow keys, Home, and End move between the tabs.
Overflow Scroll
Overflow Scroll
MinWidthPercent and MaxWidthPercent set the tab list width bounds as percentages of its container. MinWidthClass and MaxWidthClass apply Tailwind width classes to the same bounds. The horizontal tab list scrolls when the tabs exceed it.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Icon: "ph-gear", Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", Icon: "ph-shield-check", Content: TabsDemoSecurityPanel()},
{Label: "Notifications", Value: "notifications", Icon: "ph-bell", Content: TabsDemoNotificationsPanel()},
{Label: "Billing", Value: "billing", Icon: "ph-credit-card", Content: TabsDemoBillingPanel()},
{Label: "API", Value: "api", Icon: "ph-key", Content: TabsDemoApiPanel()},
{Label: "Integrations", Value: "integrations", Icon: "ph-plugs-connected", Content: TabsDemoIntegrationsPanel()},
{Label: "Team", Value: "team", Icon: "ph-users", Content: TabsDemoTeamPanel()},
{Label: "Audit", Value: "audit", Icon: "ph-clock-counter-clockwise", Content: TabsDemoAuditPanel()},
{Label: "Danger", Value: "danger", Icon: "ph-warning", Content: TabsDemoDangerPanel()},
},
SelectedValueTwoWayStatePath: "selectedOverflowTab",
// OptionalFields
MinWidthPercent: 50,
MaxWidthPercent: 80,
MinWidthClass: "min-w-64",
MaxWidthClass: "max-w-80",
})General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Notifications
Email, push, and in-app notification preferences.
Billing
Plan, payment method, and invoice history.
API
API keys, webhooks, and rate limits.
Integrations
Connect third-party services to your workspace.
Team
Members, roles, and invitations.
Audit
A log of every change made to the workspace.
Danger
Delete the workspace and everything in it.
Vertical Overflow Scroll
Vertical Overflow Scroll
MinHeightPercent and MaxHeightPercent set the vertical tab list height bounds as percentages of the tab area. MinHeightClass and MaxHeightClass apply Tailwind height classes to the same bounds. MaxVisibleTabs measures the tallest tab at runtime and caps the list to that many tabs instead. The vertical tab list scrolls when the tabs exceed the cap.
Usage
@uiStructural.Tabs(uiStructural.TabSettings{
Items: []uiStructural.TabItemSettings{
{Label: "General", Value: "general", Icon: "ph-gear", Content: TabsDemoGeneralPanel()},
{Label: "Security", Value: "security", Icon: "ph-shield-check", Content: TabsDemoSecurityPanel()},
{Label: "Notifications", Value: "notifications", Icon: "ph-bell", Content: TabsDemoNotificationsPanel()},
{Label: "Billing", Value: "billing", Icon: "ph-credit-card", Content: TabsDemoBillingPanel()},
{Label: "API", Value: "api", Icon: "ph-key", Content: TabsDemoApiPanel()},
{Label: "Integrations", Value: "integrations", Icon: "ph-plugs-connected", Content: TabsDemoIntegrationsPanel()},
{Label: "Team", Value: "team", Icon: "ph-users", Content: TabsDemoTeamPanel()},
{Label: "Audit", Value: "audit", Icon: "ph-clock-counter-clockwise", Content: TabsDemoAuditPanel()},
{Label: "Danger", Value: "danger", Icon: "ph-warning", Content: TabsDemoDangerPanel()},
},
SelectedValueTwoWayStatePath: "selectedVerticalOverflowTab",
// OptionalFields
Orientation: uiStructural.TabOrientationVertical,
MinHeightPercent: 30,
MaxHeightPercent: 60,
MinHeightClass: "min-h-32",
MaxHeightClass: "max-h-48",
// Or cap the list to a number of tabs
MaxVisibleTabs: 4,
})General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Notifications
Email, push, and in-app notification preferences.
Billing
Plan, payment method, and invoice history.
API
API keys, webhooks, and rate limits.
Integrations
Connect third-party services to your workspace.
Team
Members, roles, and invitations.
Audit
A log of every change made to the workspace.
Danger
Delete the workspace and everything in it.
General
Workspace name, language, and timezone live here. The panel stays in the DOM so its inputs keep their state while you switch tabs.
Security
Two-factor authentication and session controls. This tab carries a badge count.
Notifications
Email, push, and in-app notification preferences.
Billing
Plan, payment method, and invoice history.
API
API keys, webhooks, and rate limits.
Integrations
Connect third-party services to your workspace.
Team
Members, roles, and invitations.
Audit
A log of every change made to the workspace.
Danger
Delete the workspace and everything in it.
.PageHeading
The page heading block for both page titles and section headings: header title, optional icon and description, and a right-aligned action slot. One component with a Level setting so pages stop hand-rolling headers.
Usage
@uiStructural.PageHeading(uiStructural.PageHeadingSettings{
HeaderTitle: "Records",
Level: uiStructural.PageHeadingLevelPage,
// OptionalFields
Description: "Manage the server records",
HeaderIcon: "ph-table",
ActionsContent: PageHeadingDemoActions(),
})Live Example
The complete page-level heading: title, icon, description, and actions.
Records
Manage the server records and their lifecycle.
Advanced Examples
Open a panel to see one variation with its settings and the rendered result.
Title Only
Title Only
With no icon, sub-heading, or actions the heading is a single line.
Usage
@uiStructural.PageHeading(uiStructural.PageHeadingSettings{
HeaderTitle: "Title Only",
Level: uiStructural.PageHeadingLevelSection,
})Title Only
Levels & Sizes
Levels & Sizes
Level page renders the h1 page header and defaults to xl. Level section renders the h2 section heading and defaults to lg. HeaderSize scales either level: xs, sm, md, lg, or xl.
Usage
@uiStructural.PageHeading(uiStructural.PageHeadingSettings{
HeaderTitle: "Records",
Level: uiStructural.PageHeadingLevelPage,
// OptionalFields
HeaderSize: uiDisplay.HeaderSizeSm,
})Page Level
Section Level
xs
sm
md
lg
xl
Icon Styles
Icon Styles
HeaderIcon stamps a Phosphor icon on the heading. HeaderIconColor and HeaderIconPosition style it. HeaderIconBackgroundColor, HeaderIconBorderRadius, and HeaderIconPaddingSize shape the chip. A section-level icon carries a chip background by default.
Usage
@uiStructural.PageHeading(uiStructural.PageHeadingSettings{
HeaderTitle: "Records",
// OptionalFields
HeaderIcon: "ph-star",
HeaderIconColor: "amber-400",
HeaderIconBackgroundColor: "amber-400/20",
HeaderIconBorderRadius: uiDisplay.HeaderIconBorderRadiusSm,
HeaderIconPaddingSize: uiDisplay.HeaderIconPaddingSizeSm,
HeaderIconPosition: uiDisplay.HeaderIconPositionLeft,
})Amber Star
Icon on Left
Section Chip
State-Bound Title
State-Bound Title
HeaderTitleOneWayStatePath and HeaderSubHeadingOneWayStatePath drive the heading text from Alpine state. HeaderSubHeading sets the starting sub-heading text, and HeaderSubHeadingColor tints it.
Usage
@uiStructural.PageHeading(uiStructural.PageHeadingSettings{
HeaderTitle: "Records",
// OptionalFields
HeaderIcon: "ph-arrows-clockwise",
HeaderTitleOneWayStatePath: "pageTitle",
HeaderSubHeading: "Bound to Alpine state",
HeaderSubHeadingColor: "emerald-300",
HeaderSubHeadingOneWayStatePath: "pageSubHeading",
})Live Title
Bound to Alpine state
Text Case
Text Case
TextCase transforms the title and description. It accepts uiToolset.TextCaseNone (the default, as typed), TextCaseLower, TextCaseUpper, or TextCaseCapitalize. HeaderTitleColor and TextColor set the title and block text colors.
Usage
@uiStructural.PageHeading(uiStructural.PageHeadingSettings{
HeaderTitle: "Network Interfaces",
Level: uiStructural.PageHeadingLevelSection,
// OptionalFields
HeaderTitleColor: "amber-300",
TextColor: "neutral-200",
TextCase: uiToolset.TextCaseUpper,
})Network Interfaces
Description and Actions
Description and Actions
Description fills the sub-heading. It is an alias for HeaderSubHeading and wins when both are set. ActionsContent renders right-aligned controls.
Usage
@uiStructural.PageHeading(uiStructural.PageHeadingSettings{
HeaderTitle: "Servers",
Level: uiStructural.PageHeadingLevelPage,
// OptionalFields
Description: "Manage the server records",
ActionsContent: PageHeadingDemoActions(),
})Servers
Manage the server records