initial port of the UI kit
This commit is contained in:
65
go/webui/toggleswitch.go
Normal file
65
go/webui/toggleswitch.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package webui
|
||||
|
||||
import "kjol/vdom"
|
||||
|
||||
// Port of web/kit/ToggleSwitch.tsx. Reactive accessors collapse to plain values.
|
||||
|
||||
// ToggleSwitch renders an on/off <button role="switch"> with an optional label
|
||||
// and description. onChange receives the next checked state.
|
||||
func ToggleSwitch(checked bool, onChange func(bool), label, description string, disabled bool, class string) *vdom.VNode {
|
||||
toggle := func() {
|
||||
if disabled {
|
||||
return
|
||||
}
|
||||
onChange(!checked)
|
||||
}
|
||||
|
||||
trackState := "bg-neutral-300"
|
||||
if checked {
|
||||
trackState = "bg-primary"
|
||||
}
|
||||
trackCls := cx("relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors focus-visible:outline-2 focus-visible:outline-primary focus-visible:outline-offset-2 disabled:cursor-not-allowed disabled:opacity-50", trackState)
|
||||
|
||||
knobState := "translate-x-0.5"
|
||||
if checked {
|
||||
knobState = "translate-x-[18px]"
|
||||
}
|
||||
knobCls := cx("inline-block h-4 w-4 transform rounded-full bg-white shadow-sm transition-transform", knobState)
|
||||
|
||||
ariaChecked := "false"
|
||||
if checked {
|
||||
ariaChecked = "true"
|
||||
}
|
||||
btnMods := []vdom.Mod{
|
||||
vdom.Attr("type", "button"),
|
||||
vdom.Attr("role", "switch"),
|
||||
vdom.Attr("aria-checked", ariaChecked),
|
||||
vdom.Attr("class", trackCls),
|
||||
vdom.On(vdom.EVENT_CLICK, toggle),
|
||||
vdom.El("span", vdom.Attr("class", knobCls)),
|
||||
}
|
||||
if disabled {
|
||||
btnMods = append(btnMods, vdom.Attr("disabled", "disabled"))
|
||||
}
|
||||
|
||||
mods := []vdom.Mod{vdom.Attr("class", cx("flex items-center gap-2", class)), vdom.El("button", btnMods...)}
|
||||
|
||||
if label != "" || description != "" {
|
||||
text := []vdom.Mod{vdom.Attr("class", "flex flex-col leading-tight")}
|
||||
if label != "" {
|
||||
labelColor := "text-neutral-800"
|
||||
if disabled {
|
||||
labelColor = "text-neutral-400"
|
||||
}
|
||||
text = append(text, vdom.El("span",
|
||||
vdom.Attr("class", cx("text-sm select-none", labelColor)),
|
||||
vdom.On(vdom.EVENT_CLICK, toggle),
|
||||
vdom.Text(label)))
|
||||
}
|
||||
if description != "" {
|
||||
text = append(text, vdom.El("span", vdom.Attr("class", "text-xs text-neutral-500"), vdom.Text(description)))
|
||||
}
|
||||
mods = append(mods, vdom.El("div", text...))
|
||||
}
|
||||
return vdom.El("div", mods...)
|
||||
}
|
||||
Reference in New Issue
Block a user