@qld-gov-au/qgds-bootstrap5 2.1.3 → 2.1.4

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 (41) hide show
  1. package/.storybook/main.mjs +1 -0
  2. package/.storybook/manager.js +31 -0
  3. package/dist/assets/components/bs5/globalAlert/globalAlert.hbs +2 -2
  4. package/dist/assets/components/bs5/head/head.hbs +1 -1
  5. package/dist/assets/components/bs5/navbar/navbar.hbs +1 -1
  6. package/dist/assets/css/qld.bootstrap.css +2 -2
  7. package/dist/assets/css/qld.bootstrap.css.map +2 -2
  8. package/dist/assets/css/qld.bootstrap.legacy.css +2 -2
  9. package/dist/assets/css/qld.bootstrap.legacy.css.map +2 -2
  10. package/dist/assets/js/handlebars.helpers.bundle.js +1 -1
  11. package/dist/assets/js/handlebars.init.min.js +5 -5
  12. package/dist/assets/js/handlebars.init.min.js.map +1 -1
  13. package/dist/assets/js/handlebars.partials.js +5 -5
  14. package/dist/assets/js/handlebars.partials.js.map +1 -1
  15. package/dist/assets/js/qld.bootstrap.min.js +6 -6
  16. package/dist/assets/js/qld.bootstrap.min.js.map +3 -3
  17. package/dist/assets/node/handlebars.init.min.js +4 -4
  18. package/dist/assets/node/handlebars.init.min.js.map +1 -1
  19. package/dist/components/bs5/globalAlert/globalAlert.hbs +2 -2
  20. package/dist/components/bs5/head/head.hbs +1 -1
  21. package/dist/components/bs5/navbar/navbar.hbs +1 -1
  22. package/dist/package.json +2 -1
  23. package/dist/sample-data/globalAlert/globalAlert.data.json +9 -9
  24. package/package.json +2 -1
  25. package/src/components/bs5/globalAlert/globalAlert.data.json +9 -9
  26. package/src/components/bs5/globalAlert/globalAlert.hbs +2 -2
  27. package/src/components/bs5/globalAlert/globalAlert.scss +24 -9
  28. package/src/components/bs5/globalAlert/globalAlert.stories.js +1 -1
  29. package/src/components/bs5/globalAlert/globalAlert.test.js +0 -14
  30. package/src/components/bs5/inpageAlert/inpageAlert.stories.js +1 -1
  31. package/src/components/bs5/linkColumns/linkColumns.stories.js +11 -10
  32. package/src/components/bs5/navbar/navbar.functions.js +52 -67
  33. package/src/components/bs5/navbar/navbar.hbs +1 -1
  34. package/src/components/bs5/navbar/navbar.scss +50 -39
  35. package/src/components/bs5/promotionalPanel/promotionalPanel.stories.js +17 -15
  36. package/src/components/bs5/quickexit/quickexit.stories.js +1 -1
  37. package/src/components/bs5/searchInput/searchInput.stories.js +1 -1
  38. package/src/components/bs5/spinner/Spinner.stories.js +14 -19
  39. package/src/components/bs5/table/table.stories.js +1 -1
  40. package/src/components/bs5/video/video.stories.js +1 -1
  41. package/src/stories/Introduction.mdx +15 -6
@@ -2,7 +2,7 @@
2
2
 
3
3
  <div class="global-alert-include">
