@kaizen/components 1.39.1 → 1.39.2

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 (123) hide show
  1. package/dist/cjs/Calendar/LegacyCalendarRange/LegacyCalendarRange.cjs.map +1 -1
  2. package/dist/cjs/Calendar/utils/formatDateAsNumeral.cjs.map +1 -1
  3. package/dist/cjs/Calendar/utils/formatDateAsText.cjs.map +1 -1
  4. package/dist/cjs/Calendar/utils/parseDateAsTextOrNumeral.cjs.map +1 -1
  5. package/dist/cjs/Calendar/utils/parseDateFromNumeralFormatValue.cjs.map +1 -1
  6. package/dist/cjs/Calendar/utils/parseDateFromTextFormatValue.cjs.map +1 -1
  7. package/dist/cjs/DateInput/DateInputDescription/DateInputDescription.cjs.map +1 -1
  8. package/dist/cjs/DateInput/DateInputDescription/utils/formatDescriptionInputFormat.cjs.map +1 -1
  9. package/dist/cjs/DatePicker/subcomponents/DateInputField/DateInputField.cjs.map +1 -1
  10. package/dist/cjs/DatePicker/utils/getLocale.cjs.map +1 -1
  11. package/dist/cjs/Filter/Filter/Filter.cjs +4 -1
  12. package/dist/cjs/Filter/Filter/Filter.cjs.map +1 -1
  13. package/dist/cjs/Filter/FilterBar/subcomponents/FilterBarButton/FilterBarButton.cjs +3 -3
  14. package/dist/cjs/Filter/FilterBar/subcomponents/FilterBarButton/FilterBarButton.cjs.map +1 -1
  15. package/dist/cjs/Filter/FilterBar/subcomponents/FilterBarDatePicker/FilterBarDatePicker.cjs +1 -1
  16. package/dist/cjs/Filter/FilterBar/subcomponents/FilterBarDatePicker/FilterBarDatePicker.cjs.map +1 -1
  17. package/dist/cjs/Filter/FilterBar/subcomponents/FilterBarDateRangePicker/FilterBarDateRangePicker.cjs +1 -1
  18. package/dist/cjs/Filter/FilterBar/subcomponents/FilterBarDateRangePicker/FilterBarDateRangePicker.cjs.map +1 -1
  19. package/dist/cjs/Filter/FilterBar/subcomponents/FilterBarSelect/FilterBarSelect.cjs +1 -1
  20. package/dist/cjs/Filter/FilterBar/subcomponents/FilterBarSelect/FilterBarSelect.cjs.map +1 -1
  21. package/dist/cjs/Filter/FilterDatePicker/hooks/useDateInputHandlers.cjs.map +1 -1
  22. package/dist/cjs/Filter/FilterDatePicker/subcomponents/DateInputField/DateInputField.cjs.map +1 -1
  23. package/dist/cjs/Filter/FilterDatePicker/utils/transformDateToInputValue.cjs.map +1 -1
  24. package/dist/cjs/Filter/FilterDateRangePicker/subcomponents/DateRangeDisplayLabel/DateRangeDisplayLabel.cjs.map +1 -1
  25. package/dist/cjs/Filter/FilterDateRangePicker/subcomponents/DateRangeInputField/DateRangeInputField.cjs.map +1 -1
  26. package/dist/cjs/dts/Calendar/LegacyCalendarRange/LegacyCalendarRange.d.ts +1 -0
  27. package/dist/cjs/dts/Calendar/utils/formatDateAsNumeral.d.ts +1 -0
  28. package/dist/cjs/dts/Calendar/utils/formatDateAsText.d.ts +1 -0
  29. package/dist/cjs/dts/Calendar/utils/parseDateAsTextOrNumeral.d.ts +1 -0
  30. package/dist/cjs/dts/Calendar/utils/parseDateFromNumeralFormatValue.d.ts +1 -0
  31. package/dist/cjs/dts/Calendar/utils/parseDateFromTextFormatValue.d.ts +1 -0
  32. package/dist/cjs/dts/DateInput/DateInputDescription/DateInputDescription.d.ts +1 -0
  33. package/dist/cjs/dts/DateInput/DateInputDescription/utils/formatDescriptionInputFormat.d.ts +1 -0
  34. package/dist/cjs/dts/DatePicker/subcomponents/DateInputField/DateInputField.d.ts +1 -0
  35. package/dist/cjs/dts/DatePicker/utils/getLocale.d.ts +1 -0
  36. package/dist/cjs/dts/Filter/Filter/Filter.d.ts +1 -0
  37. package/dist/cjs/dts/Filter/FilterBar/subcomponents/FilterBarButton/FilterBarButton.d.ts +2 -2
  38. package/dist/cjs/dts/Filter/FilterDatePicker/hooks/useDateInputHandlers.d.ts +1 -0
  39. package/dist/cjs/dts/Filter/FilterDatePicker/subcomponents/DateInputField/DateInputField.d.ts +1 -0
  40. package/dist/cjs/dts/Filter/FilterDatePicker/utils/transformDateToInputValue.d.ts +1 -0
  41. package/dist/cjs/dts/Filter/FilterDateRangePicker/subcomponents/DateRangeDisplayLabel/DateRangeDisplayLabel.d.ts +1 -0
  42. package/dist/cjs/dts/Filter/FilterDateRangePicker/subcomponents/DateRangeInputField/DateRangeInputField.d.ts +1 -0
  43. package/dist/cjs/index.css +4 -4
  44. package/dist/esm/Calendar/LegacyCalendarRange/LegacyCalendarRange.mjs.map +1 -1
  45. package/dist/esm/Calendar/utils/formatDateAsNumeral.mjs.map +1 -1
  46. package/dist/esm/Calendar/utils/formatDateAsText.mjs.map +1 -1
  47. package/dist/esm/Calendar/utils/parseDateAsTextOrNumeral.mjs.map +1 -1
  48. package/dist/esm/Calendar/utils/parseDateFromNumeralFormatValue.mjs.map +1 -1
  49. package/dist/esm/Calendar/utils/parseDateFromTextFormatValue.mjs.map +1 -1
  50. package/dist/esm/DateInput/DateInputDescription/DateInputDescription.mjs.map +1 -1
  51. package/dist/esm/DateInput/DateInputDescription/utils/formatDescriptionInputFormat.mjs.map +1 -1
  52. package/dist/esm/DatePicker/subcomponents/DateInputField/DateInputField.mjs.map +1 -1
  53. package/dist/esm/DatePicker/utils/getLocale.mjs.map +1 -1
  54. package/dist/esm/Filter/Filter/Filter.mjs +5 -2
  55. package/dist/esm/Filter/Filter/Filter.mjs.map +1 -1
  56. package/dist/esm/Filter/FilterBar/subcomponents/FilterBarButton/FilterBarButton.mjs +3 -3
  57. package/dist/esm/Filter/FilterBar/subcomponents/FilterBarButton/FilterBarButton.mjs.map +1 -1
  58. package/dist/esm/Filter/FilterBar/subcomponents/FilterBarDatePicker/FilterBarDatePicker.mjs +1 -1
  59. package/dist/esm/Filter/FilterBar/subcomponents/FilterBarDatePicker/FilterBarDatePicker.mjs.map +1 -1
  60. package/dist/esm/Filter/FilterBar/subcomponents/FilterBarDateRangePicker/FilterBarDateRangePicker.mjs +1 -1
  61. package/dist/esm/Filter/FilterBar/subcomponents/FilterBarDateRangePicker/FilterBarDateRangePicker.mjs.map +1 -1
  62. package/dist/esm/Filter/FilterBar/subcomponents/FilterBarSelect/FilterBarSelect.mjs +1 -1
  63. package/dist/esm/Filter/FilterBar/subcomponents/FilterBarSelect/FilterBarSelect.mjs.map +1 -1
  64. package/dist/esm/Filter/FilterDatePicker/hooks/useDateInputHandlers.mjs.map +1 -1
  65. package/dist/esm/Filter/FilterDatePicker/subcomponents/DateInputField/DateInputField.mjs.map +1 -1
  66. package/dist/esm/Filter/FilterDatePicker/utils/transformDateToInputValue.mjs.map +1 -1
  67. package/dist/esm/Filter/FilterDateRangePicker/subcomponents/DateRangeDisplayLabel/DateRangeDisplayLabel.mjs.map +1 -1
  68. package/dist/esm/Filter/FilterDateRangePicker/subcomponents/DateRangeInputField/DateRangeInputField.mjs.map +1 -1
  69. package/dist/esm/dts/Calendar/LegacyCalendarRange/LegacyCalendarRange.d.ts +1 -0
  70. package/dist/esm/dts/Calendar/utils/formatDateAsNumeral.d.ts +1 -0
  71. package/dist/esm/dts/Calendar/utils/formatDateAsText.d.ts +1 -0
  72. package/dist/esm/dts/Calendar/utils/parseDateAsTextOrNumeral.d.ts +1 -0
  73. package/dist/esm/dts/Calendar/utils/parseDateFromNumeralFormatValue.d.ts +1 -0
  74. package/dist/esm/dts/Calendar/utils/parseDateFromTextFormatValue.d.ts +1 -0
  75. package/dist/esm/dts/DateInput/DateInputDescription/DateInputDescription.d.ts +1 -0
  76. package/dist/esm/dts/DateInput/DateInputDescription/utils/formatDescriptionInputFormat.d.ts +1 -0
  77. package/dist/esm/dts/DatePicker/subcomponents/DateInputField/DateInputField.d.ts +1 -0
  78. package/dist/esm/dts/DatePicker/utils/getLocale.d.ts +1 -0
  79. package/dist/esm/dts/Filter/Filter/Filter.d.ts +1 -0
  80. package/dist/esm/dts/Filter/FilterBar/subcomponents/FilterBarButton/FilterBarButton.d.ts +2 -2
  81. package/dist/esm/dts/Filter/FilterDatePicker/hooks/useDateInputHandlers.d.ts +1 -0
  82. package/dist/esm/dts/Filter/FilterDatePicker/subcomponents/DateInputField/DateInputField.d.ts +1 -0
  83. package/dist/esm/dts/Filter/FilterDatePicker/utils/transformDateToInputValue.d.ts +1 -0
  84. package/dist/esm/dts/Filter/FilterDateRangePicker/subcomponents/DateRangeDisplayLabel/DateRangeDisplayLabel.d.ts +1 -0
  85. package/dist/esm/dts/Filter/FilterDateRangePicker/subcomponents/DateRangeInputField/DateRangeInputField.d.ts +1 -0
  86. package/dist/esm/index.css +2 -2
  87. package/dist/index.d.ts +2 -0
  88. package/dist/styles.css +1 -1
  89. package/package.json +3 -3
  90. package/src/Calendar/CalendarRange/_docs/CalendarRange.stickersheet.stories.tsx +19 -8
  91. package/src/Calendar/CalendarSingle/_docs/CalendarSingle.stickersheet.stories.tsx +22 -29
  92. package/src/Calendar/LegacyCalendarRange/LegacyCalendarRange.tsx +1 -0
  93. package/src/Calendar/utils/formatDateAsNumeral.ts +1 -1
  94. package/src/Calendar/utils/formatDateAsText.ts +1 -1
  95. package/src/Calendar/utils/isSelectingDayInCalendar.spec.tsx +4 -5
  96. package/src/Calendar/utils/parseDateAsTextOrNumeral.ts +1 -0
  97. package/src/Calendar/utils/parseDateFromNumeralFormatValue.ts +1 -1
  98. package/src/Calendar/utils/parseDateFromTextFormatValue.ts +1 -1
  99. package/src/Calendar/utils/setFocusInCalendar.spec.tsx +21 -16
  100. package/src/DateInput/DateInputDescription/DateInputDescription.tsx +1 -0
  101. package/src/DateInput/DateInputDescription/utils/formatDescriptionInputFormat.ts +2 -0
  102. package/src/DatePicker/DatePicker.spec.tsx +12 -16
  103. package/src/DatePicker/subcomponents/DateInputField/DateInputField.tsx +1 -0
  104. package/src/DatePicker/utils/getLocale.ts +1 -0
  105. package/src/Filter/Filter/Filter.spec.tsx +6 -4
  106. package/src/Filter/Filter/Filter.tsx +11 -1
  107. package/src/Filter/FilterBar/FilterBar.spec.tsx +12 -1
  108. package/src/Filter/FilterBar/subcomponents/FilterBarButton/FilterBarButton.spec.tsx +1 -1
  109. package/src/Filter/FilterBar/subcomponents/FilterBarButton/FilterBarButton.tsx +3 -3
  110. package/src/Filter/FilterBar/subcomponents/FilterBarDatePicker/FilterBarDatePicker.spec.tsx +17 -22
  111. package/src/Filter/FilterBar/subcomponents/FilterBarDatePicker/FilterBarDatePicker.tsx +1 -1
  112. package/src/Filter/FilterBar/subcomponents/FilterBarDateRangePicker/FilterBarDateRangePicker.spec.tsx +6 -7
  113. package/src/Filter/FilterBar/subcomponents/FilterBarDateRangePicker/FilterBarDateRangePicker.tsx +1 -1
  114. package/src/Filter/FilterBar/subcomponents/FilterBarSelect/FilterBarSelect.tsx +1 -1
  115. package/src/Filter/FilterDatePicker/FilterDatePicker.spec.stories.tsx +1 -1
  116. package/src/Filter/FilterDatePicker/FilterDatePicker.spec.tsx +3 -5
  117. package/src/Filter/FilterDatePicker/hooks/useDateInputHandlers.ts +1 -0
  118. package/src/Filter/FilterDatePicker/subcomponents/DateInputField/DateInputField.tsx +1 -0
  119. package/src/Filter/FilterDatePicker/subcomponents/FilterDatePickerField/FilterDatePickerField.spec.tsx +25 -21
  120. package/src/Filter/FilterDatePicker/utils/transformDateToInputValue.ts +1 -0
  121. package/src/Filter/FilterDateRangePicker/subcomponents/DateRangeDisplayLabel/DateRangeDisplayLabel.tsx +1 -0
  122. package/src/Filter/FilterDateRangePicker/subcomponents/DateRangeInputField/DateRangeInputField.tsx +1 -0
  123. package/src/Filter/FilterDateRangePicker/subcomponents/FilterDateRangePickerField/FilterDateRangePickerField.spec.tsx +30 -24
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaizen/components",
3
- "version": "1.39.1",
3
+ "version": "1.39.2",
4
4
  "description": "Kaizen component library",
