feat(html): add tabindex 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 16:31:22 +00:00
parent 48884f7974
commit 149d31b140
4 changed files with 23 additions and 1 deletions

View file

@ -32,6 +32,13 @@ All concrete node types are unexported structs with exported constructor functio
| `Switch(selector, cases)` | Renders one of several named cases based on a runtime selector function. Returns empty string when no case matches. |
| `Entitled(feature, Node)` | Renders the child only when the context's entitlement function grants the named feature. Deny-by-default: returns empty string when no entitlement function is set. |
Accessibility-oriented helpers are also provided for common attribute patterns:
- `AriaLabel(node, label)`
- `Alt(node, text)`
- `AriaHidden(node, hidden)`
- `TabIndex(node, index)`
### Safety Guarantees
- **XSS prevention**: `Text()` nodes always HTML-escape their output via `html.EscapeString()`. User-supplied strings passed through `Text()` cannot inject HTML.

View file

@ -114,6 +114,6 @@ These are not regressions; they are design choices or deferred work recorded for
These items were captured during the WASM size reduction work and expert review sessions. They are not committed work items.
- **TypeScript type definitions** alongside `GenerateBundle()` for typed Web Component consumers.
- **Accessibility helpers**`aria-label` builder, `alt` text helpers, focus management nodes. The layout has semantic HTML and ARIA roles but no API for fine-grained accessibility attributes beyond `Attr()`.
- **Accessibility helpers**`aria-label`, `alt`, `aria-hidden`, and `tabindex` helpers. The layout has semantic HTML and ARIA roles, and the node layer now exposes common accessibility attribute shortcuts beyond `Attr()`.
- **Layout variant validation** — return a warning or sentinel error from `NewLayout` when the variant string contains unrecognised slot characters.
- **Daemon mode for codegen** — watch mode for regenerating the JS bundle when slot config changes, for development workflows.

View file

@ -5,6 +5,7 @@ import (
"iter"
"maps"
"slices"
"strconv"
"strings"
i18n "dappco.re/go/core/i18n"
@ -115,6 +116,11 @@ func AriaHidden(n Node, hidden bool) Node {
return Attr(n, "aria-hidden", "false")
}
// TabIndex sets the tabindex attribute on an element node.
func TabIndex(n Node, index int) Node {
return Attr(n, "tabindex", strconv.Itoa(index))
}
func (n *elNode) Render(ctx *Context) string {
var b strings.Builder

View file

@ -211,6 +211,15 @@ func TestAriaHiddenHelper(t *testing.T) {
}
}
func TestTabIndexHelper(t *testing.T) {
ctx := NewContext()
node := TabIndex(El("button", Raw("action")), -1)
got := node.Render(ctx)
if !strings.Contains(got, `tabindex="-1"`) {
t.Errorf("TabIndex() = %q, want tabindex=\"-1\"", got)
}
}
func TestElNode_MultipleAttrs(t *testing.T) {
ctx := NewContext()
node := Attr(Attr(El("a", Raw("link")), "href", "/home"), "class", "nav")