# 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 **`/wasm/kit`** demo page in `cmd/kjol-web` (Layers → Kjol Wasm Web).

## 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.