5
5
  "author": "Geoffrey Chong <geoff.chong@cultureamp.com>",
6
6
  "homepage": "https://cultureamp.design",
@@ -64,7 +64,7 @@
64
64
  "@react-stately/select": "^3.6.1",
65
65
  "@react-types/shared": "^3.22.0",
66
66
  "classnames": "^2.5.1",
67
- "date-fns": "^2.30.0",
67
+ "date-fns": "^3.0.6",
68
68
  "lodash.debounce": "^4.0.8",
69
69
  "nanobus": "^4.5.0",
70
70
  "prosemirror-commands": "^1.5.2",
@@ -79,7 +79,7 @@
79
79
  "prosemirror-utils": "^1.2.1-0",
80
80
  "prosemirror-view": "^1.32.7",
81
81
  "react-animate-height": "^3.2.3",
82
- "react-day-picker": "8.4.1",
82
+ "react-day-picker": "^8.10.0",
83
83
  "react-focus-lock": "^2.9.6",
84
84
  "react-focus-on": "^3.9.1",
85
85
  "react-media": "^1.10.0",
@@ -96,29 +96,40 @@ const StickerSheetTemplate: StickerSheetStory = {
96
96
  const applyStickerSheetStyles = (canvasElement: HTMLElement): void => {
97
97
  const canvas = within(canvasElement)
98
98
 
99
- const getElementWithinCalendar = (id: string, name: string): HTMLElement => {
99
+ const getElementWithinCalendar = (
100
+ id: string,
101
+ monthName: string,
102
+ dayName: string
103
+ ): HTMLElement => {
100
104
  const calendar = canvas.getByTestId(id)
101
- return within(calendar).getByRole("button", { name })
105
+ const month = within(calendar).getByRole("grid", { name: monthName })
106
+ return within(month).getByRole("gridcell", { name: dayName })
102
107
  }
103
108
 
104
109
  const calendarsPseudoStates = [
105
110
  {
106
111
  id: "id__calendar-range__start",
107
- buttonDescription: "19th February (Saturday)",
112
+ monthName: "February 2022",
113
+ dayName: "19",
108
114
  },
109
115
  {
110
116
  id: "id__calendar-range__middle",
111
- buttonDescription: "26th February (Saturday)",
117
+ monthName: "February 2022",
118
+ dayName: "26",
119
+ },
120
+ {
121
+ id: "id__calendar-range__end",
122
+ monthName: "March 2022",
123
+ dayName: "4",
112
124
  },
113
- { id: "id__calendar-range__end", buttonDescription: "4th March (Friday)" },
114
125
  ]
115
126
 
116
- calendarsPseudoStates.forEach(({ id, buttonDescription }) => {
117
- getElementWithinCalendar(`${id}--hover`, buttonDescription).setAttribute(
127
+ calendarsPseudoStates.forEach(({ id, monthName, dayName }) => {
128
+ getElementWithinCalendar(`${id}--hover`, monthName, dayName).setAttribute(
118
129
  "data-sb-pseudo-styles",
119
130
  "hover"
120
131
  )
121
- getElementWithinCalendar(`${id}--focus`, buttonDescription).setAttribute(
132
+ getElementWithinCalendar(`${id}--focus`, monthName, dayName).setAttribute(
122
133
  "data-sb-pseudo-styles",
123
134
  "focus"
124
135
  )
@@ -109,9 +109,13 @@ const StickerSheetTemplate: StickerSheetStory = {
109
109
  const applyStickerSheetStyles = (canvasElement: HTMLElement): void => {
110
110
  const canvas = within(canvasElement)
111
111
 
112
- const getElementWithinCalendar = (id: string, name: string): HTMLElement => {
112
+ const getElementWithinCalendar = (
113
+ id: string,
114
+ role: string,
115
+ name: string
116
+ ): HTMLElement => {
113
117
  const calendar = canvas.getByTestId(id)
114
- return within(calendar).getByRole("button", { name })
118
+ return within(calendar).getByRole(role, { name })
115
119
  }
116
120
 
117
121
  const todayCalendarIds = [
@@ -121,44 +125,33 @@ const applyStickerSheetStyles = (canvasElement: HTMLElement): void => {
121
125
  ]
122
126
 
123
127
  todayCalendarIds.forEach(id => {
124
- getElementWithinCalendar(id, "1st May (Sunday)").classList.add(
125
- styles.dayToday
126
- )
128
+ getElementWithinCalendar(id, "gridcell", "1").classList.add(styles.dayToday)
127
129
  })
128
130
 
129
- const calendarsHover = [
130
- { id: "id--calendar--hover", buttonDescription: "5th September (Sunday)" },
131
+ const calendarsPseudoStates = [
132
+ {
133
+ id: "id--calendar",
134
+ role: "gridcell",
135
+ name: "5",
136
+ },
131
137
  {
132
- id: "id--calendar-selected--hover",
133
- buttonDescription: "5th September (Sunday)",
138
+ id: "id--calendar-selected",
139
+ role: "gridcell",
140
+ name: "5",
134
141
  },
135
142
  {
136
- id: "id--calendar-navigation--hover",
137
- buttonDescription: "Go to previous month",
143
+ id: "id--calendar-navigation",
144
+ role: "button",
145
+ name: "Go to previous month",
138
146
  },
139
147
  ]
140
148
 
141
- calendarsHover.forEach(({ id, buttonDescription }) => {
142
- getElementWithinCalendar(id, buttonDescription).setAttribute(
149
+ calendarsPseudoStates.forEach(({ id, role, name }) => {
150
+ getElementWithinCalendar(`${id}--hover`, role, name).setAttribute(
143
151
  "data-sb-pseudo-styles",
144
152
  "hover"
145
153
  )
146
- })
147
-
148
- const calendarsFocus = [
149
- { id: "id--calendar--focus", buttonDescription: "5th September (Sunday)" },
150
- {
151
- id: "id--calendar-selected--focus",
152
- buttonDescription: "5th September (Sunday)",
153
- },
154
- {
155
- id: "id--calendar-navigation--focus",
156
- buttonDescription: "Go to previous month",
157
- },
158
- ]
159
-
160
- calendarsFocus.forEach(({ id, buttonDescription }) => {
161
- getElementWithinCalendar(id, buttonDescription).setAttribute(
154
+ getElementWithinCalendar(`${id}--focus`, role, name).setAttribute(
162
155
  "data-sb-pseudo-styles",
163
156
  "focus"
164
157
  )
@@ -1,4 +1,5 @@
1
1
  import React from "react"
2
+ import type { Locale } from "date-fns"
2
3
  import {
3
4
  DayPicker,
4
5
  DateRange,
@@ -1,4 +1,4 @@
1
- import { format } from "date-fns"
1
+ import { Locale, format } from "date-fns"
2
2
  import { DateFormat } from "../enums"
3
3
  import { isInvalidDate } from "./isInvalidDate"
4
4
 
@@ -1,4 +1,4 @@
1
- import { format } from "date-fns"
1
+ import { Locale, format } from "date-fns"
2
2
  import { DateFormat } from "../enums"
3
3
  import { DisabledDays } from "../types"
4
4
  import { isDisabledDate } from "./isDisabledDate"
@@ -1,15 +1,14 @@
1
1
  import React from "react"
2
- import { render, screen } from "@testing-library/react"
2
+ import { render, screen, within } from "@testing-library/react"
3
3
  import { CalendarSingle } from "../CalendarSingle"
4
4
  import { isSelectingDayInCalendar } from "./isSelectingDayInCalendar"
5
5
 
6
6
  describe("isSelectingDayInCalendar", () => {
7
7
  it("returns true when target is a Calendar day", () => {
8
8
  render(<CalendarSingle defaultMonth={new Date("2022-02-01")} />)
9
- const calendarDayElement = screen.getByRole("button", {
10
- name: "1st February (Tuesday)",
11
- })
12
- expect(isSelectingDayInCalendar(calendarDayElement)).toBe(true)
9
+ const targetMonth = screen.getByRole("grid", { name: "February 2022" })
10
+ const targetDay = within(targetMonth).getByRole("gridcell", { name: "1" })
11
+ expect(isSelectingDayInCalendar(targetDay)).toBe(true)
13
12
  })
14
13
 
15
14
  it("returns false when target is not a Calendar day", () => {
@@ -1,3 +1,4 @@
1
+ import type { Locale } from "date-fns"
1
2
  import { parseDateFromNumeralFormatValue } from "./parseDateFromNumeralFormatValue"
2
3
  import { parseDateFromTextFormatValue } from "./parseDateFromTextFormatValue"
3
4
 
@@ -1,4 +1,4 @@
1
- import { parse } from "date-fns"
1
+ import { Locale, parse } from "date-fns"
2
2
  import { DateFormat } from "../enums"
3
3
 
4
4
  export const parseDateFromNumeralFormatValue = (
@@ -1,4 +1,4 @@
1
- import { parse } from "date-fns"
1
+ import { Locale, parse } from "date-fns"
2
2
  import { DateFormat } from "../enums"
3
3
 
4
4
  export const parseDateFromTextFormatValue = (
@@ -1,5 +1,5 @@
1
1
  import React from "react"
2
- import { render, screen } from "@testing-library/react"
2
+ import { render, screen, within } from "@testing-library/react"
3
3
  import { format } from "date-fns"
4
4
  import { enUS } from "date-fns/locale"
5
5
  import { CalendarSingle, CalendarSingleProps } from "../CalendarSingle"
@@ -8,9 +8,9 @@ import { setFocusInCalendar } from "./setFocusInCalendar"
8
8
  const CalendarWrapper = (props: Partial<CalendarSingleProps>): JSX.Element => (
9
9
  <CalendarSingle
10
10
  id="calendar-dialog"
11
- onDayClick={jest.fn<void, [Date]>()}
11
+ onDayClick={jest.fn()}
12
12
  locale={enUS}
13
- onMount={(calendarElement): void =>
13
+ onMount={calendarElement =>
14
14
  setFocusInCalendar(calendarElement, props.selected)
15
15
  }
16
16
  {...props}
@@ -18,38 +18,43 @@ const CalendarWrapper = (props: Partial<CalendarSingleProps>): JSX.Element => (
18
18
  )
19
19
 
20
20
  const today = new Date()
21
- const todayFormatted = format(today, "do MMMM (eeee)") // e.g 6th June (Monday)
21
+ const todayMonth = format(today, "MMMM yyyy") // e.g "June 2023"
22
+ const todayDay = today.getDate().toString() // e.g "6"
22
23
 
23
24
  describe("setFocusInCalendar", () => {
24
25
  it("should focus on today when no date is selected", () => {
25
26
  render(<CalendarWrapper />)
26
27
 
27
- const dayToFocus = screen.getByRole("button", { name: todayFormatted })
28
- expect(dayToFocus).toHaveFocus()
28
+ const targetMonth = screen.getByRole("grid", { name: todayMonth })
29
+ const targetDay = within(targetMonth).getByRole("gridcell", {
30
+ name: todayDay,
31
+ })
32
+ expect(targetDay).toHaveFocus()
29
33
  })
30
34
 
31
35
  it("should focus on the selected day", () => {
32
36
  render(<CalendarWrapper selected={new Date("2022-08-15")} />)
33
37
 
34
- const dayToFocus = screen.getByRole("button", {
35
- name: "15th August (Monday)",
36
- })
37
- expect(dayToFocus).toHaveFocus()
38
+ const targetMonth = screen.getByRole("grid", { name: "August 2022" })
39
+ const targetDay = within(targetMonth).getByRole("gridcell", { name: "15" })
40
+ expect(targetDay).toHaveFocus()
38
41
  })
39
42
 
40
43
  it("should focus on today when selected date is invalid", () => {
41
44
  render(<CalendarWrapper selected={new Date("potato")} />)
42
45
 
43
- const dayToFocus = screen.getByRole("button", { name: todayFormatted })
44
- expect(dayToFocus).toHaveFocus()
46
+ const targetMonth = screen.getByRole("grid", { name: todayMonth })
47
+ const targetDay = within(targetMonth).getByRole("gridcell", {
48
+ name: todayDay,
49
+ })
50
+ expect(targetDay).toHaveFocus()
45
51
  })
46
52
 
47
53
  it("should focus on the first of the month when there is no selected day nor in the current month", () => {
48
54
  render(<CalendarWrapper defaultMonth={new Date("2022-05-01")} />)
49
55
 
50
- const dayToFocus = screen.getByRole("button", {
51
- name: "1st May (Sunday)",
52
- })
53
- expect(dayToFocus).toHaveFocus()
56
+ const targetMonth = screen.getByRole("grid", { name: "May 2022" })
57
+ const targetDay = within(targetMonth).getByRole("gridcell", { name: "1" })
58
+ expect(targetDay).toHaveFocus()
54
59
  })
55
60
  })
@@ -1,5 +1,6 @@
1
1
  import React from "react"
2
2
  import { useIntl } from "@cultureamp/i18n-react-intl"
3
+ import type { Locale } from "date-fns"
3
4
  import { LabelledMessage } from "~components/LabelledMessage"
4
5
  import { formatDescriptionInputFormat } from "./utils/formatDescriptionInputFormat"
5
6
  import styles from "./DateInputDescription.module.scss"
@@ -1,2 +1,4 @@
1
+ import type { Locale } from "date-fns"
2
+
1
3
  export const formatDescriptionInputFormat = (locale: Locale): string =>
2
4
  locale.formatLong?.date({ width: "short" }).toLowerCase()
@@ -1,5 +1,5 @@
1
1
  import React, { useEffect, useState } from "react"
2
- import { render, screen, waitFor } from "@testing-library/react"
2
+ import { render, screen, waitFor, within } from "@testing-library/react"
3
3
  import userEvent from "@testing-library/user-event"
4
4
  import { DatePicker } from "./DatePicker"
5
5
  import { ValidationResponse } from "./types"
@@ -166,9 +166,8 @@ describe("<DatePicker /> - Focus element", () => {
166
166
  expect(screen.queryByRole("dialog")).toBeVisible()
167
167
  })
168
168
 
169
- const dateToSelect = screen.getByRole("button", {
170
- name: "6th March (Sunday)",
171
- })
169
+ const month = screen.getByRole("grid", { name: "March 2022" })
170
+ const dateToSelect = within(month).getByRole("gridcell", { name: "6" })
172
171
  await user.click(dateToSelect)
173
172
 
174
173
  const input = screen.getByLabelText("Input label")
@@ -193,9 +192,8 @@ describe("<DatePicker /> - Focus element", () => {
193
192
  expect(screen.queryByRole("dialog")).toBeVisible()
194
193
  })
195
194
 
196
- const selectedDate = screen.getByRole("button", {
197
- name: "1st March (Tuesday)",
198
- })
195
+ const month = screen.getByRole("grid", { name: "March 2022" })
196
+ const selectedDate = within(month).getByRole("gridcell", { name: "1" })
199
197
  expect(selectedDate).toHaveFocus()
200
198
  })
201
199
 
@@ -233,9 +231,8 @@ describe("<DatePicker /> - Focus element", () => {
233
231
  expect(screen.getByRole("dialog")).toBeVisible()
234
232
  })
235
233
 
236
- const selectedDate = screen.getByRole("button", {
237
- name: "1st March (Tuesday)",
238
- })
234
+ const month = screen.getByRole("grid", { name: "March 2022" })
235
+ const selectedDate = within(month).getByRole("gridcell", { name: "1" })
239
236
  expect(selectedDate).toHaveFocus()
240
237
  })
241
238
 
@@ -278,9 +275,8 @@ describe("<DatePicker /> - Focus element", () => {
278
275
  expect(screen.getByRole("dialog")).toBeVisible()
279
276
  })
280
277
 
281
- const selectedDate = screen.getByRole("button", {
282
- name: "1st March (Tuesday)",
283
- })
278
+ const month = screen.getByRole("grid", { name: "March 2022" })
279
+ const selectedDate = within(month).getByRole("gridcell", { name: "1" })
284
280
  expect(selectedDate).toHaveFocus()
285
281
  })
286
282
 
@@ -418,9 +414,9 @@ describe("<DatePicker /> - Validation", () => {
418
414
  await waitFor(() => {
419
415
  expect(screen.queryByRole("dialog")).toBeVisible()
420
416
  })
421
- const dateToSelect = screen.getByRole("button", {
422
- name: "6th March (Sunday)",
423
- })
417
+
418
+ const month = screen.getByRole("grid", { name: "March 2022" })
419
+ const dateToSelect = within(month).getByRole("gridcell", { name: "6" })
424
420
  await user.click(dateToSelect)
425
421
  await waitFor(() => {
426
422
  expect(onValidate).toBeCalledTimes(1)
@@ -1,5 +1,6 @@
1
1
  import React, { useId } from "react"
2
2
  import classnames from "classnames"
3
+ import type { Locale } from "date-fns"
3
4
  import { enAU } from "date-fns/locale"
4
5
  import {
5
6
  DateInputDescription,
@@ -1,3 +1,4 @@
1
+ import type { Locale } from "date-fns"
1
2
  import { enAU, enUS } from "date-fns/locale"
2
3
  import { StringSuggestions } from "~types/StringSuggestions"
3
4
 
@@ -25,13 +25,15 @@ const FilterWrapper = (customProps?: Partial<FilterProps>): JSX.Element => {
25
25
  describe("<Filter />", () => {
26
26
  it("does not show content initially", () => {
27
27
  render(<FilterWrapper />)
28
- expect(screen.queryByRole("dialog")).not.toBeInTheDocument()
28
+ expect(
29
+ screen.queryByRole("dialog", { name: "Label" })
30
+ ).not.toBeInTheDocument()
29
31
  })
30
32
 
31
33
  it("shows content when isOpen is true", async () => {
32
34
  render(<FilterWrapper isOpen />)
33
35
  await waitFor(() => {
34
- expect(screen.getByRole("dialog")).toBeVisible()
36
+ expect(screen.getByRole("dialog", { name: "Label" })).toBeVisible()
35
37
  expect(screen.getByText("Filter Contents")).toBeVisible()
36
38
  })
37
39
  })
@@ -41,7 +43,7 @@ describe("<Filter />", () => {
41
43
  const filterButton = screen.getByRole("button", { name: "Label" })
42
44
  await user.click(filterButton)
43
45
  await waitFor(() => {
44
- expect(screen.getByRole("dialog")).toBeVisible()
46
+ expect(screen.getByRole("dialog", { name: "Label" })).toBeVisible()
45
47
  expect(screen.getByText("Filter Contents")).toBeVisible()
46
48
  })
47
49
  })
@@ -54,7 +56,7 @@ describe("<Filter />", () => {
54
56
  await user.keyboard("{Enter}")
55
57
 
56
58
  await waitFor(() => {
57
- expect(screen.getByRole("dialog")).toBeVisible()
59
+ expect(screen.getByRole("dialog", { name: "Label" })).toBeVisible()
58
60
  expect(screen.getByText("Filter Contents")).toBeVisible()
59
61
  })
60
62
  })
@@ -1,4 +1,10 @@
1
- import React, { HTMLAttributes, useEffect, useRef, useState } from "react"
1
+ import React, {
2
+ HTMLAttributes,
3
+ useEffect,
4
+ useId,
5
+ useRef,
6
+ useState,
7
+ } from "react"
2
8
  import { FocusOn } from "react-focus-on"
3
9
  import { OverrideClassName } from "~types/OverrideClassName"
4
10
  import { FilterPopover } from "./subcomponents/FilterPopover"
@@ -9,6 +15,7 @@ export type FilterProps = {
9
15
  isOpen: boolean
10
16
  setIsOpen: (isOpen: boolean) => void
11
17
  renderTrigger: (triggerProps: {
18
+ id: string
12
19
  onClick: () => void
13
20
  isOpen: boolean
14
21
  }) => JSX.Element & { ref?: React.RefObject<FilterTriggerRef> }
@@ -24,9 +31,11 @@ export const Filter = ({
24
31
  onMount,
25
32
  ...restProps
26
33
  }: FilterProps): JSX.Element => {
34
+ const triggerId = useId()
27
35
  const [isRefLoaded, setIsRefLoaded] = useState<boolean>(false)
28
36
 
29
37
  const trigger = renderTrigger({
38
+ id: triggerId,
30
39
  onClick: (): void => setIsOpen(!isOpen),
31
40
  isOpen,
32
41
  })
@@ -59,6 +68,7 @@ export const Filter = ({
59
68
  referenceElement={
60
69
  filterButtonRef.current?.triggerRef?.current || null
61
70
  }
71
+ aria-labelledby={trigger.props.id}
62
72
  >
63
73
  {children}
64
74
  </FilterPopover>
@@ -1,5 +1,5 @@
1
1
  import React, { useEffect, useState } from "react"
2
- import { render, waitFor, within } from "@testing-library/react"
2
+ import { render, screen, waitFor, within } from "@testing-library/react"
3
3
  import userEvent from "@testing-library/user-event"
4
4
  import { FilterMultiSelect } from "../index"
5
5
  import { FilterBar, FilterBarProps } from "./FilterBar"
@@ -149,6 +149,17 @@ describe("<FilterBar />", () => {
149
149
  expect(filters[2]).toHaveTextContent("Ice Level")
150
150
  })
151
151
 
152
+ it("retains Filter accessibility", async () => {
153
+ render(<FilterBarWrapper filters={simpleFilters} />)
154
+
155
+ const filterButton = screen.getByRole("button", { name: "Flavour" })
156
+ await user.click(filterButton)
157
+
158
+ await waitFor(() => {
159
+ expect(screen.getByRole("dialog", { name: "Flavour" })).toBeVisible()
160
+ })
161
+ })
162
+
152
163
  describe("Removable filters", () => {
153
164
  it("shows inactive filters in the Add Filters menu only", async () => {
154
165
  const { getByRole, queryByText } = render(
@@ -29,7 +29,7 @@ const FilterBarButtonWrapper = (
29
29
  {Object.values(filters).map(({ id, name }) => (
30
30
  <FilterBarButton
31
31
  key={id}
32
- id={id}
32
+ filterId={id}
33
33
  label={name}
34
34
  isRemovable={false}
35
35
  {...props}
@@ -8,21 +8,21 @@ import {
8
8
  } from "~components/Filter/FilterButton"
9
9
 
10
10
  export type FilterBarButtonProps = FilterButtonProps & {
11
- id: string
11
+ filterId: string
12
12
  isRemovable: boolean | undefined
13
13
  }
14
14
 
15
15
  export const FilterBarButton = forwardRef<
16
16
  FilterTriggerRef,
17
17
  FilterBarButtonProps
18
- >(({ id, isRemovable = false, ...props }, ref): JSX.Element => {
18
+ >(({ filterId, isRemovable = false, ...props }, ref): JSX.Element => {
19
19
  const { hideFilter } = useFilterBarContext()
20
20
 
21
21
  return isRemovable ? (
22
22
  <FilterButtonRemovable
23
23
  ref={ref}
24
24
  triggerButtonProps={props}
25
- removeButtonProps={{ onClick: () => hideFilter(id) }}
25
+ removeButtonProps={{ onClick: () => hideFilter(filterId) }}
26
26
  />
27
27
  ) : (
28
28
  <FilterButton ref={ref} {...props} />
@@ -1,5 +1,5 @@
1
1
  import React, { useState } from "react"
2
- import { render, waitFor } from "@testing-library/react"
2
+ import { render, screen, waitFor, within } from "@testing-library/react"
3
3
  import userEvent from "@testing-library/user-event"
4
4
  import {
5
5
  FilterAttributes,
@@ -113,53 +113,48 @@ describe("<FilterBarDatePicker />", () => {
113
113
  })
114
114
 
115
115
  it("updates the selected value in the trigger button when selecting a date", async () => {
116
- const { getByRole } = render(
116
+ render(
117
117
  <FilterBarDatePickerWrapper
118
118
  defaultValues={{ drank: new Date("2023-06-06") }}
119
119
  />
120
120
  )
121
- const triggerButton = getByRole("button", {
121
+ const triggerButton = screen.getByRole("button", {
122
122
  name: "Drank : 6 Jun 2023",
123
123
  })
124
124
 
125
125
  await user.click(triggerButton)
126
126
 
127
127
  await waitFor(() => {
128
- const dialog = getByRole("dialog")
128
+ const dialog = screen.getByRole("dialog")
129
129
  expect(dialog).toBeInTheDocument()
130
130
  })
131
131
 
132
- await user.click(
133
- getByRole("button", {
134
- name: "7th June (Wednesday)",
135
- })
136
- )
132
+ const targetMonth = screen.getByRole("grid", { name: "June 2023" })
133
+ const targetDay = within(targetMonth).getByRole("gridcell", { name: "7" })
134
+
135
+ await user.click(targetDay)
137
136
 
138
137
  await waitFor(() => {
139
138
  expect(
140
- getByRole("button", { name: "Drank : 7 Jun 2023" })
139
+ screen.getByRole("button", { name: "Drank : 7 Jun 2023" })
141
140
  ).toBeInTheDocument()
142
141
  })
143
142
  })
144
143
 
145
144
  it("allows calling additional functions on selection change", async () => {
146
- const onChange = jest.fn<void, [Date | undefined]>()
147
- const { getByRole } = render(
148
- <FilterBarDatePickerWrapper onDateChange={onChange} />
149
- )
150
- const triggerButton = getByRole("button", { name: "Drank" })
145
+ const onChange = jest.fn()
146
+ render(<FilterBarDatePickerWrapper onDateChange={onChange} />)
151
147
 
148
+ const triggerButton = screen.getByRole("button", { name: "Drank" })
152
149
  await user.click(triggerButton)
150
+
153
151
  await waitFor(() => {
154
- const dialog = getByRole("dialog")
155
- expect(dialog).toBeInTheDocument()
152
+ expect(screen.getByRole("dialog")).toBeInTheDocument()
156
153
  })
157
154
 
158
- await user.click(
159
- getByRole("button", {
160
- name: "7th June (Wednesday)",
161
- })
162
- )
155
+ const targetMonth = screen.getByRole("grid", { name: "June 2023" })
156
+ const targetDay = within(targetMonth).getByRole("gridcell", { name: "7" })
157
+ await user.click(targetDay)
163
158
 
164
159
  await waitFor(() => {
165
160
  expect(onChange.mock.calls).toEqual([[new Date("2023-06-07")]])
@@ -45,7 +45,7 @@ export const FilterBarDatePicker = ({
45
45
  renderTrigger={(triggerProps): JSX.Element => (
46
46
  <FilterBarButton
47
47
  {...triggerProps}
48
- id={id}
48
+ filterId={id}
49
49
  isRemovable={filterState.isRemovable}
50
50
  />
51
51
  )}
@@ -1,5 +1,5 @@
1
1
  import React, { useState } from "react"
2
- import { render, waitFor } from "@testing-library/react"
2
+ import { render, screen, waitFor, within } from "@testing-library/react"
3
3
  import userEvent from "@testing-library/user-event"
4
4
  import {
5
5
  FilterAttributes,
@@ -134,9 +134,8 @@ describe("<FilterBarDateRangePicker />", () => {
134
134
  expect(getByText("May 2022")).toBeVisible()
135
135
  })
136
136
 
137
- const targetDay = getByRole("button", {
138
- name: "23rd June (Thursday)",
139
- })
137
+ const targetMonth = screen.getByRole("grid", { name: "June 2022" })
138
+ const targetDay = within(targetMonth).getByRole("gridcell", { name: "23" })
140
139
  await user.click(targetDay)
141
140
  await user.click(document.body) // Exit the focus lock
142
141
 
@@ -169,10 +168,10 @@ describe("<FilterBarDateRangePicker />", () => {
169
168
  expect(getByText("May 2022")).toBeVisible()
170
169
  })
171
170
 
172
- const targetDay = getByRole("button", {
173
- name: "23rd June (Thursday)",
174
- })
171
+ const targetMonth = screen.getByRole("grid", { name: "June 2022" })
172
+ const targetDay = within(targetMonth).getByRole("gridcell", { name: "23" })
175
173
  await user.click(targetDay)
174
+
176
175
  await waitFor(() => {
177
176
  expect(onChange).toHaveBeenCalledWith({
178
177
  from: new Date("2022-05-01"),