@nypl/design-system-react-components 0.25.0 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/components/Accordion/Accordion.d.ts +14 -14
  3. package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +11 -14
  4. package/dist/components/Breadcrumbs/BreadcrumbsTypes.d.ts +6 -0
  5. package/dist/components/Button/ButtonTypes.d.ts +2 -1
  6. package/dist/components/Card/Card.d.ts +1 -1
  7. package/dist/components/Card/CardTypes.d.ts +2 -2
  8. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +43 -0
  9. package/dist/components/CheckboxGroup/CheckboxGroupLayoutTypes.d.ts +4 -0
  10. package/dist/components/DatePicker/DatePicker.d.ts +3 -3
  11. package/dist/components/Form/Form.d.ts +13 -8
  12. package/dist/components/Form/FormTypes.d.ts +2 -8
  13. package/dist/components/Grid/GridTypes.d.ts +9 -0
  14. package/dist/components/Grid/SimpleGrid.d.ts +14 -0
  15. package/dist/components/Heading/Heading.d.ts +4 -4
  16. package/dist/components/Hero/Hero.d.ts +19 -14
  17. package/dist/components/Hero/HeroTypes.d.ts +10 -5
  18. package/dist/components/Icons/Icon.d.ts +13 -16
  19. package/dist/components/Icons/IconTypes.d.ts +78 -64
  20. package/dist/components/Label/Label.d.ts +5 -17
  21. package/dist/components/Link/Link.d.ts +8 -12
  22. package/dist/components/SearchBar/SearchBar.d.ts +45 -27
  23. package/dist/components/Select/Select.d.ts +32 -35
  24. package/dist/components/Select/SelectTypes.d.ts +4 -0
  25. package/dist/components/SkeletonLoader/SkeletonLoader.d.ts +1 -1
  26. package/dist/components/SkeletonLoader/SkeletonLoaderTypes.d.ts +2 -2
  27. package/dist/components/StatusBadge/StatusBadge.d.ts +8 -6
  28. package/dist/components/StatusBadge/StatusBadgeTypes.d.ts +5 -0
  29. package/dist/components/Template/Template.d.ts +91 -0
  30. package/dist/components/Text/Text.d.ts +16 -0
  31. package/dist/components/Text/TextTypes.d.ts +6 -0
  32. package/dist/components/TextInput/TextInput.d.ts +32 -31
  33. package/dist/components/TextInput/TextInputTypes.d.ts +5 -0
  34. package/dist/design-system-react-components.cjs.development.js +2597 -1170
  35. package/dist/design-system-react-components.cjs.development.js.map +1 -1
  36. package/dist/design-system-react-components.cjs.production.min.js +1 -1
  37. package/dist/design-system-react-components.cjs.production.min.js.map +1 -1
  38. package/dist/design-system-react-components.esm.js +2580 -1173
  39. package/dist/design-system-react-components.esm.js.map +1 -1
  40. package/dist/index.d.ts +8 -1
  41. package/dist/styles.css +1 -1
  42. package/dist/theme/components/accordion.d.ts +25 -0
  43. package/dist/theme/components/breadcrumb.d.ts +90 -0
  44. package/dist/theme/components/button.d.ts +17 -7
  45. package/dist/theme/components/checkbox.d.ts +7 -7
  46. package/dist/theme/components/customCheckboxGroup.d.ts +18 -0
  47. package/dist/theme/components/customRadioGroup.d.ts +4 -3
  48. package/dist/theme/components/global.d.ts +55 -0
  49. package/dist/theme/components/globalMixins.d.ts +15 -0
  50. package/dist/theme/components/heading.d.ts +50 -20
  51. package/dist/theme/components/hero.d.ts +492 -0
  52. package/dist/theme/components/icon.d.ts +13 -0
  53. package/dist/theme/components/label.d.ts +16 -0
  54. package/dist/theme/components/link.d.ts +45 -0
  55. package/dist/theme/components/radio.d.ts +8 -7
  56. package/dist/theme/components/searchBar.d.ts +20 -0
  57. package/dist/theme/components/select.d.ts +58 -0
  58. package/dist/theme/components/statusBadge.d.ts +25 -0
  59. package/dist/theme/components/tabs.d.ts +9 -9
  60. package/dist/theme/components/template.d.ts +105 -0
  61. package/dist/theme/components/text.d.ts +20 -0
  62. package/dist/theme/components/textInput.d.ts +105 -0
  63. package/dist/theme/foundations/global.d.ts +3 -0
  64. package/dist/theme/foundations/shadows.d.ts +4 -0
  65. package/dist/utils/utils.d.ts +6 -0
  66. package/package.json +3 -2
  67. package/src/components/Accordion/Accordion.stories.mdx +227 -33
  68. package/src/components/Accordion/Accordion.test.tsx +135 -19
  69. package/src/components/Accordion/Accordion.tsx +81 -56
  70. package/src/components/Autosuggest/Autosuggest.stories.mdx +1 -1
  71. package/src/components/Autosuggest/Autosuggest.stories.tsx +1 -1
  72. package/src/components/Autosuggest/_Autosuggest.scss +2 -2
  73. package/src/components/Breadcrumbs/Breadcrumbs.stories.mdx +46 -52
  74. package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +31 -25
  75. package/src/components/Breadcrumbs/Breadcrumbs.tsx +71 -73
  76. package/src/components/Breadcrumbs/BreadcrumbsTypes.tsx +6 -0
  77. package/src/components/Breadcrumbs/__snapshots__/Breadcrumbs.test.tsx.snap +100 -0
  78. package/src/components/Button/Button.stories.mdx +31 -27
  79. package/src/components/Button/Button.test.tsx +17 -5
  80. package/src/components/Button/ButtonTypes.tsx +1 -0
  81. package/src/components/Button/_Button.scss +3 -27
  82. package/src/components/Button/__snapshots__/Button.test.tsx.snap +11 -0
  83. package/src/components/Card/Card.stories.mdx +24 -20
  84. package/src/components/Card/Card.test.tsx +13 -19
  85. package/src/components/Card/Card.tsx +1 -1
  86. package/src/components/Card/CardTypes.tsx +2 -2
  87. package/src/components/Card/_Card.scss +1 -1
  88. package/src/components/CardEdition/CardEdition.stories.tsx +11 -6
  89. package/src/components/CardEdition/CardEdition.test.tsx +23 -31
  90. package/src/components/CardEdition/_CardEdition.scss +2 -2
  91. package/src/components/Chakra/Center.stories.mdx +31 -14
  92. package/src/components/Chakra/Grid.stories.mdx +79 -0
  93. package/src/components/Chakra/Stack.stories.mdx +4 -4
  94. package/src/components/Checkbox/Checkbox.tsx +9 -12
  95. package/src/components/Checkbox/__snapshots__/Checkbox.test.tsx.snap +2 -5
  96. package/src/components/CheckboxGroup/CheckboxGroup.stories.mdx +249 -0
  97. package/src/components/CheckboxGroup/CheckboxGroup.test.tsx +345 -0
  98. package/src/components/CheckboxGroup/CheckboxGroup.tsx +148 -0
  99. package/src/components/CheckboxGroup/CheckboxGroupLayoutTypes.tsx +4 -0
  100. package/src/components/CheckboxGroup/__snapshots__/CheckboxGroup.test.tsx.snap +1360 -0
  101. package/src/components/DatePicker/DatePicker.test.tsx +4 -4
  102. package/src/components/DatePicker/DatePicker.tsx +13 -13
  103. package/src/components/DatePicker/_DatePicker.scss +1 -0
  104. package/src/components/Form/Form.stories.mdx +46 -21
  105. package/src/components/Form/Form.test.tsx +58 -45
  106. package/src/components/Form/Form.tsx +49 -21
  107. package/src/components/Form/FormTypes.tsx +3 -8
  108. package/src/components/Form/__snapshots__/Form.test.tsx.snap +24 -14
  109. package/src/components/Grid/GridTypes.tsx +9 -0
  110. package/src/components/Grid/SimpleGrid.stories.mdx +275 -0
  111. package/src/components/Grid/SimpleGrid.test.tsx +66 -0
  112. package/src/components/Grid/SimpleGrid.tsx +37 -0
  113. package/src/components/Grid/__snapshots__/SimpleGrid.test.tsx.snap +8 -0
  114. package/src/components/Heading/Heading.stories.mdx +1 -0
  115. package/src/components/Heading/Heading.tsx +12 -6
  116. package/src/components/HelperErrorText/_HelperErrorText.scss +1 -1
  117. package/src/components/Hero/Hero.stories.mdx +188 -121
  118. package/src/components/Hero/Hero.test.tsx +537 -107
  119. package/src/components/Hero/Hero.tsx +79 -92
  120. package/src/components/Hero/HeroTypes.tsx +17 -5
  121. package/src/components/Hero/__snapshots__/Hero.test.tsx.snap +307 -0
  122. package/src/components/HorizontalRule/_HorizontalRule.scss +1 -1
  123. package/src/components/Icons/Icon.stories.mdx +83 -74
  124. package/src/components/Icons/Icon.test.tsx +30 -22
  125. package/src/components/Icons/Icon.tsx +63 -61
  126. package/src/components/Icons/IconTypes.tsx +80 -64
  127. package/src/components/Input/_Input.scss +2 -2
  128. package/src/components/Label/Label.stories.mdx +28 -7
  129. package/src/components/Label/Label.test.tsx +43 -12
  130. package/src/components/Label/Label.tsx +21 -34
  131. package/src/components/Label/__snapshots__/Label.test.tsx.snap +41 -0
  132. package/src/components/Link/Link.stories.mdx +41 -41
  133. package/src/components/Link/Link.test.tsx +33 -44
  134. package/src/components/Link/Link.tsx +114 -100
  135. package/src/components/List/List.stories.mdx +0 -2
  136. package/src/components/List/List.stories.tsx +5 -5
  137. package/src/components/List/_List.scss +3 -3
  138. package/src/components/Modal/_Modal.scss +1 -1
  139. package/src/components/Notification/Notification.stories.mdx +12 -1
  140. package/src/components/Notification/Notification.test.tsx +3 -16
  141. package/src/components/Notification/Notification.tsx +9 -10
  142. package/src/components/Notification/_Notification.scss +4 -4
  143. package/src/components/Pagination/Pagination.test.tsx +16 -10
  144. package/src/components/RadioGroup/RadioGroup.stories.mdx +1 -1
  145. package/src/components/RadioGroup/RadioGroup.tsx +2 -10
  146. package/src/components/SearchBar/SearchBar.Test.tsx +151 -16
  147. package/src/components/SearchBar/SearchBar.stories.mdx +189 -219
  148. package/src/components/SearchBar/SearchBar.tsx +151 -46
  149. package/src/components/Select/Select.stories.mdx +188 -170
  150. package/src/components/Select/Select.test.tsx +125 -380
  151. package/src/components/Select/Select.tsx +118 -165
  152. package/src/components/Select/SelectTypes.tsx +4 -0
  153. package/src/components/SkeletonLoader/SkeletonLoader.stories.mdx +13 -25
  154. package/src/components/SkeletonLoader/SkeletonLoader.test.tsx +7 -7
  155. package/src/components/SkeletonLoader/SkeletonLoader.tsx +4 -2
  156. package/src/components/SkeletonLoader/SkeletonLoaderTypes.tsx +2 -2
  157. package/src/components/SkeletonLoader/_SkeletonLoader.scss +3 -3
  158. package/src/components/StatusBadge/StatusBadge.stories.mdx +91 -0
  159. package/src/components/StatusBadge/StatusBadge.test.tsx +35 -7
  160. package/src/components/StatusBadge/StatusBadge.tsx +24 -25
  161. package/src/components/StatusBadge/StatusBadgeTypes.tsx +5 -0
  162. package/src/components/StatusBadge/__snapshots__/StatusBadge.test.tsx.snap +28 -0
  163. package/src/components/StyleGuide/Bidirectionality.stories.mdx +16 -16
  164. package/src/components/StyleGuide/Buttons.stories.mdx +15 -15
  165. package/src/components/StyleGuide/Colors.stories.mdx +336 -0
  166. package/src/components/StyleGuide/Iconography.stories.mdx +88 -90
  167. package/src/components/StyleGuide/UIDocCard.tsx +1 -1
  168. package/src/components/Tabs/Tabs.tsx +7 -9
  169. package/src/components/Template/Template.stories.mdx +574 -0
  170. package/src/components/Template/Template.test.tsx +124 -0
  171. package/src/components/Template/Template.tsx +226 -0
  172. package/src/components/Text/Text.stories.mdx +70 -0
  173. package/src/components/Text/Text.test.tsx +63 -0
  174. package/src/components/Text/Text.tsx +55 -0
  175. package/src/components/Text/TextTypes.tsx +6 -0
  176. package/src/components/Text/__snapshots__/Text.test.tsx.snap +33 -0
  177. package/src/components/TextInput/TextInput.stories.mdx +89 -90
  178. package/src/components/TextInput/TextInput.test.tsx +65 -86
  179. package/src/components/TextInput/TextInput.tsx +101 -95
  180. package/src/components/TextInput/TextInputTypes.tsx +6 -0
  181. package/src/components/VideoPlayer/_VideoPlayer.scss +1 -1
  182. package/src/docs/Chakra.stories.mdx +4 -4
  183. package/src/docs/Intro.stories.mdx +15 -13
  184. package/src/index.ts +20 -0
  185. package/src/styles/01-colors/_colors-brand.scss +6 -0
  186. package/src/styles/01-colors/_colors-utility.scss +14 -12
  187. package/src/styles/base/_04-base.scss +2 -1
  188. package/src/styles/base/_place-holder.scss +1 -1
  189. package/src/styles.scss +10 -12
  190. package/src/theme/components/accordion.ts +30 -0
  191. package/src/theme/components/breadcrumb.ts +77 -0
  192. package/src/theme/components/button.ts +77 -63
  193. package/src/theme/components/checkbox.ts +15 -27
  194. package/src/theme/components/customCheckboxGroup.ts +12 -0
  195. package/src/theme/components/customRadioGroup.ts +4 -10
  196. package/src/theme/components/global.ts +71 -0
  197. package/src/theme/components/globalMixins.ts +16 -0
  198. package/src/theme/components/heading.ts +15 -8
  199. package/src/theme/components/hero.ts +239 -0
  200. package/src/theme/components/icon.ts +79 -0
  201. package/src/theme/components/label.ts +17 -0
  202. package/src/theme/components/link.ts +47 -0
  203. package/src/theme/components/radio.ts +20 -31
  204. package/src/theme/components/searchBar.ts +21 -0
  205. package/src/theme/components/select.ts +50 -0
  206. package/src/theme/components/statusBadge.ts +27 -0
  207. package/src/theme/components/tabs.ts +72 -69
  208. package/src/theme/components/template.ts +114 -0
  209. package/src/theme/components/text.ts +31 -0
  210. package/src/theme/components/textInput.ts +61 -0
  211. package/src/theme/foundations/colors.ts +29 -13
  212. package/src/theme/foundations/global.ts +3 -0
  213. package/src/theme/foundations/shadows.ts +5 -0
  214. package/src/theme/index.ts +37 -7
  215. package/src/utils/componentCategories.ts +8 -2
  216. package/src/utils/utils.ts +13 -0
  217. package/dist/components/Accordion/Accordion.stories.d.ts +0 -6
  218. package/dist/components/StatusBadge/StatusBadge.stories.d.ts +0 -8
  219. package/dist/components/StyleGuide/Colors.stories.d.ts +0 -25
  220. package/dist/components/Template/Template.stories.d.ts +0 -30
  221. package/src/components/Accordion/Accordion.stories.tsx +0 -66
  222. package/src/components/Accordion/_Accordion.scss +0 -81
  223. package/src/components/Breadcrumbs/_Breadcrumbs.scss +0 -97
  224. package/src/components/Form/_Form.scss +0 -67
  225. package/src/components/Hero/_Hero.scss +0 -256
  226. package/src/components/Icons/_Icons.scss +0 -116
  227. package/src/components/Label/_Label.scss +0 -22
  228. package/src/components/Link/_Link.scss +0 -73
  229. package/src/components/SearchBar/_SearchBar.scss +0 -16
  230. package/src/components/Select/_Select.scss +0 -82
  231. package/src/components/StatusBadge/StatusBadge.stories.tsx +0 -34
  232. package/src/components/StatusBadge/_StatusBadge.scss +0 -23
  233. package/src/components/StyleGuide/Colors.stories.tsx +0 -289
  234. package/src/components/Template/Template.stories.tsx +0 -86
  235. package/src/components/Template/_Template.scss +0 -63
  236. package/src/components/TextInput/_TextInput.scss +0 -59
