A comprehensive collection of reusable UI components for the LiveTemplate framework.
go get github.com/livetemplate/lvt/components
import "github.com/livetemplate/lvt/components"
tmpl := livetemplate.NewTemplates(
livetemplate.WithComponentTemplates(components.All()),
livetemplate.ParseGlob("internal/app/**/*.tmpl"),
)
import "github.com/livetemplate/lvt/components/dropdown"
type State struct {
CountrySelect *dropdown.Searchable
}
// In init
CountrySelect: dropdown.NewSearchable("country", countries,
dropdown.WithPlaceholder("Select country"),
dropdown.WithSelected(user.CountryCode),
)
<div class="form-group">
<label>Country</label>
{{template "lvt:dropdown:searchable:v1" .CountrySelect}}
</div>
| Component | Package | Templates | Description |
|---|---|---|---|
| Dropdown | dropdown |
default, searchable, multi | Single and multi-select dropdowns |
| Autocomplete | autocomplete |
default | Search with suggestions |
| Date Picker | datepicker |
single, range, inline | Date selection |
| Time Picker | timepicker |
default | Time selection |
| Tags Input | tagsinput |
default | Tag/chip input |
| Toggle | toggle |
default, checkbox | Toggle switches |
| Rating | rating |
default | Star ratings |
| Component | Package | Templates | Description |
|---|---|---|---|
| Tabs | tabs |
horizontal, vertical, pills | Tab navigation |
| Accordion | accordion |
default, single | Collapsible sections |
| Modal | modal |
default, confirm, sheet | Modal dialogs |
| Drawer | drawer |
default | Slide-out panels |
| Component | Package | Templates | Description |
|---|---|---|---|
| Toast | toast |
default, container | Toast notifications |
| Tooltip | tooltip |
default | Tooltips |
| Popover | popover |
default | Rich content popovers |
| Progress | progress |
default, circular, spinner | Progress indicators |
| Skeleton | skeleton |
default, avatar, card | Loading placeholders |
| Component | Package | Templates | Description |
|---|---|---|---|
| Data Table | datatable |
default | Tables with sorting/pagination |
| Timeline | timeline |
default | Event timelines |
| Breadcrumbs | breadcrumbs |
default | Navigation breadcrumbs |
| Component | Package | Templates | Description |
|---|---|---|---|
| Menu | menu |
default, nested | Navigation menus |
All templates follow the pattern: lvt:<component>:<variant>:v<version>
{{template "lvt:dropdown:default:v1" .MyDropdown}}
{{template "lvt:dropdown:searchable:v1" .SearchDropdown}}
{{template "lvt:tabs:horizontal:v1" .MyTabs}}
{{template "lvt:modal:confirm:v1" .ConfirmModal}}
Components come with Tailwind CSS classes baked in:
dropdown.New("id", options)
For custom CSS or other frameworks, use unstyled mode:
dropdown.New("id", options, dropdown.WithStyled(false))
This renders semantic HTML without any classes.
Most customization can be achieved through functional options:
dropdown.NewSearchable("country", countries,
dropdown.WithPlaceholder("Select country"),
dropdown.WithSelected("US"),
dropdown.WithMinChars(2),
dropdown.WithDebounce(300),
)
Define the same template name in your project - it takes precedence:
{{/* internal/app/templates/dropdown-override.tmpl */}}
{{define "lvt:dropdown:searchable:v1"}}
<div class="my-custom-dropdown">
{{/* Your custom markup */}}
</div>
{{end}}
Extract just the HTML template while keeping the Go logic:
lvt component eject-template dropdown searchable
Get complete source code for total control:
lvt component eject dropdown
lvt component list
lvt component eject <component>
lvt component eject dropdown --dest internal/ui/dropdown
lvt component eject-template <component> <template>
lvt component eject-template dropdown searchable
lvt new component <name>
lvt new component my-widget
lvt new component rating
This creates:
components/rating/
rating.go # Component struct and constructor
options.go # Functional options
templates.go # Template embedding
rating_test.go # Tests
templates/
default.tmpl # HTML template
// rating.go
package rating
import "github.com/livetemplate/lvt/components/base"
type Rating struct {
base.Base
Value int
MaxStars int
}
func New(id string, opts ...Option) *Rating {
r := &Rating{
Base: base.NewBase(id, "rating"),
MaxStars: 5,
}
for _, opt := range opts {
opt(r)
}
return r
}
{{define "lvt:rating:default:v1"}}
{{if .IsStyled}}
<div class="flex gap-1" data-component="rating" data-id="{{.ID}}">
{{/* Tailwind styled version */}}
</div>
{{else}}
<div data-component="rating" data-id="{{.ID}}">
{{/* Unstyled semantic HTML */}}
</div>
{{end}}
{{end}}
The components module is fully independent from the parent lvt CLI tool.
This means external projects can import and use components without pulling
in the entire lvt dependency tree.
What CI checks:
github.com/livetemplate/lvt (parent module)github.com/livetemplate/lvt/internal or github.com/livetemplate/lvt/commands (fully-qualified import paths)components/go.mod does not require the parent modulego build ./... and go test ./... pass with GOWORK=offUsing components in your project:
import "github.com/livetemplate/lvt/components/modal"
m := modal.New("my-modal", modal.WithTitle("Confirm"))
No lvt CLI installation required — components are a standalone Go library.
See CONTRIBUTING.md for guidelines on:
MIT License - see LICENSE file for details.