@automattic/vip-design-system 2.18.1 → 2.20.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.
- package/.storybook/preview-head.html +1 -0
- package/build/system/Badge/Badge.js +2 -1
- package/build/system/DescriptionList/DescriptionList.js +0 -1
- package/build/system/Form/Label.d.ts +1 -3
- package/build/system/Form/Label.js +1 -3
- package/build/system/Form/RadioBoxGroup.jsx +12 -1
- package/build/system/Form/RadioBoxGroup.stories.jsx +6 -1
- package/build/system/Heading/Heading.js +2 -3
- package/build/system/Heading/Heading.stories.js +15 -2
- package/build/system/Nav/styles/variants/menu.js +1 -2
- package/build/system/NewForm/FormAutocompleteMultiselect.jsx +143 -12
- package/build/system/NewForm/FormAutocompleteMultiselect.stories.d.ts +22 -2
- package/build/system/NewForm/FormAutocompleteMultiselect.stories.jsx +21 -0
- package/build/system/NewForm/FormAutocompleteMultiselect.test.jsx +67 -1
- package/build/system/NewForm/FormAutocompleteMultiselectInlineChip.d.ts +7 -0
- package/build/system/NewForm/FormAutocompleteMultiselectInlineChip.js +62 -0
- package/build/system/Notice/Notice.js +1 -1
- package/build/system/Pagination/styles.js +1 -4
- package/build/system/Table/TableCell.js +1 -1
- package/build/system/Text/Text.js +0 -1
- package/build/system/Text/Text.stories.js +16 -13
- package/build/system/Toolbar/Logo.js +22 -6
- package/build/system/Wizard/Wizard.stories.js +11 -11
- package/build/system/Wizard/WizardStep.js +0 -2
- package/build/system/theme/generated/valet-theme-dark.json +224 -227
- package/build/system/theme/generated/valet-theme-light.json +224 -227
- package/build/system/theme/getPropValue.js +3 -7
- package/build/system/theme/index.d.ts +20 -12
- package/build/system/theme/index.js +27 -20
- package/docs/SETUP.md +1 -1
- package/package.json +1 -1
- package/src/system/Badge/Badge.tsx +2 -1
- package/src/system/DescriptionList/DescriptionList.tsx +0 -1
- package/src/system/Form/Label.tsx +1 -3
- package/src/system/Form/RadioBoxGroup.jsx +12 -1
- package/src/system/Form/RadioBoxGroup.stories.jsx +6 -1
- package/src/system/Heading/Heading.stories.tsx +10 -1
- package/src/system/Heading/Heading.tsx +1 -2
- package/src/system/Nav/styles/variants/menu.ts +1 -2
- package/src/system/NewForm/FormAutocompleteMultiselect.jsx +143 -12
- package/src/system/NewForm/FormAutocompleteMultiselect.stories.jsx +21 -0
- package/src/system/NewForm/FormAutocompleteMultiselect.test.jsx +67 -1
- package/src/system/NewForm/FormAutocompleteMultiselectInlineChip.tsx +72 -0
- package/src/system/Notice/Notice.tsx +1 -1
- package/src/system/Pagination/styles.ts +1 -4
- package/src/system/Table/TableCell.tsx +1 -1
- package/src/system/Text/Text.stories.tsx +7 -4
- package/src/system/Text/Text.tsx +0 -1
- package/src/system/Toolbar/Logo.tsx +19 -2
- package/src/system/Wizard/Wizard.stories.tsx +11 -11
- package/src/system/Wizard/WizardStep.tsx +0 -2
- package/src/system/theme/generated/valet-theme-dark.json +224 -227
- package/src/system/theme/generated/valet-theme-light.json +224 -227
- package/src/system/theme/getPropValue.ts +1 -8
- package/src/system/theme/index.ts +33 -18
- package/tokens/valet-core/valet-core.json +39 -9
- package/tokens/valet-core/wpvip-product-core.json +88 -125
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<link rel="stylesheet" href="https://use.typekit.net/yym8qzc.css" />
|
|
@@ -25,6 +25,7 @@ export var Badge = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
25
25
|
as: "span",
|
|
26
26
|
sx: _extends({
|
|
27
27
|
fontSize: 0,
|
|
28
|
+
letterSpacing: '0.01em',
|
|
28
29
|
padding: 0,
|
|
29
30
|
// do we need padding declared twice here?
|
|
30
31
|
bg: "tag." + variant + ".background",
|
|
@@ -34,7 +35,7 @@ export var Badge = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
34
35
|
px: 2,
|
|
35
36
|
display: 'inline-block',
|
|
36
37
|
borderRadius: 1,
|
|
37
|
-
fontWeight: '
|
|
38
|
+
fontWeight: 'medium',
|
|
38
39
|
a: {
|
|
39
40
|
color: "tag." + variant + ".text",
|
|
40
41
|
'&:hover, &:focus, &:active': {
|
|
@@ -6,9 +6,7 @@ import React from 'react';
|
|
|
6
6
|
import { BoxProps } from 'theme-ui';
|
|
7
7
|
export declare const baseLabelColor = "input.label.default";
|
|
8
8
|
export declare const baseLabelStyle: {
|
|
9
|
-
|
|
10
|
-
fontSize: number;
|
|
11
|
-
lineHeight: number;
|
|
9
|
+
variant: string;
|
|
12
10
|
color: string;
|
|
13
11
|
};
|
|
14
12
|
export interface LabelProps extends BoxProps {
|
|
@@ -16,9 +16,7 @@ import { RequiredLabel } from './RequiredLabel';
|
|
|
16
16
|
import { jsx as _jsx, jsxs as _jsxs } from "theme-ui/jsx-runtime";
|
|
17
17
|
export var baseLabelColor = 'input.label.default';
|
|
18
18
|
export var baseLabelStyle = {
|
|
19
|
-
|
|
20
|
-
fontSize: 2,
|
|
21
|
-
lineHeight: 1.5,
|
|
19
|
+
variant: 'forms.label',
|
|
22
20
|
color: baseLabelColor
|
|
23
21
|
};
|
|
24
22
|
/**
|
|
@@ -72,7 +72,14 @@ const RadioOption = ( {
|
|
|
72
72
|
{ ...restOption }
|
|
73
73
|
/>
|
|
74
74
|
<div
|
|
75
|
-
sx={ {
|
|
75
|
+
sx={ {
|
|
76
|
+
mb: 0,
|
|
77
|
+
color: 'input.radio-box.label.primary.default',
|
|
78
|
+
fontWeight: 'semibold',
|
|
79
|
+
p: 3,
|
|
80
|
+
pr: 0,
|
|
81
|
+
flex: 'auto',
|
|
82
|
+
} }
|
|
76
83
|
>
|
|
77
84
|
<label htmlFor={ forLabel } { ...labelProps }>
|
|
78
85
|
{ label }
|
|
@@ -82,7 +89,11 @@ const RadioOption = ( {
|
|
|
82
89
|
sx={ {
|
|
83
90
|
color: 'input.radio-box.label.secondary.default',
|
|
84
91
|
mb: 0,
|
|
92
|
+
mt: 1,
|
|
85
93
|
fontSize: 1,
|
|
94
|
+
fontWeight: 'regular',
|
|
95
|
+
letterSpacing: '0.01em',
|
|
96
|
+
lineHeight: '140%',
|
|
86
97
|
display: 'block',
|
|
87
98
|
} }
|
|
88
99
|
id={ describedById }
|
|
@@ -60,7 +60,12 @@ export const Primary = {
|
|
|
60
60
|
args: {
|
|
61
61
|
defaultValue: 'one',
|
|
62
62
|
options: [
|
|
63
|
-
{
|
|
63
|
+
{
|
|
64
|
+
label: 'One',
|
|
65
|
+
value: 'one',
|
|
66
|
+
description:
|
|
67
|
+
'This is a longer description that allows us to see the text wrap and determine if the line height is correct',
|
|
68
|
+
},
|
|
64
69
|
{ label: 'Two', value: 'two', description: 'This is a description' },
|
|
65
70
|
{ label: 'Three', value: 'three', description: 'This is a description' },
|
|
66
71
|
],
|
|
@@ -19,10 +19,9 @@ export var Heading = /*#__PURE__*/forwardRef(function (_ref, ref) {
|
|
|
19
19
|
rest = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
20
20
|
return _jsx(ThemeHeading, _extends({
|
|
21
21
|
as: variant,
|
|
22
|
+
variant: variant,
|
|
22
23
|
sx: _extends({
|
|
23
|
-
color: 'heading'
|
|
24
|
-
// pass variant prop to sx
|
|
25
|
-
variant: "text." + variant.toString()
|
|
24
|
+
color: 'heading'
|
|
26
25
|
}, sx),
|
|
27
26
|
className: classNames('vip-heading-component', className),
|
|
28
27
|
ref: ref
|
|
@@ -32,8 +32,21 @@ export var Default = {
|
|
|
32
32
|
variant: "h5",
|
|
33
33
|
children: "Heading Five"
|
|
34
34
|
}), _jsx(Heading, {
|
|
35
|
-
variant: "
|
|
36
|
-
|
|
35
|
+
variant: "h3",
|
|
36
|
+
as: "h1",
|
|
37
|
+
children: "Heading One with Heading Three Styles"
|
|
38
|
+
}), _jsx(Heading, {
|
|
39
|
+
as: "p",
|
|
40
|
+
sx: {
|
|
41
|
+
variant: 'text.caps'
|
|
42
|
+
},
|
|
43
|
+
children: "Paragraph with Caps Styles"
|
|
44
|
+
}), _jsx(Heading, {
|
|
45
|
+
as: "h3",
|
|
46
|
+
sx: {
|
|
47
|
+
variant: 'text.caps'
|
|
48
|
+
},
|
|
49
|
+
children: "Heading Three with Caps Styles"
|
|
37
50
|
})]
|
|
38
51
|
});
|
|
39
52
|
}
|
|
@@ -13,6 +13,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
|
13
13
|
*/
|
|
14
14
|
import { FormAutocompleteMultiselectBadge } from './FormAutocompleteMultiselectBadge';
|
|
15
15
|
import { FormAutocompleteMultiselectButton } from './FormAutocompleteMultiselectButton';
|
|
16
|
+
import { FormAutocompleteMultiselectInlineChip } from './FormAutocompleteMultiselectInlineChip';
|
|
16
17
|
import { FormSelectArrow } from './FormSelectArrow';
|
|
17
18
|
import { FormSelectContent } from './FormSelectContent';
|
|
18
19
|
import { FormSelectLoading } from './FormSelectLoading';
|
|
@@ -22,6 +23,14 @@ import { Validation } from '../Form';
|
|
|
22
23
|
import { baseControlBorderStyle, inputBaseText } from '../Form/Input.styles';
|
|
23
24
|
import { Label } from '../Form/Label';
|
|
24
25
|
|
|
26
|
+
const escapeHtml = str =>
|
|
27
|
+
String( str )
|
|
28
|
+
.replace( /&/g, '&' )
|
|
29
|
+
.replace( /</g, '<' )
|
|
30
|
+
.replace( />/g, '>' )
|
|
31
|
+
.replace( /"/g, '"' )
|
|
32
|
+
.replace( /'/g, ''' );
|
|
33
|
+
|
|
25
34
|
const baseBorderTextColors = {
|
|
26
35
|
...baseControlBorderStyle,
|
|
27
36
|
backgroundColor: 'layer.2',
|
|
@@ -96,7 +105,33 @@ const searchIconStyles = {
|
|
|
96
105
|
},
|
|
97
106
|
};
|
|
98
107
|
|
|
99
|
-
const
|
|
108
|
+
const inlineChipsContainerStyles = {
|
|
109
|
+
...defaultStyles,
|
|
110
|
+
display: 'flex',
|
|
111
|
+
flexWrap: 'wrap',
|
|
112
|
+
alignItems: 'center',
|
|
113
|
+
p: 1,
|
|
114
|
+
pr: 0,
|
|
115
|
+
position: 'relative',
|
|
116
|
+
'& .autocomplete__input': {
|
|
117
|
+
...defaultStyles[ '& .autocomplete__input' ],
|
|
118
|
+
lineHeight: '24px',
|
|
119
|
+
minHeight: '24px',
|
|
120
|
+
},
|
|
121
|
+
'&:focus-within': theme => theme.outline,
|
|
122
|
+
'& .autocomplete__wrapper': {
|
|
123
|
+
position: 'static',
|
|
124
|
+
width: '100%',
|
|
125
|
+
lineHeight: '24px',
|
|
126
|
+
minHeight: '24px',
|
|
127
|
+
'& .autocomplete__dropdown-arrow-down': {
|
|
128
|
+
top: 'unset',
|
|
129
|
+
bottom: '6px',
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const DefaultArrow = config => <FormSelectArrow className={ config.className } />;
|
|
100
135
|
|
|
101
136
|
const AddSelectionStatus = ( { status } ) => {
|
|
102
137
|
return (
|
|
@@ -156,10 +191,12 @@ const FormAutocompleteMultiselect = React.forwardRef(
|
|
|
156
191
|
listType = 'button',
|
|
157
192
|
initialValue = [],
|
|
158
193
|
allowCustom = false,
|
|
194
|
+
variant,
|
|
159
195
|
...props
|
|
160
196
|
},
|
|
161
197
|
forwardRef
|
|
162
198
|
) => {
|
|
199
|
+
const isInlineChips = variant === 'inline-chips';
|
|
163
200
|
const OPTION_ACTION = {
|
|
164
201
|
ADD: 'add',
|
|
165
202
|
REMOVE: 'remove',
|
|
@@ -175,6 +212,7 @@ const FormAutocompleteMultiselect = React.forwardRef(
|
|
|
175
212
|
option: null,
|
|
176
213
|
index: -1,
|
|
177
214
|
} );
|
|
215
|
+
const justSelectedRef = React.useRef( false );
|
|
178
216
|
let debounceTimeout;
|
|
179
217
|
forwardRef = forwardRef || React.createRef();
|
|
180
218
|
|
|
@@ -283,11 +321,44 @@ const FormAutocompleteMultiselect = React.forwardRef(
|
|
|
283
321
|
data = handleTypeChange( query );
|
|
284
322
|
}
|
|
285
323
|
const optionForDisplay = data?.map( option => optionLabel( option ) );
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
324
|
+
if ( isInlineChips ) {
|
|
325
|
+
populateResults( optionForDisplay );
|
|
326
|
+
} else {
|
|
327
|
+
populateResults(
|
|
328
|
+
optionForDisplay.filter( option => ! selectedOptions.includes( option ) )
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
[ autoFilter, isDirty, isInlineChips, onInputChange, options, selectedOptions ]
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
const onValueChangeInlineChips = useCallback(
|
|
336
|
+
inputValue => {
|
|
337
|
+
if ( ! inputValue ) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
justSelectedRef.current = true;
|
|
341
|
+
if ( selectedOptions.includes( inputValue ) ) {
|
|
342
|
+
unselectValue( inputValue, selectedOptions.indexOf( inputValue ) );
|
|
343
|
+
} else {
|
|
344
|
+
setCurrentOption( { action: OPTION_ACTION.ADD, option: inputValue } );
|
|
345
|
+
setSelectedOptions( [ ...selectedOptions, inputValue ] );
|
|
346
|
+
}
|
|
289
347
|
},
|
|
290
|
-
[
|
|
348
|
+
[ selectedOptions, unselectValue ]
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
const inlineChipsTemplates = useMemo(
|
|
352
|
+
() => ( {
|
|
353
|
+
suggestion: suggestion => {
|
|
354
|
+
const isSelected = selectedOptions.includes( suggestion );
|
|
355
|
+
const check = isSelected ? '✓' : '';
|
|
356
|
+
return `<span style="display:flex;align-items:center;gap:8px"><span style="width:16px;flex-shrink:0">${ check }</span>${ escapeHtml(
|
|
357
|
+
suggestion
|
|
358
|
+
) }</span>`;
|
|
359
|
+
},
|
|
360
|
+
} ),
|
|
361
|
+
[ selectedOptions ]
|
|
291
362
|
);
|
|
292
363
|
|
|
293
364
|
useEffect( () => {
|
|
@@ -332,7 +403,16 @@ const FormAutocompleteMultiselect = React.forwardRef(
|
|
|
332
403
|
selectedOptions,
|
|
333
404
|
selectedOptions.map( option => option?.label || option )
|
|
334
405
|
);
|
|
335
|
-
|
|
406
|
+
if ( isInlineChips && justSelectedRef.current && forwardRef?.current ) {
|
|
407
|
+
justSelectedRef.current = false;
|
|
408
|
+
forwardRef.current.setState( {
|
|
409
|
+
...forwardRef.current.state,
|
|
410
|
+
query: '',
|
|
411
|
+
menuOpen: true,
|
|
412
|
+
} );
|
|
413
|
+
} else {
|
|
414
|
+
resetInputState();
|
|
415
|
+
}
|
|
336
416
|
}, [ selectedOptions ] );
|
|
337
417
|
|
|
338
418
|
// Update the select status for screen readers
|
|
@@ -340,15 +420,65 @@ const FormAutocompleteMultiselect = React.forwardRef(
|
|
|
340
420
|
if ( currentOption.action === OPTION_ACTION.ADD ) {
|
|
341
421
|
setAddStatus( `${ currentOption.option } added to the list.` );
|
|
342
422
|
setCurrentOption( { action: OPTION_ACTION.NONE, option: null } );
|
|
343
|
-
} else if ( currentOption.
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
423
|
+
} else if ( currentOption.action === OPTION_ACTION.REMOVE ) {
|
|
424
|
+
setAddStatus( `${ currentOption.option } removed from the list.` );
|
|
425
|
+
if ( isInlineChips ) {
|
|
426
|
+
global.document.querySelector( `#${ forLabel }` )?.focus();
|
|
427
|
+
} else if ( currentOption.index === selectedOptions.length && selectedOptions.length > 0 ) {
|
|
428
|
+
global.document.querySelector( '.vip-button-component' )?.focus();
|
|
429
|
+
} else if ( selectedOptions.length === 0 ) {
|
|
430
|
+
global.document.querySelector( '.autocomplete__input' )?.focus();
|
|
431
|
+
}
|
|
432
|
+
setCurrentOption( { action: OPTION_ACTION.NONE, option: null } );
|
|
349
433
|
}
|
|
350
434
|
}, [ currentOption ] );
|
|
351
435
|
|
|
436
|
+
if ( isInlineChips ) {
|
|
437
|
+
return (
|
|
438
|
+
<div className={ classNames( 'vip-form-autocomplete-component', className ) }>
|
|
439
|
+
{ label && <SelectLabel /> }
|
|
440
|
+
<div sx={ inlineChipsContainerStyles }>
|
|
441
|
+
{ selectedOptions.map( ( option, idx ) => (
|
|
442
|
+
<FormAutocompleteMultiselectInlineChip
|
|
443
|
+
key={ option }
|
|
444
|
+
index={ idx }
|
|
445
|
+
option={ option }
|
|
446
|
+
unselectValue={ unselectValue }
|
|
447
|
+
/>
|
|
448
|
+
) ) }
|
|
449
|
+
<div sx={ { flex: '1 1 120px', minWidth: '120px' } }>
|
|
450
|
+
<Autocomplete
|
|
451
|
+
id={ forLabel }
|
|
452
|
+
aria-busy={ loading }
|
|
453
|
+
showAllValues={ true }
|
|
454
|
+
ref={ forwardRef }
|
|
455
|
+
source={ source || suggest }
|
|
456
|
+
defaultValue={ value }
|
|
457
|
+
displayMenu={ displayMenu }
|
|
458
|
+
onConfirm={ onValueChangeInlineChips }
|
|
459
|
+
tNoResults={ noOptionsMessage }
|
|
460
|
+
required={ required }
|
|
461
|
+
dropdownArrow={ dropdownArrow }
|
|
462
|
+
confirmOnBlur={ false }
|
|
463
|
+
templates={ inlineChipsTemplates }
|
|
464
|
+
{ ...props }
|
|
465
|
+
placeholder={ selectedOptions.length > 0 ? '' : props.placeholder || '' }
|
|
466
|
+
/>
|
|
467
|
+
</div>
|
|
468
|
+
{ addStatus && <AddSelectionStatus status={ addStatus } /> }
|
|
469
|
+
{ loading && <FormSelectLoading sx={ { right: 7 } } /> }
|
|
470
|
+
</div>
|
|
471
|
+
{ hasError && errorMessage && (
|
|
472
|
+
<Flex sx={ { mt: 2 } }>
|
|
473
|
+
<Validation isValid={ false } describedId={ forLabel }>
|
|
474
|
+
{ errorMessage }
|
|
475
|
+
</Validation>
|
|
476
|
+
</Flex>
|
|
477
|
+
) }
|
|
478
|
+
</div>
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
|
|
352
482
|
return (
|
|
353
483
|
<div className={ classNames( 'vip-form-autocomplete-component', className ) }>
|
|
354
484
|
{ label && ! isInline && <SelectLabel /> }
|
|
@@ -435,6 +565,7 @@ FormAutocompleteMultiselect.propTypes = {
|
|
|
435
565
|
dropdownArrow: PropTypes.node,
|
|
436
566
|
initialValue: PropTypes.array,
|
|
437
567
|
allowCustom: PropTypes.bool,
|
|
568
|
+
variant: PropTypes.string,
|
|
438
569
|
};
|
|
439
570
|
|
|
440
571
|
FormAutocompleteMultiselect.displayName = 'FormAutocompleteMultiselect';
|
|
@@ -92,9 +92,29 @@ export namespace WithStaticData {
|
|
|
92
92
|
}
|
|
93
93
|
export { args_5 as args };
|
|
94
94
|
}
|
|
95
|
-
export namespace
|
|
96
|
-
export function render_6(): import("react").JSX.Element;
|
|
95
|
+
export namespace InlineChips {
|
|
96
|
+
export function render_6(props: any): import("react").JSX.Element;
|
|
97
97
|
export { render_6 as render };
|
|
98
|
+
export namespace args_6 {
|
|
99
|
+
let label_3: string;
|
|
100
|
+
export { label_3 as label };
|
|
101
|
+
export let options: {
|
|
102
|
+
value: string;
|
|
103
|
+
label: string;
|
|
104
|
+
}[];
|
|
105
|
+
export let variant: string;
|
|
106
|
+
let showAllValues_2: boolean;
|
|
107
|
+
export { showAllValues_2 as showAllValues };
|
|
108
|
+
let placeholder_3: string;
|
|
109
|
+
export { placeholder_3 as placeholder };
|
|
110
|
+
let initialValue_1: string[];
|
|
111
|
+
export { initialValue_1 as initialValue };
|
|
112
|
+
}
|
|
113
|
+
export { args_6 as args };
|
|
114
|
+
}
|
|
115
|
+
export namespace WithDynamicData {
|
|
116
|
+
export function render_7(): import("react").JSX.Element;
|
|
117
|
+
export { render_7 as render };
|
|
98
118
|
}
|
|
99
119
|
declare const shortOptions: {
|
|
100
120
|
value: string;
|
|
@@ -134,6 +134,27 @@ export const WithStaticData = {
|
|
|
134
134
|
},
|
|
135
135
|
};
|
|
136
136
|
|
|
137
|
+
export const InlineChips = {
|
|
138
|
+
render: props => <DefaultComponent { ...props } width={ 500 } />,
|
|
139
|
+
args: {
|
|
140
|
+
label: 'Post Categories',
|
|
141
|
+
options: [
|
|
142
|
+
{ value: 'breaking-news', label: 'Breaking News' },
|
|
143
|
+
{ value: 'world-news', label: 'World News' },
|
|
144
|
+
{ value: 'us-news', label: 'U.S. News' },
|
|
145
|
+
{ value: 'climate-environment', label: 'Climate & Environment' },
|
|
146
|
+
{ value: 'obituaries', label: 'Obituaries' },
|
|
147
|
+
{ value: 'technology', label: 'Technology' },
|
|
148
|
+
{ value: 'entertainment', label: 'Entertainment' },
|
|
149
|
+
{ value: 'real-estate', label: 'Real Estate' },
|
|
150
|
+
],
|
|
151
|
+
variant: 'inline-chips',
|
|
152
|
+
showAllValues: true,
|
|
153
|
+
placeholder: 'Search categories...',
|
|
154
|
+
initialValue: [ 'Breaking News' ],
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
|
|
137
158
|
export const WithDynamicData = {
|
|
138
159
|
render: () => {
|
|
139
160
|
const [ selectedValues, setSelectedValues ] = useState( [] );
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
5
5
|
import { axe } from 'jest-axe';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -37,3 +37,69 @@ describe( '<FormAutocompleteMultiselect />', () => {
|
|
|
37
37
|
await expect( await axe( container ) ).toHaveNoViolations();
|
|
38
38
|
} );
|
|
39
39
|
} );
|
|
40
|
+
|
|
41
|
+
describe( '<FormAutocompleteMultiselect variant="inline-chips" />', () => {
|
|
42
|
+
it( 'renders the inline-chips variant', async () => {
|
|
43
|
+
const { container } = render(
|
|
44
|
+
<FormAutocompleteMultiselect
|
|
45
|
+
forLabel="my_inline_chips"
|
|
46
|
+
label="Categories"
|
|
47
|
+
options={ options }
|
|
48
|
+
variant="inline-chips"
|
|
49
|
+
showAllValues
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
expect( screen.getByLabelText( 'Categories' ) ).toBeInTheDocument();
|
|
53
|
+
await expect( await axe( container ) ).toHaveNoViolations();
|
|
54
|
+
} );
|
|
55
|
+
|
|
56
|
+
it( 'renders initial values as inline chips', () => {
|
|
57
|
+
render(
|
|
58
|
+
<FormAutocompleteMultiselect
|
|
59
|
+
forLabel="my_inline_chips_init"
|
|
60
|
+
label="Categories"
|
|
61
|
+
options={ options }
|
|
62
|
+
variant="inline-chips"
|
|
63
|
+
showAllValues
|
|
64
|
+
initialValue={ [ 'Chocolate', 'Vanilla' ] }
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
expect( screen.getByText( 'Chocolate' ) ).toBeInTheDocument();
|
|
68
|
+
expect( screen.getByText( 'Vanilla' ) ).toBeInTheDocument();
|
|
69
|
+
expect( screen.getByRole( 'button', { name: 'Remove Chocolate' } ) ).toBeInTheDocument();
|
|
70
|
+
expect( screen.getByRole( 'button', { name: 'Remove Vanilla' } ) ).toBeInTheDocument();
|
|
71
|
+
} );
|
|
72
|
+
|
|
73
|
+
it( 'removes a chip when the close button is clicked', () => {
|
|
74
|
+
render(
|
|
75
|
+
<FormAutocompleteMultiselect
|
|
76
|
+
forLabel="my_inline_chips_remove"
|
|
77
|
+
label="Categories"
|
|
78
|
+
options={ options }
|
|
79
|
+
variant="inline-chips"
|
|
80
|
+
showAllValues
|
|
81
|
+
initialValue={ [ 'Chocolate', 'Vanilla' ] }
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
expect( screen.getByText( 'Chocolate' ) ).toBeInTheDocument();
|
|
85
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Remove Chocolate' } ) );
|
|
86
|
+
expect( screen.queryByText( 'Chocolate' ) ).not.toBeInTheDocument();
|
|
87
|
+
expect( screen.getByText( 'Vanilla' ) ).toBeInTheDocument();
|
|
88
|
+
} );
|
|
89
|
+
|
|
90
|
+
it( 'announces removal to screen readers', () => {
|
|
91
|
+
const { container } = render(
|
|
92
|
+
<FormAutocompleteMultiselect
|
|
93
|
+
forLabel="my_inline_chips_a11y"
|
|
94
|
+
label="Categories"
|
|
95
|
+
options={ options }
|
|
96
|
+
variant="inline-chips"
|
|
97
|
+
showAllValues
|
|
98
|
+
initialValue={ [ 'Chocolate', 'Vanilla' ] }
|
|
99
|
+
/>
|
|
100
|
+
);
|
|
101
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Remove Chocolate' } ) );
|
|
102
|
+
const statusEl = container.querySelector( '#vip-autocompletemultiselect-status' );
|
|
103
|
+
expect( statusEl ).toHaveTextContent( 'Chocolate removed from the list.' );
|
|
104
|
+
} );
|
|
105
|
+
} );
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
declare const FormAutocompleteMultiselectInlineChip: ({ index, option, unselectValue, }: {
|
|
3
|
+
index: number;
|
|
4
|
+
option: string;
|
|
5
|
+
unselectValue: (option: string, index: number) => void;
|
|
6
|
+
}) => import("react").JSX.Element;
|
|
7
|
+
export { FormAutocompleteMultiselectInlineChip };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* External dependencies
|
|
5
|
+
*/
|
|
6
|
+
import { MdClose } from 'react-icons/md';
|
|
7
|
+
import { jsx as _jsx, jsxs as _jsxs } from "theme-ui/jsx-runtime";
|
|
8
|
+
var FormAutocompleteMultiselectInlineChip = function FormAutocompleteMultiselectInlineChip(_ref) {
|
|
9
|
+
var index = _ref.index,
|
|
10
|
+
option = _ref.option,
|
|
11
|
+
unselectValue = _ref.unselectValue;
|
|
12
|
+
return _jsxs("span", {
|
|
13
|
+
sx: {
|
|
14
|
+
display: 'inline-flex',
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
gap: 1,
|
|
17
|
+
px: 2,
|
|
18
|
+
py: '2px',
|
|
19
|
+
m: 1,
|
|
20
|
+
bg: 'layer.1',
|
|
21
|
+
borderRadius: 1,
|
|
22
|
+
fontSize: 1,
|
|
23
|
+
lineHeight: '16px',
|
|
24
|
+
whiteSpace: 'nowrap',
|
|
25
|
+
maxWidth: '100%'
|
|
26
|
+
},
|
|
27
|
+
children: [_jsx("span", {
|
|
28
|
+
sx: {
|
|
29
|
+
overflow: 'hidden',
|
|
30
|
+
textOverflow: 'ellipsis',
|
|
31
|
+
whiteSpace: 'nowrap'
|
|
32
|
+
},
|
|
33
|
+
children: option
|
|
34
|
+
}), _jsx("button", {
|
|
35
|
+
type: "button",
|
|
36
|
+
"aria-label": "Remove " + option,
|
|
37
|
+
onClick: function onClick(e) {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
e.stopPropagation();
|
|
40
|
+
unselectValue(option, index);
|
|
41
|
+
},
|
|
42
|
+
sx: {
|
|
43
|
+
display: 'inline-flex',
|
|
44
|
+
alignItems: 'center',
|
|
45
|
+
justifyContent: 'center',
|
|
46
|
+
p: 0,
|
|
47
|
+
border: 'none',
|
|
48
|
+
bg: 'transparent',
|
|
49
|
+
cursor: 'pointer',
|
|
50
|
+
color: 'text',
|
|
51
|
+
lineHeight: 0,
|
|
52
|
+
'&:hover': {
|
|
53
|
+
opacity: 0.7
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
children: _jsx(MdClose, {
|
|
57
|
+
size: 14
|
|
58
|
+
})
|
|
59
|
+
})]
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
export { FormAutocompleteMultiselectInlineChip };
|
|
@@ -23,8 +23,7 @@ export var pageButtonStyles = {
|
|
|
23
23
|
bg: 'transparent',
|
|
24
24
|
color: 'heading',
|
|
25
25
|
cursor: 'pointer',
|
|
26
|
-
|
|
27
|
-
fontFamily: 'body',
|
|
26
|
+
variant: 'text.default',
|
|
28
27
|
px: 2,
|
|
29
28
|
borderBottom: '3px solid',
|
|
30
29
|
borderColor: 'transparent',
|
|
@@ -79,8 +78,6 @@ export var compactTriggerStyles = {
|
|
|
79
78
|
bg: 'transparent',
|
|
80
79
|
color: 'heading',
|
|
81
80
|
cursor: 'pointer',
|
|
82
|
-
fontSize: 2,
|
|
83
|
-
fontFamily: 'body',
|
|
84
81
|
fontWeight: 'bold',
|
|
85
82
|
px: 2,
|
|
86
83
|
borderRadius: 1,
|
|
@@ -27,7 +27,7 @@ export var TableCell = function TableCell(_ref) {
|
|
|
27
27
|
borderTop: head ? '1px solid' : 'none',
|
|
28
28
|
// borderColor should come after borderTop so it can override it
|
|
29
29
|
borderColor: 'table.border',
|
|
30
|
-
|
|
30
|
+
variant: 'text.default',
|
|
31
31
|
px: 3,
|
|
32
32
|
py: 2,
|
|
33
33
|
textAlign: 'left'
|