initial port of the UI kit

This commit is contained in:
2026-07-13 01:58:29 -04:00
parent 261a7f2b4d
commit b02df48a66
51 changed files with 7507 additions and 154 deletions

57
go/webui/README.md Normal file
View File

@@ -0,0 +1,57 @@
# webui — Go/WebAssembly component kit
A Go port of kjol's Solid.js component kit (`web/kit`) for the **gowasm** engine.
Components are neutral `*vdom.VNode` builders (SSR on the server, hydrate on the
client) styled with **Tailwind** utility classes. Import as `kjol/webui`.
```go
import ui "kjol/webui"
ui.Button(ui.ButtonProps{Color: ui.ButtonPrimary, Text: "Save", OnClick: save})
ui.Alert(ui.AlertGreen, "Done", vdom.Text("Saved."))
ui.ToggleSwitch(on, func(v bool){ on = v }, "Notifications", "", false, "")
```
See the runnable **`/kit`** demo page in `cmd/examples/go-wasm-web` (app nav → "UI Kit").
## Conventions
- A TSX `function Foo(props)``func Foo(p FooProps, children ...*vdom.VNode) *vdom.VNode`
(simple components take positional params). Reactive accessors collapse: pass plain
current values (read a signal at the call site); state changes come back via `OnChange`
callbacks (the whole tree re-renders and reconciles).
- Tailwind classes are copied verbatim so `kjol/cmd/twcss` (scanning these `.go` files)
emits the CSS. Custom tokens (`rounded-default`, `bg-primary`, `text-text-heading`, …)
come from the app's `@theme` block.
- Icons via `Icon(name, size, class)`; the registry ships a small default set, apps add
more with `RegisterIcon`. Unregistered names render an empty (correctly-sized) box.
## Components
- **Layout/content:** `Card*`, `BorderCard`, `CardHeader`, `PageHeader`, `PageContainer`,
`Breadcrumbs`, `Divider`, `CodeBox`, `Loader`, `Sidebar*`, `Icon*`.
- **Controls:** `Button`, `ButtonLink`, `SegmentedButtons`, `BackLink`, `Badge`,
`ToggleSwitch`, and the `Form*` family (`FormInput`, `FormTextarea`, `FormSelect`,
`FormLabel`, `FormFieldset`, `FormNumberInput`/`FormCurrencyInput`/`FormEmailInput`/… ).
- **Disclosure/nav:** `Alert`, `TabGroup`, `CrmTabGroup`, `Accordion`/`SingleAccordion`,
`Menu`*, `Submenu`, `EnvBadge`, `RemoteUpdateFlash`.
- **Overlays/floating:** `Modal`/`ConfirmModal`/`WizardModal`, `Toast*`, `Tooltip`/
`HoverTooltip`, `Popover`/`HoverPopover`, `Floating*`.
- **Data:** `PrettyTable`, `AutoTable`, `CellGrid`, `ReactiveChart`, `Calendar`,
`DatePicker`, `FuzzyMatch*` (+ pure matchers), `Tutorial`.
- **Pure logic (no vdom):** `formatters.go` (`FormatPhoneNumber`, `FormatDate`, …) and
`validation.go` (`IsEmailValid`, `CreateValidation`, …).
## Runtime limitations (what the TSX did that this can't)
The neutral runtime has **no floating-ui, portals, refs, element measurement, focus
traps, or timers**. Components that relied on those are ported as **structure +
Tailwind + signal/event wiring**, with open/selection state lifted to props +
callbacks and positioning approximated with static Tailwind. Each such gap is marked
with a `// NOTE:` in the component's file. Concretely: dropdown/menu/tooltip/modal
positioning is static (not computed); outside-click / Escape / hover-delay dismissal,
auto-dismiss timers, and enter/exit animations are dropped (caller-driven); `AutoTable`
omits virtual scrolling, column resize/reorder, inline editing, and the formula engine;
`ReactiveChart` renders only its container (the example draws charts server-side with
go-chart); a few `Form*` controls that needed canvas/async (`FormSignaturePad`,
`FormAsyncCombobox`) are omitted. Everything compiles on native (SSR) and js/wasm.