initial port of the UI kit
This commit is contained in:
92
go/webui/general.go
Normal file
92
go/webui/general.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package webui
|
||||
|
||||
import "kjol/vdom"
|
||||
|
||||
// Port of web/kit/General.tsx. Anchor components render plain <a href>; the app
|
||||
// wires SPA navigation on top (e.g. its layout nav uses Button/OnClick).
|
||||
|
||||
// PageContainer wraps a page body (marker class kept for app CSS).
|
||||
func PageContainer(children ...*vdom.VNode) *vdom.VNode {
|
||||
return vdom.El("div", kids([]vdom.Mod{vdom.Attr("class", "admin-page-container")}, children)...)
|
||||
}
|
||||
|
||||
// Divider is a thin horizontal rule.
|
||||
func Divider() *vdom.VNode { return vdom.El("hr", vdom.Attr("class", "text-neutral-200 mt-1 mb-3")) }
|
||||
|
||||
// CodeBox renders a dark monospace code block.
|
||||
func CodeBox(code, class string) *vdom.VNode {
|
||||
return vdom.El("div",
|
||||
vdom.Attr("class", cx("text-xs p-3 bg-neutral-800 text-neutral-100 border border-neutral-700 rounded-default", class)),
|
||||
vdom.El("pre", vdom.El("code", vdom.Text(code))),
|
||||
)
|
||||
}
|
||||
|
||||
// PageHeader is a centered page title with an underline.
|
||||
func PageHeader(text, class string) *vdom.VNode {
|
||||
return vdom.El("header", vdom.Attr("class", class),
|
||||
vdom.El("div", vdom.Attr("class", "mt-1"),
|
||||
vdom.El("h1", vdom.Attr("class", "text-center text-2xl font-light text-neutral-800 mb-2"), vdom.Text(text)),
|
||||
vdom.El("hr", vdom.Attr("class", "text-neutral-200 mb-2")),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// PageLink is an inline text link (blue). newTab opens in a new tab.
|
||||
func PageLink(href string, newTab bool, class string, children ...*vdom.VNode) *vdom.VNode {
|
||||
mods := []vdom.Mod{
|
||||
vdom.Attr("href", href),
|
||||
vdom.Attr("class", cx("text-sky-700 hover:text-sky-800 hover:underline hover:decoration-1", class)),
|
||||
}
|
||||
if newTab {
|
||||
mods = append(mods, vdom.Attr("target", "_blank"), vdom.Attr("rel", "noopener noreferrer"))
|
||||
}
|
||||
return vdom.El("a", kids(mods, children)...)
|
||||
}
|
||||
|
||||
// Loader is a centered spinning ring.
|
||||
func Loader() *vdom.VNode {
|
||||
return vdom.El("div", vdom.Attr("class", "flex items-center justify-center p-8"),
|
||||
vdom.El("div", vdom.Attr("class", "h-8 w-8 border-4 border-sky-700 border-t-transparent rounded-full animate-spin")),
|
||||
)
|
||||
}
|
||||
|
||||
// BreadcrumbItem is one crumb (URL + display text).
|
||||
type BreadcrumbItem struct {
|
||||
URL string
|
||||
DisplayText string
|
||||
}
|
||||
|
||||
// Breadcrumbs renders a chevron-separated crumb trail; the last item is bold and
|
||||
// not linked.
|
||||
func Breadcrumbs(items []BreadcrumbItem) *vdom.VNode {
|
||||
mods := []vdom.Mod{vdom.Attr("class", "flex flex-row items-center text-neutral-400 text-xs")}
|
||||
for i, crumb := range items {
|
||||
if i != len(items)-1 {
|
||||
mods = append(mods, vdom.El("span", vdom.Attr("class", "flex items-center"),
|
||||
vdom.El("a", vdom.Attr("href", crumb.URL),
|
||||
vdom.Attr("class", "text-neutral-500 cursor-pointer no-underline hover:text-neutral-700 hover:underline"),
|
||||
vdom.Text(crumb.DisplayText)),
|
||||
Icon("chevron-right", 12, "mx-[0.15rem] opacity-50"),
|
||||
))
|
||||
} else {
|
||||
mods = append(mods, vdom.El("span", vdom.Attr("class", "text-neutral-700 font-medium"), vdom.Text(crumb.DisplayText)))
|
||||
}
|
||||
}
|
||||
return vdom.El("div", mods...)
|
||||
}
|
||||
|
||||
// ManagerPageHeader is a title/description row with an optional action slot
|
||||
// (marker classes kept for app CSS).
|
||||
func ManagerPageHeader(title, description string, action *vdom.VNode) *vdom.VNode {
|
||||
inner := vdom.El("div",
|
||||
vdom.El("h2", vdom.Attr("class", "page-title"), vdom.Text(title)),
|
||||
)
|
||||
if description != "" {
|
||||
inner.Children = append(inner.Children, vdom.El("p", vdom.Attr("class", "page-desc"), vdom.Text(description)))
|
||||
}
|
||||
mods := []vdom.Mod{vdom.Attr("class", "page-header"), inner}
|
||||
if action != nil {
|
||||
mods = append(mods, action)
|
||||
}
|
||||
return vdom.El("div", mods...)
|
||||
}
|
||||
Reference in New Issue
Block a user