4
4
  {{#each alertItems}}
5
- <section role="region" class="global-alert alert container-full d-none {{variant}}" data-variant="{{variant}}"
5
+ <section role="region" class="global-alert d-none {{variant}}" data-variant="{{variant}}"
6
6
  {{#if ariaLabel}} aria-label="{{ ariaLabel }}"
7
7
  {{~else ifCond variant "==" "global-alert-critical"}} aria-label="Critical alert"
8
8
  {{~else ifCond variant "==" "global-alert-info"}} aria-label="Informational alert"
@@ -11,7 +11,7 @@
11
11
  {{~/if}}
12
12
  {{#if id}} data-id="{{id}}" {{/if}}{{#if dismissedExpiryDays}}
13
13
  data-expiry-days="{{dismissedExpiryDays}}" {{/if}}>
14
- <div class="qld-global-alert-main">
14
+ <div class="qld-global-alert-main container">
15
15
  <div class="global-alert-icon">
16
16
  {{#ifCond variant '==' 'global-alert-critical'}}
17
17
  <span class="qld-icon qld-icon-sm qld-icon-alert-danger" aria-hidden="true"></span>
@@ -1,5 +1,5 @@
1
1
 
2
- <!-- VERSION_DETAILS={"project_id":"@qld-gov-au/qgds-bootstrap5","version":"2.1.3","branch":"HEAD","tag":"v2.1.3","commit":"0459f9571a74eab35ed443c3d02fece2a811642c","majorVersion":"v2"} -->
2
+ <!-- VERSION_DETAILS={"project_id":"@qld-gov-au/qgds-bootstrap5","version":"2.1.4","branch":"HEAD","tag":"v2.1.4","commit":"119a2bb84ace0878da734ff1026c633117afc4bc","majorVersion":"v2"} -->
3
3
 
4
4
  {{! Select environment, used verbatium if not using predefind key
5
5
  cdn := PROD|STAGING|BETA|TEST|DEV|???
@@ -26,7 +26,7 @@
26
26
  {{text}}
27
27
  {{/if}}
28
28
  </a>
29
- <button class="nav-link dropdown-toggle"{{#if currentPage}} aria-current="page"{{/if}} data-bs-toggle="dropdown" aria-expanded="false" aria-selected="false" aria-label="Toggle navigation">
29
+ <button class="nav-link dropdown-toggle"{{#if currentPage}} aria-current="page"{{/if}} data-bs-toggle="dropdown" data-bs-auto-close="false" aria-expanded="false" aria-selected="false" aria-label="Toggle navigation">
30
30
  <span class="visually-hidden">Expand</span>
31
31
  </button>
32
32
  <ul class="dropdown-menu">
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qld-gov-au/qgds-bootstrap5",
3
- "version": "2.1.3",
3
+ "version": "2.1.4",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -99,6 +99,7 @@
99
99
  "selenium-webdriver": "^4.38.0",
100
100
  "storybook": "^10.0.8",
101
101
  "storybook-addon-deep-controls": "^0.10.0",
102
+ "storybook-addon-tag-badges": "^3.0.2",
102
103
  "vite": "^7.1.11",
103
104
  "vitest": "^4.0.10"
104
105
  },
@@ -6,7 +6,7 @@
6
6
  "variant": "global-alert-critical",
7
7
  "ariaLabel": "Critical alert",
8
8
  "dismissedExpiryDays": 0,
9
- "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare <a href='#'>your home and businesses</a> or check for <a href='#'>available support</a>.",
9
+ "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare your home and businesses or check for available support.",
10
10
  "action": "<a href='https://www.qld.gov.au/'><span>Read more</span></a>"
11
11
  }
12
12
  ]
@@ -17,7 +17,7 @@
17
17
  "id": "service-delay-weather",
18
18
  "variant": "global-alert-warning",
19
19
  "ariaLabel": "Warning alert",
20
- "content": "<strong>Service Delay:</strong> Various <a href='#'>services</a> are experiencing delays due to the weather event.",
20
+ "content": "<strong>Service Delay:</strong> Various services are experiencing delays due to the weather event.",
21
21
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>"
22
22
  }
23
23
  ]
@@ -28,7 +28,7 @@
28
28
  "id": "caretaker-period-2024",
29
29
  "variant": "global-alert-info",
30
30
  "ariaLabel": "Information alert",
31
- "content": "<strong>Caretaker period:</strong> The Queensland Government is in a <a href='#'>caretaker period</a> until after the <a href='#'>state election</a>. Minimal updates will be made to this site until after the election results are declared.",
31
+ "content": "<strong>Caretaker period:</strong> The Queensland Government is in a caretaker period until after the state election. Minimal updates will be made to this site until after the election results are declared.",
32
32
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>"
33
33
  }
34
34
  ]
@@ -39,14 +39,14 @@
39
39
  "id": "cyclone-xyz-critical",
40
40
  "variant": "global-alert-critical",
41
41
  "ariaLabel": "Critical alert",
42
- "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare <a href='#'>your home and businesses</a> or check for <a href='#'>available support</a>.",
42
+ "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare your home and businesses or check for available support.",
43
43
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>"
44
44
  },
45
45
  {
46
46
  "id": "flood-warning-southeast",
47
47
  "variant": "global-alert-critical",
48
48
  "ariaLabel": "Critical alert",
49
- "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare <a href='#'>your home and businesses</a> or check for <a href='#'>available support</a>.",
49
+ "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare your home and businesses or check for available support.",
50
50
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>",
51
51
  "preventDismiss": true
52
52
  },
@@ -54,14 +54,14 @@
54
54
  "id": "transport-delays-brisbane",
55
55
  "variant": "global-alert-warning",
56
56
  "ariaLabel": "Warning alert",
57
- "content": "<strong>Service Delay:</strong> Various <a href='#'>services</a> are experiencing delays due to the weather event.",
57
+ "content": "<strong>Service Delay:</strong> Various services are experiencing delays due to the weather event.",
58
58
  "action": "<a href='https://www.qld.gov.au/'><span>Read more</span></a>"
59
59
  },
60
60
  {
61
61
  "id": "health-services-disruption",
62
62
  "variant": "global-alert-warning",
63
63
  "ariaLabel": "Warning alert",
64
- "content": "<strong>Service Delay:</strong> Various <a href='#'>services</a> are experiencing delays due to the weather event.",
64
+ "content": "<strong>Service Delay:</strong> Various services are experiencing delays due to the weather event.",
65
65
  "action": "<a href='https://www.qld.gov.au/'><span>Read more</span></a>",
66
66
  "preventDismiss": true
67
67
  },
@@ -69,13 +69,13 @@
69
69
  "id": "election-caretaker-info",
70
70
  "variant": "global-alert-info",
71
71
  "ariaLabel": "Information alert",
72
- "content": "<strong>Caretaker period:</strong> The Queensland Government is in a <a href='#'>caretaker period</a> until after the <a href='#'>state election</a>. Minimal updates will be made to this site until after the election results are declared.",
72
+ "content": "<strong>Caretaker period:</strong> The Queensland Government is in a caretaker period until after the state election. Minimal updates will be made to this site until after the election results are declared.",
73
73
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>"
74
74
  },
75
75
  {
76
76
  "variant": "global-alert-info",
77
77
  "ariaLabel": "Information alert",
78
- "content": "<strong>Caretaker period:</strong> The Queensland Government is in a <a href='#'>caretaker period</a> until after the <a href='#'>state election</a>. Minimal updates will be made to this site until after the election results are declared.",
78
+ "content": "<strong>Caretaker period:</strong> The Queensland Government is in a caretaker period until after the state election. Minimal updates will be made to this site until after the election results are declared.",
79
79
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>",
80
80
  "preventDismiss": true
81
81
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qld-gov-au/qgds-bootstrap5",
3
- "version": "2.1.3",
3
+ "version": "2.1.4",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -99,6 +99,7 @@
99
99
  "selenium-webdriver": "^4.38.0",
100
100
  "storybook": "^10.0.8",
101
101
  "storybook-addon-deep-controls": "^0.10.0",
102
+ "storybook-addon-tag-badges": "^3.0.2",
102
103
  "vite": "^7.1.11",
103
104
  "vitest": "^4.0.10"
104
105
  },
@@ -6,7 +6,7 @@
6
6
  "variant": "global-alert-critical",
7
7
  "ariaLabel": "Critical alert",
8
8
  "dismissedExpiryDays": 0,
9
- "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare <a href='#'>your home and businesses</a> or check for <a href='#'>available support</a>.",
9
+ "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare your home and businesses or check for available support.",
10
10
  "action": "<a href='https://www.qld.gov.au/'><span>Read more</span></a>"
11
11
  }
12
12
  ]
@@ -17,7 +17,7 @@
17
17
  "id": "service-delay-weather",
18
18
  "variant": "global-alert-warning",
19
19
  "ariaLabel": "Warning alert",
20
- "content": "<strong>Service Delay:</strong> Various <a href='#'>services</a> are experiencing delays due to the weather event.",
20
+ "content": "<strong>Service Delay:</strong> Various services are experiencing delays due to the weather event.",
21
21
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>"
22
22
  }
23
23
  ]
