desy-html 5.0.1 → 5.2.1

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 (30) hide show
  1. package/docs/_include.template-header.njk +8 -0
  2. package/docs/_macro.example-render.njk +8 -0
  3. package/docs/componentes.html +6 -0
  4. package/docs/ds/_ds.example.menu-vertical.njk +3 -3
  5. package/docs/ds/_ds.example.toggle.njk +56 -0
  6. package/docs/ds/_ds.example.tree.njk +457 -0
  7. package/docs/ds/_ds.section.forms.njk +5 -0
  8. package/docs/ds/_ds.section.mostrar-ocultar.njk +5 -0
  9. package/docs/examples-toggle.html +5 -0
  10. package/docs/examples-tree.html +5 -0
  11. package/docs/index.html +20 -1
  12. package/package.json +1 -1
  13. package/src/css/styles.css +1 -0
  14. package/src/js/aria/tree.js +245 -0
  15. package/src/js/aria/treeitem.js +260 -0
  16. package/src/js/desy-html.js +28 -0
  17. package/src/js/index.js +3 -1
  18. package/src/templates/components/checkboxes/_template.checkboxes.njk +1 -2
  19. package/src/templates/components/menubar/_examples.menubar.njk +169 -0
  20. package/src/templates/components/pagination/_examples.pagination.njk +32 -0
  21. package/src/templates/components/pagination/_template.pagination.njk +1 -0
  22. package/src/templates/components/toggle/_examples.toggle.njk +52 -0
  23. package/src/templates/components/toggle/_macro.toggle.njk +3 -0
  24. package/src/templates/components/toggle/_template.toggle.njk +37 -0
  25. package/src/templates/components/toggle/params.toggle.yaml +57 -0
  26. package/src/templates/components/tree/_examples.tree.njk +1171 -0
  27. package/src/templates/components/tree/_macro.tree.njk +3 -0
  28. package/src/templates/components/tree/_styles.tree.css +45 -0
  29. package/src/templates/components/tree/_template.tree.njk +178 -0
  30. package/src/templates/components/tree/params.tree.yaml +163 -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,178 @@
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
+ {% from "../searchbar/_macro.searchbar.njk" import componentSearchbar %}
6
+
7
+ {#- If an id 'prefix' is not passed, fall back to using the name attribute
8
+ instead. We need this for error messages and hints as well -#}
9
+ {% set idPrefix = params.idPrefix if params.idPrefix else params.name %}
10
+
11
+ {#- a record of other elements that we need to associate with the input using
12
+ aria-describedby – for example hints or error messages -#}
13
+ {% set describedBy = params.describedBy if params.describedBy else "" %}
14
+ {% if params.fieldset.describedBy %}
15
+ {% set describedBy = params.fieldset.describedBy %}
16
+ {% endif %}
17
+
18
+ {% set subLevel = "" %}
19
+
20
+ {#- fieldset is false by default -#}
21
+ {% set hasFieldset = true if params.fieldset else false %}
22
+
23
+ {#- macro to generate checkboxes -#}
24
+ {% macro checkboxItem(item, id, name, type) %}
25
+ {% set hasHint = true if item.hint.text or item.hint.html %}
26
+ {% set itemHintId = id + "-item-hint" if hasHint else "" %}
27
+ {% set itemDescribedBy = describedBy if not hasFieldset else "" %}
28
+ {% set itemDescribedBy = (itemDescribedBy + " " + itemHintId) | trim %}
29
+ <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 %}">
30
+ <div class="relative flex items-start py-xs">
31
+ <div class="flex items-center mx-sm">
32
+ <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 }}"
33
+ {{-" checked" if item.checked }}
34
+ {{-" disabled" if item.disabled }}
35
+ {%- if itemDescribedBy %} aria-describedby="{{ itemDescribedBy }}"{% endif -%}
36
+ {%- if params.errorMessage %} aria-invalid="true"{% endif -%}
37
+ {%- for attribute, value in item.attributes %} {{ attribute }}="{{ value }}"{% endfor -%}
38
+ {%- if item.isIndeterminate or 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
+ <div 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
+ </div>
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
+ <div class="font-bold">
96
+ {{ checkboxItem(subitem, subId, name, type) }}
97
+ </div>
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
+ {% if params.searchbar %}
136
+ {{ componentSearchbar(params.searchbar) }}
137
+ {% endif %}
138
+ <ul class="c-tree {%- if params.classes %} {{ params.classes }}{% endif %}" role="tree" {%- for attribute, value in params.attributes %} {{ attribute }}="{{ value }}"{% endfor %} data-module="c-tree">
139
+ {% for item in params.items %}
140
+ {% if item %}
141
+ {#- If the user explicitly sets an id, use this instead of the regular idPrefix -#}
142
+ {%- if item.id -%}
143
+ {%- set id = item.id -%}
144
+ {%- else -%}
145
+ {%- set id = idPrefix + "-" + loop.index0 -%}
146
+ {%- endif -%}
147
+ {% set subId = "sub-" + id %}
148
+ {% set name = item.name if item.name else params.name %}
149
+ {% set hasHint = true if item.hint.text or item.hint.html %}
150
+ {% set itemHintId = id + "-item-hint" if hasHint else "" %}
151
+ {% set itemDescribedBy = describedBy if not hasFieldset else "" %}
152
+ {% set itemDescribedBy = (itemDescribedBy + " " + itemHintId) | trim %}
153
+ <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 %}>
154
+ {{ childrenTree(item, id, name, params.type) }}
155
+ </li>
156
+ {% endif %}
157
+ {% endfor %}
158
+ </ul>
159
+ {% endset -%}
160
+
161
+ <!-- tree -->
162
+ <div class="c-form-group {%- if params.errorMessage %} c-form-group--error{% endif %} {%- if params.formGroup.classes %} {{ params.formGroup.classes }}{% endif %}">
163
+ {% if params.fieldset %}
164
+ {% call componentFieldset({
165
+ describedBy: describedBy,
166
+ errorId: errorId,
167
+ classes: params.fieldset.classes,
168
+ attributes: params.fieldset.attributes,
169
+ legend: params.fieldset.legend,
170
+ headingLevel: params.fieldset.headingLevel
171
+ }) %}
172
+ {{ innerHtml | trim | safe }}
173
+ {% endcall %}
174
+ {% else %}
175
+ {{ innerHtml | trim | safe }}
176
+ {% endif %}
177
+ </div>
178
+ <!-- /tree -->
@@ -0,0 +1,163 @@
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: searchbar
7
+ type: component
8
+ required: false
9
+ description: A searchbar component to filter the items. Inherits all the searchbar component params.
10
+ - name: describedBy
11
+ type: string
12
+ required: false
13
+ 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.
14
+ - name: fieldset
15
+ type: object
16
+ required: false
17
+ description: Options for the fieldset component (e.g. legend).
18
+ isComponent: true
19
+ - name: hint
20
+ type: object
21
+ required: false
22
+ description: Options for the hint component (e.g. text).
23
+ isComponent: true
24
+ - name: errorMessage
25
+ type: object
26
+ required: false
27
+ 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`.
28
+ isComponent: true
29
+ - name: formGroup
30
+ type: object
31
+ required: false
32
+ description: Options for the form-group wrapper
33
+ params:
34
+ - name: classes
35
+ type: string
36
+ required: false
37
+ description: Classes to add to the form group (e.g. to show error state for the whole group)
38
+ - name: idPrefix
39
+ type: string
40
+ required: false
41
+ description: String to prefix id for each item if no id is specified on each item.
42
+ - name: name
43
+ type: string
44
+ required: true
45
+ description: Name attribute for all checkbox/radio items.
46
+ - name: heading
47
+ type: object
48
+ required: true
49
+ description: Options for the heading
50
+ params:
51
+ - name: text
52
+ type: string
53
+ required: true
54
+ 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.
55
+ - name: html
56
+ type: string
57
+ required: true
58
+ 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.
59
+ - name: classes
60
+ type: string
61
+ required: false
62
+ description: Classes to add to the heading.
63
+ - name: headingLevel
64
+ type: number
65
+ required: false
66
+ 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.
67
+ - name: items
68
+ type: array
69
+ required: true
70
+ description: Array of tree items objects.
71
+ params:
72
+ - name: text
73
+ type: string
74
+ required: true
75
+ 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.
76
+ - name: html
77
+ type: string
78
+ required: true
79
+ 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.
80
+ - name: id
81
+ type: string
82
+ required: false
83
+ description: Specific id attribute for the item. If omitted, then idPrefix option will be applied.
84
+ - name: name
85
+ type: string
86
+ required: true
87
+ description: Specific name for the checkbox/radio item. If omitted, then component global `name` string will be applied.
88
+ - name: value
89
+ type: string
90
+ required: true
91
+ description: Value for the checkbox/radio input.
92
+ - name: label
93
+ type: object
94
+ required: false
95
+ description: Provide attributes and classes to each checkbox/radio item label.
96
+ isComponent: true
97
+ - name: hint
98
+ type: object
99
+ required: false
100
+ description: Provide hint to each checkbox/radio item.
101
+ isComponent: true
102
+ - name: checked
103
+ type: boolean
104
+ required: false
105
+ description: If true, checkbox/radio will be checked.
106
+ - name: isIndeterminate
107
+ type: boolean
108
+ required: false
109
+ description: If true, the checkbox will have an additional indeterminate state to show a partial true. Only for checkbox item.
110
+ - name: indeterminateChecked
111
+ type: boolean
112
+ required: false
113
+ description: If true, the checkbox will have an indeterminate checked initial state. This will override isChecked value. Only for checkbox item.
114
+ - name: disabled
115
+ type: boolean
116
+ required: false
117
+ description: If true, tree will be disabled.
118
+ - name: classes
119
+ type: string
120
+ required: false
121
+ description: Classes to add to the item.
122
+ - name: attributes
123
+ type: object
124
+ required: false
125
+ description: HTML attributes (for example data attributes) to add to the item.
126
+ - name: expanded
127
+ type: boolean
128
+ required: false
129
+ description: If true, tree sub will be expanded.
130
+ - name: sub
131
+ type: boolean
132
+ required: false
133
+ description: If true, content provided will be revealed when the item is expanded.
134
+ - name: sub.classes
135
+ type: string
136
+ required: false
137
+ description: Classes to add to the sub container.
138
+ - name: sub.attributes
139
+ type: string
140
+ required: false
141
+ description: HTML attributes (for example data attributes) to add to the sub container.
142
+ - name: sub.items
143
+ type: array
144
+ required: false
145
+ description: Provide subitems for the sub reveal. Each items have same params as this item.
146
+ - name: classes
147
+ type: string
148
+ required: false
149
+ description: Classes to add to the tree container.
150
+ - name: attributes
151
+ type: object
152
+ required: false
153
+ description: HTML attributes (for example data attributes) to add to the tree container.
154
+
155
+ accessibilityCriteria: |
156
+ ## sub reveals
157
+ Must:
158
+ - be visible as static content if JavaScript is unavailable or fails
159
+ - be hidden if JavaScript is available and is collapsed
160
+ - indicate if content is expanded or collapsed
161
+ - indicate that there is collapsed content to interact with
162
+
163
+ Note that alphagov have known issues against this criteria: https://github.com/alphagov/govuk_elements/issues/575