WASM reactive UI framework for Go: - reactive/ - Signal[T], Effect, Runtime - ui/ - Button, Text, Input, View, Canvas, SVG components - navigation/ - Router, guards, history management - auth/ - OIDC client for WASM applications - host/ - Static file server Extracted from arcadia as open-source component. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
90
ui/layout.go
Normal file
90
ui/layout.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package ui
|
||||
|
||||
import "strings"
|
||||
|
||||
// VerticalGroup is a view that arranges its children vertically
|
||||
// It uses CSS Grid with a single column
|
||||
func VerticalGroup(children ...View) View {
|
||||
v := NewView()
|
||||
v.e.Grid()
|
||||
v.e.GridTemplateColumns("1fr") // Force single column
|
||||
v.e.GridAutoFlow("row")
|
||||
v.e.Width("100%")
|
||||
for _, child := range children {
|
||||
v.Child(child)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// HorizontalGroup is a view that arranges its children horizontally
|
||||
// It uses flexbox to do so
|
||||
func HorizontalGroup(children ...View) View {
|
||||
v := NewView()
|
||||
v.e.Grid()
|
||||
v.e.GridTemplateColumns("repeat(auto-fit, minmax(250px, 1fr))")
|
||||
v.e.Width("100%")
|
||||
for _, child := range children {
|
||||
v.Child(child)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Spacer is a view that takes up all available space
|
||||
// It uses flexbox to do so
|
||||
func Spacer() View {
|
||||
v := NewView()
|
||||
v.e.Get("style").Call("setProperty", "flex", "1")
|
||||
return v
|
||||
}
|
||||
|
||||
// OverlayGroup creates a container where children are stacked on top of each other
|
||||
func OverlayGroup(children ...View) View {
|
||||
v := NewView()
|
||||
v.e.Get("style").Call("setProperty", "position", "relative")
|
||||
v.e.Get("style").Call("setProperty", "display", "block")
|
||||
|
||||
// Add children with absolute positioning (except first one)
|
||||
for i, child := range children {
|
||||
if i == 0 {
|
||||
// First child acts as the base layer
|
||||
v.Child(child)
|
||||
} else {
|
||||
// Subsequent children are absolutely positioned as overlays
|
||||
// They need pointer-events: none so clicks pass through to layers below
|
||||
child.e.Get("style").Call("setProperty", "position", "absolute")
|
||||
child.e.Get("style").Call("setProperty", "top", "0")
|
||||
child.e.Get("style").Call("setProperty", "left", "0")
|
||||
child.e.Get("style").Call("setProperty", "width", "100%")
|
||||
child.e.Get("style").Call("setProperty", "height", "100%")
|
||||
child.e.Get("style").Call("setProperty", "pointer-events", "none")
|
||||
v.Child(child)
|
||||
}
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// Divider creates a visual separator line
|
||||
func Divider() View {
|
||||
v := NewView()
|
||||
v.e.Get("style").Call("setProperty", "border-top", "1px solid #ccc")
|
||||
v.e.Get("style").Call("setProperty", "margin", "8px 0")
|
||||
v.e.Get("style").Call("setProperty", "width", "100%")
|
||||
v.e.Get("style").Call("setProperty", "height", "1px")
|
||||
return v
|
||||
}
|
||||
|
||||
// FlexLayout creates a horizontal layout with explicit column sizing
|
||||
// Example: FlexLayout([]string{"48px", "1fr", "240px"}, left, center, right)
|
||||
// Supports fixed widths (e.g., "48px"), flexible ("1fr"), and auto-sized ("auto")
|
||||
func FlexLayout(columns []string, children ...View) View {
|
||||
v := NewView()
|
||||
v.e.Grid()
|
||||
v.e.Get("style").Call("setProperty", "grid-template-columns", strings.Join(columns, " "))
|
||||
v.e.Width("100%")
|
||||
v.e.Height("100%")
|
||||
for _, child := range children {
|
||||
v.Child(child)
|
||||
}
|
||||
return v
|
||||
}
|
||||
Reference in New Issue
Block a user