@@ -2,16 +2,17 @@ import {
2
2
  Meta,
3
3
  Story,
4
4
  ArgsTable,
5
- Preview,
5
+ Canvas,
6
6
  Description,
7
7
  } from "@storybook/addon-docs/blocks";
8
8
  import Accordion from "./Accordion";
9
9
  import { withDesign } from "storybook-addon-designs";
10
- import * as stories from "./Accordion.stories.tsx";
11
10
  import { listRenderer as ListStory } from "../List/List.stories.tsx";
12
11
  import { ListTypes } from "../List/ListTypes";
12
+ import Card, { CardHeading, CardContent } from "../Card/Card";
13
+ import { CardImageRatios, CardLayouts } from "../Card/CardTypes";
14
+ import { HeadingLevels } from "../Heading/HeadingTypes";
13
15
  import { Source } from "@storybook/addon-docs/blocks";
14
- import dedent from "ts-dedent";
15
16
  import ReactDOMServer from "react-dom/server";
16
17
  import { getCategory } from "../../utils/componentCategories";
17
18
 
@@ -28,7 +29,8 @@ import { getCategory } from "../../utils/componentCategories";
28
29
  jest: ["Accordion.test.tsx"],
29
30
  }}
30
31
  argTypes={{
31
- children: { table: { disable: true } },
32
+ contentData: { table: { disable: true } },
33
+ id: { table: { disable: true } },
32
34
  }}
