diff --git a/responsive.go b/responsive.go
index 046d092..fc40939 100644
--- a/responsive.go
+++ b/responsive.go
@@ -1,6 +1,8 @@
package html
import (
+ "maps"
+ "slices"
"strconv"
"strings"
)
@@ -10,6 +12,7 @@ import (
// Each variant is rendered inside a container with data-variant for CSS targeting.
type Responsive struct {
variants []responsiveVariant
+ attrs map[string]string
}
type responsiveVariant struct {
@@ -20,7 +23,19 @@ type responsiveVariant struct {
// responsive.go: NewResponsive creates a new multi-variant responsive compositor.
// Example: r := NewResponsive().
func NewResponsive() *Responsive {
- return &Responsive{}
+ return &Responsive{
+ attrs: make(map[string]string),
+ }
+}
+
+func (r *Responsive) setAttr(key, value string) {
+ if r == nil {
+ return
+ }
+ if r.attrs == nil {
+ r.attrs = make(map[string]string)
+ }
+ r.attrs[key] = value
}
// escapeCSSString escapes a string for safe use inside a double-quoted CSS
@@ -85,7 +100,19 @@ func (r *Responsive) Render(ctx *Context) string {
var b strings.Builder
for _, v := range r.variants {
- b.WriteString(`
`)
b.WriteString(Render(v.layout, ctx))
diff --git a/responsive_test.go b/responsive_test.go
index 351ed3b..ee0a3e6 100644
--- a/responsive_test.go
+++ b/responsive_test.go
@@ -115,6 +115,28 @@ func TestResponsive_NilLayoutVariant(t *testing.T) {
}
}
+func TestResponsive_Attributes(t *testing.T) {
+ ctx := NewContext()
+ r := Attr(NewResponsive().
+ Variant("desktop", NewLayout("C").C(Raw("main"))).
+ Variant("mobile", NewLayout("C").C(Raw("main"))),
+ "aria-label", "Responsive content",
+ )
+ r = Attr(r, "class", "responsive-shell")
+
+ got := r.Render(ctx)
+
+ if count := strings.Count(got, `aria-label="Responsive content"`); count != 2 {
+ t.Fatalf("responsive attrs should apply to each wrapper, got %d in:\n%s", count, got)
+ }
+ if count := strings.Count(got, `class="responsive-shell"`); count != 2 {
+ t.Fatalf("responsive class should apply to each wrapper, got %d in:\n%s", count, got)
+ }
+ if !strings.Contains(got, `aria-label="Responsive content" class="responsive-shell" data-variant="desktop"`) {
+ t.Fatalf("responsive wrapper attrs should be sorted and preserved, got:\n%s", got)
+ }
+}
+
func TestVariantSelector(t *testing.T) {
tests := []struct {
name string