feat(html): add hidden helper
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-03 19:51:26 +00:00
parent 24565df459
commit fd1f7cea74
3 changed files with 28 additions and 2 deletions

View file

@ -39,7 +39,7 @@ This builds a Header-Content-Footer layout with semantic HTML elements (`<header
| Path | Purpose |
|------|---------|
| `node.go` | `Node` interface and all node types: `El`, `Text`, `Raw`, `If`, `Unless`, `Each`, `EachSeq`, `Switch`, `Entitled`, plus `AriaLabel`, `Alt`/`AltText`, `AriaBusy`, `AriaLive`, `AriaDisabled`, `AriaChecked`, `AriaInvalid`, `AriaRequired`, `AriaPressed`, `AriaSelected`, `TabIndex`, and `AutoFocus` helpers |
| `node.go` | `Node` interface and all node types: `El`, `Text`, `Raw`, `If`, `Unless`, `Each`, `EachSeq`, `Switch`, `Entitled`, plus `AriaLabel`, `Alt`/`AltText`, `AriaBusy`, `AriaLive`, `AriaDisabled`, `AriaChecked`, `AriaInvalid`, `AriaRequired`, `AriaPressed`, `AriaSelected`, `Hidden`, `TabIndex`, and `AutoFocus` helpers |
| `layout.go` | HLCRF compositor with semantic HTML elements and ARIA roles |
| `responsive.go` | Multi-variant breakpoint wrapper (`data-variant` containers, CSS scoping helpers) |
| `context.go` | Rendering context: identity, locale, entitlements, i18n service |
@ -52,7 +52,7 @@ This builds a Header-Content-Footer layout with semantic HTML elements (`<header
## Key Concepts
**Node tree** -- All renderable units implement `Node`, a single-method interface: `Render(ctx *Context) string`. The library composes nodes into trees using `El()` for elements, `Text()` for translated text, and control-flow constructors (`If`, `Unless`, `Each`, `Switch`, `Entitled`), plus accessibility helpers such as `AriaLabel()`, `AriaControls()`, `AriaCurrent()`, `AriaBusy()`, `AriaLive()`, `AriaHidden()`, `AriaDisabled()`, `AriaChecked()`, `AriaInvalid()`, `AriaRequired()`, and `TabIndex()`.
**Node tree** -- All renderable units implement `Node`, a single-method interface: `Render(ctx *Context) string`. The library composes nodes into trees using `El()` for elements, `Text()` for translated text, and control-flow constructors (`If`, `Unless`, `Each`, `Switch`, `Entitled`), plus accessibility and visibility helpers such as `AriaLabel()`, `AriaControls()`, `AriaCurrent()`, `AriaBusy()`, `AriaLive()`, `AriaHidden()`, `Hidden()`, `AriaDisabled()`, `AriaChecked()`, `AriaInvalid()`, `AriaRequired()`, and `TabIndex()`.
**HLCRF Layout** -- A five-slot compositor that maps to semantic HTML: `<header>` (H), `<aside>` (L/R), `<main>` (C), `<footer>` (F). The variant string controls which slots render: `"HLCRF"` for all five, `"HCF"` for three, `"C"` for content only. Layouts nest: placing a `Layout` inside another layout's slot produces hierarchical `data-block` paths like `L-0-C-0`.

10
node.go
View file

@ -300,6 +300,16 @@ func AriaHidden(n Node, hidden bool) Node {
return n
}
// node.go: Hidden sets the HTML hidden attribute on an element node.
// Example: Hidden(El("section"), true).
// Hidden is a standard HTML visibility flag and omits the attribute when false.
func Hidden(n Node, hidden bool) Node {
if hidden {
return Attr(n, "hidden", "hidden")
}
return n
}
// node.go: AriaExpanded sets the aria-expanded attribute on an element node.
// Example: AriaExpanded(El("button"), true).
func AriaExpanded(n Node, expanded bool) Node {

View file

@ -488,6 +488,22 @@ func TestAriaHiddenHelper(t *testing.T) {
}
}
func TestHiddenHelper(t *testing.T) {
ctx := NewContext()
hidden := Hidden(El("section", Raw("content")), true)
gotHidden := hidden.Render(ctx)
if !strings.Contains(gotHidden, `hidden="hidden"`) {
t.Errorf("Hidden(true) = %q, want hidden=\"hidden\"", gotHidden)
}
visible := Hidden(El("section", Raw("content")), false)
gotVisible := visible.Render(ctx)
if strings.Contains(gotVisible, `hidden=`) {
t.Errorf("Hidden(false) = %q, want no hidden attribute", gotVisible)
}
}
func TestAriaExpandedHelper(t *testing.T) {
ctx := NewContext()