@nypl/design-system-react-components 0.25.7 → 0.25.8

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 (80) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/components/Icons/IconSvgs.d.ts +1 -0
  3. package/dist/components/Icons/IconTypes.d.ts +1 -0
  4. package/dist/components/Image/ImageTypes.d.ts +3 -1
  5. package/dist/components/Link/LinkTypes.d.ts +1 -0
  6. package/dist/components/Notification/Notification.d.ts +2 -0
  7. package/dist/components/Select/Select.d.ts +2 -0
  8. package/dist/components/Toggle/Toggle.d.ts +47 -0
  9. package/dist/components/Toggle/ToggleSizes.d.ts +4 -0
  10. package/dist/components/VideoPlayer/VideoPlayer.d.ts +5 -3
  11. package/dist/design-system-react-components.cjs.development.js +613 -366
  12. package/dist/design-system-react-components.cjs.development.js.map +1 -1
  13. package/dist/design-system-react-components.cjs.production.min.js +1 -1
  14. package/dist/design-system-react-components.cjs.production.min.js.map +1 -1
  15. package/dist/design-system-react-components.esm.js +606 -354
  16. package/dist/design-system-react-components.esm.js.map +1 -1
  17. package/dist/index.d.ts +3 -0
  18. package/dist/theme/components/notification.d.ts +8 -4
  19. package/dist/theme/components/toggle.d.ts +68 -0
  20. package/dist/theme/foundations/spacing.d.ts +2 -0
  21. package/package.json +1 -1
  22. package/src/components/Accordion/Accordion.stories.mdx +1 -2
  23. package/src/components/Breadcrumbs/Breadcrumbs.stories.mdx +1 -1
  24. package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +10 -0
  25. package/src/components/Breadcrumbs/__snapshots__/Breadcrumbs.test.tsx.snap +99 -0
  26. package/src/components/Button/Button.tsx +0 -1
  27. package/src/components/Card/Card.stories.mdx +74 -7
  28. package/src/components/Card/Card.tsx +9 -8
  29. package/src/components/Card/__snapshots__/Card.test.tsx.snap +67 -35
  30. package/src/components/Chakra/Grid.stories.mdx +11 -14
  31. package/src/components/DatePicker/DatePicker.test.tsx +8 -6
  32. package/src/components/DatePicker/__snapshots__/DatePicker.test.tsx.snap +5 -4
  33. package/src/components/Icons/Icon.stories.mdx +3 -2
  34. package/src/components/Icons/IconSvgs.tsx +2 -0
  35. package/src/components/Icons/IconTypes.tsx +1 -0
  36. package/src/components/Image/Image.stories.mdx +152 -90
  37. package/src/components/Image/Image.test.tsx +10 -0
  38. package/src/components/Image/ImageTypes.ts +2 -0
  39. package/src/components/Image/__snapshots__/Image.test.tsx.snap +24 -8
  40. package/src/components/Label/Label.stories.mdx +1 -1
  41. package/src/components/Link/Link.stories.mdx +2 -3
  42. package/src/components/Link/Link.test.tsx +71 -0
  43. package/src/components/Link/Link.tsx +41 -9
  44. package/src/components/Link/LinkTypes.tsx +1 -0
  45. package/src/components/Link/__snapshots__/Link.test.tsx.snap +201 -0
  46. package/src/components/Notification/Notification.stories.mdx +36 -3
  47. package/src/components/Notification/Notification.test.tsx +62 -16
  48. package/src/components/Notification/Notification.tsx +17 -5
  49. package/src/components/Notification/__snapshots__/Notification.test.tsx.snap +117 -0
  50. package/src/components/Pagination/Pagination.stories.mdx +1 -2
  51. package/src/components/Pagination/__snapshots__/Pagination.test.tsx.snap +42 -0
  52. package/src/components/ProgressIndicator/ProgressIndicator.stories.mdx +2 -3
  53. package/src/components/SearchBar/SearchBar.stories.mdx +1 -1
  54. package/src/components/Select/Select.stories.mdx +132 -55
  55. package/src/components/Select/Select.test.tsx +2 -2
  56. package/src/components/Select/Select.tsx +6 -2
  57. package/src/components/Slider/Slider.stories.mdx +3 -2
  58. package/src/components/Slider/Slider.test.tsx +35 -0
  59. package/src/components/Slider/Slider.tsx +8 -2
  60. package/src/components/Template/Template.stories.mdx +1 -2
  61. package/src/components/Toggle/Toggle.stories.mdx +176 -0
  62. package/src/components/Toggle/Toggle.test.tsx +140 -0
  63. package/src/components/Toggle/Toggle.tsx +118 -0
  64. package/src/components/Toggle/ToggleSizes.tsx +4 -0
  65. package/src/components/Toggle/__snapshots__/Toggle.test.tsx.snap +255 -0
  66. package/src/components/VideoPlayer/VideoPlayer.stories.mdx +39 -18
  67. package/src/components/VideoPlayer/VideoPlayer.test.tsx +103 -1
  68. package/src/components/VideoPlayer/VideoPlayer.tsx +57 -17
  69. package/src/components/VideoPlayer/__snapshots__/VideoPlayer.test.tsx.snap +48 -0
  70. package/src/index.ts +6 -0
  71. package/src/theme/components/breadcrumb.ts +1 -1
  72. package/src/theme/components/card.ts +4 -5
  73. package/src/theme/components/global.ts +1 -1
  74. package/src/theme/components/icon.ts +2 -2
  75. package/src/theme/components/image.ts +8 -0
  76. package/src/theme/components/notification.ts +8 -6
  77. package/src/theme/components/toggle.ts +65 -0
  78. package/src/theme/foundations/spacing.ts +3 -0
  79. package/src/theme/index.ts +2 -0
  80. package/src/utils/componentCategories.ts +3 -1