33
35
  />
34
36
 
@@ -37,52 +39,244 @@ import { getCategory } from "../../utils/componentCategories";
37
39
  | Component Version | DS Version |
38
40
  | ----------------- | ---------- |
39
41
  | Added | `0.1.0` |
40
- | Latest | `0.21.1` |
42
+ | Latest | `0.25.1` |
41
43
 
42
44
  <Description of={Accordion} />
43
45
 
44
- The Accordion component pushes existing content on the page down. The
45
- implementation is built using basic input/label DOM elements and CSS.
46
- Therefore, make sure to pass the `inputId` prop to associate the label with
47
- the input element. If multiple Accordion components are used on a page, make
48
- sure that each `inputId` is unique.
46
+ The `Accordion` component displays a list of high-level options that can
47
+ expand/collapse to reveal associated sections of content. This component pushes
48
+ existing content on the page down. Each accordion item is self contained but
49
+ when multiple are rendered together, they render in a "FAQ" style. When multiple
50
+ accordions are rendered together, they can each open and close independent of
51
+ each other.
49
52
 
50
- <Preview withToolbar>
53
+ The only way to render an `Accordion` component is to pass in an array of objects
54
+ with `label` and `panel` properties for each accordion item. Note that you can
55
+ pass in a string or DOM elements into the `panel` property in each object. This
56
+ approach is needed because, internally, we deal with the logic to render the
57
+ necessary icon, Chakra components, and styles.
58
+
59
+ <Canvas withToolbar>
51
60
  <Story
