@pnx-mixtape/mxds 0.1.0-rc.2 → 0.1.0-rc.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 (211) hide show
  1. package/.storybook/{preview.ts → preview.tsx} +4 -0
  2. package/.storybook/src/docs.tsx +29 -0
  3. package/dist/build/accordion.css +1 -1
  4. package/dist/build/accordion.entry.js +1 -1
  5. package/dist/build/autocomplete.css +1 -1
  6. package/dist/build/autocomplete.entry.js +1 -1
  7. package/dist/build/base.css +1 -1
  8. package/dist/build/breadcrumb.css +1 -1
  9. package/dist/build/button.css +1 -1
  10. package/dist/build/card.css +1 -1
  11. package/dist/build/carousel.css +1 -1
  12. package/dist/build/chunks/{Accordion-z-dH6nFH.js → Accordion-GN0sME4W.js} +1 -1
  13. package/dist/build/chunks/{AccordionMobile-BYPPNyf5.js → AccordionMobile-DG5jSe8Q.js} +1 -1
  14. package/dist/build/chunks/{Autocomplete-2L6tLLuh.js → Autocomplete-B4RtkAyh.js} +1 -1
  15. package/dist/build/chunks/{ClosableAlert-DdXbF1J2.js → ClosableAlert-DEhj8Nxm.js} +1 -1
  16. package/dist/build/chunks/{Dialog-Ds8gzhri.js → Dialog-Haahn-Yn.js} +1 -1
  17. package/dist/build/chunks/Gallery-D8NGXy2Q.js +1 -0
  18. package/dist/build/chunks/GlobalToggle-B52fdBQu.js +1 -0
  19. package/dist/build/chunks/{InPageNavigation-CVieEl9u.js → InPageNavigation-Dyn2TR-N.js} +1 -1
  20. package/dist/build/chunks/Navigation-hOrfLq7h.js +1 -0
  21. package/dist/build/chunks/{Sticky-cWUVSOXN.js → Sticky-BGCuuEJK.js} +1 -1
  22. package/dist/build/chunks/{Tabs-DA_Ez8pv.js → Tabs-DYy1YTdU.js} +1 -1
  23. package/dist/build/chunks/enums-DLV_1NAf.js +1 -0
  24. package/dist/build/chunks/utilities-_Bq3TxAQ.js +1 -0
  25. package/dist/build/constants.css +1 -1
  26. package/dist/build/cookie-consent.css +1 -1
  27. package/dist/build/dialog.css +1 -1
  28. package/dist/build/dialog.entry.js +1 -1
  29. package/dist/build/elements.js +1 -1
  30. package/dist/build/filters.css +1 -1
  31. package/dist/build/filters.entry.js +1 -1
  32. package/dist/build/form.css +1 -1
  33. package/dist/build/gallery.entry.js +1 -1
  34. package/dist/build/global-alert.css +1 -1
  35. package/dist/build/global-alert.entry.js +1 -1
  36. package/dist/build/grid.css +1 -1
  37. package/dist/build/header.css +1 -1
  38. package/dist/build/header.entry.js +1 -1
  39. package/dist/build/icon.css +1 -1
  40. package/dist/build/in-page-navigation.entry.js +1 -1
  41. package/dist/build/list-item.css +1 -1
  42. package/dist/build/navigation.css +1 -1
  43. package/dist/build/navigation.entry.js +1 -1
  44. package/dist/build/one-time-code.css +1 -0
  45. package/dist/build/popover.css +1 -1
  46. package/dist/build/print.css +1 -1
  47. package/dist/build/react.js +1 -1
  48. package/dist/build/steps.css +1 -1
  49. package/dist/build/sticky.entry.js +1 -1
  50. package/dist/build/tabs.css +1 -1
  51. package/dist/build/tabs.entry.js +1 -1
  52. package/dist/build/utilities.css +1 -1
  53. package/dist/types/Atom/Link/Link.d.ts.map +1 -1
  54. package/dist/types/Component/Accordion/Accordion.d.ts.map +1 -1
  55. package/dist/types/Component/Dialog/Dialog.d.ts.map +1 -1
  56. package/dist/types/Component/Filters/Elements/Filters.d.ts +20 -1
  57. package/dist/types/Component/Filters/Elements/Filters.d.ts.map +1 -1
  58. package/dist/types/Component/Filters/Filters.d.ts +7 -2
  59. package/dist/types/Component/Filters/Filters.d.ts.map +1 -1
  60. package/dist/types/Component/Gallery/Gallery.d.ts.map +1 -1
  61. package/dist/types/Component/Pagination/Components/PaginationContext.d.ts.map +1 -1
  62. package/dist/types/Component/Tabs/Tabs.d.ts.map +1 -1
  63. package/dist/types/Form/Autocomplete/Autocomplete.d.ts +2 -2
  64. package/dist/types/Form/Autocomplete/Autocomplete.d.ts.map +1 -1
  65. package/dist/types/Form/Autocomplete/Elements/Autocomplete.d.ts +10 -0
  66. package/dist/types/Form/Autocomplete/Elements/Autocomplete.d.ts.map +1 -1
  67. package/dist/types/Form/OneTimeCode/OneTimeCode.d.ts +12 -0
  68. package/dist/types/Form/OneTimeCode/OneTimeCode.d.ts.map +1 -0
  69. package/dist/types/Utility/Hooks/useIsomorphicLayoutEffect.d.ts +4 -0
  70. package/dist/types/Utility/Hooks/useIsomorphicLayoutEffect.d.ts.map +1 -0
  71. package/dist/types/enums.d.ts +4 -0
  72. package/dist/types/enums.d.ts.map +1 -1
  73. package/dist/types/react.d.ts +1 -0
  74. package/dist/types/react.d.ts.map +1 -1
  75. package/package.json +3 -3
  76. package/src/Atom/Button/__snapshots__/Button.stories.ts.snap +2 -3
  77. package/src/Atom/Button/_buttons.css +16 -0
  78. package/src/Atom/Button/button.twig +4 -1
  79. package/src/Atom/DefinitionList/DefinitionList.stories.ts +3 -0
  80. package/src/Atom/Icon/_icon.css +3 -0
  81. package/src/Atom/Link/Link.tsx +16 -3
  82. package/src/Atom/Link/__snapshots__/Link.stories.ts.snap +7 -12
  83. package/src/Atom/Link/__snapshots__/Link.stories.tsx.snap +1 -1
  84. package/src/Atom/Link/_links.css +9 -0
  85. package/src/Atom/Link/link.twig +8 -2
  86. package/src/Atom/LinkedImage/linked-image.twig +1 -2
  87. package/src/Atom/_generic.css +0 -10
  88. package/src/Component/Accordion/Accordion.stories.ts +31 -0
  89. package/src/Component/Accordion/Accordion.tsx +3 -2
  90. package/src/Component/Accordion/AccordionItem.stories.ts +27 -0
  91. package/src/Component/Accordion/__snapshots__/Accordion.stories.ts.snap +36 -0
  92. package/src/Component/Accordion/__snapshots__/AccordionItem.stories.ts.snap +16 -0
  93. package/src/Component/Accordion/accordion.css +3 -1
  94. package/src/Component/Breadcrumb/__snapshots__/Breadcrumb.stories.ts.snap +3 -6
  95. package/src/Component/Breadcrumb/breadcrumb.css +4 -0
  96. package/src/Component/Card/__snapshots__/Card.stories.ts.snap +11 -22
  97. package/src/Component/Card/card.css +2 -2
  98. package/src/Component/Carousel/Carousel.stories.ts +55 -0
  99. package/src/Component/Carousel/Carousel.stories.tsx +74 -0
  100. package/src/Component/Carousel/__snapshots__/Carousel.stories.ts.snap +273 -88
  101. package/src/Component/Carousel/__snapshots__/Carousel.stories.tsx.snap +5 -3
  102. package/src/Component/Carousel/carousel.css +1 -1
  103. package/src/Component/ContentBlock/__snapshots__/ContentBlock.stories.ts.snap +12 -24
  104. package/src/Component/CookieConsent/cookie-consent.css +6 -1
  105. package/src/Component/Dialog/Dialog.stories.ts +33 -0
  106. package/src/Component/Dialog/Dialog.stories.tsx +25 -0
  107. package/src/Component/Dialog/Dialog.tsx +2 -2
  108. package/src/Component/Dialog/__snapshots__/Dialog.stories.ts.snap +33 -2
  109. package/src/Component/Dialog/__snapshots__/Dialog.stories.tsx.snap +2 -0
  110. package/src/Component/Dialog/dialog.css +5 -2
  111. package/src/Component/DropMenu/DropMenu.stories.ts +39 -1
  112. package/src/Component/DropMenu/DropMenu.stories.tsx +29 -0
  113. package/src/Component/DropMenu/DropMenu.tsx +1 -1
  114. package/src/Component/DropMenu/__snapshots__/DropMenu.stories.ts.snap +14 -0
  115. package/src/Component/DropMenu/__snapshots__/DropMenu.stories.tsx.snap +3 -1
  116. package/src/Component/Filters/Elements/Filters.ts +71 -1
  117. package/src/Component/Filters/FilterItem.stories.ts +2 -1
  118. package/src/Component/Filters/FilterItem.tsx +1 -1
  119. package/src/Component/Filters/Filters.figma.ts +1 -1
  120. package/src/Component/Filters/Filters.stories.ts +95 -3
  121. package/src/Component/Filters/Filters.stories.tsx +246 -17
  122. package/src/Component/Filters/Filters.tsx +145 -29
  123. package/src/Component/Filters/README.md +102 -37
  124. package/src/Component/Filters/__snapshots__/FilterItem.stories.tsx.snap +3 -3
  125. package/src/Component/Filters/__snapshots__/Filters.stories.ts.snap +82 -4
  126. package/src/Component/Filters/__snapshots__/Filters.stories.tsx.snap +9 -3
  127. package/src/Component/Filters/filters.css +11 -0
  128. package/src/Component/Gallery/Gallery.tsx +2 -2
  129. package/src/Component/GlobalAlert/global-alert.css +3 -0
  130. package/src/Component/HeroBanner/HeroBanner.stories.ts +1 -1
  131. package/src/Component/HeroBanner/__snapshots__/HeroBanner.stories.ts.snap +4 -8
  132. package/src/Component/HeroSearch/__snapshots__/HeroSearch.stories.ts.snap +5 -10
  133. package/src/Component/InPageAlert/__snapshots__/InPageAlert.stories.ts.snap +6 -12
  134. package/src/Component/InPageNavigation/InPageNavigation.stories.ts +50 -0
  135. package/src/Component/InPageNavigation/InPageNavigation.stories.tsx +78 -0
  136. package/src/Component/InPageNavigation/__snapshots__/InPageNavigation.stories.ts.snap +35 -1
  137. package/src/Component/InPageNavigation/__snapshots__/InPageNavigation.stories.tsx.snap +2 -0
  138. package/src/Component/LinkList/__snapshots__/LinkList.stories.ts.snap +6 -12
  139. package/src/Component/ListItem/__snapshots__/ListItem.stories.ts.snap +7 -14
  140. package/src/Component/ListItem/list-item.css +1 -1
  141. package/src/Component/Navigation/Dropdown.stories.tsx +46 -0
  142. package/src/Component/Navigation/Navigation.stories.ts +56 -0
  143. package/src/Component/Navigation/__snapshots__/Dropdown.stories.tsx.snap +2 -0
  144. package/src/Component/Navigation/__snapshots__/Navigation.stories.ts.snap +57 -0
  145. package/src/Component/Navigation/_navigation-collapsible.css +3 -1
  146. package/src/Component/Navigation/_navigation-dropdown.css +3 -1
  147. package/src/Component/Pagination/Components/PaginationContext.tsx +2 -1
  148. package/src/Component/Pagination/Components/PaginationItem.tsx +1 -1
  149. package/src/Component/Pagination/Pagination.stories.ts +36 -0
  150. package/src/Component/Pagination/Pagination.stories.tsx +31 -0
  151. package/src/Component/Pagination/__snapshots__/Pagination.stories.ts.snap +69 -12
  152. package/src/Component/Pagination/__snapshots__/Pagination.stories.tsx.snap +3 -1
  153. package/src/Component/Pagination/pagination-item.twig +1 -1
  154. package/src/Component/Popover/__snapshots__/Popover.stories.ts.snap +13 -26
  155. package/src/Component/Popover/popover.css +4 -2
  156. package/src/Component/SideNavigation/__snapshots__/SideNavigation.stories.ts.snap +1 -2
  157. package/src/Component/SocialLinks/__snapshots__/SocialLinks.stories.ts.snap +6 -9
  158. package/src/Component/Steps/Steps.stories.ts +1 -1
  159. package/src/Component/Steps/steps.css +13 -0
  160. package/src/Component/Tabs/Tabs.stories.ts +22 -0
  161. package/src/Component/Tabs/Tabs.stories.tsx +24 -0
  162. package/src/Component/Tabs/Tabs.tsx +2 -2
  163. package/src/Component/Tabs/__snapshots__/Tabs.stories.ts.snap +18 -0
  164. package/src/Component/Tabs/__snapshots__/Tabs.stories.tsx.snap +3 -1
  165. package/src/Component/Tabs/tabs.css +6 -5
  166. package/src/Form/Autocomplete/Autocomplete.stories.ts +81 -4
  167. package/src/Form/Autocomplete/Autocomplete.stories.tsx +85 -1
  168. package/src/Form/Autocomplete/Autocomplete.tsx +19 -6
  169. package/src/Form/Autocomplete/Elements/Autocomplete.ts +24 -1
  170. package/src/Form/Autocomplete/__snapshots__/Autocomplete.stories.ts.snap +38 -4
  171. package/src/Form/Autocomplete/__snapshots__/Autocomplete.stories.tsx.snap +8 -4
  172. package/src/Form/Autocomplete/autocomplete.css +12 -1
  173. package/src/Form/Autocomplete/autocomplete.twig +1 -1
  174. package/src/Form/OneTimeCode/OneTimeCode.stories.ts +20 -0
  175. package/src/Form/OneTimeCode/OneTimeCode.stories.tsx +18 -0
  176. package/src/Form/OneTimeCode/OneTimeCode.tsx +56 -0
  177. package/src/Form/OneTimeCode/README.md +83 -0
  178. package/src/Form/OneTimeCode/__snapshots__/OneTimeCode.stories.ts.snap +7 -0
  179. package/src/Form/OneTimeCode/__snapshots__/OneTimeCode.stories.tsx.snap +3 -0
  180. package/src/Form/OneTimeCode/one-time-code.css +13 -0
  181. package/src/Form/OneTimeCode/one-time-code.twig +31 -0
  182. package/src/Form/__snapshots__/Validation.stories.ts.snap +1 -1
  183. package/src/Form/form.css +95 -35
  184. package/src/Layout/Footer/__snapshots__/Footer.stories.ts.snap +18 -33
  185. package/src/Layout/Grid/Grid.stories.ts +1 -0
  186. package/src/Layout/Grid/Grid.stories.tsx +26 -0
  187. package/src/Layout/Grid/__snapshots__/Grid.stories.tsx.snap +2 -0
  188. package/src/Layout/Grid/grid.css +12 -0
  189. package/src/Layout/Header/Header.stories.ts +33 -0
  190. package/src/Layout/Header/Header.stories.tsx +31 -0
  191. package/src/Layout/Header/__snapshots__/Header.stories.ts.snap +50 -0
  192. package/src/Layout/Header/__snapshots__/Header.stories.tsx.snap +2 -0
  193. package/src/Layout/Header/_header.css +4 -2
  194. package/src/Layout/Header/_toggles.css +4 -1
  195. package/src/Layout/Masthead/__snapshots__/Masthead.stories.ts.snap +8 -16
  196. package/src/Layout/Section/__snapshots__/Background.stories.ts.snap +2 -4
  197. package/src/Layout/Section/__snapshots__/Section.stories.ts.snap +4 -8
  198. package/src/Utility/Hooks/useIsomorphicLayoutEffect.ts +8 -0
  199. package/src/Utility/_mixins.css +46 -0
  200. package/src/Utility/print.css +1 -1
  201. package/src/Utility/utilities.css +20 -0
  202. package/src/_custom-media.css +3 -2
  203. package/src/constants.css +3 -13
  204. package/src/enums.ts +5 -0
  205. package/src/react.ts +1 -0
  206. package/tools/test-utils/screen-reader.ts +33 -0
  207. package/dist/build/chunks/Gallery-BT3cxS5m.js +0 -1
  208. package/dist/build/chunks/GlobalToggle-DQHho97V.js +0 -1
  209. package/dist/build/chunks/Navigation-B9Wug-ok.js +0 -1
  210. package/dist/build/chunks/disclosure-widget-BETzOHLO.js +0 -1
  211. package/dist/build/chunks/utilities-C5dAO2YA.js +0 -1
