66 lines
2.1 KiB
Go
66 lines
2.1 KiB
Go
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...)
|
|
}
|