52
61
  name="Basic"
53
62
  args={{
54
- accordionLabel: "Click to expand",
55
- children: <ListStory type={ListTypes.Unordered} />,
56
- inputId: "accordionBtn",
63
+ isDefaultOpen: false,
57
64
  }}
58
65
  >
59
- {(args) => <Accordion {...args} />}
66
+ {(args) => (
67
+ <Accordion
68
+ {...args}
69
+ contentData={[
70
+ {
71
+ label: "Tom Nook",
72
+ panel: (
73
+ <Card
74
+ layout={CardLayouts.Row}
75
+ center
76
+ imageSrc="https://play.nintendo.com/images/AC_Tom_FRYtwIN.17345b1513ac044897cfc243542899dce541e8dc.9afde10b.png"
77
+ imageAlt="Alt text"
78
+ imageAspectRatio={CardImageRatios.TwoByOne}
79
+ >
80
+ <CardHeading level={HeadingLevels.Four} id="heading1">
81
+ Tom Nook
82
+ </CardHeading>
83
+ <CardContent>
84
+ Tom Nook, <b>known in Japan as Tanukichi</b>, is a fictional
85
+ character in the Animal Crossing series who operates the
86
+ village store.
87
+ </CardContent>
88
+ </Card>
89
+ ),
90
+ },
91
+ ]}
92
+ />
93
+ )}
60
94
  </Story>
61
- </Preview>
95
+ </Canvas>
96
+
97
+ ```jsx
98
+ const contentData = [
99
+ {
100
+ label: "Tom Nook",
101
+ panel: (
102
+ <Card
103
+ layout={CardLayouts.Row}
104
+ center
105
+ imageSrc="https://play.nintendo.com/images/AC_Tom_FRYtwIN.17345b1513ac044897cfc243542899dce541e8dc.9afde10b.png"
106
+ imageAlt="Alt text"
107
+ imageAspectRatio={CardImageRatios.TwoByOne}
108
+ >
109
+ <CardHeading level={HeadingLevels.Four} id="heading1">
110
+ Tom Nook
111
+ </CardHeading>
112
+ <CardContent>
113
+ Tom Nook, <b>known in Japan as Tanukichi</b>, is a fictional
114
+ character in the Animal Crossing series who operates the
115
+ village store.
116
+ </CardContent>
117
+ </Card>
118
+ ),
119
+ },
120
+ ];
121
+
122
+ ...
123
+
124
+ <Accordion contentData={contentData} />
125
+ ```
62
126
 
