desy-html 4.2.1 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/docs/_include.template-header.njk +51 -47
  2. package/docs/_macro.example-render.njk +4 -0
  3. package/docs/componentes.html +3 -0
  4. package/docs/ds/_ds.example.header.njk +1 -1
  5. package/docs/ds/_ds.example.menu-vertical.njk +3 -3
  6. package/docs/ds/_ds.example.menubar-en-uso.njk +6 -18
  7. package/docs/ds/_ds.example.menubar-variaciones.njk +51 -121
  8. package/docs/examples-tree.html +5 -0
  9. package/docs/index.html +18 -0
  10. package/package.json +1 -1
  11. package/src/css/styles.css +1 -0
  12. package/src/js/aria/tree.js +245 -0
  13. package/src/js/aria/treeitem.js +260 -0
  14. package/src/js/desy-html.js +28 -0
  15. package/src/js/index.js +3 -1
  16. package/src/templates/components/description-list/_examples.description-list.njk +63 -0
  17. package/src/templates/components/dropdown/params.dropdown.yaml +6 -6
  18. package/src/templates/components/header/_examples.header.njk +35 -3
  19. package/src/templates/components/header/_template.header.header__dropdown.njk +7 -2
  20. package/src/templates/components/header/_template.header.header__offcanvas.njk +1 -1
  21. package/src/templates/components/header/_template.header.header__subnav.njk +17 -13
  22. package/src/templates/components/header/_template.header.njk +42 -30
  23. package/src/templates/components/header/params.header.yaml +45 -5
  24. package/src/templates/components/menu-horizontal/_examples.menu-horizontal.njk +2 -1
  25. package/src/templates/components/menu-horizontal/_template.menu-horizontal.njk +1 -1
  26. package/src/templates/components/menubar/_examples.menubar.njk +349 -143
  27. package/src/templates/components/menubar/_styles.menubar.css +1 -0
  28. package/src/templates/components/menubar/_template.menubar.njk +2 -2
  29. package/src/templates/components/menubar/params.menubar.yaml +4 -0
  30. package/src/templates/components/tree/_examples.tree.njk +987 -0
  31. package/src/templates/components/tree/_macro.tree.njk +3 -0
  32. package/src/templates/components/tree/_styles.tree.css +45 -0
  33. package/src/templates/components/tree/_template.tree.njk +175 -0
  34. package/src/templates/components/tree/params.tree.yaml +159 -0
