@hyphen/hyphen-components 2.13.1 → 2.14.0

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.
@@ -5253,6 +5253,10 @@
5253
5253
  display: table-cell;
5254
5254
  }
5255
5255
 
5256
+ .display-contents {
5257
+ display: contents;
5258
+ }
5259
+
5256
5260
  @media (min-width: 680px) {
5257
5261
  .display-inherit-tablet {
5258
5262
  display: inherit;
@@ -5281,6 +5285,9 @@
5281
5285
  .display-table-cell-tablet {
5282
5286
  display: table-cell;
5283
5287
  }
5288
+ .display-contents-tablet {
5289
+ display: contents;
5290
+ }
5284
5291
  }
5285
5292
  @media (min-width: 992px) {
5286
5293
  .display-inherit-desktop {
@@ -5310,6 +5317,9 @@
5310
5317
  .display-table-cell-desktop {
5311
5318
  display: table-cell;
5312
5319
  }
5320
+ .display-contents-desktop {
5321
+ display: contents;
5322
+ }
5313
5323
  }
5314
5324
  @media (min-width: 1280px) {
5315
5325
  .display-inherit-hd {
@@ -5339,6 +5349,9 @@
5339
5349
  .display-table-cell-hd {
5340
5350
  display: table-cell;
5341
5351
  }
5352
+ .display-contents-hd {
5353
+ display: contents;
5354
+ }
5342
5355
  }
5343
5356
  .flex-auto {
5344
5357
  flex: 1 1 auto;
@@ -30,7 +30,7 @@ export type CssFlexDirectionValue = 'column' | 'column-reverse' | 'row' | 'row-r
30
30
  export type CssAlignItemsValue = 'flex-start' | 'flex-end' | 'center' | 'baseline' | 'stretch';
31
31
  export type CssFlexValue = 'auto' | 'initial' | 'none' | 'inherit' | 'unset';
32
32
  export type CssOverflowValue = 'visible' | 'hidden' | 'clip' | 'scroll' | 'auto' | 'inherit' | 'initial' | 'unset';
33
- export type CssDisplayValue = 'none' | 'flex' | 'inline-flex' | 'block' | 'inline-block' | 'inline' | 'inherit' | 'grid' | 'table-cell';
33
+ export type CssDisplayValue = 'none' | 'flex' | 'inline-flex' | 'block' | 'inline-block' | 'inline' | 'inherit' | 'grid' | 'table-cell' | 'contents';
34
34
  export type CssTextAlignValue = 'left' | 'center' | 'right';
35
35
  export type BaseSpacing = SpacingSize | string | undefined;
36
36
  export type BorderRadiusSize = BorderRadius | string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyphen/hyphen-components",
3
- "version": "2.13.1",
3
+ "version": "2.14.0",
4
4
  "license": "MIT",
5
5
  "author": {
6
6
  "name": "@hyphen"
@@ -1,10 +1,12 @@
1
- import { CssDisplayValue, CssOverflowValue } from '../../types';
2
-
1
+ import {
2
+ CssDisplayValue,
3
+ CssFlexDirectionValue,
4
+ CssOverflowValue,
5
+ ResponsiveProp,
6
+ } from '../../types';
3
7
  import { Box } from './Box';
4
- /* eslint-disable react/no-array-index-key */
5
8
  import React from 'react';
6
- import { render } from '@testing-library/react';
7
-
9
+ import { fireEvent, render } from '@testing-library/react';
8
10
  import {
9
11
  BACKGROUND_COLOR_OPTIONS,
10
12
  BORDER_COLOR_OPTIONS,
@@ -16,65 +18,97 @@ import {
16
18
  } from '../../lib';
17
19
 
18
20
  describe('Box', () => {
19
- test('aria-label is applied if set', () => {
20
- const { getByLabelText } = render(<Box aria-label="test label" />);
21
- expect(getByLabelText('test label')).toBeDefined();
21
+ const renderBox = (props = {}) => render(<Box {...props}>Test Box</Box>);
22
+
23
+ describe('aria attributes', () => {
24
+ test('aria-label is applied if set', () => {
25
+ const { getByLabelText } = renderBox({ 'aria-label': 'test label' });
26
+ expect(getByLabelText('test label')).toBeDefined();
27
+ });
22
28
  });
23
29
 
24
- test('background color token classes are applied', () => {
25
- [...BACKGROUND_COLOR_OPTIONS].forEach((color, i) => {
26
- const { queryAllByText } = render(
27
- <Box background={color} key={i}>
28
- Test Box
29
- </Box>
30
- );
31
- expect(queryAllByText('Test Box')[i].classList).toContain(
32
- `background-color-${color}`
33
- );
30
+ test('renders with default display value of flex', () => {
31
+ const { getByText } = renderBox();
32
+ expect(getByText('Test Box')).toHaveClass('display-flex');
33
+ });
34
+
35
+ describe('Invalid props', () => {
36
+ test('handles invalid direction value gracefully', () => {
37
+ const { getByText } = renderBox({ direction: 'invalid' });
38
+ expect(getByText('Test Box')).not.toHaveClass('direction-invalid');
34
39
  });
40
+
41
+ // test('handles invalid padding value gracefully', () => {
42
+ // const { getByText } = renderBox({ padding: 'invalid' });
43
+ // expect(getByText('Test Box')).not.toHaveClass('p-invalid');
44
+ // });
45
+
46
+ // test('handles invalid margin value gracefully', () => {
47
+ // const { getByText } = renderBox({ margin: 'invalid' });
48
+ // expect(getByText('Test Box')).not.toHaveClass('m-invalid');
49
+ // });
35
50
  });
36
51
 
37
- test('font size token classes are applied', () => {
38
- [...FONT_SIZE_OPTIONS].forEach((fontSize, i) => {
39
- const { queryAllByText } = render(
40
- <Box fontSize={fontSize} key={i}>
41
- Test Box
42
- </Box>
43
- );
52
+ test('renders with proper hover classes', () => {
53
+ const { getByText } = renderBox({ hover: { background: 'primary' } });
54
+ expect(getByText('Test Box')).toHaveClass('hover:background-color-primary');
55
+ });
56
+
57
+ test('renders with proper focus classes', () => {
58
+ const { getByText } = renderBox({ focus: { borderColor: 'primary' } });
59
+ expect(getByText('Test Box')).toHaveClass('focus:border-color-primary');
60
+ });
61
+
62
+ test('renders with proper cursor class', () => {
63
+ const { getByText } = renderBox({ cursor: 'pointer' });
64
+ expect(getByText('Test Box')).toHaveClass('cursor-pointer');
65
+ });
66
+
67
+ test('renders with proper border radius class', () => {
68
+ const { getByText } = renderBox({ radius: 'md' });
69
+ expect(getByText('Test Box')).toHaveClass('br-md');
70
+ });
71
+
72
+ test('renders with proper box shadow class', () => {
73
+ const { getByText } = renderBox({ shadow: 'lg' });
74
+ expect(getByText('Test Box')).toHaveClass('shadow-lg');
75
+ });
76
+
77
+ const testTokenClasses = (
78
+ propName: string,
79
+ options: any[],
80
+ classNamePrefix: string
81
+ ) => {
82
+ options.forEach((option, i) => {
83
+ const { queryAllByText } = renderBox({ [propName]: option, key: i });
44
84
  expect(queryAllByText('Test Box')[i].classList).toContain(
45
- `font-size-${fontSize}`
85
+ `${classNamePrefix}-${option}`
46
86
  );
47
87
  });
88
+ };
89
+
90
+ test('background color token classes are applied', () => {
91
+ testTokenClasses(
92
+ 'background',
93
+ BACKGROUND_COLOR_OPTIONS,
94
+ 'background-color'
95
+ );
96
+ });
97
+
98
+ test('font size token classes are applied', () => {
99
+ testTokenClasses('fontSize', FONT_SIZE_OPTIONS, 'font-size');
48
100
  });
49
101
 
50
102
  test('text color token classes are applied', () => {
51
- [...FONT_COLOR_OPTIONS].forEach((color, i) => {
52
- const { queryAllByText } = render(
53
- <Box color={color} key={i}>
54
- Test Box
55
- </Box>
56
- );
57
- expect(queryAllByText('Test Box')[i].classList).toContain(
58
- `font-color-${color}`
59
- );
60
- });
103
+ testTokenClasses('color', FONT_COLOR_OPTIONS, 'font-color');
61
104
  });
62
105
 
63
106
  test('border color token classes are applied', () => {
64
- [...BORDER_COLOR_OPTIONS].forEach((color, i) => {
65
- const { queryAllByText } = render(
66
- <Box borderColor={color} key={i}>
67
- Test Box
68
- </Box>
69
- );
70
- expect(queryAllByText('Test Box')[i].classList).toContain(
71
- `border-color-${color}`
72
- );
73
- });
107
+ testTokenClasses('borderColor', BORDER_COLOR_OPTIONS, 'border-color');
74
108
  });
75
109
 
76
110
  test('overflow option classes are applied', () => {
77
- const overflowOptions = [
111
+ const overflowOptions: CssOverflowValue[] = [
78
112
  'visible',
79
113
  'hidden',
80
114
  'clip',
@@ -83,24 +117,17 @@ describe('Box', () => {
83
117
  'inherit',
84
118
  'initial',
85
119
  'unset',
86
- ] as CssOverflowValue[];
87
-
88
- [...overflowOptions].forEach((value, i) => {
89
- const { queryAllByText } = render(
90
- <Box overflow={value} key={i}>
91
- Test Box
92
- </Box>
93
- );
94
- expect(queryAllByText('Test Box')[i].classList).toContain(
95
- `overflow-${value}`
96
- );
97
- });
120
+ ];
121
+ testTokenClasses('overflow', overflowOptions, 'overflow');
98
122
  });
99
123
 
100
- test('childGap margin classes are applied for column layout', () => {
101
- [...SPACING_OPTIONS].forEach((value, optionIndex) => {
124
+ const testChildGapClasses = (
125
+ direction: CssFlexDirectionValue | ResponsiveProp<CssFlexDirectionValue>,
126
+ marginClass: string
127
+ ) => {
128
+ SPACING_OPTIONS.forEach((value, optionIndex) => {
102
129
  const { container } = render(
103
- <Box childGap={value} key={optionIndex}>
130
+ <Box childGap={value} key={optionIndex} direction={direction}>
104
131
  <Box className="foo" key={`child1${optionIndex}`}>
105
132
  child 1
106
133
  </Box>
@@ -111,49 +138,68 @@ describe('Box', () => {
111
138
  );
112
139
 
113
140
  const { children } = container.children[0];
114
-
115
141
  Array.from(children).forEach((child, childIndex) => {
116
142
  expect(child.classList).toContain('foo');
117
- if (childIndex > children.length - 1) {
118
- expect(child.classList).toContain(`m-bottom-${value}`);
143
+ if (childIndex < children.length - 1) {
144
+ expect(child.classList).toContain(`${marginClass}-${value}`);
119
145
  }
120
146
  });
121
147
  });
148
+ };
149
+
150
+ test('childGap margin classes are applied for column layout', () => {
151
+ testChildGapClasses('column', 'm-bottom');
122
152
  });
123
153
 
124
154
  test('childGap margin classes are applied for row layout', () => {
125
- [...SPACING_OPTIONS].forEach((value, optionIndex) => {
126
- const { container } = render(
127
- <Box childGap={value} key={optionIndex} direction="row">
128
- <Box className="foo" key={`child1${optionIndex}`}>
129
- child 1
130
- </Box>
131
- <Box className="foo" key={`child2${optionIndex}`}>
132
- child 2
133
- </Box>
134
- </Box>
135
- );
155
+ testChildGapClasses('row', 'm-right');
156
+ });
136
157
 
137
- const { children } = container.children[0];
158
+ describe('Event Handlers', () => {
159
+ test('calls onClick handler when clicked', () => {
160
+ const handleClick = jest.fn();
161
+ const { getByText } = renderBox({ onClick: handleClick });
162
+ getByText('Test Box').click();
163
+ expect(handleClick).toHaveBeenCalledTimes(1);
164
+ });
138
165
 
139
- Array.from(children).forEach((child, childIndex) => {
140
- expect(child.classList).toContain('foo');
141
- if (childIndex > children.length - 1) {
142
- expect(child.classList).toContain(`m-right-${value}`);
143
- }
144
- });
166
+ test('calls onMouseEnter handler when hovered', () => {
167
+ const handleMouseEnter = jest.fn();
168
+ const { getByText } = renderBox({ onMouseEnter: handleMouseEnter });
169
+ fireEvent.mouseEnter(getByText('Test Box'));
170
+ expect(handleMouseEnter).toHaveBeenCalledTimes(1);
171
+ });
172
+
173
+ test('calls onMouseLeave handler when mouse leaves', () => {
174
+ const handleMouseLeave = jest.fn();
175
+ const { getByText } = renderBox({ onMouseLeave: handleMouseLeave });
176
+ fireEvent.mouseLeave(getByText('Test Box'));
177
+ expect(handleMouseLeave).toHaveBeenCalledTimes(1);
178
+ });
179
+
180
+ test('calls onFocus handler when focused', () => {
181
+ const handleFocus = jest.fn();
182
+ const { getByText } = renderBox({ onFocus: handleFocus });
183
+ fireEvent.focus(getByText('Test Box'));
184
+ expect(handleFocus).toHaveBeenCalledTimes(1);
185
+ });
186
+
187
+ test('calls onBlur handler when focus is lost', () => {
188
+ const handleBlur = jest.fn();
189
+ const { getByText } = renderBox({ onBlur: handleBlur });
190
+ fireEvent.blur(getByText('Test Box'));
191
+ expect(handleBlur).toHaveBeenCalledTimes(1);
145
192
  });
146
193
  });
147
194
 
148
195
  describe('Display', () => {
149
196
  test('box renders with default display value of flex', () => {
150
- const { getByText } = render(<Box>Hello</Box>);
151
-
152
- expect(getByText('Hello')).toHaveClass('display-flex');
197
+ const { getByText } = renderBox();
198
+ expect(getByText('Test Box')).toHaveClass('display-flex');
153
199
  });
154
200
 
155
201
  test('box renders with display class matching prop', () => {
156
- const displayValues = [
202
+ const displayValues: CssDisplayValue[] = [
157
203
  'flex',
158
204
  'inline-flex',
159
205
  'block',
@@ -161,13 +207,9 @@ describe('Box', () => {
161
207
  'inline',
162
208
  'inherit',
163
209
  'grid',
164
- ] as CssDisplayValue[];
165
-
166
- displayValues.forEach((value, i) => {
167
- const { queryAllByText } = render(<Box display={value}>hello</Box>);
168
-
169
- expect(queryAllByText('hello')[i]).toHaveClass(`display-${value}`);
170
- });
210
+ 'contents',
211
+ ];
212
+ testTokenClasses('display', displayValues, 'display');
171
213
  });
172
214
  });
173
215
 
@@ -182,121 +224,93 @@ describe('Box', () => {
182
224
  'inherit',
183
225
  'initial',
184
226
  'unset',
185
- ] as any[];
227
+ ];
186
228
 
187
229
  positions.forEach((p) => {
188
230
  test(`renders with class for position ${p}`, () => {
189
- const { getByText } = render(<Box position={p}>my box</Box>);
190
- expect(getByText('my box')).toHaveClass(`position-${p}`);
231
+ const { getByText } = renderBox({ position: p });
232
+ expect(getByText('Test Box')).toHaveClass(`position-${p}`);
191
233
  });
192
234
  });
193
235
  });
194
236
 
195
237
  describe('wrap', () => {
196
238
  test('box renders with wrap class if wrap is true', () => {
197
- const { getByText } = render(<Box wrap>Hello</Box>);
198
- expect(getByText('Hello')).toHaveClass('flex-wrap');
239
+ const { getByText } = renderBox({ wrap: true });
240
+ expect(getByText('Test Box')).toHaveClass('flex-wrap');
199
241
  });
200
242
 
201
243
  test('box renders with nowrap class if wrap is false', () => {
202
- const { getByText } = render(<Box wrap={false}>Hello</Box>);
203
- expect(getByText('Hello')).toHaveClass('flex-nowrap');
244
+ const { getByText } = renderBox({ wrap: false });
245
+ expect(getByText('Test Box')).toHaveClass('flex-nowrap');
204
246
  });
205
247
 
206
248
  test('box will not add wrap class if display is not flex', () => {
207
- const { getByText } = render(
208
- <Box display="block" wrap>
209
- Hello
210
- </Box>
211
- );
212
- expect(getByText('Hello')).not.toHaveClass('flex-wrap');
249
+ const { getByText } = renderBox({ display: 'block', wrap: true });
250
+ expect(getByText('Test Box')).not.toHaveClass('flex-wrap');
213
251
  });
214
252
  });
215
253
 
216
254
  describe('Responsive styles and Classes', () => {
217
- test('box renders with the correct responsive spacing classes based on props', () => {
218
- const spacing = {
219
- base: 'sm',
220
- tablet: 'md',
221
- desktop: 'lg',
222
- hd: 'xl',
223
- } as any;
224
-
225
- const position = {
226
- base: 'sticky',
227
- tablet: 'absolute',
228
- desktop: 'relative',
229
- hd: 'fixed',
230
- } as any;
231
- const { getByText } = render(
232
- <Box
233
- width={spacing}
234
- height={spacing}
235
- maxWidth={spacing}
236
- maxHeight={spacing}
237
- padding={spacing}
238
- margin={spacing}
239
- fontSize={spacing}
240
- position={position}
241
- >
242
- my box
243
- </Box>
244
- );
245
- const box = getByText('my box');
246
-
247
- expect(box).toHaveClass(
248
- ...[
249
- 'w-sm',
250
- 'w-md-tablet',
251
- 'w-lg-desktop',
252
- 'w-xl-hd',
253
- 'h-sm',
254
- 'h-md-tablet',
255
- 'h-lg-desktop',
256
- 'h-xl-hd',
257
- 'mw-sm',
258
- 'mw-md-tablet',
259
- 'mw-lg-desktop',
260
- 'mw-xl-hd',
261
- 'mh-sm',
262
- 'mh-md-tablet',
263
- 'mh-lg-desktop',
264
- 'mh-xl-hd',
265
- 'p-sm',
266
- 'p-md-tablet',
267
- 'p-lg-desktop',
268
- 'p-xl-hd',
269
- 'm-sm',
270
- 'm-md-tablet',
271
- 'm-lg-desktop',
272
- 'm-xl-hd',
273
- 'font-size-sm',
274
- 'font-size-md-tablet',
275
- 'font-size-lg-desktop',
276
- 'font-size-xl-hd',
277
- 'position-sticky',
278
- 'position-absolute-tablet',
279
- 'position-relative-desktop',
280
- 'position-fixed-hd',
281
- ]
282
- );
255
+ const responsiveProps = {
256
+ width: 'w',
257
+ height: 'h',
258
+ maxWidth: 'mw',
259
+ maxHeight: 'mh',
260
+ padding: 'p',
261
+ margin: 'm',
262
+ fontSize: 'font-size',
263
+ position: 'position',
264
+ zIndex: 'z-index',
265
+ radius: 'br',
266
+ shadow: 'shadow',
267
+ };
268
+
269
+ Object.entries(responsiveProps).forEach(([prop, classNamePrefix]) => {
270
+ test(`box renders with the correct responsive ${prop} classes based on props`, () => {
271
+ const responsiveValues = {
272
+ base: 'sm',
273
+ tablet: 'md',
274
+ desktop: 'lg',
275
+ hd: 'xl',
276
+ };
277
+ const { getByText } = renderBox({ [prop]: responsiveValues });
278
+ const box = getByText('Test Box');
279
+ expect(box).toHaveClass(
280
+ `${classNamePrefix}-sm`,
281
+ `${classNamePrefix}-md-tablet`,
282
+ `${classNamePrefix}-lg-desktop`,
283
+ `${classNamePrefix}-xl-hd`
284
+ );
285
+ });
283
286
  });
284
287
 
285
288
  test('box renders children with the correct gap classes for its children', () => {
286
- const direction = {
289
+ const direction: ResponsiveProp<CssFlexDirectionValue> = {
287
290
  base: 'column',
288
291
  tablet: 'column',
289
292
  desktop: 'row',
290
293
  hd: 'row',
291
- } as any;
292
-
293
- const childGap = {
294
+ };
295
+ const childGap: ResponsiveProp<
296
+ | 'sm'
297
+ | 'md'
298
+ | 'lg'
299
+ | 'xl'
300
+ | '0'
301
+ | '2xs'
302
+ | 'xs'
303
+ | '2xl'
304
+ | '3xl'
305
+ | '4xl'
306
+ | '5xl'
307
+ | 'auto'
308
+ > = {
294
309
  base: 'sm',
295
310
  tablet: 'md',
296
311
  desktop: 'lg',
297
312
  hd: 'xl',
298
- } as any;
299
-
313
+ };
300
314
  const { getByText } = render(
301
315
  <Box direction={direction} childGap={childGap}>
302
316
  <div>one</div>
@@ -304,175 +318,76 @@ describe('Box', () => {
304
318
  </Box>
305
319
  );
306
320
  const childBox = getByText('one');
307
-
308
321
  expect(childBox).toHaveClass(
309
- ...[
310
- 'm-bottom-sm',
311
- 'm-right-0',
312
- 'm-bottom-md-tablet',
313
- 'm-right-0-tablet',
314
- 'm-right-lg-desktop',
315
- 'm-bottom-0-desktop',
316
- 'm-right-xl-hd',
317
- 'm-bottom-0-hd',
318
- ]
322
+ 'm-bottom-sm',
323
+ 'm-right-0',
324
+ 'm-bottom-md-tablet',
325
+ 'm-right-0-tablet',
326
+ 'm-right-lg-desktop',
327
+ 'm-bottom-0-desktop',
328
+ 'm-right-xl-hd',
329
+ 'm-bottom-0-hd'
319
330
  );
320
331
  });
321
332
  });
322
333
 
323
334
  describe('Focus States', () => {
324
- test('Background Hover -- box rendered with proper background hover classes', () => {
325
- [...BACKGROUND_COLOR_OPTIONS].forEach((brandColorOption, i) => {
326
- const { queryAllByText } = render(
327
- <Box hover={{ background: brandColorOption }} key={i}>
328
- Test Box
329
- </Box>
330
- );
331
- expect(queryAllByText('Test Box')[i].classList).toContain(
332
- `hover:background-color-${brandColorOption}`
333
- );
334
- });
335
- });
336
-
337
- test('Border Color Hover -- box rendered with proper border color hover classes', () => {
338
- [...BORDER_COLOR_OPTIONS].forEach((brandColorOption, i) => {
339
- const { queryAllByText } = render(
340
- <Box hover={{ borderColor: brandColorOption }} key={i}>
341
- Test Box
342
- </Box>
343
- );
344
- expect(queryAllByText('Test Box')[i].classList).toContain(
345
- `hover:border-color-${brandColorOption}`
346
- );
347
- });
348
- });
349
-
350
- test('Border Width Hover -- box rendered with proper border width hover classes', () => {
351
- [...BORDER_SIZE_OPTIONS].forEach((borderWidthOption, i) => {
352
- const { queryAllByText } = render(
353
- <Box hover={{ borderWidth: borderWidthOption }} key={i}>
354
- Test Box
355
- </Box>
356
- );
357
- expect(queryAllByText('Test Box')[i].classList).toContain(
358
- `hover:border-width-${borderWidthOption}`
359
- );
360
- });
361
- });
362
-
363
- test('Font Size Hover -- box rendered with proper font size hover classes', () => {
364
- [...FONT_SIZE_OPTIONS].forEach((fontSizeOption, i) => {
335
+ const testFocusClasses = (
336
+ propName: string,
337
+ options: any[],
338
+ classNamePrefix: string
339
+ ) => {
340
+ options.forEach((option, i) => {
365
341
  const { queryAllByText } = render(
366
- <Box hover={{ fontSize: fontSizeOption }} key={i}>
342
+ <Box focus={{ [propName]: option }} key={i}>
367
343
  Test Box
368
344
  </Box>
369
345
  );
370
346
  expect(queryAllByText('Test Box')[i].classList).toContain(
371
- `hover:font-size-${fontSizeOption}`
347
+ `focus:${classNamePrefix}-${option}`
372
348
  );
373
349
  });
374
- });
350
+ };
375
351
 
376
- test('Font Color Hover -- box rendered with proper font color hover classes', () => {
377
- [...FONT_COLOR_OPTIONS].forEach((fontColorOption, i) => {
378
- const { queryAllByText } = render(
379
- <Box hover={{ color: fontColorOption }} key={i}>
380
- Test Box
381
- </Box>
382
- );
383
- expect(queryAllByText('Test Box')[i].classList).toContain(
384
- `hover:font-color-${fontColorOption}`
385
- );
386
- });
387
- });
388
-
389
- test('Shadow Hover -- box rendered with proper font color hover classes', () => {
390
- [...BOX_SHADOW_OPTIONS].forEach((boxShadowOption, i) => {
391
- const { queryAllByText } = render(
392
- <Box hover={{ shadow: boxShadowOption }} key={i}>
393
- Test Box
394
- </Box>
395
- );
396
- expect(queryAllByText('Test Box')[i].classList).toContain(
397
- `hover:shadow-${boxShadowOption}`
398
- );
399
- });
400
- });
401
- });
402
-
403
- describe('Focus States', () => {
404
352
  test('Background Focus -- box rendered with proper background focus classes', () => {
405
- [...BACKGROUND_COLOR_OPTIONS].forEach((brandColorOption, i) => {
406
- const { queryAllByText } = render(
407
- <Box focus={{ background: brandColorOption }} key={i}>
408
- Test Box
409
- </Box>
410
- );
411
- expect(queryAllByText('Test Box')[i].classList).toContain(
412
- `focus:background-color-${brandColorOption}`
413
- );
414
- });
353
+ testFocusClasses(
354
+ 'background',
355
+ BACKGROUND_COLOR_OPTIONS,
356
+ 'background-color'
357
+ );
415
358
  });
416
359
 
417
360
  test('Border Color Focus -- box rendered with proper border color focus classes', () => {
418
- [...BORDER_COLOR_OPTIONS].forEach((brandColorOption, i) => {
419
- const { queryAllByText } = render(
420
- <Box focus={{ borderColor: brandColorOption }} key={i}>
421
- Test Box
422
- </Box>
423
- );
424
- expect(queryAllByText('Test Box')[i].classList).toContain(
425
- `focus:border-color-${brandColorOption}`
426
- );
427
- });
361
+ testFocusClasses('borderColor', BORDER_COLOR_OPTIONS, 'border-color');
428
362
  });
429
363
 
430
364
  test('Border Width Focus -- box rendered with proper border width focus classes', () => {
431
- [...BORDER_SIZE_OPTIONS].forEach((borderWidthOption, i) => {
432
- const { queryAllByText } = render(
433
- <Box focus={{ borderWidth: borderWidthOption }} key={i}>
434
- Test Box
435
- </Box>
436
- );
437
- expect(queryAllByText('Test Box')[i].classList).toContain(
438
- `focus:border-width-${borderWidthOption}`
439
- );
440
- });
365
+ testFocusClasses('borderWidth', BORDER_SIZE_OPTIONS, 'border-width');
441
366
  });
442
367
 
443
368
  test('Font Color Focus -- box rendered with proper font color focus classes', () => {
444
- [...FONT_COLOR_OPTIONS].forEach((fontColorOption, i) => {
445
- const { queryAllByText } = render(
446
- <Box focus={{ color: fontColorOption }} key={i}>
447
- Test Box
448
- </Box>
449
- );
450
- expect(queryAllByText('Test Box')[i].classList).toContain(
451
- `focus:font-color-${fontColorOption}`
452
- );
453
- });
369
+ testFocusClasses('color', FONT_COLOR_OPTIONS, 'font-color');
454
370
  });
455
371
 
456
- test('Shadow Focus -- box rendered with proper font color focus classes', () => {
457
- [...BOX_SHADOW_OPTIONS].forEach((boxShadowOption, i) => {
458
- const { queryAllByText } = render(
459
- <Box focus={{ shadow: boxShadowOption }} key={i}>
460
- Test Box
461
- </Box>
462
- );
463
- expect(queryAllByText('Test Box')[i].classList).toContain(
464
- `focus:shadow-${boxShadowOption}`
465
- );
466
- });
372
+ test('Shadow Focus -- box rendered with proper shadow focus classes', () => {
373
+ testFocusClasses('shadow', BOX_SHADOW_OPTIONS, 'shadow');
467
374
  });
468
375
  });
469
376
 
470
377
  describe('Cursor', () => {
471
378
  test('Renders with proper cursor utility class when prop is passed', () => {
472
- const { queryAllByText } = render(<Box cursor="pointer">Test Box</Box>);
379
+ const { queryAllByText } = renderBox({ cursor: 'pointer' });
473
380
  expect(queryAllByText('Test Box')[0].classList).toContain(
474
381
  'cursor-pointer'
475
382
  );
476
383
  });
477
384
  });
385
+
386
+ test('padding classes are applied', () => {
387
+ testTokenClasses('padding', SPACING_OPTIONS, 'p');
388
+ });
389
+
390
+ test('margin classes are applied', () => {
391
+ testTokenClasses('margin', SPACING_OPTIONS, 'm');
392
+ });
478
393
  });
@@ -27,6 +27,9 @@
27
27
  .display-table-cell {
28
28
  display: table-cell;
29
29
  }
30
+ .display-contents {
31
+ display: contents;
32
+ }
30
33
 
31
34
  @media (min-width: $size-breakpoint-tablet) {
32
35
  .display-inherit-tablet {
@@ -56,6 +59,9 @@
56
59
  .display-table-cell-tablet {
57
60
  display: table-cell;
58
61
  }
62
+ .display-contents-tablet {
63
+ display: contents;
64
+ }
59
65
  }
60
66
 
61
67
  @media (min-width: $size-breakpoint-desktop) {
@@ -86,6 +92,9 @@
86
92
  .display-table-cell-desktop {
87
93
  display: table-cell;
88
94
  }
95
+ .display-contents-desktop {
96
+ display: contents;
97
+ }
89
98
  }
90
99
 
91
100
  @media (min-width: $size-breakpoint-hd) {
@@ -116,4 +125,7 @@
116
125
  .display-table-cell-hd {
117
126
  display: table-cell;
118
127
  }
128
+ .display-contents-hd {
129
+ display: contents;
130
+ }
119
131
  }
@@ -119,7 +119,8 @@ export type CssDisplayValue =
119
119
  | 'inline'
120
120
  | 'inherit'
121
121
  | 'grid'
122
- | 'table-cell';
122
+ | 'table-cell'
123
+ | 'contents';
123
124
 
124
125
  export type CssTextAlignValue = 'left' | 'center' | 'right';
125
126