63
127
  <ArgsTable story="Basic" />
64
128
 
65
129
  ## FAQ example
66
130
 
67
- The Accordion component has an optional `modifiers` prop that has pre-styled
68
- designs. For example, when building out FAQ-like pages, pass
69
- `modifiers=["faq"]` into the Accordion component.
70
-
71
- <Preview withToolbar>
72
- <Story story={stories.AccordionAsFAQSet} />
73
- </Preview>
131
+ export const faqContent = [
132
+ {
133
+ label: "Tom Nook",
134
+ panel: (
135
+ <Card
136
+ layout={CardLayouts.Row}
137
+ center
138
+ imageSrc="https://play.nintendo.com/images/AC_Tom_FRYtwIN.17345b1513ac044897cfc243542899dce541e8dc.9afde10b.png"
139
+ imageAlt="Alt text"
140
+ imageAspectRatio={CardImageRatios.TwoByOne}
141
+ >
142
+ <CardHeading level={HeadingLevels.Four} id="heading1">
143
+ Tom Nook
144
+ </CardHeading>
145
+ <CardContent>
146
+ Tom Nook, <b>known in Japan as Tanukichi</b>, is a fictional character
147
+ in the Animal Crossing series who operates the village store.
148
+ </CardContent>
149
+ </Card>
150
+ ),
151
+ },
152
+ {
153
+ label: "Isabelle",
154
+ panel: (
155
+ <Card
156
+ layout={CardLayouts.Row}
157
+ center
158
+ imageSrc="https://play.nintendo.com/images/AC_Isabelle_7XU6aGu.17345b1513ac044897cfc243542899dce541e8dc.9afde10b.png"
159
+ imageAlt="Alt text"
160
+ imageAspectRatio={CardImageRatios.TwoByOne}
161
+ >
162
+ <CardHeading level={HeadingLevels.Four} id="heading1">
163
+ Isabelle
164
+ </CardHeading>
165
+ <CardContent>
166
+ Isabelle, known as Shizue in Japan, is a fictional character from the
167
+ Animal Crossing series of video games. She is a kindly Shih Tzu that
168
+ debuted in the 2012 release Animal Crossing: New Leaf, where she
169
+ serves as the secretary to the player character.
170
+ </CardContent>
171
+ </Card>
172
+ ),
173
+ },
174
+ {
175
+ label: "K.K. Slider",
176
+ panel: (
177
+ <Card
178
+ layout={CardLayouts.Row}
179
+ center
180
+ imageSrc="https://play.nintendo.com/images/AC_KK_jh4yj5t.17345b1513ac044897cfc243542899dce541e8dc.9afde10b.png"
181
+ imageAlt="Alt text"
182
+ imageAspectRatio={CardImageRatios.TwoByOne}
183
+ >
184
+ <CardHeading level={HeadingLevels.Four} id="heading1">
185
+ K.K. Slider
186
+ </CardHeading>
187
+ <CardContent>
188
+ <p>
189
+ Totakeke, more commonly known as <b>K.K. Slider or K.K.</b>, is a
190
+ fictional character within the Animal Crossing franchise. One of the
191
+ franchise's most popular characters, he debuted in the title Animal
192
+ Crossing, and has appeared in every installment since.
193
+ </p>
194
+ </CardContent>
195
+ </Card>
196
+ ),
197
+ },
198
+ ];
74
199
 
75
- ## Scrollable example
200
+ Building out FAQ-like accordions happens automatically when there are more than
201
+ one object in the array passed into the `contentData` prop.
76
202
 
77
- Use modifiers=["fixed-height"] when you'd like the accordion height to match that of its
78
- parent container. In this example, we wrap the accordion in a container whose height is
79
- set to 300px. If the contents within the accordion are taller than the height of the parent
80
- container, a scrollbar will appear.
203
+ <Canvas withToolbar>
204
+ <Story name="FAQ">
205
+ <Accordion contentData={faqContent} />
206
+ </Story>
207
+ </Canvas>
81
208
 