@@ -0,0 +1,3 @@
1
+ {% macro componentTree(params) %}
2
+ {% include "./_template.tree.njk" %}
3
+ {% endmacro %}
@@ -0,0 +1,45 @@
1
+ /* ==========================================================================
2
+ _styles.tree.css
3
+ ========================================================================== */
4
+
5
+ @layer components {
6
+ .c-tree--sm {
7
+ input[type="checkbox"],
8
+ input[type="radio"] {
9
+ @apply w-base !important;
10
+ @apply h-base !important;
11
+ }
12
+ }
13
+
14
+ .c-tree__item {
15
+ &[aria-expanded="true"] {
16
+ & > ul {
17
+ @apply block;
18
+ }
19
+ .c-tree__plus {
20
+ @apply hidden;
21
+ }
22
+ .c-tree__minus {
23
+ @apply block;
24
+ }
25
+ }
26
+
27
+ &[aria-expanded="false"] {
28
+ & > ul {
29
+ @apply hidden;
30
+ }
31
+ .c-tree__plus {
32
+ @apply block;
33
+ }
34
+ .c-tree__minus {
35
+ @apply hidden;
36
+ }
37
+ }
38
+ }
39
+
40
+ .c-tree__item--focus {
41
+ @apply bg-warning-base outline-none shadow-outline-focus text-black;
42
+ }
43
+ }
44
+
45
+
@@ -0,0 +1,175 @@
1
+ {% from "../error-message/_macro.error-message.njk" import componentErrorMessage -%}
2
+ {% from "../fieldset/_macro.fieldset.njk" import componentFieldset %}
3
+ {% from "../hint/_macro.hint.njk" import componentHint %}
4
+ {% from "../label/_macro.label.njk" import componentLabel %}
5
+
6
+ {#- If an id 'prefix' is not passed, fall back to using the name attribute
7
+ instead. We need this for error messages and hints as well -#}
8
+ {% set idPrefix = params.idPrefix if params.idPrefix else params.name %}
9
+
10
+ {#- a record of other elements that we need to associate with the input using
11
+ aria-describedby – for example hints or error messages -#}
12
+ {% set describedBy = params.describedBy if params.describedBy else "" %}
13
+ {% if params.fieldset.describedBy %}
14
+ {% set describedBy = params.fieldset.describedBy %}
15
+ {% endif %}
16
+
17
+ {% set subLevel = "" %}
18
+
19
+ {#- fieldset is false by default -#}
20
+ {% set hasFieldset = true if params.fieldset else false %}
21
+
22
+ {#- macro to generate checkboxes -#}
23
+ {% macro checkboxItem(item, id, name, type) %}
24
+ {% set hasHint = true if item.hint.text or item.hint.html %}
25
+ {% set itemHintId = id + "-item-hint" if hasHint else "" %}
26
+ {% set itemDescribedBy = describedBy if not hasFieldset else "" %}
27
+ {% set itemDescribedBy = (itemDescribedBy + " " + itemHintId) | trim %}
28
+ <div x-data="{ isChecked: {% if not item.checked %}false{% else %}true{% endif %} }" {%- if item.indeterminateChecked %} x-init="$refs.inputCheck.indeterminate=$refs.inputCheck.readOnly=true"{% endif %} class="{%- if params.hasDividers %} border-t border-b border-neutral-base -mb-px{% endif %} {%- if item.classes %} {{ item.classes }}{% endif %}">
29
+ <div class="relative flex items-start py-xs">
30
+ <div class="flex items-center mx-sm">
31
+ <input x-model="isChecked" x-ref="inputCheck" class="w-6 h-6 transition duration-150 ease-in-out border-black focus:border-black focus:shadow-outline-focus-input focus:ring-4 focus:ring-offset-0 focus:ring-warning-base disabled:bg-neutral-base disabled:border-neutral-base text-primary-base" id="{{ id }}-input" name="{{ name }}" {%- if type == 'checkbox' %} type="checkbox"{% else %} type="radio"{% endif -%} value="{{ item.value }}"
32
+ {{-" checked" if item.checked }}
33
+ {{-" disabled" if item.disabled }}
34
+ {%- if itemDescribedBy %} aria-describedby="{{ itemDescribedBy }}"{% endif -%}
35
+ {%- if params.errorMessage %} aria-invalid="true"{% endif -%}
36
+ {%- for attribute, value in item.attributes %} {{ attribute }}="{{ value }}"{% endfor -%}
37
+ {%- if item.isIndeterminate %} onclick="if (this.readOnly) this.checked=this.readOnly=false; else if (!this.checked) this.readOnly=this.indeterminate=true;"{% endif %}
38
+ {%- if item.indeterminateChecked %} onclick="if (this.readOnly) this.checked=this.readOnly=false; else if (!this.checked) this.readOnly=this.indeterminate=true;"{% endif %}>
39
+ </div>
40
+ <div class="flex-1 pt-0.5 leading-5">
41
+ {{ componentLabel({
42
+ html: item.html,
43
+ text: item.text,
44
+ classes: item.label.classes if item.label.classes else 'block relative -top-xs -left-8 pl-8 py-xs',
45
+ attributes: item.label.attributes,
46
+ for: id + '-input'
47
+ }) | indent(6) | trim }}
48
+ {% if hasHint %}
49
+ {{ componentHint({
50
+ id: itemHintId,
51
+ classes: (item.hint.classes if item.hint.classes),
52
+ attributes: item.hint.attributes,
53
+ html: item.hint.html,
54
+ text: item.hint.text
55
+ }) | indent(6) | trim }}
56
+ {% endif %}
57
+ </div>
58
+ </div>
59
+ </div>
60
+ {% endmacro %}
61
+
62
+ {#- macro to generate children -#}
63
+ {% macro childrenTree(itemNode, id, name, type) %}
64
+ {% if itemNode.sub %}
65
+ <div class="w-full h-full">
66
+ <span class="w-full flex items-center relative focus:bg-warning-base focus:outline-none focus:shadow-outline-focus focus:text-black text-left {%- if itemNode.classes %} {{ itemNode.classes }}{% endif %}"
67
+ {%- for attribute, value in itemNode.attributes %} {{ attribute }}="{{ value }}"{% endfor -%}>
68
+ <span class="absolute top-3 -left-4 flex items-center w-4 h-2.5 text-primary-base font-bold">
69
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" width="10" height="10" aria-hidden="true" class="c-tree__minus"><path fill="currentColor" d="M9.286 5.714H.714a.714.714 0 010-1.428h8.572a.714.714 0 010 1.428z"/></svg>
70
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10" width="10" height="10" aria-hidden="true" class="c-tree__plus"><path fill="currentColor" d="M9.286 4.286H5.893a.179.179 0 01-.179-.179V.714a.714.714 0 00-1.428 0v3.393a.179.179 0 01-.179.179H.714a.714.714 0 000 1.428h3.393a.179.179 0 01.179.179v3.393a.714.714 0 001.428 0V5.893a.179.179 0 01.179-.179h3.393a.714.714 0 000-1.428z"/></svg>
71
+ </span>
72
+ {{ checkboxItem(itemNode, id, name, type) }}
73
+ </span>
74
+ </div>
75
+ {% else %}
76
+ {{ checkboxItem(itemNode, id, name, type) }}
77
+ {% endif %}
78
+ {% if itemNode.sub.items %}
79
+ {% set subLevel = subLevel + "sub-" %}
80
+ <ul role="group" class="c-tree__itemgroup {%- if itemNode.sub.classes %} {{ itemNode.sub.classes }}{% endif %}" {%- for attribute, value in itemNode.sub.attributes %} {{ attribute }}="{{ value }}"{% endfor -%}>
81
+ {% for subitem in itemNode.sub.items %}
82
+ {% if subitem %}
83
+ {#- If the user explicitly sets an id, use this instead of the regular idPrefix -#}
84
+ {%- if subitem.id -%}
85
+ {%- set subId = subitem.id -%}
86
+ {%- else -%}
87
+ {%- set subId = subLevel + id + "-" + loop.index0 -%}
88
+ {%- endif %}
89
+ <li class="c-tree__item ml-8 origin-top-left focus:outline-none" id="{{ subId }}" role="treeitem" data-module="c-tree__item" {%- if subitem.sub%}{% if subitem.expanded %} aria-expanded="true"{% else %} aria-expanded="false"{% endif %}{% endif %}>
90
+ {% if subitem.sub %}
91
+ {{ childrenTree(subitem, subId, name, type) }}
92
+ {% else %}
93
+ <div {%- if subitem.id %} id="{{ id }}"{% endif %} class="block {%- if subitem.classes %} {{ subitem.classes }}{% endif %} {%- if subitem.active %} font-bold{% endif %}" {%- if subitem.title %} title="{{ subitem.title }}"{% endif %} {%- if subitem.active %} aria-current="page"{% endif %} {%- if subitem.disabled %} disabled="disabled" aria-disabled="true" tabindex="-1"{% endif %} {%- for attribute, value in subitem.attributes %} {{ attribute }}="{{ value }}"{% endfor -%}>
94
+ {% if subitem.active %}
95
+ <strong>
96
+ {{ checkboxItem(subitem, subId, name, type) }}
97
+ </strong>
98
+ {% else %}
99
+ {{ checkboxItem(subitem, subId, name, type) }}
100
+ {% endif %}
101
+ </div>
102
+ {% endif %}
103
+ </li>
104
+ {% endif %}
105
+ {% endfor %}
106
+ </ul>
107
+ {% endif %}
108
+ {% endmacro %}
109
+
110
+ {#- Capture the HTML so we can optionally nest it in a fieldset -#}
111
+ {% set innerHtml %}
112
+ {% if params.hint %}
113
+ {% set hintId = idPrefix + '-hint' %}
114
+ {% set describedBy = describedBy + ' ' + hintId if describedBy else hintId %}
115
+ {{ componentHint({
116
+ id: hintId,
117
+ classes: params.hint.classes,
118
+ attributes: params.hint.attributes,
119
+ html: params.hint.html,
120
+ text: params.hint.text
121
+ }) | indent(2) | trim }}
122
+ {% endif %}
123
+ {% if params.errorMessage %}
124
+ {% set errorId = idPrefix + '-error' %}
125
+ {% set describedBy = describedBy + ' ' + errorId if describedBy else errorId %}
126
+ {{ componentErrorMessage({
127
+ id: errorId,
128
+ classes: params.errorMessage.classes,
129
+ attributes: params.errorMessage.attributes,
130
+ html: params.errorMessage.html,
131
+ text: params.errorMessage.text,
132
+ visuallyHiddenText: params.errorMessage.visuallyHiddenText
133
+ }) | indent(2) | trim }}
134
+ {% endif %}
135
+ <ul class="c-tree {%- if params.classes %} {{ params.classes }}{% endif %}" role="tree" aria-labelledby="{{ idPrefix }}-heading" {%- for attribute, value in params.attributes %} {{ attribute }}="{{ value }}"{% endfor %} data-module="c-tree">
136
+ {% for item in params.items %}
137
+ {% if item %}
138
+ {#- If the user explicitly sets an id, use this instead of the regular idPrefix -#}
139
+ {%- if item.id -%}
140
+ {%- set id = item.id -%}
141
+ {%- else -%}
142
+ {%- set id = idPrefix + "-" + loop.index0 -%}
143
+ {%- endif -%}
144
+ {% set subId = "sub-" + id %}
145
+ {% set name = item.name if item.name else params.name %}
146
+ {% set hasHint = true if item.hint.text or item.hint.html %}
147
+ {% set itemHintId = id + "-item-hint" if hasHint else "" %}
148
+ {% set itemDescribedBy = describedBy if not hasFieldset else "" %}
149
+ {% set itemDescribedBy = (itemDescribedBy + " " + itemHintId) | trim %}
150
+ <li id="{{ id }}" class="c-tree__item ml-4 focus:outline-none {%- if item.active %} font-bold{% endif %}" role="treeitem" data-module="c-tree__item" {%- if item.sub%}{% if item.expanded %} aria-expanded="true"{% else %} aria-expanded="false"{% endif %}{% endif %}{%- if item.active %} aria-current="page"{% endif %} {%- if item.disabled %} disabled="disabled" aria-disabled="true" tabindex="-1"{% endif %}>
151
+ {{ childrenTree(item, id, name, params.type) }}
152
+ </li>
153
+ {% endif %}
154
+ {% endfor %}
155
+ </ul>
156
+ {% endset -%}
157
+
158
+ <!-- tree -->
159
+ <div class="c-form-group {%- if params.errorMessage %} c-form-group--error{% endif %} {%- if params.formGroup.classes %} {{ params.formGroup.classes }}{% endif %}">
160
+ {% if params.fieldset %}
161
+ {% call componentFieldset({
162
+ describedBy: describedBy,
163
+ errorId: errorId,
164
+ classes: params.fieldset.classes,
165
+ attributes: params.fieldset.attributes,
166
+ legend: params.fieldset.legend,
167
+ headingLevel: params.fieldset.headingLevel
168
+ }) %}
169
+ {{ innerHtml | trim | safe }}
170
+ {% endcall %}
171
+ {% else %}
172
+ {{ innerHtml | trim | safe }}
173
+ {% endif %}
174
+ </div>
175
+ <!-- /tree -->
@@ -0,0 +1,159 @@
1
+ params:
2
+ - name: type
3
+ type: string
4
+ required: false
5
+ description: Type of input control to render. Admitted values are `checkbox` and `radio` or not set. Defaults to `radio`.
6
+ - name: describedBy
7
+ type: string
8
+ required: false
9
+ description: One or more element IDs to add to the input `aria-describedby` attribute without a fieldset, used to provide additional descriptive information for screenreader users.
10
+ - name: fieldset
11
+ type: object
12
+ required: false
13
+ description: Options for the fieldset component (e.g. legend).
14
+ isComponent: true
15
+ - name: hint
16
+ type: object
17
+ required: false
18
+ description: Options for the hint component (e.g. text).
19
+ isComponent: true
20
+ - name: errorMessage
21
+ type: object
22
+ required: false
23
+ description: Options for the error message component. The error message component will not display if you use a falsy value for `errorMessage`, for example `false` or `null`.
24
+ isComponent: true
25
+ - name: formGroup
26
+ type: object
27
+ required: false
28
+ description: Options for the form-group wrapper
29
+ params:
30
+ - name: classes
31
+ type: string
32
+ required: false
33
+ description: Classes to add to the form group (e.g. to show error state for the whole group)
34
+ - name: idPrefix
35
+ type: string
36
+ required: false
37
+ description: String to prefix id for each item if no id is specified on each item.
38
+ - name: name
39
+ type: string
40
+ required: true
41
+ description: Name attribute for all checkbox/radio items.
42
+ - name: heading
43
+ type: object
44
+ required: true
45
+ description: Options for the heading
46
+ params:
47
+ - name: text
48
+ type: string
49
+ required: true
50
+ description: If `html` is set, this is not required. Text to use within the heading. If `html` is provided, the `text` argument will be ignored.
51
+ - name: html
52
+ type: string
53
+ required: true
54
+ description: If `text` is set, this is not required. HTML to use within the heading. If `html` is provided, the `text` argument will be ignored.
55
+ - name: classes
56
+ type: string
57
+ required: false
58
+ description: Classes to add to the heading.
59
+ - name: headingLevel
60
+ type: number
61
+ required: false
62
+ description: If headingLevel is 1, the parent heading tag needed inside this component will be a h1, if 2 will be a h2, and so on.
63
+ - name: items
64
+ type: array
65
+ required: true
66
+ description: Array of tree items objects.
67
+ params:
68
+ - name: text
69
+ type: string
70
+ required: true
71
+ description: If `html` is set, this is not required. Text to use within each tree item label. If `html` is provided, the `text` argument will be ignored.
72
+ - name: html
73
+ type: string
74
+ required: true
75
+ description: If `text` is set, this is not required. HTML to use within each tree item label. If `html` is provided, the `text` argument will be ignored.
76
+ - name: id
77
+ type: string
78
+ required: false
79
+ description: Specific id attribute for the item. If omitted, then idPrefix option will be applied.
80
+ - name: name
81
+ type: string
82
+ required: true
83
+ description: Specific name for the checkbox/radio item. If omitted, then component global `name` string will be applied.
84
+ - name: value
85
+ type: string
86
+ required: true
87
+ description: Value for the checkbox/radio input.
88
+ - name: label
89
+ type: object
90
+ required: false
91
+ description: Provide attributes and classes to each checkbox/radio item label.
92
+ isComponent: true
93
+ - name: hint
94
+ type: object
95
+ required: false
96
+ description: Provide hint to each checkbox/radio item.
97
+ isComponent: true
98
+ - name: checked
99
+ type: boolean
100
+ required: false
101
+ description: If true, checkbox/radio will be checked.
102
+ - name: isIndeterminate
103
+ type: boolean
104
+ required: false
105
+ description: If true, the checkbox will have an additional indeterminate state to show a partial true. Only for checkbox item.
106
+ - name: indeterminateChecked
107
+ type: boolean
108
+ required: false
109
+ description: If true, the checkbox will have an indeterminate checked initial state. This will override isChecked value. Only for checkbox item.
110
+ - name: disabled
111
+ type: boolean
112
+ required: false
113
+ description: If true, tree will be disabled.
114
+ - name: classes
115
+ type: string
116
+ required: false
117
+ description: Classes to add to the item.
118
+ - name: attributes
119
+ type: object
120
+ required: false
121
+ description: HTML attributes (for example data attributes) to add to the item.
122
+ - name: expanded
123
+ type: boolean
124
+ required: false
125
+ description: If true, tree sub will be expanded.
126
+ - name: sub
127
+ type: boolean
128
+ required: false
129
+ description: If true, content provided will be revealed when the item is expanded.
130
+ - name: sub.classes
131
+ type: string
132
+ required: false
133
+ description: Classes to add to the sub container.
134
+ - name: sub.attributes
135
+ type: string
136
+ required: false
137
+ description: HTML attributes (for example data attributes) to add to the sub container.
138
+ - name: sub.items
139
+ type: array
140
+ required: false
141
+ description: Provide subitems for the sub reveal. Each items have same params as this item.
142
+ - name: classes
143
+ type: string
144
+ required: false
145
+ description: Classes to add to the tree container.
146
+ - name: attributes
147
+ type: object
148
+ required: false
149
+ description: HTML attributes (for example data attributes) to add to the tree container.
150
+
151
+ accessibilityCriteria: |
152
+ ## sub reveals
153
+ Must:
154
+ - be visible as static content if JavaScript is unavailable or fails
155
+ - be hidden if JavaScript is available and is collapsed
156
+ - indicate if content is expanded or collapsed
157
+ - indicate that there is collapsed content to interact with
158
+
159
+ Note that alphagov have known issues against this criteria: https://github.com/alphagov/govuk_elements/issues/575