@@ -8,8 +8,7 @@ exports[`Block Link 1`] = `
8
8
 
9
9
  <a href="#">
10
10
 
11
- <span>List item title</span>
12
-
11
+ List item title
13
12
  </a>
14
13
 
15
14
  </div>
@@ -30,8 +29,7 @@ exports[`Image Reverse 1`] = `
30
29
 
31
30
  <a href="#">
32
31
 
33
- <span>List item title</span>
34
-
32
+ List item title
35
33
  </a>
36
34
 
37
35
  </div>
@@ -56,8 +54,7 @@ exports[`List Item 1`] = `
56
54
 
57
55
  <a href="#">
58
56
 
59
- <span>List item title</span>
60
-
57
+ List item title
61
58
  </a>
62
59
 
63
60
  </div>
@@ -78,8 +75,7 @@ exports[`With Image 1`] = `
78
75
 
79
76
  <a href="#">
80
77
 
81
- <span>List item title</span>
82
-
78
+ List item title
83
79
  </a>
84
80
 
85
81
  </div>
@@ -106,8 +102,7 @@ exports[`With Info 1`] = `
106
102
 
107
103
  <a href="#">
108
104
 
109
- <span>List item title</span>
110
-
105
+ List item title
111
106
  </a>
112
107
 
113
108
  </div>
@@ -127,8 +122,7 @@ exports[`With Tags 1`] = `
127
122
 