82
- As in the other examples, any page content underneath the accordion will continue to be pushed down.
209
+ ```jsx
210
+ export const faqContent = [
211
+ {
212
+ label: "Tom Nook",
213
+ panel: (
214
+ <Card
215
+ layout={CardLayouts.Row}
216
+ center
217
+ imageSrc="https://play.nintendo.com/images/AC_Tom_FRYtwIN.17345b1513ac044897cfc243542899dce541e8dc.9afde10b.png"
218
+ imageAlt="Alt text"
219
+ imageAspectRatio={CardImageRatios.TwoByOne}
220
+ >
221
+ <CardHeading level={HeadingLevels.Four} id="heading1">
222
+ Tom Nook
223
+ </CardHeading>
224
+ <CardContent>
225
+ Tom Nook, <b>known in Japan as Tanukichi</b>, is a fictional character
226
+ in the Animal Crossing series who operates the village store.
227
+ </CardContent>
228
+ </Card>
229
+ ),
230
+ },
231
+ {
232
+ label: "Isabelle",
233
+ panel: (
234
+ <Card
235
+ layout={CardLayouts.Row}
236
+ center
237
+ imageSrc="https://play.nintendo.com/images/AC_Isabelle_7XU6aGu.17345b1513ac044897cfc243542899dce541e8dc.9afde10b.png"
238
+ imageAlt="Alt text"
239
+ imageAspectRatio={CardImageRatios.TwoByOne}
240
+ >
241
+ <CardHeading level={HeadingLevels.Four} id="heading1">
242
+ Isabelle
243
+ </CardHeading>
244
+ <CardContent>
245
+ Isabelle, known as Shizue in Japan, is a fictional character from the
246
+ Animal Crossing series of video games. She is a kindly Shih Tzu that
247
+ debuted in the 2012 release Animal Crossing: New Leaf, where she
248
+ serves as the secretary to the player character.
249
+ </CardContent>
250
+ </Card>
251
+ ),
252
+ },
253
+ {
254
+ label: "K.K. Slider",
255
+ panel: (
256
+ <Card
257
+ layout={CardLayouts.Row}
258
+ center
259
+ imageSrc="https://play.nintendo.com/images/AC_KK_jh4yj5t.17345b1513ac044897cfc243542899dce541e8dc.9afde10b.png"
260
+ imageAlt="Alt text"
261
+ imageAspectRatio={CardImageRatios.TwoByOne}
262
+ >
263
+ <CardHeading level={HeadingLevels.Four} id="heading1">
264
+ K.K. Slider
265
+ </CardHeading>
266
+ <CardContent>
267
+ <p>
268
+ Totakeke, more commonly known as <b>K.K. Slider or K.K.</b>, is a
269
+ fictional character within the Animal Crossing franchise. One of the
270
+ franchise's most popular characters, he debuted in the title Animal
271
+ Crossing, and has appeared in every installment since.
272
+ </p>
273
+ </CardContent>
274
+ </Card>
275
+ ),
276
+ },
277
+ ];
83
278
 
84
- <Preview withToolbar>
85
- <Story story={stories.AccordionScroll} />
86
- </Preview>
279
+ ...
87
280
 
88
- <Source code={ReactDOMServer.renderToString(stories.AccordionScroll)} />
281
+ <Accordion contentData={faqContent} />
282
+ ```
@@ -1,37 +1,153 @@
1
1
  import * as React from "react";
2
2
  import { render, screen } from "@testing-library/react";
3
3
  import { axe } from "jest-axe";
4
+ import userEvent from "@testing-library/user-event";
4
5
 
5
6
  import Accordion from "./Accordion";
6
7
 