@@ -28,7 +28,7 @@
28
28
  "id": "caretaker-period-2024",
29
29
  "variant": "global-alert-info",
30
30
  "ariaLabel": "Information alert",
31
- "content": "<strong>Caretaker period:</strong> The Queensland Government is in a <a href='#'>caretaker period</a> until after the <a href='#'>state election</a>. Minimal updates will be made to this site until after the election results are declared.",
31
+ "content": "<strong>Caretaker period:</strong> The Queensland Government is in a caretaker period until after the state election. Minimal updates will be made to this site until after the election results are declared.",
32
32
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>"
33
33
  }
34
34
  ]
@@ -39,14 +39,14 @@
39
39
  "id": "cyclone-xyz-critical",
40
40
  "variant": "global-alert-critical",
41
41
  "ariaLabel": "Critical alert",
42
- "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare <a href='#'>your home and businesses</a> or check for <a href='#'>available support</a>.",
42
+ "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare your home and businesses or check for available support.",
43
43
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>"
44
44
  },
45
45
  {
46
46
  "id": "flood-warning-southeast",
47
47
  "variant": "global-alert-critical",
48
48
  "ariaLabel": "Critical alert",
49
- "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare <a href='#'>your home and businesses</a> or check for <a href='#'>available support</a>.",
49
+ "content": "<strong>Severe weather:</strong> Cyclone XYZ is expected to impact the coast area. Prepare your home and businesses or check for available support.",
50
50
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>",
51
51
  "preventDismiss": true
52
52
  },
