@qld-gov-au/qgds-bootstrap5 2.0.10 → 2.0.12
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.
- package/.storybook/main.mjs +2 -2
- package/.storybook/preview.js +5 -2
- package/dist/assets/components/bs5/banner/banner.hbs +3 -6
- package/dist/assets/components/bs5/card/card.hbs +2 -2
- package/dist/assets/components/bs5/dateinput/dateinput.hbs +27 -27
- package/dist/assets/components/bs5/formcheck/formcheck.hbs +10 -2
- package/dist/assets/components/bs5/head/head.hbs +1 -1
- package/dist/assets/components/bs5/searchInput/searchInput.hbs +31 -29
- package/dist/assets/components/bs5/select/select.hbs +19 -19
- package/dist/assets/components/bs5/tag/tag.hbs +1 -1
- package/dist/assets/components/bs5/textarea/textarea.hbs +17 -17
- package/dist/assets/components/bs5/textbox/textbox.hbs +17 -18
- package/dist/assets/css/qld.bootstrap.css +2 -2
- package/dist/assets/css/qld.bootstrap.css.map +3 -3
- package/dist/assets/css/qld.bootstrap.legacy.css +2 -2
- package/dist/assets/css/qld.bootstrap.legacy.css.map +3 -3
- package/dist/assets/js/handlebars.helpers.bundle.js +2 -2
- package/dist/assets/js/handlebars.helpers.bundle.js.map +2 -2
- package/dist/assets/js/handlebars.init.min.js +141 -135
- package/dist/assets/js/handlebars.init.min.js.map +2 -2
- package/dist/assets/js/handlebars.partials.js +141 -135
- package/dist/assets/js/handlebars.partials.js.map +2 -2
- package/dist/assets/js/qld.bootstrap.min.js +9 -10
- package/dist/assets/js/qld.bootstrap.min.js.map +4 -4
- package/dist/assets/node/handlebars.init.min.js +59 -11
- package/dist/assets/node/handlebars.init.min.js.map +2 -2
- package/dist/components/bs5/banner/banner.hbs +3 -6
- package/dist/components/bs5/card/card.hbs +2 -2
- package/dist/components/bs5/dateinput/dateinput.hbs +27 -27
- package/dist/components/bs5/formcheck/formcheck.hbs +10 -2
- package/dist/components/bs5/head/head.hbs +1 -1
- package/dist/components/bs5/searchInput/searchInput.hbs +31 -29
- package/dist/components/bs5/select/select.hbs +19 -19
- package/dist/components/bs5/tag/tag.hbs +1 -1
- package/dist/components/bs5/textarea/textarea.hbs +17 -17
- package/dist/components/bs5/textbox/textbox.hbs +17 -18
- package/dist/package.json +1 -1
- package/dist/sample-data/card/card.data.json +4 -1
- package/dist/sample-data/dateinput/dateinput.data.json +14 -12
- package/dist/sample-data/formcheck/stories/checkbox/checkbox.data.json +4 -5
- package/dist/sample-data/formcheck/stories/radio/radio.data.json +4 -4
- package/dist/sample-data/searchInput/searchInput.data.json +19 -10
- package/dist/sample-data/select/select.data.json +12 -10
- package/dist/sample-data/tag/tag.data.json +149 -143
- package/dist/sample-data/textarea/textarea.data.json +14 -11
- package/dist/sample-data/textbox/textbox.data.json +13 -10
- package/package.json +1 -1
- package/src/components/bs5/banner/banner.hbs +3 -6
- package/src/components/bs5/banner/banner.scss +10 -7
- package/src/components/bs5/banner/banner.stories.js +2 -5
- package/src/components/bs5/button/button.scss +4 -11
- package/src/components/bs5/button/button.stories.js +17 -15
- package/src/components/bs5/card/Card.js +31 -2
- package/src/components/bs5/card/Card.mdx +4 -0
- package/src/components/bs5/card/card--icon-list-footer.stories.js +2 -24
- package/src/components/bs5/card/card--multi-action.stories.js +9 -28
- package/src/components/bs5/card/card--no-action.stories.js +5 -27
- package/src/components/bs5/card/card--single-action.stories.js +4 -33
- package/src/components/bs5/card/card.data.json +4 -1
- package/src/components/bs5/card/card.hbs +2 -2
- package/src/components/bs5/dateinput/Dateinput.js +26 -11
- package/src/components/bs5/dateinput/dateinput.data.json +14 -12
- package/src/components/bs5/dateinput/dateinput.hbs +27 -27
- package/src/components/bs5/footer/footer_formio.scss +5 -5
- package/src/components/bs5/formcheck/Formcheck.js +57 -6
- package/src/components/bs5/formcheck/_form-variables.scss +131 -0
- package/src/components/bs5/formcheck/formcheck.hbs +10 -2
- package/src/components/bs5/formcheck/formcheck.scss +229 -66
- package/src/components/bs5/formcheck/stories/bootstrap-validation/bootstrap-validation.stories.js +304 -0
- package/src/components/bs5/formcheck/stories/checkbox/checkbox.data.json +4 -5
- package/src/components/bs5/formcheck/stories/checkbox/checkbox.stories.js +19 -111
- package/src/components/bs5/formcheck/stories/radio/radio.data.json +4 -4
- package/src/components/bs5/formcheck/stories/radio/radio.stories.js +30 -122
- package/src/components/bs5/inpageAlert/inpageAlert.scss +1 -1
- package/src/components/bs5/modal/modal.scss +106 -99
- package/src/components/bs5/navbar/navbar.functions.js +122 -19
- package/src/components/bs5/pageLayout/{ThemeShowcase.stories.js → PaletteShowcase.stories.js} +36 -35
- package/src/components/bs5/searchInput/__snapshots__/searchInput.test.js.snap +24 -28
- package/src/components/bs5/searchInput/search.functions.js +93 -76
- package/src/components/bs5/searchInput/searchInput.data.json +19 -10
- package/src/components/bs5/searchInput/searchInput.hbs +31 -29
- package/src/components/bs5/searchInput/searchInput.scss +140 -196
- package/src/components/bs5/searchInput/searchInput.stories.js +35 -13
- package/src/components/bs5/searchInput/searchInput.test.js +5 -1
- package/src/components/bs5/select/Select.js +13 -5
- package/src/components/bs5/select/Select.stories.js +27 -83
- package/src/components/bs5/select/select.data.json +12 -10
- package/src/components/bs5/select/select.hbs +19 -19
- package/src/components/bs5/tag/tag--status.stories.js +1 -0
- package/src/components/bs5/tag/tag.data.json +149 -143
- package/src/components/bs5/tag/tag.hbs +1 -1
- package/src/components/bs5/tag/tag.scss +2 -5
- package/src/components/bs5/tag/tag.stories.js +1 -0
- package/src/components/bs5/textarea/Textarea.js +13 -5
- package/src/components/bs5/textarea/Textarea.stories.js +29 -55
- package/src/components/bs5/textarea/textarea.data.json +14 -11
- package/src/components/bs5/textarea/textarea.hbs +17 -17
- package/src/components/bs5/textbox/Textbox.js +16 -5
- package/src/components/bs5/textbox/Textbox.stories.js +26 -51
- package/src/components/bs5/textbox/textInput.scss +12 -232
- package/src/components/bs5/textbox/textbox.data.json +13 -10
- package/src/components/bs5/textbox/textbox.hbs +17 -18
- package/src/components/bs5/typography/typography.stories.js +1 -1
- package/src/css/functions/_index.scss +2 -0
- package/src/css/functions/remify.scss +32 -0
- package/src/css/functions/snap-line-height.scss +7 -0
- package/src/css/main.scss +1 -1
- package/src/css/mixins/focusable.scss +4 -1
- package/src/css/mixins/make-icon.scss +1 -1
- package/src/css/{qld-theme.scss → qld-palettes.scss} +30 -23
- package/src/js/handlebars.helpers.js +9 -1
- package/src/js/utils.js +142 -0
- package/src/components/bs5/formcheck/_formcheck.stories.bak.js +0 -432
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// FormcheckRadio.stories.js
|
|
2
|
-
import { Formcheck } from "../../Formcheck.js";
|
|
2
|
+
import { Formcheck, argTypes } from "../../Formcheck.js";
|
|
3
3
|
import defaultdata from "./radio.data.json";
|
|
4
4
|
|
|
5
5
|
export default {
|
|
@@ -11,169 +11,77 @@ export default {
|
|
|
11
11
|
globals: { backgrounds: { value: "default" } },
|
|
12
12
|
parameters: { backgrounds: { disable: false } },
|
|
13
13
|
//https://storybook.js.org/docs/api/arg-types
|
|
14
|
-
argTypes
|
|
14
|
+
argTypes,
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
// Default story for Formcheck component
|
|
18
17
|
export const Default = {
|
|
19
18
|
args: { ...defaultdata },
|
|
20
|
-
parameters: {
|
|
21
|
-
controls: { include: `listitems` },
|
|
22
|
-
},
|
|
23
19
|
globals: { backgrounds: { value: "default" } },
|
|
24
20
|
};
|
|
25
21
|
|
|
26
22
|
export const RadioDark = {
|
|
27
23
|
args: { ...defaultdata },
|
|
28
24
|
globals: { backgrounds: { value: "dark" } },
|
|
29
|
-
|
|
30
|
-
(Story) => {
|
|
31
|
-
return `
|
|
32
|
-
<div class="dark">
|
|
33
|
-
${Story()}
|
|
34
|
-
</div>
|
|
35
|
-
`;
|
|
36
|
-
},
|
|
37
|
-
],
|
|
25
|
+
render: (args) => `<div class="dark">${new Formcheck(args).html}</div>`,
|
|
38
26
|
};
|
|
39
27
|
|
|
40
28
|
export const RadioSmall = {
|
|
41
|
-
args: { ...defaultdata, id: "
|
|
42
|
-
|
|
43
|
-
(Story) => {
|
|
44
|
-
return `
|
|
45
|
-
<div class="small">
|
|
46
|
-
${Story()}
|
|
47
|
-
</div>
|
|
48
|
-
`;
|
|
49
|
-
},
|
|
50
|
-
],
|
|
29
|
+
args: { ...defaultdata, id: "checkboxSmall" },
|
|
30
|
+
render: (args) => `<div class="small">${new Formcheck(args).html}</div>`,
|
|
51
31
|
};
|
|
52
32
|
|
|
53
33
|
export const RadioSmallDark = {
|
|
54
|
-
args: { ...defaultdata, id: "
|
|
34
|
+
args: { ...defaultdata, id: "checkboxSmallDark" },
|
|
55
35
|
globals: { backgrounds: { value: "dark" } },
|
|
56
|
-
|
|
57
|
-
(Story) => {
|
|
58
|
-
return `
|
|
59
|
-
<div class="dark"><div class="small">
|
|
60
|
-
${Story()}
|
|
61
|
-
</div></div>
|
|
62
|
-
`;
|
|
63
|
-
},
|
|
64
|
-
],
|
|
36
|
+
render: (args) => `<div class="dark small">${new Formcheck(args).html}</div>`,
|
|
65
37
|
};
|
|
66
38
|
|
|
67
39
|
export const RadioValid = {
|
|
68
|
-
args: { ...defaultdata, id: "
|
|
69
|
-
render: (args) => {
|
|
70
|
-
return `
|
|
71
|
-
<div class="valid">${new Formcheck(args).html}</div>
|
|
72
|
-
`;
|
|
73
|
-
},
|
|
40
|
+
args: { ...defaultdata, id: "checkboxValid" },
|
|
41
|
+
render: (args) => `${new Formcheck({ ...args, isValid: true }).html}`,
|
|
74
42
|
};
|
|
75
43
|
|
|
76
44
|
export const RadioValidSmall = {
|
|
77
|
-
args: { ...defaultdata, id: "
|
|
78
|
-
render: (args) =>
|
|
79
|
-
|
|
80
|
-
<div class="small"><div class="valid">${new Formcheck(args).html}</div></div>
|
|
81
|
-
`;
|
|
82
|
-
},
|
|
45
|
+
args: { ...defaultdata, id: "checkboxValidSmall" },
|
|
46
|
+
render: (args) =>
|
|
47
|
+
`<div class="small">${new Formcheck({ ...args, isValid: true }).html}</div>`,
|
|
83
48
|
};
|
|
84
49
|
|
|
85
50
|
export const RadioValidDark = {
|
|
86
|
-
args: { ...defaultdata, id: "
|
|
87
|
-
render: (args) =>
|
|
88
|
-
|
|
89
|
-
<div class="dark">
|
|
90
|
-
<div class="valid">${new Formcheck(args).html}</div></div>
|
|
91
|
-
`;
|
|
92
|
-
},
|
|
51
|
+
args: { ...defaultdata, id: "checkboxValidDark" },
|
|
52
|
+
render: (args) =>
|
|
53
|
+
`<div class="dark">${new Formcheck({ ...args, isValid: true }).html}</div>`,
|
|
93
54
|
globals: { backgrounds: { value: "dark" } },
|
|
94
|
-
decorators: [
|
|
95
|
-
(Story) => {
|
|
96
|
-
return `
|
|
97
|
-
<div class="dark"><div class="valid">
|
|
98
|
-
${Story()}
|
|
99
|
-
</div></div>
|
|
100
|
-
`;
|
|
101
|
-
},
|
|
102
|
-
],
|
|
103
55
|
};
|
|
104
56
|
|
|
105
57
|
export const RadioValidSmallDark = {
|
|
106
|
-
args: { ...defaultdata, id: "
|
|
107
|
-
render: (args) =>
|
|
108
|
-
|
|
109
|
-
<div class="dark">
|
|
110
|
-
<div class="valid">${new Formcheck(args).html}</div></div>
|
|
111
|
-
`;
|
|
112
|
-
},
|
|
58
|
+
args: { ...defaultdata, id: "checkboxValidSmallDark" },
|
|
59
|
+
render: (args) =>
|
|
60
|
+
`<div class="dark small">${new Formcheck({ ...args, isValid: true }).html}</div>`,
|
|
113
61
|
globals: { backgrounds: { value: "dark" } },
|
|
114
|
-
decorators: [
|
|
115
|
-
(Story) => {
|
|
116
|
-
return `
|
|
117
|
-
<div class="dark"><div class="small"><div class="valid">
|
|
118
|
-
${Story()}
|
|
119
|
-
</div></div></div>
|
|
120
|
-
`;
|
|
121
|
-
},
|
|
122
|
-
],
|
|
123
62
|
};
|
|
124
63
|
|
|
125
64
|
export const RadioInvalid = {
|
|
126
|
-
args: { ...defaultdata, id: "
|
|
127
|
-
render: (args) => {
|
|
128
|
-
return `
|
|
129
|
-
<div class="invalid">${new Formcheck(args).html}</div>
|
|
130
|
-
`;
|
|
131
|
-
},
|
|
65
|
+
args: { ...defaultdata, id: "checkboxInvalid" },
|
|
66
|
+
render: (args) => `${new Formcheck({ ...args, isValid: false }).html}`,
|
|
132
67
|
};
|
|
133
68
|
|
|
134
69
|
export const RadioInvalidSmall = {
|
|
135
|
-
args: { ...defaultdata, id: "
|
|
136
|
-
render: (args) =>
|
|
137
|
-
|
|
138
|
-
<div class="small"><div class="invalid">${new Formcheck(args).html}</div></div>
|
|
139
|
-
`;
|
|
140
|
-
},
|
|
70
|
+
args: { ...defaultdata, id: "checkboxInvalidSmall" },
|
|
71
|
+
render: (args) =>
|
|
72
|
+
`<div class="small">${new Formcheck({ ...args, isValid: false }).html}</div>`,
|
|
141
73
|
};
|
|
74
|
+
|
|
142
75
|
export const RadioInvalidDark = {
|
|
143
|
-
args: { ...defaultdata, id: "
|
|
144
|
-
render: (args) =>
|
|
145
|
-
|
|
146
|
-
<div class="invalid"><div class="dark">${new Formcheck(args).html}</div></div>
|
|
147
|
-
`;
|
|
148
|
-
},
|
|
76
|
+
args: { ...defaultdata, id: "checkboxInvalidDark" },
|
|
77
|
+
render: (args) =>
|
|
78
|
+
`<div class="dark">${new Formcheck({ ...args, isValid: false }).html}</div>`,
|
|
149
79
|
globals: { backgrounds: { value: "dark" } },
|
|
150
|
-
decorators: [
|
|
151
|
-
(Story) => {
|
|
152
|
-
return `
|
|
153
|
-
<div class="dark">
|
|
154
|
-
${Story()}
|
|
155
|
-
</div>
|
|
156
|
-
`;
|
|
157
|
-
},
|
|
158
|
-
],
|
|
159
80
|
};
|
|
160
81
|
|
|
161
82
|
export const RadioInvalidSmallDark = {
|
|
162
|
-
args: { ...defaultdata, id: "
|
|
163
|
-
render: (args) =>
|
|
164
|
-
|
|
165
|
-
<div class="dark">
|
|
166
|
-
<div class="invalid">${new Formcheck(args).html}</div></div>
|
|
167
|
-
`;
|
|
168
|
-
},
|
|
83
|
+
args: { ...defaultdata, id: "checkboxInvalidSmallDark" },
|
|
84
|
+
render: (args) =>
|
|
85
|
+
`<div class="dark small">${new Formcheck({ ...args, isValid: false }).html}</div>`,
|
|
169
86
|
globals: { backgrounds: { value: "dark" } },
|
|
170
|
-
decorators: [
|
|
171
|
-
(Story) => {
|
|
172
|
-
return `
|
|
173
|
-
<div class="dark"><div class="small"><div class="invalid">
|
|
174
|
-
${Story()}
|
|
175
|
-
</div></div></div>
|
|
176
|
-
`;
|
|
177
|
-
},
|
|
178
|
-
],
|
|
179
87
|
};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
//To account for this, we redefine the global vars at the .alert scope
|
|
6
6
|
|
|
7
7
|
.alert {
|
|
8
|
-
@
|
|
8
|
+
@extend %qld-palette-default;
|
|
9
9
|
--qld-headings-color: var(--#{$prefix}light-text-text);
|
|
10
10
|
--qld-alert-color: var(--#{$prefix}light-text-text);
|
|
11
11
|
--qld-alert-bg: #fff;
|
|
@@ -4,117 +4,124 @@
|
|
|
4
4
|
|
|
5
5
|
// QGDS specific modal variables.
|
|
6
6
|
.modal {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
7
|
+
--#{$prefix}modal-zindex: #{$zindex-modal};
|
|
8
|
+
--#{$prefix}modal-width: #{$modal-md};
|
|
9
|
+
|
|
10
|
+
--#{$prefix}modal-margin: #{$modal-dialog-margin};
|
|
11
|
+
--#{$prefix}modal-color: #{$modal-content-color};
|
|
12
|
+
--#{$prefix}modal-bg: #{$modal-content-bg};
|
|
13
|
+
--#{$prefix}modal-padding: 1.5rem 2rem;
|
|
14
|
+
|
|
15
|
+
--#{$prefix}modal-border-color: var(--#{$prefix}light-grey);
|
|
16
|
+
--#{$prefix}modal-border-width: 1px;
|
|
17
|
+
--#{$prefix}modal-border-radius: 0.75rem;
|
|
18
|
+
|
|
19
|
+
--#{$prefix}modal-box-shadow: #{$modal-content-box-shadow-xs};
|
|
20
|
+
--#{$prefix}modal-inner-border-radius: #{$modal-content-inner-border-radius};
|
|
21
|
+
|
|
22
|
+
--#{$prefix}modal-header-padding: 2rem 2rem 0;
|
|
23
|
+
--#{$prefix}modal-header-border-width: 0px;
|
|
24
|
+
|
|
25
|
+
--#{$prefix}modal-title-line-height: 2rem;
|
|
26
|
+
|
|
27
|
+
--#{$prefix}modal-footer-gap: 0;
|
|
28
|
+
--#{$prefix}modal-footer-bg: none;
|
|
29
|
+
--#{$prefix}modal-footer-border-color: none;
|
|
30
|
+
--#{$prefix}modal-footer-border-width: none;
|
|
31
|
+
|
|
32
|
+
.btn-close {
|
|
33
|
+
--#{$prefix}btn-close-icon: "data:image/svg+xml,%3Csvg width='13' height='13' viewBox='0 0 13 13' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M18.0547 18.5938C17.8203 18.8281 17.3906 18.8281 17.1562 18.5938L12 13.3984L6.80469 18.5938C6.57031 18.8281 6.14062 18.8281 5.90625 18.5938C5.67188 18.3594 5.67188 17.9297 5.90625 17.6953L11.1016 12.5L5.90625 7.34375C5.67188 7.10938 5.67188 6.67969 5.90625 6.44531C6.14062 6.21094 6.57031 6.21094 6.80469 6.44531L12 11.6406L17.1562 6.44531C17.3906 6.21094 17.8203 6.21094 18.0547 6.44531C18.2891 6.67969 18.2891 7.10938 18.0547 7.34375L12.8594 12.5L18.0547 17.6953C18.2891 17.9297 18.2891 18.3594 18.0547 18.5938Z' /%3E%3C/svg%3E%0A";
|
|
34
|
+
--#{$prefix}btn-close-color: var(
|
|
35
|
+
--#{$prefix}color-default-color-light-text-lighter
|
|
36
|
+
);
|
|
37
|
+
--#{$prefix}btn-close-width: 40px;
|
|
38
|
+
--#{$prefix}btn-border-radius: 50%;
|
|
39
|
+
|
|
40
|
+
//Hover state
|
|
41
|
+
--#{$prefix}btn-close-hover-color: var(
|
|
42
|
+
--#{$prefix}color-default-color-light-text-heading
|
|
43
|
+
);
|
|
44
|
+
--#{$prefix}btn-close-hover-bg: var(
|
|
45
|
+
--#{$prefix}core-default-color-neutral-lightest
|
|
46
|
+
);
|
|
47
|
+
--#{$prefix}btn-close-hover-bg-size: 15px;
|
|
48
|
+
|
|
49
|
+
//Focus state
|
|
50
|
+
--#{$prefix}btn-close-focus-color: var(
|
|
51
|
+
--#{$prefix}color-default-color-light-text-heading
|
|
52
|
+
);
|
|
53
|
+
--#{$prefix}btn-close-focus-shadow: none;
|
|
54
|
+
--#{$prefix}btn-close-focus-border: var(--#{$prefix}focus-color) solid 3px;
|
|
55
|
+
}
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
// General styling rules.
|
|
51
59
|
.modal {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
&:hover {
|
|
61
|
-
width: var(--#{$prefix}btn-close-width);
|
|
62
|
-
height: var(--#{$prefix}btn-close-width);
|
|
63
|
-
color: var(--#{$prefix}btn-close-hover-color);
|
|
64
|
-
background-size: var(--#{$prefix}btn-close-hover-bg-size);
|
|
65
|
-
background-color: var(--#{$prefix}btn-close-hover-bg);
|
|
66
|
-
}
|
|
67
|
-
&:focus {
|
|
68
|
-
width: var(--#{$prefix}btn-close-width);
|
|
69
|
-
height: var(--#{$prefix}btn-close-width);
|
|
70
|
-
color: var(--#{$prefix}btn-close-focus-color);
|
|
71
|
-
background-size: var(--#{$prefix}btn-close-hover-bg-size);
|
|
72
|
-
background-color: var(--#{$prefix}btn-close-hover-bg);
|
|
73
|
-
outline: var(--#{$prefix}btn-close-focus-border);
|
|
74
|
-
outline-offset: 2px;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
60
|
+
.btn-close {
|
|
61
|
+
width: var(--#{$prefix}btn-close-width);
|
|
62
|
+
height: var(--#{$prefix}btn-close-width);
|
|
63
|
+
border-radius: var(--#{$prefix}btn-border-radius);
|
|
64
|
+
background-size: 12px;
|
|
65
|
+
padding: 0;
|
|
66
|
+
flex-shrink: 0; //Flex, do not shrink this perfectly round button.
|
|
77
67
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
68
|
+
&:hover {
|
|
69
|
+
width: var(--#{$prefix}btn-close-width);
|
|
70
|
+
height: var(--#{$prefix}btn-close-width);
|
|
71
|
+
color: var(--#{$prefix}btn-close-hover-color);
|
|
72
|
+
background-size: var(--#{$prefix}btn-close-hover-bg-size);
|
|
73
|
+
background-color: var(--#{$prefix}btn-close-hover-bg);
|
|
74
|
+
}
|
|
75
|
+
&:focus {
|
|
76
|
+
width: var(--#{$prefix}btn-close-width);
|
|
77
|
+
height: var(--#{$prefix}btn-close-width);
|
|
78
|
+
color: var(--#{$prefix}btn-close-focus-color);
|
|
79
|
+
background-size: var(--#{$prefix}btn-close-hover-bg-size);
|
|
80
|
+
background-color: var(--#{$prefix}btn-close-hover-bg);
|
|
81
|
+
outline: var(--#{$prefix}btn-close-focus-border);
|
|
82
|
+
outline-offset: 2px;
|
|
83
83
|
}
|
|
84
|
+
}
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
justify-content: flex-end;
|
|
90
|
-
|
|
91
|
-
.btn {
|
|
92
|
-
margin: 0 0 0 1.5rem;
|
|
93
|
-
}
|
|
86
|
+
.modal-header {
|
|
87
|
+
.modal-title {
|
|
88
|
+
line-height: var(--#{$prefix}modal-title-line-height);
|
|
89
|
+
font-size: 1.5rem;
|
|
94
90
|
}
|
|
91
|
+
}
|
|
95
92
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
93
|
+
.modal-footer {
|
|
94
|
+
padding: 0 2rem 2rem;
|
|
95
|
+
flex-direction: row;
|
|
96
|
+
flex-wrap: nowrap;
|
|
97
|
+
justify-content: flex-end;
|
|
98
|
+
|
|
99
|
+
.btn {
|
|
100
|
+
margin: 0 0 0 1.5rem;
|
|
107
101
|
}
|
|
102
|
+
}
|
|
108
103
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
104
|
+
//Rescope for smaller modals
|
|
105
|
+
.modal-dialog {
|
|
106
|
+
&.modal-sm {
|
|
107
|
+
.modal-footer {
|
|
108
|
+
flex-wrap: wrap;
|
|
109
|
+
.btn {
|
|
110
|
+
width: 100%;
|
|
111
|
+
margin: 1rem 0;
|
|
117
112
|
}
|
|
113
|
+
}
|
|
118
114
|
}
|
|
115
|
+
}
|
|
119
116
|
|
|
117
|
+
//Rescope for smaller viewports
|
|
118
|
+
@include media-breakpoint-down(md) {
|
|
119
|
+
.modal-footer {
|
|
120
|
+
flex-wrap: wrap;
|
|
121
|
+
.btn {
|
|
122
|
+
width: 100%;
|
|
123
|
+
margin: 1rem 0;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
120
127
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createFocusTrap } from "../../../js/utils.js";
|
|
2
|
+
|
|
1
3
|
export function initializeNavbar() {
|
|
2
4
|
const navbarCollapse = document.getElementById("main-nav");
|
|
3
5
|
const overlay = document.getElementById("overlay");
|
|
@@ -8,13 +10,112 @@ export function initializeNavbar() {
|
|
|
8
10
|
.map((id) => document.getElementById(id))
|
|
9
11
|
.filter(Boolean);
|
|
10
12
|
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
+
// Helper to set aria-hidden
|
|
14
|
+
const setAriaHidden = (hidden) => {
|
|
15
|
+
hideTargets.forEach((el) => {
|
|
16
|
+
if (hidden) {
|
|
17
|
+
el.setAttribute("aria-hidden", "true");
|
|
18
|
+
} else {
|
|
19
|
+
el.removeAttribute("aria-hidden");
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Focus trap instances (created on-demand)
|
|
25
|
+
let mobileFocusTrap = null;
|
|
26
|
+
const dropdownFocusTraps = new Map();
|
|
27
|
+
|
|
28
|
+
// Helper function to close navbar
|
|
29
|
+
function closeNavbar() {
|
|
13
30
|
if (navbarCollapse?.classList.contains("show")) {
|
|
14
31
|
navbarCollapse.classList.remove("show");
|
|
15
|
-
overlay
|
|
32
|
+
overlay?.classList.remove("show");
|
|
16
33
|
document.body.style.overflow = "";
|
|
34
|
+
setAriaHidden(false);
|
|
35
|
+
|
|
36
|
+
// Deactivate and destroy mobile focus trap
|
|
37
|
+
if (mobileFocusTrap) {
|
|
38
|
+
mobileFocusTrap.deactivate();
|
|
39
|
+
mobileFocusTrap = null;
|
|
40
|
+
}
|
|
17
41
|
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Create mobile focus trap on-demand (when mobile menu opens)
|
|
45
|
+
function createMobileFocusTrap() {
|
|
46
|
+
if (!mobileFocusTrap && navbarCollapse) {
|
|
47
|
+
mobileFocusTrap = createFocusTrap(navbarCollapse, {
|
|
48
|
+
returnFocusElement: burgerBtn,
|
|
49
|
+
onEscape: () => {
|
|
50
|
+
closeNavbar();
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return mobileFocusTrap;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Create dropdown focus trap on-demand (when dropdown opens)
|
|
58
|
+
function getOrCreateDropdownFocusTrap(dropdown, toggle) {
|
|
59
|
+
if (!dropdownFocusTraps.has(dropdown)) {
|
|
60
|
+
const dropdownTrap = createFocusTrap(dropdown, {
|
|
61
|
+
returnFocusElement: toggle,
|
|
62
|
+
onEscape: () => {
|
|
63
|
+
// Close the dropdown using Bootstrap's API
|
|
64
|
+
const bsDropdown = bootstrap.Dropdown.getInstance(toggle);
|
|
65
|
+
if (bsDropdown) {
|
|
66
|
+
bsDropdown.hide();
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
dropdownFocusTraps.set(dropdown, dropdownTrap);
|
|
71
|
+
}
|
|
72
|
+
return dropdownFocusTraps.get(dropdown);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Setup dropdown event listeners
|
|
76
|
+
function setupDropdownListeners() {
|
|
77
|
+
// Find all dropdown toggles (elements with data-bs-toggle="dropdown")
|
|
78
|
+
const dropdownToggles = navbarCollapse?.querySelectorAll(
|
|
79
|
+
'[data-bs-toggle="dropdown"]',
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
dropdownToggles?.forEach((toggle) => {
|
|
83
|
+
// Find the associated dropdown menu within the same parent container
|
|
84
|
+
const parentItem =
|
|
85
|
+
toggle.closest(".dropdown") || toggle.closest(".nav-item");
|
|
86
|
+
if (!parentItem) return;
|
|
87
|
+
|
|
88
|
+
const dropdown = parentItem.querySelector(".dropdown-menu");
|
|
89
|
+
if (!dropdown) return;
|
|
90
|
+
|
|
91
|
+
// Listen for dropdown show event (desktop only)
|
|
92
|
+
toggle.addEventListener("shown.bs.dropdown", () => {
|
|
93
|
+
const isMobile = window.innerWidth < 992;
|
|
94
|
+
if (!isMobile) {
|
|
95
|
+
// Create and activate focus trap on-demand
|
|
96
|
+
const dropdownTrap = getOrCreateDropdownFocusTrap(dropdown, toggle);
|
|
97
|
+
setTimeout(() => dropdownTrap.activate(), 0);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Listen for dropdown hide event
|
|
102
|
+
toggle.addEventListener("hidden.bs.dropdown", () => {
|
|
103
|
+
const dropdownTrap = dropdownFocusTraps.get(dropdown);
|
|
104
|
+
if (dropdownTrap && dropdownTrap.isActive()) {
|
|
105
|
+
dropdownTrap.deactivate();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Setup dropdown listeners on load
|
|
112
|
+
if (navbarCollapse) {
|
|
113
|
+
setupDropdownListeners();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Close navbar when overlay is clicked
|
|
117
|
+
overlay?.addEventListener("click", () => {
|
|
118
|
+
closeNavbar();
|
|
18
119
|
});
|
|
19
120
|
|
|
20
121
|
const resetNavbarState = () => {
|
|
@@ -42,23 +143,25 @@ export function initializeNavbar() {
|
|
|
42
143
|
window.addEventListener("resize", resetNavbarState);
|
|
43
144
|
resetNavbarState();
|
|
44
145
|
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
146
|
+
// Burger buttons - handle open (mobile only)
|
|
147
|
+
navbarCollapse?.addEventListener("shown.bs.collapse", () => {
|
|
148
|
+
// Check if navbar is opening
|
|
149
|
+
setTimeout(() => {
|
|
150
|
+
if (navbarCollapse?.classList.contains("show")) {
|
|
151
|
+
setAriaHidden(true);
|
|
152
|
+
|
|
153
|
+
// Create and activate focus trap when navbar opens (mobile only - whole navbar)
|
|
154
|
+
const isMobile = window.innerWidth < 992;
|
|
155
|
+
if (isMobile) {
|
|
156
|
+
const trap = createMobileFocusTrap();
|
|
157
|
+
trap.activate();
|
|
158
|
+
}
|
|
52
159
|
}
|
|
53
|
-
});
|
|
54
|
-
};
|
|
160
|
+
}, 0);
|
|
161
|
+
});
|
|
55
162
|
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
btn.addEventListener("click", () => {
|
|
60
|
-
setAriaHidden(true);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
163
|
+
// Close button
|
|
164
|
+
burgerCloseBtn?.addEventListener("click", () => {
|
|
165
|
+
closeNavbar();
|
|
63
166
|
});
|
|
64
167
|
}
|