7
8
  describe("Accordion Accessibility", () => {
8
- it("passes axe accessibility test", async () => {
9
+ it("passes axe accessibility test for one item", async () => {
9
10
  const { container } = render(
10
11
  <Accordion
11
- id="accordion"
12
- inputId="accordionBtn"
13
- accordionLabel="Click to expand"
14
- >
15
- <p className="accordion-content">this is the accordion content</p>
16
- </Accordion>
12
+ contentData={[
13
+ {
14
+ label: "Tom Nook",
15
+ panel: (
16
+ <p>
17
+ Tom Nook, <b>known in Japan as Tanukichi</b>, is a fictional
18
+ character in the Animal Crossing series who operates the village
19
+ store.
20
+ </p>
21
+ ),
22
+ },
23
+ ]}
24
+ />
17
25
  );
18
26
  expect(await axe(container)).toHaveNoViolations();
19
27
  });
20
- });
21
28
 
22
- describe("Accordion", () => {
23
- it("Renders an input checkbox and label", () => {
24
- render(
29
+ it("passes axe accessibility test for multiple items", async () => {
30
+ const { container } = render(
25
31
  <Accordion
26
- id="accordion"
27
- inputId="accordionBtn"
28
- accordionLabel="Click to expand"
29
- >
30
- <p className="accordion-content">this is the accordion content</p>
31
- </Accordion>
32
+ contentData={[
33
+ {
34
+ label: "Tom Nook",
35
+ panel: (
36
+ <p>
37
+ Tom Nook, <b>known in Japan as Tanukichi</b>, is a fictional
38
+ character in the Animal Crossing series who operates the village
39
+ store.
40
+ </p>
41
+ ),
42
+ },
43
+ {
44
+ label: "Isabelle",
45
+ panel:
46
+ "Isabelle, known as Shizue in Japan, is a fictional character " +
47
+ "from the Animal Crossing series of video games. She is a kindly Shih " +
48
+ "Tzu that debuted in the 2012 release Animal Crossing: New Leaf, where " +
49
+ "she serves as the secretary to the player character.",
50
+ },
51
+ ]}
52
+ />
32
53
  );
54
+ expect(await axe(container)).toHaveNoViolations();
55
+ });
56
+ });
57
+
58
+ export const contentData = [
59
+ {
60
+ label: "Tom Nook",
61
+ panel: (
62
+ <p>
63
+ Tom Nook, <b>known in Japan as Tanukichi</b>, is a fictional character
64
+ in the Animal Crossing series who operates the village store.
65
+ </p>
66
+ ),
67
+ },
68
+ {
69
+ label: "Isabelle",
70
+ panel:
71
+ "Isabelle, known as Shizue in Japan, is a fictional character " +
72
+ "from the Animal Crossing series of video games. She is a kindly Shih " +
73
+ "Tzu that debuted in the 2012 release Animal Crossing: New Leaf, where " +
74
+ "she serves as the secretary to the player character.",
75
+ },
76
+ {
77
+ label: "K.K. Slider",
78
+ panel:
79
+ "<p>Totakeke, more commonly known as <b>K.K. Slider or K.K.</b>, is a " +
80
+ "fictional character within the Animal Crossing franchise. One of the " +
81
+ "franchise's most popular characters, he debuted in the title Animal " +
82
+ "Crossing, and has appeared in every installment since.</p>",
83
+ },
84
+ ];
85
+
86
+ describe("Accordion", () => {
87
+ it("renders a visible button with a label to click on", () => {
88
+ render(<Accordion contentData={[contentData[0]]} />);
89
+ const accordionLabel = screen.getByRole("button", { name: "Tom Nook" });
90
+
91
+ expect(accordionLabel).toBeInTheDocument();
92
+ // Closed by default.
93
+ expect(accordionLabel).toHaveAttribute("aria-expanded", "false");
94
+ expect(screen.getByText(/known in Japan as Tanukichi/i)).not.toBeVisible();
95
+ });
96
+
97
+ it("opens the panel by default with isDefaultOpen passed", () => {
98
+ render(<Accordion isDefaultOpen contentData={[contentData[0]]} />);
99
+ const accordionLabel = screen.getByRole("button", { name: "Tom Nook" });
100
+
101
+ expect(accordionLabel).toBeInTheDocument();
102
+ expect(accordionLabel).toHaveAttribute("aria-expanded", "true");
103
+ });
104
+
105
+ it("opens the accordion when the label is clicked", () => {
106
+ render(<Accordion contentData={[contentData[0]]} />);
107
+
108
+ const accordionLabel = screen.getByRole("button", { name: "Tom Nook" });
109
+ expect(accordionLabel).toHaveAttribute("aria-expanded", "false");
110
+ userEvent.click(accordionLabel);
111
+ expect(accordionLabel).toHaveAttribute("aria-expanded", "true");
112
+ });
113
+
114
+ it("renders multiple accordion items grouped together", () => {
115
+ render(<Accordion contentData={contentData} />);
116
+
117
+ const accordion1 = screen.getByRole("button", { name: "Tom Nook" });
118
+ const accordion2 = screen.getByRole("button", { name: "Isabelle" });
119
+ const accordion3 = screen.getByRole("button", { name: "K.K. Slider" });
120
+
121
+ expect(accordion1).toHaveAttribute("aria-expanded", "false");
122
+ expect(accordion2).toHaveAttribute("aria-expanded", "false");
123
+ expect(accordion3).toHaveAttribute("aria-expanded", "false");
124
+ });
125
+
126
+ it("opens each accordion item independently of each other", () => {
127
+ render(<Accordion contentData={contentData} />);
128
+
129
+ const accordion1 = screen.getByRole("button", { name: "Tom Nook" });
130
+ const accordion2 = screen.getByRole("button", { name: "Isabelle" });
131
+ const accordion3 = screen.getByRole("button", { name: "K.K. Slider" });
132
+
133
+ expect(accordion1).toHaveAttribute("aria-expanded", "false");
134
+ expect(accordion2).toHaveAttribute("aria-expanded", "false");
135
+ expect(accordion3).toHaveAttribute("aria-expanded", "false");
136
+
137
+ userEvent.click(accordion1);
138
+ expect(accordion1).toHaveAttribute("aria-expanded", "true");
139
+ expect(accordion2).toHaveAttribute("aria-expanded", "false");
140
+ expect(accordion3).toHaveAttribute("aria-expanded", "false");
141
+
142
+ userEvent.click(accordion2);
143
+ expect(accordion1).toHaveAttribute("aria-expanded", "true");
144
+ expect(accordion2).toHaveAttribute("aria-expanded", "true");
145
+ expect(accordion3).toHaveAttribute("aria-expanded", "false");
33
146
 
34
- expect(screen.getByRole("checkbox")).toBeInTheDocument();
35
- expect(screen.getByLabelText("Click to expand")).toBeInTheDocument();
147
+ userEvent.click(accordion3);
148
+ userEvent.click(accordion1);
149
+ expect(accordion1).toHaveAttribute("aria-expanded", "false");
150
+ expect(accordion2).toHaveAttribute("aria-expanded", "true");
151
+ expect(accordion3).toHaveAttribute("aria-expanded", "true");
36
152
  });
37
153
  });
@@ -1,69 +1,94 @@
1
1
  import * as React from "react";
2
- import bem from "../../utils/bem";
2
+ import {
3
+ Box,
4
+ Accordion as ChakraAccordion,
5
+ AccordionItem,
6
+ AccordionButton,
7
+ AccordionPanel,
8
+ } from "@chakra-ui/react";
9
+
3
10
  import Icon from "../Icons/Icon";
4
- import { IconNames } from "../Icons/IconTypes";
11
+ import { IconNames, IconSizes } from "../Icons/IconTypes";
12
+ import generateUUID from "../../helpers/generateUUID";
13
+
14
+ export interface AccordionContentDataProps {
15
+ label: string;
16
+ panel: string | React.ReactNode;
17
+ }
5
18
 
6
19
  export interface AccordionProps {
7
- /** Inner label on the button that opens the accordion */
8
- accordionLabel?: React.ReactNode;
9
- /** BlockName for use with BEM. See how to work with blockNames and BEM here: http://getbem.com/introduction/ */
10
- blockName?: string;
11
- /** className you can add in addition to 'input' */
12
- className?: string;
13
- /** Whether the accordion is open by default */
14
- defaultOpen?: boolean;
20
+ /** Array of data to display */
21
+ contentData: AccordionContentDataProps[];
15
22
  /** ID that other components can cross reference for accessibility purposes */
16
23
  id?: string;
17
- /** accordionLabel's input ID */
18
- inputId?: string;
19
- /** Modifiers array for use with BEM. See how to work with modifiers and BEM here: http://getbem.com/introduction/ */
20
- modifiers?: string[];
24
+ /** Whether the accordion is open by default only on its initial rendering */
25
+ isDefaultOpen?: boolean;
21
26
  }
22
27
 
23
- /** Accordion component that shows content on toggle */
24
- export default function Accordion(
25
- props: React.PropsWithChildren<AccordionProps>
26
- ) {
27
- const {
28
- modifiers = [],
29
- blockName,
30
- id,
31
- className,
32
- inputId,
33
- defaultOpen = false,
34
- accordionLabel,
35
- children,
36
- } = props;
28
+ /**
29
+ * Get the minus or plus icon depending on whether the accordion
30
+ * is open or closed.
31
+ */
32
+ const getIcon = (isExpanded = false) => {
33
+ const iconName = isExpanded ? IconNames.Minus : IconNames.Plus;
34
+ return <Icon name={iconName} size={IconSizes.Small} />;
35
+ };
37
36
 
38
- return (
39
- <div
40
- id={id}
41
- className={bem("accordion", modifiers, blockName, [className])}
42
- >
43
- <input
44
- id={`accordion-${inputId}`}
45
- className={bem("input", modifiers, "accordion")}
46
- type="checkbox"
47
- defaultChecked={defaultOpen}
48
- />
49
- <label
50
- htmlFor={`accordion-${inputId}`}
51
- className={bem("label", modifiers, "accordion")}
52
- >
53
- {accordionLabel}
54
- <Icon
55
- decorative={true}
56
- name={IconNames.minus}
57
- modifiers={["small", `${IconNames.minus}`]}
58
- />
59
- <Icon
60
- decorative={true}
61
- name={IconNames.plus}
62
- modifiers={["small", `${IconNames.plus}`]}
37
+ /**
38
+ * Returns `AccordionItems` for every accordion object in the data
39
+ * array. This automatically creates the `AccordionButton` and `AccordionPanel`
40
+ * combination that is required for the Chakra `Accordion` component.
41
+ */
42
+ const getElementsFromContentData = (data = []) => {
43
+ // For FAQ-style multiple accordions, the button should be bigger.
44
+ // Otherwise, use the default.
45
+ const multiplePadding = data?.length > 1 ? 4 : null;
46
+
47
+ return data.map((content, index) => {
48
+ // This is done to support both string and DOM element input.
49
+ const panel =
50
+ typeof content.panel === "string" ? (
51
+ <AccordionPanel
52
+ key={index}
53
+ dangerouslySetInnerHTML={{ __html: content.panel }}
63
54
  />
64
- </label>
55
+ ) : (
56
+ <AccordionPanel key={index}>{content.panel}</AccordionPanel>
57
+ );
58
+
59
+ return (
60
+ <AccordionItem key={index}>
61
+ {/* Get the current state to render the correct icon. */}
62
+ {({ isExpanded }) => (
63
+ <>
64
+ <AccordionButton padding={multiplePadding}>
65
+ <Box flex="1" textAlign="left">
66
+ {content.label}
67
+ </Box>
68
+ {getIcon(isExpanded)}
69
+ </AccordionButton>
70
+ {panel}
71
+ </>
72
+ )}
73
+ </AccordionItem>
74
+ );
75
+ });
76
+ };
77
+
78
+ /**
79
+ * Accordion component that shows content on toggle. Can be used to display
80
+ * multiple accordion items together.
81
+ */
82
+ function Accordion(props: React.PropsWithChildren<AccordionProps>) {
83
+ const { contentData, id = generateUUID(), isDefaultOpen = false } = props;
65
84
 
66
- <div className={bem("content", modifiers, "accordion")}>{children}</div>
67
- </div>
85
+ // Pass `0` to open the first accordion in the 0-index based array.
86
+ const openFirstAccordion = isDefaultOpen ? 0 : undefined;
87
+ return (
88
+ <ChakraAccordion id={id} defaultIndex={[openFirstAccordion]} allowMultiple>
89
+ {getElementsFromContentData(contentData)}
90
+ </ChakraAccordion>
68
91
  );
69
92
  }
93
+
94
+ export default Accordion;
@@ -34,7 +34,7 @@ typing "c" or "tr" in the following input.
34
34
  const renderSuggestion = (suggestion) => (
35
35
  <span>
36
36
  {suggestion}
37
- <Icon name={IconNames["check"]} decorative={true}></Icon>
37
+ <Icon name={IconNames.Check} />
38
38
  </span>
39
39
  );
40
40
  ```
@@ -168,7 +168,7 @@ const FishExample = () => {
168
168
  const renderSuggestion = (suggestion) => (
169
169
  <span>
170
170
  {suggestion}
171
- <Icon name={IconNames["check"]} decorative={true}></Icon>
171
+ <Icon name={IconNames.Check} />
172
172
  </span>
173
173
  );
174
174
  const getSuggestionValue = (suggestion) => suggestion;
@@ -29,7 +29,7 @@
29
29
  display: block;
30
30
  font-weight: 300;
31
31
  margin-top: -6px; // accounts for the focus ring on the input
32
- outline: 1px solid var(--ui-gray-light);
32
+ outline: 1px solid var(--ui-gray-light-cool);
33
33
  position: absolute;
34
34
  width: 100%;
35
35
  z-index: 2;
@@ -47,7 +47,7 @@
47
47
  }
48
48
 
49
49
  .react-autosuggest__suggestion--highlighted {
50
- background-color: var(--ui-gray-light);
50
+ background-color: var(--ui-gray-light-cool);
51
51
  }
52
52
 
53
53
  .auto-suggest-bottom {