@@ -54,14 +54,14 @@
54
54
  "id": "transport-delays-brisbane",
55
55
  "variant": "global-alert-warning",
56
56
  "ariaLabel": "Warning alert",
57
- "content": "<strong>Service Delay:</strong> Various <a href='#'>services</a> are experiencing delays due to the weather event.",
57
+ "content": "<strong>Service Delay:</strong> Various services are experiencing delays due to the weather event.",
58
58
  "action": "<a href='https://www.qld.gov.au/'><span>Read more</span></a>"
59
59
  },
60
60
  {
61
61
  "id": "health-services-disruption",
62
62
  "variant": "global-alert-warning",
63
63
  "ariaLabel": "Warning alert",
64
- "content": "<strong>Service Delay:</strong> Various <a href='#'>services</a> are experiencing delays due to the weather event.",
64
+ "content": "<strong>Service Delay:</strong> Various services are experiencing delays due to the weather event.",
65
65
  "action": "<a href='https://www.qld.gov.au/'><span>Read more</span></a>",
66
66
  "preventDismiss": true
67
67
  },
@@ -69,13 +69,13 @@
69
69
  "id": "election-caretaker-info",
70
70
  "variant": "global-alert-info",
71
71
  "ariaLabel": "Information alert",
72
- "content": "<strong>Caretaker period:</strong> The Queensland Government is in a <a href='#'>caretaker period</a> until after the <a href='#'>state election</a>. Minimal updates will be made to this site until after the election results are declared.",
72
+ "content": "<strong>Caretaker period:</strong> The Queensland Government is in a caretaker period until after the state election. Minimal updates will be made to this site until after the election results are declared.",
73
73
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>"
74
74
  },