@@ -63,6 +63,46 @@ describe("VideoPlayer", () => {
63
63
  });
64
64
  });
65
65
 
66
+ describe("using embedCode prop", () => {
67
+ const embedCode = `<iframe src="https://player.vimeo.com/video/421404144?h=5467db7edd" width="640" height="360" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>`;
68
+ const embedCodeWithTitle = `<iframe title="Pre-Existing iFrame Title" src="https://player.vimeo.com/video/421404144?h=5467db7edd" width="640" height="360" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>`;
69
+
70
+ it("Renders custom embed code", () => {
71
+ render(<VideoPlayer embedCode={embedCode} />);
72
+ expect(screen.getByTitle("Video player")).toBeInTheDocument();
73
+ expect(screen.getByTitle("Video player")).toHaveAttribute(
74
+ "src",
75
+ `https://player.vimeo.com/video/421404144?h=5467db7edd`
76
+ );
77
+ });
78
+
79
+ it("Renders custom embed code with custom iframe title", () => {
80
+ render(
81
+ <VideoPlayer embedCode={embedCode} iframeTitle="Custom iFrame Title" />
82
+ );
83
+ expect(screen.getByTitle("Custom iFrame Title")).toBeInTheDocument();
84
+ });
85
+
86
+ it("Renders custom embed code with pre-existing title", () => {
87
+ render(<VideoPlayer embedCode={embedCodeWithTitle} />);
88
+ expect(
89
+ screen.getByTitle("Pre-Existing iFrame Title")
90
+ ).toBeInTheDocument();
91
+ });
92
+
93
+ it("Renders custom embed code with pre-existing title and ignores `iframeTitle` prop", () => {
94
+ render(
95
+ <VideoPlayer
96
+ embedCode={embedCodeWithTitle}
97
+ iframeTitle="Custom iFrame Title"
98
+ />
99
+ );
100
+ expect(
101
+ screen.getByTitle("Pre-Existing iFrame Title")
102
+ ).toBeInTheDocument();
103
+ });
104
+ });
105
+
66
106
  describe("text elements", () => {
67
107
  beforeEach(() => {
68
108
  utils = render(
@@ -121,7 +161,7 @@ describe("VideoPlayer", () => {
121
161
  });
122
162
 
123
163
  describe("prop validation", () => {
124
- it("Throws error if videoId not formatted properly", () => {
164
+ it("Throws error if the videoId prop not is formatted properly", () => {
125
165
  render(
126
166
  <VideoPlayer
127
167
  videoType={VideoPlayerTypes.Vimeo}
@@ -135,6 +175,56 @@ describe("VideoPlayer", () => {
135
175
  )
136
176
  ).toBeInTheDocument();
137
177
  });
178
+
179
+ it("Throws appropriate error if VideoPlayer props are not configured properly", () => {
180
+ const warn = jest.spyOn(console, "warn");
181
+
182
+ render(<VideoPlayer />);
183
+ expect(warn).toHaveBeenCalledWith(
184
+ "VideoPlayer requires either the `embedCode` prop or both the `videoType` and `videoId` props."
185
+ );
186
+
187
+ render(<VideoPlayer videoId="http://vimeo.com/474719268" />);
188
+ expect(warn).toHaveBeenCalledWith(
189
+ "VideoPlayer also requires the `videoType` prop. You have only set the `videoId` prop."
190
+ );
191
+
192
+ render(<VideoPlayer videoType={VideoPlayerTypes.Vimeo} />);
193
+ expect(warn).toHaveBeenCalledWith(
194
+ "VideoPlayer also requires the `videoId` prop. You have only set the `videoType` prop."
195
+ );
196
+
197
+ render(
198
+ <VideoPlayer
199
+ embedCode="<iframe src='https://player.vimeo.com/video/421404144?h=5467db7edd' width='640' height='360' frameborder='0' allow='autoplay; fullscreen; picture-in-picture' allowfullscreen></iframe>"
200
+ videoType={VideoPlayerTypes.Vimeo}
201
+ videoId="http://vimeo.com/474719268"
202
+ />
203
+ );
204
+ expect(warn).toHaveBeenCalledWith(
205
+ "VideoPlayer can accept the `embedCode` prop or the `videoType` and `videoId` props. You have set both."
206
+ );
207
+
208
+ render(
209
+ <VideoPlayer
210
+ embedCode="<iframe src='https://player.vimeo.com/video/421404144?h=5467db7edd' width='640' height='360' frameborder='0' allow='autoplay; fullscreen; picture-in-picture' allowfullscreen></iframe>"
211
+ videoType={VideoPlayerTypes.Vimeo}
212
+ />
213
+ );
214
+ expect(warn).toHaveBeenCalledWith(
215
+ "VideoPlayer can accept the `embedCode` prop or the `videoType` and `videoId` props. You have set both."
216
+ );
217
+
218
+ render(
219
+ <VideoPlayer
220
+ embedCode="<iframe src='https://player.vimeo.com/video/421404144?h=5467db7edd' width='640' height='360' frameborder='0' allow='autoplay; fullscreen; picture-in-picture' allowfullscreen></iframe>"
221
+ videoId="http://vimeo.com/474719268"
222
+ />
223
+ );
224
+ expect(warn).toHaveBeenCalledWith(
225
+ "VideoPlayer can accept the `embedCode` prop or the `videoType` and `videoId` props. You have set both."
226
+ );
227
+ });
138
228
  });
139
229
 
140
230
  it("renders the UI snapshot correctly", () => {
@@ -159,6 +249,17 @@ describe("VideoPlayer", () => {
159
249
  />
160
250
  )
161
251
  .toJSON();
252
+ const videoPlayerUsingEmbedCode = renderer
253
+ .create(
254
+ <VideoPlayer
255
+ descriptionText="VideoPlayer description"
256
+ embedCode="<iframe src='https://player.vimeo.com/video/421404144?h=5467db7edd' width='640' height='360' frameborder='0' allow='autoplay; fullscreen; picture-in-picture' allowfullscreen></iframe>"
257
+ headingText="VideoPlayer Heading"
258
+ id="video-player-with-text"
259
+ helperText="VideoPlayer helper test."
260
+ />
261
+ )
262
+ .toJSON();
162
263
  const videoPlayerError = renderer
163
264
  .create(
164
265
  <VideoPlayer
@@ -171,6 +272,7 @@ describe("VideoPlayer", () => {
171
272
 
172
273
  expect(videoPlayerWithoutText).toMatchSnapshot();
173
274
  expect(videoPlayerWithText).toMatchSnapshot();
275
+ expect(videoPlayerUsingEmbedCode).toMatchSnapshot();
174
276
  expect(videoPlayerError).toMatchSnapshot();
175
277
  });
176
278
  });
@@ -12,20 +12,22 @@ export interface VideoPlayerProps {
12
12
  className?: string;
13
13
  /** Optional string to set the text for a video description */
14
14
  descriptionText?: string;
15
+ /** Optional string to set a code snippet provided by YouTube or Vimeo; the `videoPlayer` component will accept the `embedCode` prop or the `videoId` and `videoType` props */
16
+ embedCode?: string;
15
17
  /** Optional string to set the text for a `Heading` component */
16
18
  headingText?: string;
17
19
  /** Optional string to set the text for a `HelperErrorText` component */
18
20
  helperText?: string;
19
21
  /** ID that other components can cross reference for accessibility purposes */
20
22
  id?: string;
21
- /** Optional title to be added to the `<iframe>` element for improved accessibility; this title should describe in a few words the content of the video; if omitted, a generic title will be added */
23
+ /** Optional title to be added to the `<iframe>` element for improved accessibility; this title should describe in a few words the content of the video; if omitted, a generic title will be added; if a `title` attribute is already present in the `embedCode` prop, this prop will be ignored */
22
24
  iframeTitle?: string;
23
25
  /** Offers the ability to hide the helper/invalid text. */
24
26
  showHelperInvalidText?: boolean;
25
27
  /** Required YouTube or Vimeo video ID. This value can be pulled from a video's YouTube or Vimeo URL. */
26
- videoId: string;
28
+ videoId?: string;
27
29
  /** Required. Used to specify which video service is being used. */
28
- videoType: VideoPlayerTypes;
30
+ videoType?: VideoPlayerTypes;
29
31
  }
30
32
 
31
33
  export default function VideoPlayer(
@@ -35,6 +37,7 @@ export default function VideoPlayer(
35
37
  aspectRatio,
36
38
  className,
37
39
  descriptionText,
40
+ embedCode,
38
41
  headingText,
39
42
  helperText,
40
43
  id = generateUUID(),
@@ -54,29 +57,64 @@ export default function VideoPlayer(
54
57
  ? `https://player.vimeo.com/video/${videoId}?autoplay=0&loop=0`
55
58
  : `https://www.youtube.com/embed/${videoId}?disablekb=1&autoplay=0&fs=1&modestbranding=0`;
56
59
 
60
+ const iFrameTitleEmbedCode = iframeTitle ? `${iframeTitle}` : `Video player`;
61
+
62
+ const embedCodeFinal =
63
+ embedCode && embedCode.includes("<iframe") && !embedCode.includes("title=")
64
+ ? embedCode.replace(
65
+ `<iframe `,
66
+ `<iframe title="${iFrameTitleEmbedCode}" `
67
+ )
68
+ : embedCode;
69
+
57
70
  const errorMessage =
58
71
  "<strong>Error:</strong> This video player has not been configured properly. Please contact the site administrator.";
59
72
 
60
73
  let isInvalid = false;
61
- if (!videoType && !videoId) {
62
- console.warn("VideoPlayer requires the `videoType` and `videoId` props");
74
+ if (!embedCodeFinal && !videoType && !videoId) {
75
+ console.warn(
76
+ "VideoPlayer requires either the `embedCode` prop or both the `videoType` and `videoId` props."
77
+ );
78
+ isInvalid = true;
79
+ } else if (!embedCodeFinal && !videoType) {
80
+ console.warn(
81
+ "VideoPlayer also requires the `videoType` prop. You have only set the `videoId` prop."
82
+ );
83
+ isInvalid = true;
84
+ } else if (!embedCodeFinal && !videoId) {
85
+ console.warn(
86
+ "VideoPlayer also requires the `videoId` prop. You have only set the `videoType` prop."
87
+ );
63
88
  isInvalid = true;
64
- } else if (!videoType) {
65
- console.warn("VideoPlayer requires the `videoType` prop");
89
+ } else if (embedCodeFinal && (videoType || videoId)) {
90
+ console.warn(
91
+ "VideoPlayer can accept the `embedCode` prop or the `videoType` and `videoId` props. You have set both."
92
+ );
66
93
  isInvalid = true;
67
- } else if (!videoId) {
68
- console.warn("VideoPlayer requires the `videoId` prop");
94
+ }
95
+
96
+ if (
97
+ videoId &&
98
+ (videoId.includes("://") ||
99
+ videoId.includes("http") ||
100
+ videoId.includes(".") ||
101
+ videoId.includes("youtube") ||
102
+ videoId.includes("vimeo"))
103
+ ) {
104
+ console.warn("The VideoPlayer `videoId` prop is not configured properly.");
69
105
  isInvalid = true;
70
106
  }
71
107
 
72
108
  if (
73
- videoId.includes("://") ||
74
- videoId.includes("http") ||
75
- videoId.includes(".") ||
76
- videoId.includes("youtube") ||
77
- videoId.includes("vimeo")
109
+ embedCodeFinal &&
110
+ ((!embedCodeFinal.includes("vimeo.com") &&
111
+ !embedCodeFinal.includes("youtube.com")) ||
112
+ !embedCodeFinal.includes("<iframe") ||
113
+ !embedCodeFinal.includes("</iframe"))
78
114
  ) {
79
- console.warn("VideoPlayer `videoId` prop is not configured properly");
115
+ console.warn(
116
+ "The VideoPlayer `embedCode` prop is not configured properly."
117
+ );
80
118
  isInvalid = true;
81
119
  }
82
120
 
@@ -85,7 +123,9 @@ export default function VideoPlayer(
85
123
  : getVariant(aspectRatio, VideoPlayerAspectRatios);
86
124
  const styles = useMultiStyleConfig("VideoPlayer", { variant });
87
125
 
88
- const embedCode = (
126
+ const embedElement = embedCodeFinal ? (
127
+ <span dangerouslySetInnerHTML={{ __html: embedCodeFinal }} />
128
+ ) : (
89
129
  <Box
90
130
  as="iframe"
91
131
  src={videoSrc}
@@ -113,7 +153,7 @@ export default function VideoPlayer(
113
153
  helperText={helperText && showHelperInvalidText ? helperText : null}
114
154
  id={`${id}-componentWrapper`}
115
155
  >
116
- <Box __css={styles.inside}>{embedCode}</Box>
156
+ <Box __css={styles.inside}>{embedElement}</Box>
117
157
  </ComponentWrapper>
118
158
  )}
119
159
  </Box>
@@ -75,6 +75,54 @@ exports[`VideoPlayer renders the UI snapshot correctly 2`] = `
75
75
  `;
76
76
 
77
77
  exports[`VideoPlayer renders the UI snapshot correctly 3`] = `
78
+ <div
79
+ className="css-0"
80
+ data-testid="video-player-component"
81
+ id="video-player-with-text"
82
+ >
83
+ <div
84
+ className="css-0"
85
+ >
86
+ <h2
87
+ className="chakra-heading css-0"
88
+ id="video-player-with-text-componentWrapper-heading"
89
+ >
90
+ VideoPlayer Heading
91
+ </h2>
92
+ <p
93
+ className="chakra-text css-0"
94
+ >
95
+ VideoPlayer description
96
+ </p>
97
+ <div
98
+ className="css-0"
99
+ >
100
+ <span
101
+ dangerouslySetInnerHTML={
102
+ Object {
103
+ "__html": "<iframe title=\\"Video player\\" src='https://player.vimeo.com/video/421404144?h=5467db7edd' width='640' height='360' frameborder='0' allow='autoplay; fullscreen; picture-in-picture' allowfullscreen></iframe>",
104
+ }
105
+ }
106
+ />
107
+ </div>
108
+ <div
109
+ className="css-0"
110
+ >
111
+ <div
112
+ aria-atomic={true}
113
+ aria-live="off"
114
+ className=" css-0"
115
+ data-isinvalid={false}
116
+ id="video-player-with-text-componentWrapper-helperText"
117
+ >
118
+ VideoPlayer helper test.
119
+ </div>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ `;
124
+
125
+ exports[`VideoPlayer renders the UI snapshot correctly 4`] = `
78
126
  <div
79
127
  className="css-0"
80
128
  data-testid="video-player-component"
package/src/index.ts CHANGED
@@ -74,6 +74,10 @@ export { default as Notification } from "./components/Notification/Notification"
74
74
  export { NotificationTypes } from "./components/Notification/NotificationTypes";
75
75
  export { default as Pagination } from "./components/Pagination/Pagination";
76
76
  export { default as ProgressIndicator } from "./components/ProgressIndicator/ProgressIndicator";
77
+ export {
78
+ ProgressIndicatorSizes,
79
+ ProgressIndicatorTypes,
80
+ } from "./components/ProgressIndicator/ProgressIndicatorTypes";
77
81
  export { default as Radio } from "./components/Radio/Radio";
78
82
  export { default as RadioGroup } from "./components/RadioGroup/RadioGroup";
79
83
  export { RadioGroupLayoutTypes } from "./components/RadioGroup/RadioGroupLayoutTypes";
@@ -113,6 +117,8 @@ export {
113
117
  TextInputRefType,
114
118
  } from "./components/TextInput/TextInput";
115
119
  export { TextInputTypes } from "./components/TextInput/TextInputTypes";
120
+ export { default as Toggle } from "./components/Toggle/Toggle";
121
+ export { ToggleSizes } from "./components/Toggle/ToggleSizes";
116
122
  export { default as useNYPLTheme } from "./hooks/useNYPLTheme";
117
123
  export { default as VideoPlayer } from "./components/VideoPlayer/VideoPlayer";
118
124
  export {
@@ -12,7 +12,7 @@ const booksAndMore = {
12
12
  bg: "section.books-and-more.secondary",
13
13
  };
14
14
  const locations = {
15
- bg: "section.locations.secondary",
15
+ bg: "section.locations.primary",
16
16
  };
17
17
  const research = {
18
18
  bg: "section.research.secondary",
@@ -1,4 +1,6 @@
1
1
  const imageSizes = {
2
+ xxsmall: { flex: { base: "0 0 100%", md: "0 0 64px" }, width: "100%" },
3
+ xsmall: { flex: { md: "0 0 96px" } },
2
4
  small: { flex: { md: "0 0 165px" } },
3
5
  medium: { flex: { md: "0 0 225px" } },
4
6
  large: { flex: { md: "0 0 360px" } },
@@ -137,11 +139,6 @@ const CardImage = {
137
139
  const layoutStyles =
138
140
  layout === "row"
139
141
  ? {
140
- display: "flex",
141
- flexFlow: {
142
- base: "column nowrap",
143
- md: "row",
144
- },
145
142
  flex: { md: "0 0 225px" },
146
143
  maxWidth: { base: "100%", md: "50%" },
147
144
  textAlign: "left",
@@ -152,10 +149,12 @@ const CardImage = {
152
149
  ? "0 0 0 var(--nypl-space-m)"
153
150
  : "0 var(--nypl-space-m) 0 0",
154
151
  },
152
+ width: { base: "100%", md: null },
155
153
  ...size,
156
154
  }
157
155
  : {
158
156
  marginBottom: "xs",
157
+ width: "100%",
159
158
  };
160
159
  const imageAtEndStyles = imageAtEnd
161
160
  ? {
@@ -51,7 +51,7 @@ const checkboxRadioHelperStyle = {
51
51
  const labelLegendText = {
52
52
  alignItems: "baseline",
53
53
  width: "100%",
54
- marginBottom: "s",
54
+ marginBottom: "xs",
55
55
  fontSize: "14px",
56
56
  fontWeight: "medium",
57
57
  display: "flex",
@@ -6,8 +6,8 @@ const svgBase = {
6
6
  };
7
7
  const align = {
8
8
  none: {},
9
- left: { marginRight: "xs" },
10
- right: { marginLeft: "xs" },
9
+ left: { marginRight: "xxs" },
10
+ right: { marginLeft: "xxs" },
11
11
  };
12
12
  const iconRotation = {
13
13
  rotate180: {
@@ -12,6 +12,14 @@ const imageSizes = {
12
12
  default: {
13
13
  maxWidth: "100%",
14
14
  },
15
+ xxsmall: {
16
+ ...sideMarginsAuto,
17
+ maxWidth: "64px",
18
+ },
19
+ xsmall: {
20
+ ...sideMarginsAuto,
21
+ maxWidth: "96px",
22
+ },
15
23
  small: {
16
24
  ...sideMarginsAuto,
17
25
  maxWidth: "165px",
@@ -49,25 +49,26 @@ const Notification = {
49
49
 
50
50
  const NotificationContent = {
51
51
  parts: ["content"],
52
- baseStyle: ({ alignText, notificationType }) => ({
52
+ baseStyle: ({ alignText, icon, notificationType }) => ({
53
53
  display: "flex",
54
54
  justifyContent: "center",
55
55
  content: {
56
- width: "100%",
57
- paddingLeft: alignText
58
- ? "calc(var(--nypl-space-m) + var(--nypl-space-s))"
59
- : null,
60
56
  color:
61
57
  notificationType === NotificationTypes.Warning
62
58
  ? "brand.primary"
63
59
  : "currentColor",
60
+ marginTop: icon ? "xxxs" : "0",
61
+ paddingLeft: alignText
62
+ ? "calc(var(--nypl-space-m) + var(--nypl-space-s))"
63
+ : null,
64
+ width: "100%",
64
65
  },
65
66
  }),
66
67
  };
67
68
 
68
69
  const NotificationHeading = {
69
70
  parts: ["heading"],
70
- baseStyle: ({ centered, notificationType }) => {
71
+ baseStyle: ({ centered, icon, notificationType }) => {
71
72
  let color = "ui.black";
72
73
  if (notificationType === NotificationTypes.Announcement) {
73
74
  color = "section.research.secondary";
@@ -80,6 +81,7 @@ const NotificationHeading = {
80
81
  justifyContent: centered ? "center" : null,
81
82
  heading: {
82
83
  marginBottom: "0",
84
+ marginTop: icon ? "xxxs" : "0",
83
85
  color,
84
86
  },
85
87
  };
@@ -0,0 +1,65 @@
1
+ import { helperTextMargin } from "./global";
2
+
3
+ const baseStyle = {
4
+ label: { display: "flex", alignItems: "center", width: "fit-content" },
5
+ helper: {
6
+ ...helperTextMargin,
7
+ marginLeft: "xs",
8
+ },
9
+ };
10
+
11
+ const Switch = {
12
+ baseStyle: {
13
+ opacity: 0.4,
14
+ track: {
15
+ p: "4px",
16
+ border: "1px solid",
17
+ borderColor: "ui.gray.medium",
18
+ _checked: {
19
+ borderColor: "ui.link.primary",
20
+ bg: "ui.link.primary",
21
+ opacity: 1,
22
+ },
23
+ _invalid: {
24
+ borderColor: "ui.error.primary",
25
+ bg: "inherit",
26
+ "> span": {
27
+ bg: "ui.error.primary",
28
+ },
29
+ },
30
+ _disabled: {
31
+ borderColor: "ui.gray.medium",
32
+ bg: "ui.gray.medium",
33
+ _checked: {
34
+ opacity: 0.4,
35
+ },
36
+ },
37
+ _focus: {
38
+ outline: "2px solid",
39
+ outlineColor: "ui.focus",
40
+ outlineOffset: "2px",
41
+ zIndex: "9999",
42
+ },
43
+ },
44
+ label: { fontSize: -1, marginLeft: "xs" },
45
+ thumb: {
46
+ _disabled: {
47
+ bg: "ui.error.primary",
48
+ },
49
+ },
50
+ },
51
+ defaultProps: {
52
+ colorScheme: "white",
53
+ },
54
+ };
55
+
56
+ const Toggle = {
57
+ parts: ["helper"],
58
+ baseStyle,
59
+ // Default values
60
+ defaultProps: {
61
+ size: "lg",
62
+ },
63
+ };
64
+
65
+ export default { Toggle, Switch };
@@ -22,6 +22,7 @@
22
22
  *
23
23
  * Chakra Number Value | Chakra Name value | DS Variable
24
24
  * ------------------- | ----------------- | -----------------
25
+ * 0.5 | xxxs | --nypl-space-xxxs
25
26
  * 1 | xxs | --nypl-space-xxs
26
27
  * 2 | xs | --nypl-space-xs
27
28
  * 4 | s | --nypl-space-s
@@ -34,6 +35,8 @@
34
35
  export const spacing = {
35
36
  px: "1px",
36
37
  0: "0",
38
+ // --nypl-space-xxxs = 2px
39
+ xxxs: "0.125rem",
37
40
  0.5: "0.125rem",
38
41
  // --nypl-space-xxs = 4px
39
42
  xxs: "0.25rem",
@@ -40,6 +40,7 @@ import Tabs from "./components/tabs";
40
40
  import TemplateStyles from "./components/template";
41
41
  import Text from "./components/text";
42
42
  import TextInput from "./components/textInput";
43
+ import Toggle from "./components/toggle";
43
44
  import VideoPlayer from "./components/videoPlayer";
44
45
 
45
46
  /**
@@ -107,6 +108,7 @@ const theme = extendTheme({
107
108
  ...TemplateStyles,
108
109
  Text,
109
110
  TextInput,
111
+ ...Toggle,
110
112
  VideoPlayer,
111
113
  },
112
114
  // Use `cssVarPrefix` to set the prefix used on the CSS vars produced by
@@ -3,7 +3,7 @@
3
3
  const categories = {
4
4
  basicContent: {
5
5
  title: "Components/Basic Elements",
6
- components: ["Card", "Hero", "Promo", "Sponsor", "Table"],
6
+ components: ["Card", "Hero", "Promo", "Sponsor"],
7
7
  },
8
8
  contentDisplay: {
9
9
  title: "Components/Content Display",
@@ -52,6 +52,7 @@ const categories = {
52
52
  "Slider",
53
53
  "Textarea",
54
54
  "TextInput",
55
+ "Toggle",
55
56
  ],
56
57
  },
57
58
  layout: {
@@ -65,6 +66,7 @@ const categories = {
65
66
  "HorizontalRule",
66
67
  "Section",
67
68
  "SimpleGrid",
69
+ "Table",
68
70
  "Template",
69
71
  ],
70
72
  },