# Focused component patterns

Read the selected framework's public types first. These patterns describe the
initial `ui.Definition` / explicit-slot API and first-party Tailwind v4 workflow.

## Ownership and optional inputs

Put pure display logic in components and request/database/auth logic in handlers.
Private markup helpers may take ordinary Go parameters. Use a public definition
when a component needs validation/defaults or is an exported/overridable contract.
A string prop cannot be supplied as HTML; a slot cannot be used as an attribute.

For a boolean defaulting to true, make the prop `Expanded *bool`. In `Defaults`,
only when `p.Expanded == nil`, assign a new local true value's address. Do not write
through the supplied pointer. The body uses `*p.Expanded` after defaulting. Prefer
ordinary `bool` when false is the intended default. For enums, use a named Go
string type with constants, default the empty value, and reject unknown values in
`Validate`. Go accepts arbitrary conversions to named string types, so constants
alone do not validate input.

`ui.Content{}` means not supplied; `ui.Text("")` means supplied empty text. Required
child/slot validation should check presence, not render it twice to inspect length.

## Attribute forwarding

Declare `Attributes ui.Attributes` only when forwarding is part of the component
contract. `ui.Merge(base, forwarded)` returns `(templ.Attributes, error)`. Propagate
that error; do not spread an unchecked arbitrary map or discard the error. A body
can prepare merged attributes in its Go factory and return a `templ.ComponentFunc`
that returns the validation error, otherwise call its private markup body. A
simpler component should declare the few specific props it needs instead.

Class strings merge distinct tokens; conflicting Tailwind utility groups do not
resolve by argument order. Prefer a typed variant that selects one complete set:

```go
func buttonClasses(danger bool) string {
    if danger { return "rounded-lg bg-red-600 px-4 py-2 text-white hover:bg-red-700" }
    return "rounded-lg bg-indigo-600 px-4 py-2 text-white hover:bg-indigo-700"
}
```

Render it as `class={ buttonClasses(p.Danger) }`. All candidate names exist literally
in source. `aria-*` values are strings (including `"false"`); HTML booleans are bools.
A label uses `for={ p.ID }`, not JSX `htmlFor`.

## Forms

Reuse `ui/form.Field` with `FieldProps{ID, Name, Label, Value, Error, Required,
MaxLength, Type, Autocomplete, Multiline}`; omitted `Type` defaults to text.
`Multiline: true` renders a textarea. IDs must be unique per page; when repeating
fields, derive a stable ID from the row identity. `Field` adds error relationships
when `Error` is nonempty. Validation/binding remains in `forms` or the handler.

A normal `<form method="post">` contains
`@form.CSRF.Call(form.CSRFProps{Token: token}, ui.NoSlots{})` and fields. The handler
obtains `token` from the existing session middleware and passes it explicitly.
Do not invent a token, suppress CSRF middleware, or retain password inputs after
failed login. Authorization remains in handlers and database query scopes.
The articles `.templ` pages are an executable reference.

## Libraries and project overrides

A library exports `Card.Export(1)` in its owning `App.Components` and declares
normal manifest dependencies. Embed resources; `ComponentAssets` lists required
paths in `Resources`. Serving assets is an explicit route choice.

For an override, copy the original definition, set `Body` to the custom compiled
function with the **original named Props and Slots types**, and put
`replacement.Override(1)` in the local `project` app's `ComponentOverrides`.
Do not redefine lookalike structs. The registry preserves original defaults and
validation, and rejects type/version mismatches or multiple overrides.

Build `cicadel.ComponentRegistry(apps)`, call `ui.Resolve(registry, library.Card)`,
check the error, then pass the resolved definition into page/handler factories.
A direct `library.Card.Call(...)` deliberately bypasses project overrides.
Add the library's Go import path to `ui.css.json` `packages` when using its Tailwind
classes. This is build-time source discovery, not app installation or registration.

## Repair loop

| Symptom/code | Repair |
| --- | --- |
| `UI_PARSE`, unterminated `if`/`for` | Use Go expressions and multiline templ control-flow blocks; check matching tags/braces. |
| `UI_TYPE`, undefined private body | Generate before type checking; check package/import names and body signature. |
| Unknown prop/slot field | Inspect the exported Go struct; use its exact name/type. |
| `UI_STALE` or `UI_CSS_STALE` | Run `ui build`, inspect source/output changes, rerun check. |
| `UI_CSS_TOOL` | Run the explicit `ui css install` once, then retry offline build. |
| `UI_CSS_PACKAGE` | Install the module with Go tooling; list an exact existing package import path. |
| Classes render but CSS is absent | Use full literal names; inspect input `@source` and config `packages`; rebuild CSS. |
| `UI_RENDER` required value/slot | Fix caller props or explicitly revise the contract; do not erase validation. |
| `UI_CONTRACT` override mismatch | Reuse original public types and contract version. |
| `UI_ATTRIBUTE`, `UI_URL`, `UI_SYNTAX` | Use permitted attributes/contexts; do not cast values to unsafe types. |
| `UI_WRITE` / committed error | Log transport failure; do not write a second response. |

`--json` diagnostics carry stable codes; type-error source locations point to the
owning `.templ` declaration and retain the exact generated Go position. Runtime
errors include nested component stacks. Keep supplied values out of public errors.