75
75
  {
76
76
  "variant": "global-alert-info",
77
77
  "ariaLabel": "Information alert",
78
- "content": "<strong>Caretaker period:</strong> The Queensland Government is in a <a href='#'>caretaker period</a> until after the <a href='#'>state election</a>. Minimal updates will be made to this site until after the election results are declared.",
78
+ "content": "<strong>Caretaker period:</strong> The Queensland Government is in a caretaker period until after the state election. Minimal updates will be made to this site until after the election results are declared.",
79
79
  "action": "<a href='https://www.qld.gov.au/'><span>Learn more</span></a>",
80
80
  "preventDismiss": true
81
81
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  <div class="global-alert-include">
4
4
  {{#each alertItems}}
5
- <section role="region" class="global-alert alert container-full d-none {{variant}}" data-variant="{{variant}}"
5
+ <section role="region" class="global-alert d-none {{variant}}" data-variant="{{variant}}"
6
6
  {{#if ariaLabel}} aria-label="{{ ariaLabel }}"
7
7
  {{~else ifCond variant "==" "global-alert-critical"}} aria-label="Critical alert"
8
8
  {{~else ifCond variant "==" "global-alert-info"}} aria-label="Informational alert"
@@ -11,7 +11,7 @@
11
11
  {{~/if}}
12
12
  {{#if id}} data-id="{{id}}" {{/if}}{{#if dismissedExpiryDays}}
13
13
  data-expiry-days="{{dismissedExpiryDays}}" {{/if}}>
14
- <div class="qld-global-alert-main">
14
+ <div class="qld-global-alert-main container">
15
15
  <div class="global-alert-icon">
16
16
  {{#ifCond variant '==' 'global-alert-critical'}}
17
17
  <span class="qld-icon qld-icon-sm qld-icon-alert-danger" aria-hidden="true"></span>
@@ -1,10 +1,13 @@
1
1
  @use "../../../css/mixins" as m;
2
2
 
3
3
  .global-alert {
4
+ --focus-colour: var(--#{$prefix}neutral-darkest);
5
+
4
6
  line-height: 1.25rem;
5
7
  border-radius: 0;
6
8
  border-top-style: solid;
7
9
  border-width: 0;
10
+ padding-block: 0.75rem;
8
11
 
9
12
  &:first-child:not(:only-child) {
10
13
  border-top-width: 1px;
@@ -14,13 +17,6 @@
14
17
  border-top-width: 1px;
15
18
  }
16
19
 
17
- &.alert {
18
- padding-top: 0.75rem;
19
- padding-bottom: 0.75rem;
20
- padding-left: 2rem;
21
- margin-bottom: 0;
22
- }
23
-
24
20
  .qld-global-alert-main {
25
21
  display: flex;
26
22
  column-gap: 1rem;
@@ -69,7 +65,7 @@
69
65
  text-wrap: nowrap;
70
66
  }
71
67
  }
72
-
68
+
73
69
  .global-alert-close {
74
70
  display: inline-flex;
75
71
  justify-content: center;
@@ -108,6 +104,10 @@
108
104
 
109
105
  @include m.focusable($outlineWidth: 2px);
110
106
  box-shadow: none;
107
+ &:focus {
108
+ outline-color: var(--focus-colour);
109
+ }
110
+
111
111
 
112
112
  @include media-breakpoint-down(lg) {
113
113
  &:hover {
@@ -119,6 +119,7 @@
119
119
 
120
120
  &.global-alert-critical {
121
121
  --#{$prefix}icon-color: #{$core-default-color-neutral-white};
122
+ --focus-colour: var(--#{$prefix}neutral-white);
122
123
 
123
124
  background-color: $qld-notify-warning;
124
125
  color: var(--#{$prefix}white);
@@ -196,7 +197,20 @@
196
197
  }
197
198
  }
198
199
  }
199
-
200
+ @include media-breakpoint-down(lg) {
201
+ .global-alert {
202
+ .global-alert-content .global-alert-action {
203
+ margin-inline-end: 2rem;
204
+ }
205
+ }
206
+ }
207
+ @include media-breakpoint-down(md) {
208
+ .global-alert {
209
+ .global-alert-content {
210
+ padding: 0;
211
+ }
212
+ }
213
+ }
200
214
  @include media-breakpoint-up(lg) {
201
215
  .global-alert {
202
216
  .global-alert-close {
@@ -215,5 +229,6 @@
215
229
  }
216
230
  }
217
231
  }
232
+
218
233
  }
219
234
  }
@@ -3,7 +3,7 @@ import { GlobalAlert } from "./GlobalAlert.js";
3
3
  import defaultdata from "./globalAlert.data.json";
4
4
 
5
5
  export default {
6
- tags: ["autodocs"],
6
+ tags: ["autodocs", "extended"],
7
7
  title: "3. Components/Global Alert",
8
8
  render: (args) => new GlobalAlert(args).html,
9
9
  argTypes: {
@@ -155,20 +155,6 @@ describe("initGlobalAlerts", () => {
155
155
  localStorage.clear();
156
156
  });
157
157
 
158
- it("Renders with proper classes applied", () => {
159
- // The reason we needed to call initGlobalAlerts() manually in the tests is because:
160
- // The JSDOM environment handles script execution and events differently than a real browser. Here's what happens:
161
- // 1. When JSDOM loads the HTML with the scripts, the scripts execute immediately
162
- // 2. The DOMContentLoaded event might fire before the test can set up localStorage properly
163
- // 3. Even if DOMContentLoaded fires, the localStorage mock might not be properly injected into the script's execution context
164
- initGlobalAlerts();
165
-
166
- const alerts = d.querySelectorAll(".global-alert");
167
- alerts.forEach((alert) => {
168
- expect(alert.classList.contains("alert")).toBe(true);
169
- });
170
- });
171
-
172
158
  test("Alert uses default variant when data-variant is not provided", () => {
173
159
  initGlobalAlerts();
174
160
 
@@ -129,7 +129,7 @@ export const AllVariants = {
129
129
  <div class="mb-4">
130
130
  ${new InpageAlert(alertData).html}
131
131
  </div>
132
- `
132
+ `,
133
133
  )
134
134
  .join("");
135
135
  },
@@ -11,23 +11,24 @@ import defaultdata from "./linkColumns.data.json";
11
11
  export default {
12
12
  tags: ["autodocs"],
13
13
  title: "3. Components/Link Columns",
14
-
14
+
15
15
  render: (args) => new LinkColumns(args).html,
16
16
  // args: defaultdata,
17
17
  argTypes: {
18
18
  columns: {
19
- description: 'Number of coloumns of links to display',
20
- control: { type: 'number', min: 1, max: 3, step: 1 },
19
+ description: "Number of coloumns of links to display",
20
+ control: { type: "number", min: 1, max: 3, step: 1 },
21
21
  },
22
- id: { control: 'text' },
22
+ id: { control: "text" },
23
23
  theme: {
24
- description: 'The types of themes that this component supports',
24
+ description: "The types of themes that this component supports",
25
25
  control: "select",
26
- options: ["default","light", "alt", "dark", "dark-alt"],
26
+ options: ["default", "light", "alt", "dark", "dark-alt"],
27
27
  },
28
28
  data: {
29
- description: 'The data for the link columns. Each link has a url, id, value, and target. The all_link option if available, displays a single link at the end of the list, with a optional class property.',
30
- control: 'object',
29
+ description:
30
+ "The data for the link columns. Each link has a url, id, value, and target. The all_link option if available, displays a single link at the end of the list, with a optional class property.",
31
+ control: "object",
31
32
  },
32
33
  },
33
34
 
@@ -46,8 +47,8 @@ export default {
46
47
  type: "figma",
47
48
  url: "https://www.figma.com/design/qKsxl3ogIlBp7dafgxXuCA/QGDS-UI-kit?node-id=23167-395563&t=RyMlGjeuzgl8p5Gx-0",
48
49
  },
49
- pageLayout: 'with-wrapper',
50
- wrapperClasses:'qld-content-body',
50
+ pageLayout: "with-wrapper",
51
+ wrapperClasses: "qld-content-body",
51
52
  },
52
53
  };
53
54
 
@@ -1,37 +1,27 @@
1
1
  import { createFocusTrap } from "../../../js/utils.js";
2
2
  import { breakpoints } from "../../../js/constants.js";
3
+ import { getFocusableElements } from "../../../js/utils.js";
4
+
5
+ const getIsMobile = () => window.innerWidth < breakpoints.lg;
3
6
 
4
7
  export function initializeNavbar() {
5
8
  const navbar = document.getElementById("main-nav");
6
9
  const overlay = document.getElementById("overlay");
7
10
  const burgerBtn = document.getElementById("burgerBtn");
8
11
  const burgerCloseBtn = document.getElementById("burgerCloseBtn");
9
- const addHideTo = ["head", "main", "footer"];
10
- const hideTargets = addHideTo
11
- .map((id) => document.getElementById(id))
12
- .filter(Boolean);
13
-
14
- // Helper to set aria-hidden
15
- const setAriaHidden = (hidden) => {
16
- hideTargets.forEach((el) => {
17
- if (hidden) {
18
- el.setAttribute("aria-hidden", "true");
19
- } else {
20
- el.removeAttribute("aria-hidden");
21
- }
22
- });
23
- };
12
+
13
+ /** @type {HTMLElement[]} */
14
+ let inertTargets = [];
24
15
 
25
16
  // Focus trap instances (created on-demand)
26
17
  let mobileFocusTrap = null;
27
- const dropdownFocusTraps = new Map();
28
18
 
29
19
  function closeNavbar() {
30
20
  // Do not call static method bootstrap.Collapse.getInstance(navbar).hide()
31
21
  // because storybook has a problem with referencing global bootstrap object in production build.
32
22
  // Instead simulate the close button click - same thing.
33
23
  // Do not put side effects of closing menu here (eg clearing menu focus trap), instead use "hidden.bs.collapse" or "hide.bs.collapse" event handlers declared below.
34
- // Need to check if menu is actually set to show, otherwise cick will open instead.
24
+ // Need to check if menu is actually set to show, otherwise click will open instead.
35
25
  if (navbar?.classList.contains("show")) {
36
26
  burgerCloseBtn?.click();
37
27
  }
@@ -50,25 +40,7 @@ export function initializeNavbar() {
50
40
  return mobileFocusTrap;
51
41
  }
52
42
 
53
- // Create dropdown focus trap on-demand (when dropdown opens)
54
- function getOrCreateDropdownFocusTrap(dropdown, toggle) {
55
- if (!dropdownFocusTraps.has(dropdown)) {
56
- const dropdownTrap = createFocusTrap(dropdown, {
57
- returnFocusElement: toggle,
58
- onEscape: () => {
59
- // Close the dropdown using Bootstrap's API
60
- const bsDropdown = bootstrap.Dropdown.getInstance(toggle);
61
- if (bsDropdown) {
62
- bsDropdown.hide();
63
- }
64
- },
65
- });
66
- dropdownFocusTraps.set(dropdown, dropdownTrap);
67
- }
68
- return dropdownFocusTraps.get(dropdown);
69
- }
70
-
71
- // Setup dropdown event listeners
43
+ // Setup dropdown event listeners.
72
44
  function setupDropdownListeners() {
73
45
  // Find all dropdown toggles (elements with data-bs-toggle="dropdown")
74
46
  const dropdownToggles = navbar?.querySelectorAll(
@@ -84,21 +56,29 @@ export function initializeNavbar() {
84
56
  const dropdown = parentItem.querySelector(".dropdown-menu");
85
57
  if (!dropdown) return;
86
58
 
87
- // Listen for dropdown show event (desktop only)
88
- toggle.addEventListener("shown.bs.dropdown", () => {
89
- const isMobile = window.innerWidth < breakpoints.lg;
90
- if (!isMobile) {
91
- // Create and activate focus trap on-demand
92
- const dropdownTrap = getOrCreateDropdownFocusTrap(dropdown, toggle);
93
- setTimeout(() => dropdownTrap.activate(), 0);
94
- }
95
- });
59
+ // Add spacebar click for <a> tags, <buttons> already have this.
60
+ if (toggle?.tagName === "A") {
61
+ toggle.addEventListener("keydown", (/** @type KeyboardEvent*/ e) => {
62
+ if (e.key === " ") {
63
+ e.preventDefault();
64
+ toggle.click();
65
+ }
66
+ });
67
+ }
96
68
 
97
- // Listen for dropdown hide event
98
- toggle.addEventListener("hidden.bs.dropdown", () => {
99
- const dropdownTrap = dropdownFocusTraps.get(dropdown);
100
- if (dropdownTrap && dropdownTrap.isActive) {
101
- dropdownTrap.deactivate();
69
+ // There are two separate toggle elements for desktop and mobile. Bootstrap only keeps one registered for these events,
70
+ // which is the mobile button, hidden on desktop. Therefore, we need to handle any `a.dropdown-toggle` updates manually. The event is caught on the
71
+ // mobile toggle, so traverse back up find the desktop toggle.
72
+ toggle.addEventListener("hidden.bs.dropdown", (e) => {
73
+ const _toggle = parentItem.querySelector(
74
+ 'a[data-bs-toggle="dropdown"]',
75
+ );
76
+ _toggle?.classList.remove("show");
77
+ if (
78
+ dropdown?.contains(document.activeElement) &&
79
+ !(getIsMobile() || navbar.classList.contains("vertical"))
80
+ ) {
81
+ _toggle?.focus();
102
82
  }
103
83
  });
104
84
  });
@@ -115,13 +95,13 @@ export function initializeNavbar() {
115
95
  });
116
96
 
117
97
  const resetNavbarState = () => {
118
- const isMobile = window.innerWidth < breakpoints.lg;
119
- const dropdownToggles = document.querySelectorAll(
120
- ".navbar a.dropdown-toggle, .navbar a.no-dropdown-toggle",
98
+ const isMobile = getIsMobile();
99
+ const dropdownToggles = navbar?.querySelectorAll(
100
+ "a.dropdown-toggle, a.no-dropdown-toggle",
121
101
  );
122
102
 
123
103
  // Toggle dropdown functionality based on screen size
124
- dropdownToggles.forEach((toggle) => {
104
+ dropdownToggles?.forEach((toggle) => {
125
105
  if (isMobile) {
126
106
  // Skip toggle items with hasNoLink class
127
107
  if (toggle.classList.contains("hasNoLink")) {
@@ -150,8 +130,9 @@ export function initializeNavbar() {
150
130
 
151
131
  // All associated side effects of navbar collapse completion belong here.
152
132
  navbar?.addEventListener("hidden.bs.collapse", () => {
153
- setAriaHidden(false);
154
-
133
+ inertTargets.forEach((target) => {
134
+ target.inert = false;
135
+ });
155
136
  // Deactivate and destroy mobile focus trap
156
137
  if (mobileFocusTrap) {
157
138
  mobileFocusTrap.deactivate();
@@ -159,20 +140,24 @@ export function initializeNavbar() {
159
140
  }
160
141
  });
161
142
 
162
- // Burger buttons - handle open (mobile only)
143
+ // All associated side effects of navbar opening belong here.
163
144
  navbar?.addEventListener("shown.bs.collapse", () => {
164
- // Check if navbar is opening
165
- setTimeout(() => {
166
- if (navbar?.classList.contains("show")) {
167
- setAriaHidden(true);
168
-
169
- // Create and activate focus trap when navbar opens (mobile only - whole navbar)
170
- const isMobile = window.innerWidth < breakpoints.lg;
171
- if (isMobile) {
145
+ if (getIsMobile) {
146
+ // Check if navbar is opening
147
+ setTimeout(() => {
148
+ if (navbar?.classList.contains("show")) {
149
+ // set all siblings to inert
150
+ inertTargets = Array.from(navbar.parentElement.children).filter(
151
+ (child) => child !== navbar,
152
+ );
153
+ inertTargets.forEach((target) => {
154
+ target.inert = true;
155
+ });
156
+
172
157
  const trap = createMobileFocusTrap();
173
158
  trap.activate();
174
159
  }
175
- }
176
- }, 0);
160
+ }, 0);
161
+ }
177
162
  });
178
163
  }
@@ -26,7 +26,7 @@
26
26
  {{text}}
27
27
  {{/if}}
28
28
  </a>
29
- <button class="nav-link dropdown-toggle"{{#if currentPage}} aria-current="page"{{/if}} data-bs-toggle="dropdown" aria-expanded="false" aria-selected="false" aria-label="Toggle navigation">
29
+ <button class="nav-link dropdown-toggle"{{#if currentPage}} aria-current="page"{{/if}} data-bs-toggle="dropdown" data-bs-auto-close="false" aria-expanded="false" aria-selected="false" aria-label="Toggle navigation">
30
30
  <span class="visually-hidden">Expand</span>
31
31
  </button>
32
32
  <ul class="dropdown-menu">