feat(html): support attributes on responsive wrappers
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
d0e7f60dab
commit
4c0669ef1a
2 changed files with 51 additions and 2 deletions
|
|
@ -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(`<div data-variant="`)
|
||||
b.WriteString(`<div`)
|
||||
if len(r.attrs) > 0 {
|
||||
keys := slices.Collect(maps.Keys(r.attrs))
|
||||
slices.Sort(keys)
|
||||
for _, key := range keys {
|
||||
b.WriteByte(' ')
|
||||
b.WriteString(escapeHTML(key))
|
||||
b.WriteString(`="`)
|
||||
b.WriteString(escapeAttr(r.attrs[key]))
|
||||
b.WriteByte('"')
|
||||
}
|
||||
}
|
||||
b.WriteString(` data-variant="`)
|
||||
b.WriteString(escapeAttr(v.name))
|
||||
b.WriteString(`">`)
|
||||
b.WriteString(Render(v.layout, ctx))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue