@automattic/vip-design-system 0.9.2 → 0.9.5
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/build/system/Avatar/Avatar.stories.js +23 -8
- package/build/system/Avatar/Avatar.test.js +41 -22
- package/build/system/Badge/Badge.stories.js +25 -8
- package/build/system/Badge/Badge.test.js +73 -0
- package/build/system/BlankState/BlankState.js +12 -9
- package/build/system/BlankState/BlankState.stories.js +27 -11
- package/build/system/BlankState/BlankState.test.js +124 -0
- package/build/system/Box/Box.stories.js +25 -8
- package/build/system/Button/Button.stories.js +36 -23
- package/build/system/Button/Button.test.js +44 -0
- package/build/system/Card/Card.stories.js +25 -8
- package/build/system/Card/Card.test.js +78 -0
- package/build/system/Code/Code.js +11 -8
- package/build/system/Code/Code.stories.js +25 -8
- package/build/system/Code/Code.test.js +167 -0
- package/build/system/ConfirmationDialog/ConfirmationDialog.stories.js +45 -22
- package/build/system/Dialog/Dialog.stories.js +71 -31
- package/build/system/Dialog/DialogContent.js +3 -1
- package/build/system/Flex/Flex.stories.js +25 -8
- package/build/system/Form/AsyncSearchSelect.js +38 -0
- package/build/system/Form/Input.js +2 -2
- package/build/system/Form/Input.stories.js +23 -8
- package/build/system/Form/SearchSelect.js +47 -11
- package/build/system/Form/Select.js +48 -12
- package/build/system/Form/Select.stories.js +108 -78
- package/build/system/Form/Select.test.js +52 -0
- package/build/system/Grid/Grid.stories.js +25 -8
- package/build/system/Heading/Heading.stories.js +43 -20
- package/build/system/Link/Link.stories.js +26 -10
- package/build/system/Notice/Notice.stories.js +47 -81
- package/build/system/Notification/Notification.stories.js +23 -8
- package/build/system/OptionRow/OptionRow.stories.js +36 -20
- package/build/system/Progress/Progress.stories.js +23 -8
- package/build/system/Spinner/Spinner.stories.js +23 -8
- package/build/system/Table/Table.stories.js +64 -42
- package/build/system/Tabs/Tabs.stories.js +32 -10
- package/build/system/Text/Text.stories.js +25 -8
- package/build/system/Timeline/Timeline.js +69 -0
- package/build/system/Timeline/Timeline.stories.js +44 -21
- package/build/system/Timeline/index.js +2 -66
- package/build/system/Tooltip/Tooltip.stories.js +41 -19
- package/build/system/Wizard/Wizard.stories.js +65 -37
- package/package.json +17 -5
- package/src/system/Avatar/Avatar.test.js +9 -10
- package/src/system/Badge/Badge.test.js +30 -0
- package/src/system/BlankState/BlankState.js +13 -5
- package/src/system/BlankState/BlankState.test.js +58 -0
- package/src/system/Button/Button.test.js +21 -0
- package/src/system/Card/Card.test.js +33 -0
- package/src/system/Code/Code.js +12 -9
- package/src/system/Code/Code.stories.js +2 -0
- package/src/system/Code/Code.test.js +69 -0
- package/src/system/Dialog/DialogContent.js +2 -0
- package/src/system/Form/AsyncSearchSelect.js +29 -0
- package/src/system/Form/Input.js +2 -2
- package/src/system/Form/SearchSelect.js +43 -3
- package/src/system/Form/Select.js +29 -6
- package/src/system/Form/Select.stories.js +82 -24
- package/src/system/Form/Select.test.js +37 -0
- package/src/system/Timeline/Timeline.js +46 -0
- package/src/system/Timeline/Timeline.stories.js +34 -0
- package/src/system/Timeline/index.js +2 -41
- package/build/system/UsageChart/UsageChart.stories.js +0 -20
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
5
|
+
import { axe } from 'jest-axe';
|
|
6
|
+
import { MdContentCopy } from 'react-icons/md';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Internal dependencies
|
|
10
|
+
*/
|
|
11
|
+
import { Code } from './Code';
|
|
12
|
+
|
|
13
|
+
const defaultProps = {
|
|
14
|
+
showCopy: false,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// Mock navigator.clipboard because jsdom doesn't support it
|
|
18
|
+
Object.defineProperty( window.navigator, 'clipboard', {
|
|
19
|
+
value: {
|
|
20
|
+
writeText: () => {},
|
|
21
|
+
},
|
|
22
|
+
} );
|
|
23
|
+
|
|
24
|
+
describe( '<Code />', () => {
|
|
25
|
+
it( 'renders the Code component', async () => {
|
|
26
|
+
const { container } = render( <Code { ...defaultProps }>This is a code</Code> );
|
|
27
|
+
|
|
28
|
+
expect( screen.getByText( 'This is a code' ) ).toBeInTheDocument();
|
|
29
|
+
|
|
30
|
+
// Check for accessibility issues
|
|
31
|
+
await expect( await axe( container ) ).toHaveNoViolations();
|
|
32
|
+
} );
|
|
33
|
+
|
|
34
|
+
// jsdom currently doesn't support pseudo-elements with getComputedStyle
|
|
35
|
+
it.skip( 'renders "$" in front of the code when in prompt mode', async () => {
|
|
36
|
+
const props = { ...defaultProps, prompt: true };
|
|
37
|
+
const { container } = render( <Code { ...props }>This is a code</Code> );
|
|
38
|
+
const codeElement = screen.getByText( 'This is a code' );
|
|
39
|
+
|
|
40
|
+
expect( window.getComputedStyle( codeElement, ':before' ).content ).toEqual( '$' );
|
|
41
|
+
|
|
42
|
+
// Check for accessibility issues
|
|
43
|
+
await expect( await axe( container ) ).toHaveNoViolations();
|
|
44
|
+
} );
|
|
45
|
+
|
|
46
|
+
it( 'renders the Code component with a copy button', async () => {
|
|
47
|
+
const props = { ...defaultProps, showCopy: true };
|
|
48
|
+
const { container } = render( <Code { ...props }>This is a code</Code> );
|
|
49
|
+
|
|
50
|
+
expect( screen.getByRole( 'button', { name: 'Copy' } ) ).toBeInTheDocument();
|
|
51
|
+
|
|
52
|
+
// Check for accessibility issues
|
|
53
|
+
await expect( await axe( container ) ).toHaveNoViolations();
|
|
54
|
+
} );
|
|
55
|
+
|
|
56
|
+
it( 'updates the the UI after clicking on "Copy"', async () => {
|
|
57
|
+
const props = { ...defaultProps, showCopy: true };
|
|
58
|
+
const { container } = render( <Code { ...props }>This is a code</Code> );
|
|
59
|
+
|
|
60
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Copy' } ) );
|
|
61
|
+
|
|
62
|
+
await waitFor( () => new Promise( res => setTimeout( res, 0 ) ) );
|
|
63
|
+
|
|
64
|
+
expect( screen.getByText( 'Copied!' ) ).toBeInTheDocument();
|
|
65
|
+
|
|
66
|
+
// Check for accessibility issues
|
|
67
|
+
await expect( await axe( container ) ).toHaveNoViolations();
|
|
68
|
+
} );
|
|
69
|
+
} );
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* External dependencies
|
|
5
|
+
*/
|
|
6
|
+
import PropTypes from 'prop-types';
|
|
7
|
+
import { withAsyncPaginate } from 'react-select-async-paginate';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Internal dependencies
|
|
11
|
+
*/
|
|
12
|
+
import { SearchSelect } from './SearchSelect';
|
|
13
|
+
|
|
14
|
+
// Asynchronous search select to load paginated results asynchronously
|
|
15
|
+
const CustomAsyncPaginate = withAsyncPaginate( SearchSelect );
|
|
16
|
+
|
|
17
|
+
const AsyncSearchSelect = ( { options, ...props } ) => (
|
|
18
|
+
<CustomAsyncPaginate
|
|
19
|
+
SelectComponent={ SearchSelect }
|
|
20
|
+
loadOptions={ options }
|
|
21
|
+
{ ...props }
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
AsyncSearchSelect.propTypes = {
|
|
26
|
+
options: PropTypes.array,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { AsyncSearchSelect };
|
package/src/system/Form/Input.js
CHANGED
|
@@ -28,7 +28,7 @@ const Input = React.forwardRef( ( { variant, label, forLabel, hasError, required
|
|
|
28
28
|
required={ required }
|
|
29
29
|
sx={ {
|
|
30
30
|
border: '1px solid',
|
|
31
|
-
borderColor: '
|
|
31
|
+
borderColor: 'border',
|
|
32
32
|
backgroundColor: 'card',
|
|
33
33
|
borderRadius: 1,
|
|
34
34
|
lineHeight: 'inherit',
|
|
@@ -47,7 +47,7 @@ const Input = React.forwardRef( ( { variant, label, forLabel, hasError, required
|
|
|
47
47
|
bg: 'backgroundSecondary',
|
|
48
48
|
},
|
|
49
49
|
'&::placeholder': {
|
|
50
|
-
color: '
|
|
50
|
+
color: 'placeholder',
|
|
51
51
|
},
|
|
52
52
|
} }
|
|
53
53
|
/>
|
|
@@ -12,6 +12,7 @@ import PropTypes from 'prop-types';
|
|
|
12
12
|
*/
|
|
13
13
|
import { Flex, Text } from '..';
|
|
14
14
|
|
|
15
|
+
// Option component
|
|
15
16
|
export const Option = ( { label, isSelected, ...props } ) => (
|
|
16
17
|
<components.Option {...props}>
|
|
17
18
|
<Flex sx={{ alignItems: 'center' }}>
|
|
@@ -32,7 +33,45 @@ Option.propTypes = {
|
|
|
32
33
|
isSelected: PropTypes.bool,
|
|
33
34
|
};
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
// DropdownIndicator component
|
|
37
|
+
export const DropdownIndicator = ( {
|
|
38
|
+
innerProps,
|
|
39
|
+
isFocused,
|
|
40
|
+
isDisabled,
|
|
41
|
+
clearValue,
|
|
42
|
+
cx,
|
|
43
|
+
getStyles,
|
|
44
|
+
getValue,
|
|
45
|
+
hasValue,
|
|
46
|
+
isMulti,
|
|
47
|
+
isRtl,
|
|
48
|
+
options,
|
|
49
|
+
selectProps,
|
|
50
|
+
setValue,
|
|
51
|
+
selectOption,
|
|
52
|
+
theme,
|
|
53
|
+
...props
|
|
54
|
+
} ) => <MdExpandMore { ...props } sx={ { color: 'text', mr: 2 } } />;
|
|
55
|
+
|
|
56
|
+
DropdownIndicator.propTypes = {
|
|
57
|
+
innerProps: PropTypes.object,
|
|
58
|
+
isFocused: PropTypes.bool,
|
|
59
|
+
isDisabled: PropTypes.bool,
|
|
60
|
+
clearValue: PropTypes.func,
|
|
61
|
+
cx: PropTypes.func,
|
|
62
|
+
getStyles: PropTypes.func,
|
|
63
|
+
getValue: PropTypes.func,
|
|
64
|
+
hasValue: PropTypes.bool,
|
|
65
|
+
isMulti: PropTypes.bool,
|
|
66
|
+
isRtl: PropTypes.bool,
|
|
67
|
+
options: PropTypes.array,
|
|
68
|
+
selectProps: PropTypes.object,
|
|
69
|
+
setValue: PropTypes.func,
|
|
70
|
+
selectOption: PropTypes.func,
|
|
71
|
+
theme: PropTypes.object,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// ClearIndicator component
|
|
36
75
|
const ClearIndicator = ( { innerProps: { ref, ...restInnerProps }, ...props } ) => (
|
|
37
76
|
<MdClose ref={ref} {...restInnerProps} {...props} sx={{ color: 'text', mr: 2 }} />
|
|
38
77
|
);
|
|
@@ -41,11 +80,12 @@ ClearIndicator.propTypes = {
|
|
|
41
80
|
innerProps: PropTypes.object,
|
|
42
81
|
};
|
|
43
82
|
|
|
83
|
+
// Parent SearchSelect component
|
|
44
84
|
const SearchSelect = props => (
|
|
45
85
|
<Select
|
|
46
|
-
{...props}
|
|
86
|
+
{ ...props }
|
|
47
87
|
classNamePrefix={ 'select' }
|
|
48
|
-
components={{ Option, DropdownIndicator, ClearIndicator }}
|
|
88
|
+
components={ { Option, DropdownIndicator, ClearIndicator } }
|
|
49
89
|
sx={ {
|
|
50
90
|
'.select__control': {
|
|
51
91
|
background: 'none',
|
|
@@ -3,27 +3,50 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* External dependencies
|
|
5
5
|
*/
|
|
6
|
+
import React from 'react';
|
|
6
7
|
import PropTypes from 'prop-types';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
* Internal dependencies
|
|
11
|
+
*/
|
|
11
12
|
import { SearchSelect } from './SearchSelect';
|
|
12
13
|
import { InlineSelect } from './InlineSelect';
|
|
14
|
+
import { AsyncSearchSelect } from './AsyncSearchSelect';
|
|
15
|
+
|
|
16
|
+
const Select = ( { isMulti = false, isInline, isAsync, options, label, isSearch, usePortal, ...props } ) => {
|
|
17
|
+
let Component;
|
|
18
|
+
const selectRef = React.useRef();
|
|
19
|
+
const portalProps = {};
|
|
13
20
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
if ( usePortal !== undefined ) {
|
|
22
|
+
portalProps.menuPortalTarget =
|
|
23
|
+
selectRef?.current?.querySelector( '.select__control' ).parentElement;
|
|
24
|
+
portalProps.styles = { menuPortal: base => ( { ...base, position: 'fixed' } ) };
|
|
17
25
|
}
|
|
18
|
-
|
|
26
|
+
|
|
27
|
+
switch ( true ) {
|
|
28
|
+
case isInline:
|
|
29
|
+
Component = InlineSelect;
|
|
30
|
+
break;
|
|
31
|
+
case isAsync:
|
|
32
|
+
Component = AsyncSearchSelect;
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
Component = SearchSelect;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return <div ref={selectRef}><Component isMulti={isMulti} label={label} options={options} {...portalProps} {...props} /></div>;
|
|
19
40
|
};
|
|
20
41
|
|
|
21
42
|
Select.propTypes = {
|
|
22
43
|
isInline: PropTypes.bool,
|
|
23
44
|
isMulti: PropTypes.bool,
|
|
45
|
+
isAsync: PropTypes.bool,
|
|
24
46
|
isSearch: PropTypes.bool,
|
|
25
47
|
label: PropTypes.string,
|
|
26
48
|
options: PropTypes.array,
|
|
49
|
+
usePortal: PropTypes.bool,
|
|
27
50
|
};
|
|
28
51
|
|
|
29
52
|
export { Select };
|
|
@@ -6,15 +6,7 @@ import { useState } from 'react';
|
|
|
6
6
|
/**
|
|
7
7
|
* Internal dependencies
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
10
|
-
Box,
|
|
11
|
-
Dialog,
|
|
12
|
-
DialogMenu,
|
|
13
|
-
DialogMenuItem,
|
|
14
|
-
DialogDivider,
|
|
15
|
-
Select,
|
|
16
|
-
Button,
|
|
17
|
-
} from '..';
|
|
9
|
+
import { Box, Dialog, DialogMenu, DialogMenuItem, DialogDivider, Select, Button } from '..';
|
|
18
10
|
|
|
19
11
|
export default {
|
|
20
12
|
title: 'Select',
|
|
@@ -44,43 +36,109 @@ const DropdownContent = (
|
|
|
44
36
|
const DropdownTrigger = <Button variant="secondary">Trigger Dropdown</Button>;
|
|
45
37
|
|
|
46
38
|
export const Multi = () => {
|
|
47
|
-
const [ value, setValue ] = useState( [
|
|
39
|
+
const [ value, setValue ] = useState( [] );
|
|
48
40
|
|
|
49
41
|
return (
|
|
50
|
-
<Box sx={
|
|
51
|
-
<Select
|
|
42
|
+
<Box sx={{ mr: 2, width: 400 }}>
|
|
43
|
+
<Select
|
|
44
|
+
label="Type"
|
|
45
|
+
value={value}
|
|
46
|
+
isMulti
|
|
47
|
+
placeholder="Select domains..."
|
|
48
|
+
options={options}
|
|
49
|
+
onChange={newValue => setValue( newValue )}
|
|
50
|
+
/>
|
|
51
|
+
</Box>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const usePortal = () => {
|
|
56
|
+
const [ value, setValue ] = useState( [] );
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<Box sx={{ mr: 2, width: 400 }}>
|
|
60
|
+
<Select
|
|
61
|
+
label="Type"
|
|
62
|
+
value={value}
|
|
63
|
+
isMulti
|
|
64
|
+
placeholder="Select domains..."
|
|
65
|
+
usePortal
|
|
66
|
+
options={options}
|
|
67
|
+
onChange={newValue => setValue( newValue )}
|
|
68
|
+
/>
|
|
52
69
|
</Box>
|
|
53
70
|
);
|
|
54
71
|
};
|
|
55
72
|
|
|
56
73
|
export const Single = () => {
|
|
57
|
-
const [ value, setValue ] = useState( [
|
|
74
|
+
const [ value, setValue ] = useState( [] );
|
|
58
75
|
|
|
59
76
|
return (
|
|
60
|
-
<Box sx={
|
|
61
|
-
<Select
|
|
77
|
+
<Box sx={{ mr: 2, width: 200 }}>
|
|
78
|
+
<Select
|
|
79
|
+
label="User"
|
|
80
|
+
value={value}
|
|
81
|
+
placeholder="Select a domain..."
|
|
82
|
+
options={options}
|
|
83
|
+
onChange={newValue => setValue( newValue )}
|
|
84
|
+
/>
|
|
62
85
|
</Box>
|
|
63
86
|
);
|
|
64
87
|
};
|
|
65
88
|
|
|
66
89
|
export const Inline = () => {
|
|
67
|
-
const [ value, setValue ] = useState( [
|
|
90
|
+
const [ value, setValue ] = useState( [] );
|
|
68
91
|
|
|
69
92
|
return (
|
|
70
|
-
<Box sx={
|
|
71
|
-
<Select
|
|
93
|
+
<Box sx={{ mr: 2, width: 200 }}>
|
|
94
|
+
<Select
|
|
95
|
+
label="User"
|
|
96
|
+
value={value}
|
|
97
|
+
isInline
|
|
98
|
+
isMulti
|
|
99
|
+
noneLabel="Everyone"
|
|
100
|
+
placeholder="Filter by user..."
|
|
101
|
+
options={options}
|
|
102
|
+
onChange={newValue => setValue( newValue )}
|
|
103
|
+
/>
|
|
72
104
|
</Box>
|
|
73
105
|
);
|
|
74
106
|
};
|
|
75
107
|
|
|
76
|
-
export const
|
|
108
|
+
export const Async = () => {
|
|
109
|
+
const [ value, setValue ] = useState( [] );
|
|
110
|
+
const loadOptions = async () => new Promise( resolve => {
|
|
111
|
+
setTimeout( () => {
|
|
112
|
+
resolve( {
|
|
113
|
+
options: [
|
|
114
|
+
...options,
|
|
115
|
+
{ value: 'newvanilla', label: 'New Vanilla' },
|
|
116
|
+
],
|
|
117
|
+
} );
|
|
118
|
+
}, 2000 );
|
|
119
|
+
} );
|
|
120
|
+
|
|
77
121
|
return (
|
|
78
|
-
<Box sx={
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
122
|
+
<Box sx={{ mr: 2, width: 200 }}>
|
|
123
|
+
<Select
|
|
124
|
+
label="Async Select"
|
|
125
|
+
value={value}
|
|
126
|
+
isAsync
|
|
127
|
+
usePortal
|
|
128
|
+
loadOptions={ loadOptions }
|
|
129
|
+
noneLabel="Everyone"
|
|
130
|
+
placeholder="Load async..."
|
|
131
|
+
options={options}
|
|
132
|
+
onChange={newValue => setValue( newValue )}
|
|
83
133
|
/>
|
|
84
134
|
</Box>
|
|
85
135
|
);
|
|
86
136
|
};
|
|
137
|
+
|
|
138
|
+
export const DropdownMenu = () => {
|
|
139
|
+
return (
|
|
140
|
+
<Box sx={{ mr: 2, width: 200 }}>
|
|
141
|
+
<Dialog trigger={DropdownTrigger} content={DropdownContent} sx={{ width: 200 }} />
|
|
142
|
+
</Box>
|
|
143
|
+
);
|
|
144
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { render, screen } from '@testing-library/react';
|
|
5
|
+
import { axe } from 'jest-axe';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
import { Select } from './Select';
|
|
11
|
+
|
|
12
|
+
describe( '<Select />', () => {
|
|
13
|
+
it( 'renders the Select component with the specified placeholder', () => {
|
|
14
|
+
render(
|
|
15
|
+
<Select
|
|
16
|
+
inputId={ 'search-select' }
|
|
17
|
+
placeholder={ 'Search...' }
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
// Can't use `getByPlaceholderText` here since it's not actually being rendered as a placeholder element
|
|
22
|
+
const placeholder = screen.getByText( 'Search...' );
|
|
23
|
+
|
|
24
|
+
expect( placeholder ).toBeInTheDocument();
|
|
25
|
+
} );
|
|
26
|
+
|
|
27
|
+
it( 'renders the Select component with accessibility props', async () => {
|
|
28
|
+
const { container } = render(
|
|
29
|
+
<Select
|
|
30
|
+
inputId={ 'search-select' }
|
|
31
|
+
aria-label={ 'Search or select from the dropdown list' }
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
expect( await axe( container ) ).toHaveNoViolations();
|
|
36
|
+
} );
|
|
37
|
+
} );
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* External dependencies
|
|
5
|
+
*/
|
|
6
|
+
import { Flex } from 'theme-ui';
|
|
7
|
+
import { MdWatchLater } from 'react-icons/md';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
|
|
10
|
+
const VerticalLine = () => {
|
|
11
|
+
return (
|
|
12
|
+
<div
|
|
13
|
+
sx={ {
|
|
14
|
+
borderLeft: '2px solid',
|
|
15
|
+
borderColor: 'border',
|
|
16
|
+
height: 'calc( 50% - 16px )',
|
|
17
|
+
borderRadius: '2px',
|
|
18
|
+
} }>
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const Timeline = ( { time, first = false, last = false, ...props } ) => (
|
|
24
|
+
<Flex { ...props }>
|
|
25
|
+
<Flex sx={ { flexDirection: 'column', justifyContent: 'space-evenly', alignItems: 'center' } }>
|
|
26
|
+
{ ! first && (
|
|
27
|
+
<VerticalLine />
|
|
28
|
+
) }
|
|
29
|
+
<MdWatchLater sx={ { color: 'border' } } size={ 18 }/>
|
|
30
|
+
{ ! last && (
|
|
31
|
+
<VerticalLine />
|
|
32
|
+
) }
|
|
33
|
+
</Flex>
|
|
34
|
+
<Flex sx={ { alignItems: 'center', ml: 2 } }>
|
|
35
|
+
{ time }
|
|
36
|
+
</Flex>
|
|
37
|
+
</Flex>
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
Timeline.propTypes = {
|
|
41
|
+
first: PropTypes.bool,
|
|
42
|
+
time: PropTypes.node,
|
|
43
|
+
last: PropTypes.bool,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { Timeline };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { Timeline } from '..';
|
|
10
|
+
import { Link } from '../Link';
|
|
11
|
+
|
|
12
|
+
export default {
|
|
13
|
+
title: 'Timeline',
|
|
14
|
+
component: Timeline,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const Default = () => {
|
|
18
|
+
return (
|
|
19
|
+
<React.Fragment>
|
|
20
|
+
<Timeline
|
|
21
|
+
time="13:00"
|
|
22
|
+
title="21:00 UTC"
|
|
23
|
+
/>
|
|
24
|
+
<Timeline
|
|
25
|
+
time={ <Link>14:00</Link> }
|
|
26
|
+
title="22:00 UTC"
|
|
27
|
+
/>
|
|
28
|
+
<Timeline
|
|
29
|
+
time="15:00"
|
|
30
|
+
title="23:00 UTC"
|
|
31
|
+
/>
|
|
32
|
+
</React.Fragment>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
@@ -1,46 +1,7 @@
|
|
|
1
|
-
/** @jsxImportSource theme-ui */
|
|
2
1
|
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
3
|
+
* Internal dependencies
|
|
5
4
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import { MdWatchLater } from 'react-icons/md';
|
|
8
|
-
import PropTypes from 'prop-types';
|
|
9
|
-
|
|
10
|
-
const VerticalLine = () => {
|
|
11
|
-
return (
|
|
12
|
-
<div
|
|
13
|
-
sx={ {
|
|
14
|
-
borderLeft: '2px solid',
|
|
15
|
-
borderColor: 'border',
|
|
16
|
-
height: 'calc( 50% - 16px )',
|
|
17
|
-
borderRadius: '2px',
|
|
18
|
-
} }>
|
|
19
|
-
</div>
|
|
20
|
-
);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const Timeline = ( { time, first = false, last = false, ...props } ) => (
|
|
24
|
-
<Flex { ...props }>
|
|
25
|
-
<Flex sx={ { flexDirection: 'column', justifyContent: 'space-evenly', alignItems: 'center' } }>
|
|
26
|
-
{ ! first && (
|
|
27
|
-
<VerticalLine />
|
|
28
|
-
) }
|
|
29
|
-
<MdWatchLater sx={ { color: 'border' } } size={ 18 }/>
|
|
30
|
-
{ ! last && (
|
|
31
|
-
<VerticalLine />
|
|
32
|
-
) }
|
|
33
|
-
</Flex>
|
|
34
|
-
<Flex sx={ { alignItems: 'center', ml: 2 } }>
|
|
35
|
-
<span>{ time }</span>
|
|
36
|
-
</Flex>
|
|
37
|
-
</Flex>
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
Timeline.propTypes = {
|
|
41
|
-
first: PropTypes.bool,
|
|
42
|
-
time: PropTypes.string,
|
|
43
|
-
last: PropTypes.bool,
|
|
44
|
-
};
|
|
5
|
+
import { Timeline } from './Timeline';
|
|
45
6
|
|
|
46
7
|
export { Timeline };
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* External dependencies
|
|
3
|
-
*/
|
|
4
|
-
import React from 'react';
|
|
5
|
-
/**
|
|
6
|
-
* Internal dependencies
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { UsageChart } from '..';
|
|
10
|
-
export default {
|
|
11
|
-
title: 'UsageChart',
|
|
12
|
-
component: UsageChart
|
|
13
|
-
};
|
|
14
|
-
export var Default = function Default() {
|
|
15
|
-
return /*#__PURE__*/React.createElement(UsageChart, {
|
|
16
|
-
total: 50,
|
|
17
|
-
max: 75,
|
|
18
|
-
variant: "primary"
|
|
19
|
-
});
|
|
20
|
-
};
|