128
123
  <a href="#">
129
124
 
130
- <span>List item title</span>
131
-
125
+ List item title
132
126
  </a>
133
127
 
134
128
  </div>
@@ -161,8 +155,7 @@ exports[`With Url 1`] = `
161
155
 
162
156
  <a href="#">
163
157
 
164
- <span>List item title</span>
165
-
158
+ List item title
166
159
  </a>
167
160
 
168
161
  </div>
@@ -29,7 +29,7 @@
29
29
  & .mx-card__content {
30
30
  --flow-gap: var(--gap-s);
31
31
 
32
- & > .mx-text--s {
32
+ & > :is(.mx-text--s, .mx-text--meta) {
33
33
  --flow-gap: 0;
34
34
  }
35
35
  }
@@ -3,6 +3,7 @@ import { expect } from "storybook/test"
3
3
  import Component from "./Dropdown"
4
4
  import "./navigation.css"
5
5
  import { Page } from "../../../.storybook-react/decorators"
6
+ import { runScreenReaderWalkthrough } from "../../../tools/test-utils/screen-reader"
6
7
 
7
8
  const meta: Meta<typeof Component> = {
8
9
  tags: ["autodocs"],
@@ -72,3 +73,48 @@ export const Dropdown: Story = {
72
73
  })
73
74
  },
74
75
  }
76
+
77
+ /**
78
+ * Steps a virtual screen reader through the page with the submenu open, and asserts on what it announces.
79
+ */
80
+ export const ScreenReaderAnnouncements: Story = {
81
+ play: async ({ canvas, canvasElement, userEvent }) => {
82
+ const trigger = canvas.getByRole("button", { name: "Sub-navigation" })
83
+
84
+ trigger.focus()
85
+ await userEvent.keyboard("{ArrowDown}")
86
+ await expect(trigger).toHaveAttribute("aria-expanded", "true")
87
+
88
+ const log = await runScreenReaderWalkthrough()
89
+ await expect(log).toEqual([
90
+ "document",
91
+ "navigation, Menu",
92
+ "list",
93
+ "listitem, level 1, position 1, set size 3",
94
+ "link, Home",
95
+ "button, Sub-navigation, 1 control, expanded",
96
+ "list",
97
+ "listitem, level 2, position 1, set size 2",
98
+ "link, Child link 1",
99
+ "end of listitem, level 2, position 1, set size 2",
100
+ "listitem, level 2, position 2, set size 2",
101
+ "link, Child link 2",
102
+ "end of listitem, level 2, position 2, set size 2",
103
+ "end of list",
104
+ "end of listitem, level 1, position 1, set size 3",
105
+ "listitem, level 1, position 2, set size 3",
106
+ "link, About",
107
+ "end of listitem, level 1, position 2, set size 3",
108
+ "listitem, level 1, position 3, set size 3",
109
+ "link, Contact",
110
+ "end of listitem, level 1, position 3, set size 3",
111
+ "end of list",
112
+ "end of navigation, Menu",
113
+ "end of document",
114
+ ])
115
+
116
+ await userEvent.keyboard("{Escape}")
117
+ await expect(trigger).toHaveAttribute("aria-expanded", "false")
118
+ await userEvent.click(canvasElement)
119
+ },
120
+ }
@@ -4,6 +4,7 @@ import Component from "./navigation.twig"
4
4
  import "./navigation.css"
5
5
  import "./Elements/Navigation"
6
6
  import { Navigation as NavigationType } from "@pnx-mixtape/ids-shape"
7
+ import { runScreenReaderWalkthrough } from "../../../tools/test-utils/screen-reader"
7
8
 
8
9
  type MxNavigationType = NavigationType & {
9
10
  type?: "collapsible" | "dropdown" | "mega" | "footer"
@@ -253,6 +254,61 @@ export const Dropdown: Story = {
253
254
  },
254
255
  }
255
256
 
257
+ /**
258
+ * Steps a virtual screen reader through the page with the submenu open, and asserts on what it announces.
259
+ */
260
+ export const ScreenReaderAnnouncements: Story = {
261
+ args: Dropdown.args,
262
+ play: async ({ canvas, canvasElement, userEvent }) => {
263
+ const trigger = canvas.getByRole("button", { name: "Sub-navigation" })
264
+
265
+ trigger.focus()
266
+ await userEvent.keyboard("{ArrowDown}")
267
+ await expect(trigger).toHaveAttribute("aria-expanded", "true")
268
+
269
+ const log = await runScreenReaderWalkthrough()
270
+ await expect(log).toEqual([
271
+ "document",
272
+ "navigation, Links",
273
+ "list",
274
+ "listitem, level 1, position 1, set size 4",
275
+ "link, News",
276
+ "end of listitem, level 1, position 1, set size 4",
277
+ "listitem, level 1, position 2, set size 4",
278
+ "link, What we do",
279
+ "button, Sub-navigation, 1 control, expanded",
280
+ "list, What we do",
281
+ "listitem, level 2, position 1, set size 4",
282
+ "link, Events",
283
+ "end of listitem, level 2, position 1, set size 4",
284
+ "listitem, level 2, position 2, set size 4",
285
+ "link, Who we are",
286
+ "end of listitem, level 2, position 2, set size 4",
287
+ "listitem, level 2, position 3, set size 4",
288
+ "link, Join us",
289
+ "end of listitem, level 2, position 3, set size 4",
290
+ "listitem, level 2, position 4, set size 4",
291
+ "link, Careers",
292
+ "end of listitem, level 2, position 4, set size 4",
293
+ "end of list, What we do",
294
+ "end of listitem, level 1, position 2, set size 4",
295
+ "listitem, level 1, position 3, set size 4",
296
+ "link, Contact",
297
+ "end of listitem, level 1, position 3, set size 4",
298
+ "listitem, level 1, position 4, set size 4",
299
+ "link, Resources",
300
+ "end of listitem, level 1, position 4, set size 4",
301
+ "end of list",
302
+ "end of navigation, Links",
303
+ "end of document",
304
+ ])
305
+
306
+ await userEvent.keyboard("{Escape}")
307
+ await expect(trigger).toHaveAttribute("aria-expanded", "false")
308
+ await userEvent.click(canvasElement)
309
+ },
310
+ }
311
+
256
312
  /**
257
313
  * Mega is horizontal on desktop requires click to access submenu, best for more than 2 levels of links.
258
314
  */
@@ -1,3 +1,5 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
3
  exports[`Dropdown 1`] = `"<nav class="mx-nav mx-nav--dropdown" aria-label="Menu" id="navigation"><ul class="mx-nav__level-1"><li class="mx-nav__has-subnav"><a href="#" class="">Home</a><button aria-controls="_r_0_" aria-expanded="false" class="mx-nav__toggle mx-icon mx-icon--only mx-icon--chevron-down" type="button">Sub-navigation</button></li><li class=""><a href="#" class="">About</a></li><li class=""><a href="#" class="">Contact</a></li></ul></nav>"`;
