diff --git a/docs/architecture.md b/docs/architecture.md
index 7f247e9..7018240 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -22,7 +22,7 @@ All concrete node types are unexported structs with exported constructor functio
| Constructor | Behaviour |
|-------------|-----------|
| `El(tag, ...Node)` | HTML element with children. Void elements (`br`, `img`, `input`, etc.) never emit a closing tag. |
-| `Attr(Node, key, value)` | Sets an attribute on an `El` node. Traverses through `If`, `Unless`, `Entitled`, `Each`, `EachSeq`, and `Switch` wrappers. Returns the node for chaining. |
+| `Attr(Node, key, value)` | Sets an attribute on an `El` node. Traverses through `If`, `Unless`, `Entitled`, `Each`, `EachSeq`, `Switch`, `Layout`, and `Responsive` wrappers. Returns the node for chaining. |
| `AriaLabel(Node, label)` | Convenience helper that sets `aria-label` on an element node. |
| `AltText(Node, text)` | Convenience helper that sets `alt` on an element node. |
| `TabIndex(Node, index)` | Convenience helper that sets `tabindex` on an element node. |
diff --git a/node.go b/node.go
index d0944f4..0956fe3 100644
--- a/node.go
+++ b/node.go
@@ -95,7 +95,8 @@ func El(tag string, children ...Node) Node {
// Attr sets an attribute on an El node. Returns the node for chaining.
// Usage example: Attr(El("a", Text("docs")), "href", "/docs")
-// It recursively traverses through wrappers like If, Unless, Entitled, and Each.
+// It recursively traverses through wrappers like If, Unless, Entitled, Each,
+// Layout, and Responsive when present.
func Attr(n Node, key, value string) Node {
if n == nil {
return n
@@ -114,6 +115,19 @@ func Attr(n Node, key, value string) Node {
for _, child := range t.cases {
Attr(child, key, value)
}
+ case *Layout:
+ if t.slots != nil {
+ for slot, children := range t.slots {
+ for i := range children {
+ children[i] = Attr(children[i], key, value)
+ }
+ t.slots[slot] = children
+ }
+ }
+ case *Responsive:
+ for i := range t.variants {
+ Attr(t.variants[i].layout, key, value)
+ }
case attrApplier:
t.applyAttr(key, value)
}
diff --git a/node_test.go b/node_test.go
index 117bc77..fa1bb07 100644
--- a/node_test.go
+++ b/node_test.go
@@ -481,6 +481,30 @@ func TestAttr_ThroughSwitchNode_Good(t *testing.T) {
}
}
+func TestAttr_ThroughLayout_Good(t *testing.T) {
+ ctx := NewContext()
+ layout := NewLayout("C").C(El("div", Raw("content")))
+ Attr(layout, "class", "page")
+
+ got := layout.Render(ctx)
+ want := `