4
+
5
+ exports[`Screen Reader Announcements 1`] = `"<nav class="mx-nav mx-nav--dropdown" aria-label="Menu" id="navigation"><ul class="mx-nav__level-1"><li class="mx-nav__has-subnav"><a href="#" class="">Home</a><button aria-controls="_r_8_" aria-expanded="false" class="mx-nav__toggle mx-icon mx-icon--only mx-icon--chevron-down" type="button">Sub-navigation</button></li><li class=""><a href="#" class="">About</a></li><li class=""><a href="#" class="">Contact</a></li></ul></nav>"`;
@@ -243,3 +243,60 @@ exports[`Navigation 1`] = `
243
243
  </nav>
244
244
  "
245
245
  `;
246
+
247
+ exports[`Screen Reader Announcements 1`] = `
248
+ "
249
+
250
+ <mx-nav flyout="">
251
+ <nav class="mx-nav mx-nav--dropdown" aria-label="Links" id="links-story">
252
+ <ul class="mx-nav__level-1">
253
+ <li>
254
+ <a href="#">
255
+ News
256
+ </a>
257
+ </li>
258
+ <li class="mx-nav__has-subnav">
259
+ <a href="#" id="unique-1">
260
+ What we do
261
+ </a>
262
+ <button class="mx-nav__toggle mx-icon mx-icon--chevron-down mx-icon--only" aria-expanded="false" aria-controls="unique-0">Sub-navigation</button>
263
+ <ul class="mx-nav__level-2" id="unique-0" aria-labelledby="unique-1" inert="">
264
+ <li>
265
+ <a href="#">
266
+ Events
267
+ </a>
268
+ </li>
269
+ <li>
270
+ <a href="#">
271
+ Who we are
272
+ </a>
273
+ </li>
274
+ <li>
275
+ <a href="#">
276
+ Join us
277
+ </a>
278
+ </li>
279
+ <li>
280
+ <a href="#">
281
+ Careers
282
+ </a>
283
+ </li>
284
+ </ul>
285
+
286
+ </li>
287
+ <li>
288
+ <a href="#">
289
+ Contact
290
+ </a>
291
+ </li>
292
+ <li>
293
+ <a href="#">
294
+ Resources
295
+ </a>
296
+ </li>
297
+ </ul>
298
+
299
+ </nav>
300
+ </mx-nav>
301
+ "
302
+ `;
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Collapsible Navigation
3
3
  */
4
+ @import "../../Utility/_mixins.css";
4
5
 
5
6
  @layer design-system.components {
6
7
  .mx-nav--collapsible {
@@ -55,7 +56,8 @@
55
56
  }
56
57
 
57
58
  & li > ul {
58
- opacity: 1;
59
+ @add-mixin transition;
60
+
59
61
  display: grid;
60
62
 
61
63
  @starting-style {
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Dropdown Navigation
3
3
  */
4
+ @import "../../Utility/_mixins.css";
4
5
 
5
6
  @layer design-system.components {
6
7
  .mx-nav--dropdown {
@@ -44,8 +45,9 @@
44
45
  }
45
46
 
46
47
  & li > ul {
48
+ @add-mixin transition;
49
+
47
50
  display: grid;
48
- opacity: 1;
49
51
 
50
52
  @starting-style {
51
53
  opacity: 0;
@@ -10,6 +10,7 @@ import {
10
10
  useEffect,
11
11
  } from "react"
12
12
  import useUrlParams from "../../../Utility/Hooks/useUrlParams"
13
+ import useIsomorphicLayoutEffect from "../../../Utility/Hooks/useIsomorphicLayoutEffect"
13
14
  import { validators } from "../../../Utility/utilities"
14
15
 
15
16
  type PaginationContextValues = {
@@ -111,7 +112,7 @@ const PaginationProvider = ({
111
112
  const { searchParams, pathname, history } = useUrlParams()
112
113
 
113
114
  // Onload, go to page from URL ?page=x
114
- useEffect(() => {
115
+ useIsomorphicLayoutEffect(() => {
115
116
  if (onLoad.current) return
116
117
  // check url for page query.
117
118
  const pageParam = searchParams?.get("page") ?? "1"
@@ -20,7 +20,7 @@ const PaginationItem = ({
20
20
  <Tag
21
21
  className={classNames(`mx-pagination__${as}`)}
22
22
  aria-current={active ? "page" : null}
23
- aria-hidden={disabled ? "true" : null}
23
+ aria-hidden={as === "ellipsis" || disabled ? "true" : null}
24
24
  >
25
25
  {as === "ellipsis" && <>...</>}
26
26
  {as === "item" && (
@@ -8,6 +8,7 @@ import "./pagination.css"
8
8
  import { Pagination as IdsPagination } from "@pnx-mixtape/ids-shape"
9
9
  import { Icons } from "../../enums"
10
10
  import { modes } from "../../../.storybook/modes"
11
+ import { runScreenReaderWalkthrough } from "../../../tools/test-utils/screen-reader"
11
12
 
12
13
  // local widening until `label` lands in @pnx-mixtape/ids-shape, and `pages` is
13
14
  // a concatenated string of pre-rendered PaginationItem markup rather than an array
@@ -132,3 +133,38 @@ export const Pagination: Story = {
132
133
  })
133
134
  },
134
135
  }
136
+
137
+ /**
138
+ * Steps a virtual screen reader through the page and asserts on what it announces.
139
+ */
140
+ export const ScreenReaderAnnouncements: Story = {
141
+ play: async () => {
142
+ const log = await runScreenReaderWalkthrough()
143
+ await expect(log).toEqual([
144
+ "document",
145
+ "navigation, Pagination",
146
+ "link, Previous",
147
+ "Previous",
148
+ "end of link, Previous",
149
+ "list",
150
+ "listitem, level 1, position 1, set size 4",
151
+ "link, 1",
152
+ "end of listitem, level 1, position 1, set size 4",
153
+ "listitem, level 1, position 2, set size 4",
154
+ "link, 2, current page",
155
+ "end of listitem, level 1, position 2, set size 4",
156
+ "listitem, level 1, position 3, set size 4",
157
+ "link, 3",
158
+ "end of listitem, level 1, position 3, set size 4",
159
+ "listitem, level 1, position 4, set size 4",
160
+ "link, 10",
161
+ "end of listitem, level 1, position 4, set size 4",
162
+ "end of list",
163
+ "link, Next",
164
+ "Next",
165
+ "end of link, Next",
166
+ "end of navigation, Pagination",
167
+ "end of document",
168
+ ])
169
+ },
170
+ }
@@ -5,6 +5,7 @@ import Component from "./Components/PaginationContext"
5
5
  import PaginationComponent from "./Pagination"
6
6
  import "./pagination.css"
7
7
  import { Page } from "../../../.storybook-react/decorators"
8
+ import { runScreenReaderWalkthrough } from "../../../tools/test-utils/screen-reader"
8
9
 
9
10
  const meta: Meta<typeof Component> = {
10
11
  tags: ["autodocs"],
@@ -81,3 +82,33 @@ export const Pagination: StoryObj<typeof meta> = {
81
82
  })
82
83
  },
83
84
  }
85
+
86
+ /**
87
+ * Steps a virtual screen reader through the page and asserts on what it announces.
88
+ */
89
+ export const ScreenReaderAnnouncements: StoryObj<typeof meta> = {
90
+ play: async () => {
91
+ const log = await runScreenReaderWalkthrough()
92
+ await expect(log).toEqual([
93
+ "document",
94
+ "navigation, Pagination",
95
+ "list",
96
+ "listitem, level 1, current page, position 1, set size 4",
97
+ "1",
98
+ "end of listitem, level 1, current page, position 1, set size 4",
99
+ "listitem, level 1, position 2, set size 4",
100
+ "button, 2",
101
+ "end of listitem, level 1, position 2, set size 4",
102
+ "listitem, level 1, position 3, set size 4",
103
+ "button, 3",
104
+ "end of listitem, level 1, position 3, set size 4",
105
+ "listitem, level 1, position 4, set size 4",
106
+ "button, 10",
107
+ "end of listitem, level 1, position 4, set size 4",
108
+ "end of list",
109
+ "button, next",
110
+ "end of navigation, Pagination",
111
+ "end of document",
112
+ ])
113
+ },
114
+ }
@@ -8,8 +8,7 @@ exports[`Pagination 1`] = `
8
8
 
9
9
  <span class="mx-icon mx-icon--arrow-left"></span>
10
10
 
11
- <span>Previous</span>
12
-
11
+ Previous
13
12
  </a>
14
13
 
15
14
  </div>
@@ -19,8 +18,7 @@ exports[`Pagination 1`] = `
19
18
 
20
19
  <a href="#">
21
20
 
22
- <span>1</span>
23
-
21
+ 1
24
22
  </a>
25
23
 
26
24
  </li>
@@ -28,8 +26,7 @@ exports[`Pagination 1`] = `
28
26
 
29
27
  <a href="#" aria-current="page">
30
28
 
31
- <span>2</span>
32
-
29
+ 2
33
30
  </a>
34
31
 
35
32
  </li>
@@ -37,18 +34,16 @@ exports[`Pagination 1`] = `
37
34
 
38
35
  <a href="#">
39
36
 
40
- <span>3</span>
41
-
37
+ 3
42
38
  </a>
43
39
 
44
40
  </li>
45
- <li class="mx-pagination__ellipsis">…</li>
41
+ <li class="mx-pagination__ellipsis" aria-hidden="true">…</li>
46
42
  <li class="mx-pagination__item">
47
43
 
48
44
  <a href="#">
49
45
 
50
- <span>10</span>
51
-
46
+ 10
52
47
  </a>
53
48
 
54
49
  </li>
@@ -58,8 +53,70 @@ exports[`Pagination 1`] = `
58
53
 
59
54
  <a href="#">
60
55
 
61
- <span>Next</span>
56
+ Next
57
+ <span class="mx-icon mx-icon--arrow-right"></span>
58
+
59
+ </a>
60
+
61
+ </div>
62
+ </nav>
63
+ "
64
+ `;
65
+
66
+ exports[`Screen Reader Announcements 1`] = `
67
+ "<nav class="mx-pagination" aria-label="Pagination">
68
+ <div class="mx-pagination__previous">
69
+
70
+ <a href="#">
71
+
72
+ <span class="mx-icon mx-icon--arrow-left"></span>
73
+
74
+ Previous
75
+ </a>
76
+
77
+ </div>
78
+ <div class="mx-pagination__label">Page 2 of 10</div>
79
+ <ul class="mx-pagination__items">
80
+ <li class="mx-pagination__item">
81
+
82
+ <a href="#">
83
+
84
+ 1
85
+ </a>
86
+
87
+ </li>
88
+ <li class="mx-pagination__item">
62
89
 
90
+ <a href="#" aria-current="page">
91
+
92
+ 2
93
+ </a>
94
+
95
+ </li>
96
+ <li class="mx-pagination__item">
97
+
98
+ <a href="#">
99
+
100
+ 3
101
+ </a>
102
+
103
+ </li>
104
+ <li class="mx-pagination__ellipsis" aria-hidden="true">…</li>
105
+ <li class="mx-pagination__item">
106
+
107
+ <a href="#">
108
+
109
+ 10
110
+ </a>
111
+
112
+ </li>
113
+
114
+ </ul>
115
+ <div class="mx-pagination__next">
116
+
117
+ <a href="#">
118
+
119
+ Next
63
120
  <span class="mx-icon mx-icon--arrow-right"></span>
64
121
 
65
122
  </a>
@@ -1,3 +1,5 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`Pagination 1`] = `"<nav class="mx-pagination" aria-label="Pagination"><div class="mx-pagination__previous" aria-hidden="true"><button type="button" disabled=""><span class="mx-icon mx-icon--arrow-left"></span><span>previous</span></button></div><div class="mx-pagination__label">Page 1 of 10</div><ul class="mx-pagination__items"><li class="mx-pagination__item" aria-current="page">1</li><li class="mx-pagination__item"><button type="button" data-page="2">2</button></li><li class="mx-pagination__item"><button type="button" data-page="3">3</button></li><li class="mx-pagination__ellipsis">...</li><li class="mx-pagination__item"><button type="button" data-page="10">10</button></li></ul><div class="mx-pagination__next"><button type="button" data-page="2"><span>next</span><span class="mx-icon mx-icon--arrow-right"></span></button></div></nav>"`;
3
+ exports[`Pagination 1`] = `"<nav class="mx-pagination" aria-label="Pagination"><div class="mx-pagination__previous" aria-hidden="true"><button type="button" disabled=""><span class="mx-icon mx-icon--arrow-left"></span><span>previous</span></button></div><div class="mx-pagination__label">Page 1 of 10</div><ul class="mx-pagination__items"><li class="mx-pagination__item" aria-current="page">1</li><li class="mx-pagination__item"><button type="button" data-page="2">2</button></li><li class="mx-pagination__item"><button type="button" data-page="3">3</button></li><li class="mx-pagination__ellipsis" aria-hidden="true">...</li><li class="mx-pagination__item"><button type="button" data-page="10">10</button></li></ul><div class="mx-pagination__next"><button type="button" data-page="2"><span>next</span><span class="mx-icon mx-icon--arrow-right"></span></button></div></nav>"`;
4
+
5
+ exports[`Screen Reader Announcements 1`] = `"<nav class="mx-pagination" aria-label="Pagination"><div class="mx-pagination__previous" aria-hidden="true"><button type="button" disabled=""><span class="mx-icon mx-icon--arrow-left"></span><span>previous</span></button></div><div class="mx-pagination__label">Page 1 of 10</div><ul class="mx-pagination__items"><li class="mx-pagination__item" aria-current="page">1</li><li class="mx-pagination__item"><button type="button" data-page="2">2</button></li><li class="mx-pagination__item"><button type="button" data-page="3">3</button></li><li class="mx-pagination__ellipsis" aria-hidden="true">...</li><li class="mx-pagination__item"><button type="button" data-page="10">10</button></li></ul><div class="mx-pagination__next"><button type="button" data-page="2"><span>next</span><span class="mx-icon mx-icon--arrow-right"></span></button></div></nav>"`;
@@ -3,5 +3,5 @@
3
3
  {{ link }}
4
4
  </li>
5
5
  {% else %}
6
- <li class="mx-pagination__ellipsis">&hellip;</li>
6
+ <li class="mx-pagination__ellipsis" aria-hidden="true">&hellip;</li>
7
7
  {% endif %}