@automattic/vip-design-system 1.3.2 → 1.4.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.tsx +3 -0
- package/README.md +17 -4
- package/build/system/Form/Radio.js +0 -2
- package/build/system/Link/Link.stories.d.ts +1 -1
- package/build/system/Link/Link.stories.js +2 -2
- package/build/system/Nav/Nav.d.ts +13 -0
- package/build/system/Nav/Nav.js +62 -0
- package/build/system/Nav/Nav.stories.d.ts +27 -0
- package/build/system/Nav/Nav.stories.js +85 -0
- package/build/system/Nav/Nav.test.d.ts +1 -0
- package/build/system/Nav/Nav.test.js +72 -0
- package/build/system/Nav/NavItem.d.ts +19 -0
- package/build/system/Nav/NavItem.js +148 -0
- package/build/system/Nav/index.d.ts +10 -0
- package/build/system/Nav/index.js +19 -0
- package/build/system/Notice/Notice.js +24 -10
- package/build/system/Notice/Notice.stories.d.ts +1 -0
- package/build/system/Notice/Notice.stories.js +34 -2
- package/build/system/Tabs/Tabs.stories.jsx +1 -1
- package/build/system/Wizard/Wizard.stories.js +1 -1
- package/build/system/index.d.ts +3 -1
- package/build/system/index.js +5 -2
- package/docs/ARCHITECTURE.md +88 -0
- package/docs/CONTRIBUTING.md +54 -0
- package/docs/RELEASING.md +70 -0
- package/docs/SETUP.md +68 -0
- package/docs/TESTING.md +63 -0
- package/package.json +2 -1
- package/src/system/Form/Radio.js +0 -2
- package/src/system/Link/Link.stories.tsx +1 -1
- package/src/system/Nav/Nav.stories.tsx +117 -0
- package/src/system/Nav/Nav.test.tsx +51 -0
- package/src/system/Nav/Nav.tsx +62 -0
- package/src/system/Nav/NavItem.tsx +152 -0
- package/src/system/Nav/index.tsx +18 -0
- package/src/system/Notice/Notice.stories.tsx +21 -3
- package/src/system/Notice/Notice.tsx +20 -13
- package/src/system/Tabs/Tabs.stories.jsx +1 -1
- package/src/system/Wizard/Wizard.stories.tsx +1 -1
- package/src/system/index.js +5 -2
- package/CONTRIBUTING.md +0 -138
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
3
|
+
// @ts-nocheck
|
|
4
|
+
/**
|
|
5
|
+
* External dependencies
|
|
6
|
+
*/
|
|
7
|
+
import { render, screen } from '@testing-library/react';
|
|
8
|
+
import { axe } from 'jest-axe';
|
|
9
|
+
import { ThemeUIProvider } from 'theme-ui';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Internal dependencies
|
|
13
|
+
*/
|
|
14
|
+
import { Nav, NavItem } from './';
|
|
15
|
+
|
|
16
|
+
import { theme } from '../';
|
|
17
|
+
|
|
18
|
+
const renderWithTheme = children =>
|
|
19
|
+
render( <ThemeUIProvider theme={ theme }>{ children }</ThemeUIProvider> );
|
|
20
|
+
|
|
21
|
+
const renderComponent = () =>
|
|
22
|
+
renderWithTheme(
|
|
23
|
+
<Nav.Primary variant="primary" label="Main">
|
|
24
|
+
<NavItem.Primary href="#">PHP</NavItem.Primary>
|
|
25
|
+
<NavItem.Primary href="https://wordpress.com">WordPress</NavItem.Primary>
|
|
26
|
+
<NavItem.Primary active href="htpps://newrelic.com/">
|
|
27
|
+
New Relic
|
|
28
|
+
</NavItem.Primary>
|
|
29
|
+
<NavItem.Primary disabled href="https://google.com/">
|
|
30
|
+
Not accessible
|
|
31
|
+
</NavItem.Primary>
|
|
32
|
+
</Nav.Primary>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
describe( '<Nav />', () => {
|
|
36
|
+
it( 'renders the Nav component with default value visible', async () => {
|
|
37
|
+
const { container } = renderComponent();
|
|
38
|
+
|
|
39
|
+
// Should find the nav label
|
|
40
|
+
expect( screen.getByLabelText( 'Main' ) ).toBeInTheDocument();
|
|
41
|
+
|
|
42
|
+
// Should find all links
|
|
43
|
+
expect( screen.queryByText( 'PHP' ) ).toBeInTheDocument();
|
|
44
|
+
expect( screen.queryByText( 'WordPress' ) ).toBeInTheDocument();
|
|
45
|
+
expect( screen.queryByText( 'New Relic' ) ).toBeInTheDocument();
|
|
46
|
+
expect( screen.queryByText( 'Not accessible' ) ).toHaveAttribute( 'aria-disabled', 'true' );
|
|
47
|
+
|
|
48
|
+
// Check for accessibility issues
|
|
49
|
+
expect( await axe( container ) ).toHaveNoViolations();
|
|
50
|
+
} );
|
|
51
|
+
} );
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
import React, { Ref, forwardRef } from 'react';
|
|
3
|
+
import * as NavigationMenu from '@radix-ui/react-navigation-menu';
|
|
4
|
+
import classNames from 'classnames';
|
|
5
|
+
|
|
6
|
+
import { VIP_NAV } from '.';
|
|
7
|
+
import { ThemeUIStyleObject } from 'theme-ui';
|
|
8
|
+
|
|
9
|
+
export type NavVariant = 'primary' | 'tabs';
|
|
10
|
+
|
|
11
|
+
export interface NavProps extends NavigationMenu.NavigationMenuProps {
|
|
12
|
+
className?: string;
|
|
13
|
+
variant?: NavVariant;
|
|
14
|
+
sx?: ThemeUIStyleObject;
|
|
15
|
+
label: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Nav = forwardRef< HTMLElement, NavProps >(
|
|
19
|
+
(
|
|
20
|
+
{ className, children, orientation, variant = 'primary', sx = {}, label }: NavProps,
|
|
21
|
+
ref: Ref< HTMLElement >
|
|
22
|
+
) => (
|
|
23
|
+
<NavigationMenu.Root
|
|
24
|
+
aria-label={ label }
|
|
25
|
+
ref={ ref }
|
|
26
|
+
className={ classNames( VIP_NAV, className ) }
|
|
27
|
+
sx={ {
|
|
28
|
+
position: 'relative',
|
|
29
|
+
display: 'flex',
|
|
30
|
+
width: variant === 'tabs' ? '100%' : 'max-content',
|
|
31
|
+
zIndex: 1,
|
|
32
|
+
pb: 0,
|
|
33
|
+
borderBottom: '1px solid',
|
|
34
|
+
borderColor: variant === 'tabs' ? 'borders.2' : 'transparent',
|
|
35
|
+
...sx,
|
|
36
|
+
} }
|
|
37
|
+
orientation={ orientation }
|
|
38
|
+
>
|
|
39
|
+
<NavigationMenu.List
|
|
40
|
+
className={ classNames( `${ VIP_NAV }-list` ) }
|
|
41
|
+
sx={ {
|
|
42
|
+
display: 'flex',
|
|
43
|
+
listStyle: 'none',
|
|
44
|
+
justifyContent: 'flex-start',
|
|
45
|
+
m: 0,
|
|
46
|
+
px: 0,
|
|
47
|
+
flexDirection: 'row',
|
|
48
|
+
} }
|
|
49
|
+
>
|
|
50
|
+
{ children }
|
|
51
|
+
</NavigationMenu.List>
|
|
52
|
+
</NavigationMenu.Root>
|
|
53
|
+
)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
export const NavPrimary = forwardRef< HTMLElement, NavProps >(
|
|
57
|
+
( props: NavProps, ref: Ref< HTMLElement > ) => <Nav { ...props } variant="primary" ref={ ref } />
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
export const NavTab = forwardRef< HTMLElement, NavProps >(
|
|
61
|
+
( props: NavProps, ref: Ref< HTMLElement > ) => <Nav { ...props } variant="tabs" ref={ ref } />
|
|
62
|
+
);
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* External dependencies
|
|
5
|
+
*/
|
|
6
|
+
import React, { Ref, forwardRef } from 'react';
|
|
7
|
+
import * as NavigationMenu from '@radix-ui/react-navigation-menu';
|
|
8
|
+
import classNames from 'classnames';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Internal dependencies
|
|
12
|
+
*/
|
|
13
|
+
import { VIP_NAV } from '.';
|
|
14
|
+
import { Theme, ThemeUIStyleObject } from 'theme-ui';
|
|
15
|
+
import { NavVariant } from './Nav';
|
|
16
|
+
|
|
17
|
+
interface NavItemTheme extends Theme {
|
|
18
|
+
outline?: Record< string, string >;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface NavItemBaseProps extends NavigationMenu.NavigationMenuItemProps {
|
|
22
|
+
className?: string;
|
|
23
|
+
sx?: ThemeUIStyleObject;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const NavItemBase = forwardRef< HTMLLIElement, NavItemBaseProps >(
|
|
27
|
+
( { children, sx = {}, className, ...rest }: NavItemBaseProps, ref: Ref< HTMLLIElement > ) => (
|
|
28
|
+
<NavigationMenu.Item
|
|
29
|
+
className={ classNames( `${ VIP_NAV }-item`, className ) }
|
|
30
|
+
{ ...rest }
|
|
31
|
+
sx={ {
|
|
32
|
+
mr: 2,
|
|
33
|
+
'&:last-of-type': {
|
|
34
|
+
mr: 0,
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
...sx,
|
|
38
|
+
} }
|
|
39
|
+
ref={ ref }
|
|
40
|
+
>
|
|
41
|
+
{ children }
|
|
42
|
+
</NavigationMenu.Item>
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const NavLink = forwardRef< HTMLAnchorElement, NavItemProps >(
|
|
47
|
+
(
|
|
48
|
+
{ children, href, active, disabled, variant, ...props }: NavItemProps,
|
|
49
|
+
ref: Ref< HTMLAnchorElement >
|
|
50
|
+
) => (
|
|
51
|
+
<NavigationMenu.Link
|
|
52
|
+
className={ classNames( `${ VIP_NAV }-item-link` ) }
|
|
53
|
+
href={ href }
|
|
54
|
+
ref={ ref }
|
|
55
|
+
sx={ styles( variant ) }
|
|
56
|
+
active={ active }
|
|
57
|
+
aria-disabled={ disabled }
|
|
58
|
+
{ ...props }
|
|
59
|
+
>
|
|
60
|
+
{ children }
|
|
61
|
+
</NavigationMenu.Link>
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
export interface NavItemProps extends NavigationMenu.NavigationMenuLinkProps {
|
|
66
|
+
className?: string;
|
|
67
|
+
disabled?: boolean;
|
|
68
|
+
variant?: NavVariant;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const styles = variant => {
|
|
72
|
+
const defaultVariantStyles: ThemeUIStyleObject =
|
|
73
|
+
variant === 'tabs'
|
|
74
|
+
? {
|
|
75
|
+
px: 0,
|
|
76
|
+
mr: 2,
|
|
77
|
+
color: 'heading',
|
|
78
|
+
'&[data-active]': {
|
|
79
|
+
color: 'link',
|
|
80
|
+
fontWeight: 'normal',
|
|
81
|
+
boxShadow: 'inset 0 -1px 0 0, 0 1px 0 0',
|
|
82
|
+
},
|
|
83
|
+
'&[aria-disabled="true"]': {
|
|
84
|
+
color: 'muted',
|
|
85
|
+
},
|
|
86
|
+
':hover': { fontWeight: 'regular', color: 'heading' },
|
|
87
|
+
}
|
|
88
|
+
: {
|
|
89
|
+
variant: `buttons.${ variant === 'link' ? 'text' : 'tertiary' }`,
|
|
90
|
+
borderRadius: 1,
|
|
91
|
+
'&[data-active]': {
|
|
92
|
+
variant: `buttons.${ variant === 'link' ? 'display' : variant }`,
|
|
93
|
+
},
|
|
94
|
+
'&[aria-disabled="true"]': {
|
|
95
|
+
opacity: 0.7,
|
|
96
|
+
color: 'texts.secondary',
|
|
97
|
+
cursor: 'not-allowed',
|
|
98
|
+
},
|
|
99
|
+
':hover': {
|
|
100
|
+
backgroundColor: `button.${ variant }.background.hover`,
|
|
101
|
+
textDecoration: 'none',
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
alignItems: 'center',
|
|
107
|
+
display: 'inline-flex',
|
|
108
|
+
fontSize: 2,
|
|
109
|
+
justifyContent: 'center',
|
|
110
|
+
lineHeight: 'inherit',
|
|
111
|
+
minHeight: '36px',
|
|
112
|
+
px: 3,
|
|
113
|
+
py: 0,
|
|
114
|
+
textDecoration: 'none',
|
|
115
|
+
verticalAlign: 'middle',
|
|
116
|
+
...defaultVariantStyles,
|
|
117
|
+
'&:focus': ( theme: NavItemTheme ) => theme.outline,
|
|
118
|
+
'&:focus-visible': ( theme: NavItemTheme ) => theme.outline,
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const NavItem = forwardRef< HTMLAnchorElement, NavItemProps >(
|
|
123
|
+
(
|
|
124
|
+
{ className, children, href, active, disabled, variant = 'primary', ...props }: NavItemProps,
|
|
125
|
+
ref: Ref< HTMLAnchorElement >
|
|
126
|
+
) => (
|
|
127
|
+
<NavItemBase className={ className }>
|
|
128
|
+
<NavLink
|
|
129
|
+
variant={ variant }
|
|
130
|
+
href={ href }
|
|
131
|
+
ref={ ref }
|
|
132
|
+
active={ active }
|
|
133
|
+
disabled={ disabled }
|
|
134
|
+
{ ...props }
|
|
135
|
+
>
|
|
136
|
+
{ children }
|
|
137
|
+
</NavLink>
|
|
138
|
+
</NavItemBase>
|
|
139
|
+
)
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
export const ItemPrimary = forwardRef< HTMLAnchorElement, NavItemProps >(
|
|
143
|
+
( props: NavItemProps, ref: Ref< HTMLAnchorElement > ) => (
|
|
144
|
+
<NavItem variant="primary" ref={ ref } { ...props } />
|
|
145
|
+
)
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
export const ItemTab = forwardRef< HTMLAnchorElement, NavItemProps >(
|
|
149
|
+
( props: NavItemProps, ref: Ref< HTMLAnchorElement > ) => (
|
|
150
|
+
<NavItem variant="tabs" ref={ ref } { ...props } />
|
|
151
|
+
)
|
|
152
|
+
);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { NavPrimary as Primary, NavTab as Tab } from './Nav';
|
|
5
|
+
|
|
6
|
+
import { ItemPrimary, ItemTab } from './NavItem';
|
|
7
|
+
|
|
8
|
+
export const VIP_NAV = 'vip-nav-component';
|
|
9
|
+
|
|
10
|
+
export const Nav = {
|
|
11
|
+
Primary,
|
|
12
|
+
Tab,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const NavItem = {
|
|
16
|
+
Primary: ItemPrimary,
|
|
17
|
+
Tab: ItemTab,
|
|
18
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
1
2
|
/**
|
|
2
3
|
* External dependencies
|
|
3
4
|
*/
|
|
@@ -6,7 +7,7 @@
|
|
|
6
7
|
* Internal dependencies
|
|
7
8
|
*/
|
|
8
9
|
import React from 'react';
|
|
9
|
-
import { Notice, Link } from '..';
|
|
10
|
+
import { Notice, Link, Heading } from '..';
|
|
10
11
|
|
|
11
12
|
export default {
|
|
12
13
|
title: 'Notice',
|
|
@@ -52,11 +53,11 @@ export const Default = () => (
|
|
|
52
53
|
|
|
53
54
|
<Notice
|
|
54
55
|
variant="alert"
|
|
55
|
-
sx={ { mb:
|
|
56
|
+
sx={ { mb: 2 } }
|
|
56
57
|
title="There are errors in your form"
|
|
57
58
|
headingVariant="h2"
|
|
58
59
|
>
|
|
59
|
-
<ul sx={ {
|
|
60
|
+
<ul sx={ { m: 0, pl: 3 } }>
|
|
60
61
|
<li>
|
|
61
62
|
<Link href="#name">Please enter your name.</Link>
|
|
62
63
|
</li>
|
|
@@ -69,6 +70,23 @@ export const Default = () => (
|
|
|
69
70
|
</ul>
|
|
70
71
|
</Notice>
|
|
71
72
|
|
|
73
|
+
<Notice variant="alert" sx={ { mb: 2 } }>
|
|
74
|
+
<>
|
|
75
|
+
<Heading variant={ 'h4' } sx={ { fontSize: 2 } }>
|
|
76
|
+
Alternative way of printing errors
|
|
77
|
+
</Heading>
|
|
78
|
+
|
|
79
|
+
<ul sx={ { m: 0, pl: 3 } }>
|
|
80
|
+
<li>
|
|
81
|
+
<Link href="#name">Please enter your name.</Link>
|
|
82
|
+
</li>
|
|
83
|
+
<li>
|
|
84
|
+
<Link href="#email">Please enter your email address.</Link>
|
|
85
|
+
</li>
|
|
86
|
+
</ul>
|
|
87
|
+
</>
|
|
88
|
+
</Notice>
|
|
89
|
+
|
|
72
90
|
<Notice variant="alert" sx={ { mb: 4 } }>
|
|
73
91
|
Bucket names in Amazon S3 are globally unique, external link ↗. To ensure that shipped data is
|
|
74
92
|
delivered to the correct location, the Bucket Name and Bucket Region entered below must match
|
|
@@ -30,7 +30,7 @@ export interface NoticeProps {
|
|
|
30
30
|
type ColorVariants = 'warning' | 'error' | 'alert' | 'success' | 'info';
|
|
31
31
|
|
|
32
32
|
const NoticeIcon = ( { color, variant }: NoticeIconProps ) => {
|
|
33
|
-
const sx = { color, flex: '0 0 auto'
|
|
33
|
+
const sx = { color, flex: '0 0 auto' };
|
|
34
34
|
const size = 20;
|
|
35
35
|
|
|
36
36
|
switch ( variant ) {
|
|
@@ -91,20 +91,27 @@ export const Notice = React.forwardRef< HTMLDivElement, NoticeProps >(
|
|
|
91
91
|
>
|
|
92
92
|
<Flex
|
|
93
93
|
sx={ {
|
|
94
|
-
|
|
94
|
+
height: '100%', // required for the dynamic height of the icon box to work
|
|
95
95
|
} }
|
|
96
96
|
>
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
97
|
+
<Box sx={ { minWidth: '32px', mr: 3, mt: 0 } }>
|
|
98
|
+
<Flex
|
|
99
|
+
sx={ {
|
|
100
|
+
flexDirection: 'column', // the trick here is to have a flex column with the icon at the bottom and an empty div that fills the space
|
|
101
|
+
minHeight: '20px',
|
|
102
|
+
maxHeight: '32px', // we're forcing the max height so that the icon is, at max, aligned between the first and the second line of text
|
|
103
|
+
alignItems: 'flex-end', // we want the icon to be aligned to the bottom
|
|
104
|
+
height: '100%', // specifying the height will allow the box to match the height of the content.
|
|
105
|
+
} }
|
|
106
|
+
>
|
|
107
|
+
<Box
|
|
108
|
+
sx={ {
|
|
109
|
+
flex: '1 100%', // we need this empty div to make the icon align to the bottom
|
|
110
|
+
} }
|
|
111
|
+
></Box>
|
|
112
|
+
<NoticeIcon color={ `notice.icon.${ variant }` } variant={ variant } />
|
|
113
|
+
</Flex>
|
|
114
|
+
</Box>
|
|
108
115
|
<Box>
|
|
109
116
|
{ title && (
|
|
110
117
|
<Heading
|
package/src/system/index.js
CHANGED
|
@@ -7,6 +7,8 @@ import { Box } from './Box';
|
|
|
7
7
|
import { Button, ButtonSubmit, ButtonVariant } from './Button';
|
|
8
8
|
import { Card } from './Card';
|
|
9
9
|
import { Code } from './Code';
|
|
10
|
+
import { Nav, NavItem } from './Nav';
|
|
11
|
+
|
|
10
12
|
import {
|
|
11
13
|
Dialog,
|
|
12
14
|
DialogButton,
|
|
@@ -48,7 +50,7 @@ import { OptionRow } from './OptionRow';
|
|
|
48
50
|
import { Table, TableRow, TableCell } from './Table';
|
|
49
51
|
import { Text } from './Text';
|
|
50
52
|
import theme from './theme';
|
|
51
|
-
import { Wizard, WizardStep
|
|
53
|
+
import { Wizard, WizardStep } from './Wizard';
|
|
52
54
|
import { Tabs, TabsList, TabsContent, TabsTrigger } from './Tabs';
|
|
53
55
|
|
|
54
56
|
export {
|
|
@@ -93,6 +95,8 @@ export {
|
|
|
93
95
|
Progress,
|
|
94
96
|
Text,
|
|
95
97
|
Tabs,
|
|
98
|
+
Nav,
|
|
99
|
+
NavItem,
|
|
96
100
|
TabsTrigger,
|
|
97
101
|
TabsContent,
|
|
98
102
|
TabsList,
|
|
@@ -101,6 +105,5 @@ export {
|
|
|
101
105
|
Validation,
|
|
102
106
|
Wizard,
|
|
103
107
|
WizardStep,
|
|
104
|
-
WizardStepHorizontal,
|
|
105
108
|
theme,
|
|
106
109
|
};
|
package/CONTRIBUTING.md
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
## Development
|
|
2
|
-
|
|
3
|
-
### Prerequisites
|
|
4
|
-
|
|
5
|
-
Make sure you have [node.js](https://nodejs.org/) and [NPM](https://docs.npmjs.com/getting-started/what-is-npm) installed. Here's a [handy installer](https://nodejs.org/download/) for Windows, Mac, and Linux.
|
|
6
|
-
|
|
7
|
-
### Install
|
|
8
|
-
|
|
9
|
-
To get setup run the following command in the `vip-design-system` directory:
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
npm install
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
### Watching for changes
|
|
16
|
-
|
|
17
|
-
You can build it continuously so that every time you make a change, build files are automatically updated:
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
npm run watch
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### Testing
|
|
24
|
-
|
|
25
|
-
We can test two ways:
|
|
26
|
-
|
|
27
|
-
**Storybook**
|
|
28
|
-
|
|
29
|
-
For components that include storybooks, we can run `npm run storybook` to view the components in a sandbox-ed storybook environment.
|
|
30
|
-
|
|
31
|
-
**npm link**
|
|
32
|
-
|
|
33
|
-
1. Run `npm link` in your checkout of this repo.
|
|
34
|
-
2. Spin up a local copy of [the VIP Dashboard](https://github.com/automattic/vip-ui) and navigate to a page using the linked components from `@automattic/vip-design-system`
|
|
35
|
-
|
|
36
|
-
Note: it's super useful to run `npm run watch` in another process, so any changes will be almost immediately available / testable.
|
|
37
|
-
|
|
38
|
-
### Updating the Theme with VIP Design System Tokens
|
|
39
|
-
|
|
40
|
-
You need to update the tokens once the VIP Design System updates the core files.
|
|
41
|
-
|
|
42
|
-
#### How the theming works
|
|
43
|
-
|
|
44
|
-
We use the VIP Design System Tokens as our base theme structure. All colors, spaces, types should come from a dynamic token system provided by the VIP Design team, currently using Figma as the design software. When the design system is updated by the Design team, they push a file to the root of this repository: `tokens/valet-core.json`.
|
|
45
|
-
|
|
46
|
-
By using the [Token Transformer](https://docs.tokens.studio/sync/github#7-how-to-use-tokens-stored-in-github-in-development) and a custom npm script, we parse this file getting only the VIP Dashboard theme we need for the react components. The light theme is called: `wpvip-product-core`, and the dark theme is called `wpvip-product-dark`.
|
|
47
|
-
|
|
48
|
-
Once the new file is updated, we need to generate a custom theme file in `src/generated/valet-theme-light.json`. This operation generates a small json file with the colors we need already filled in.
|
|
49
|
-
|
|
50
|
-
Once the theme is updated, the file `src/system/theme/index.js` reads the colors and apply to all components.
|
|
51
|
-
|
|
52
|
-
Use the section below to run the script and update the theme.
|
|
53
|
-
|
|
54
|
-
_Important:_ If you change the `generated/valet-theme.json`, make it sure to open a new pull request with these changes and release a new version if needed.
|
|
55
|
-
|
|
56
|
-
#### Update theme script
|
|
57
|
-
|
|
58
|
-
Run this command to update the VIP Valet Theme with the latest `tokens/**` files.
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
npm run theme-update
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Publishing new version
|
|
65
|
-
|
|
66
|
-
The process to release to npm should be started when all pull requests intended for publishing have been merged and the software has been fully tested for publication. You can release either using GitHub Actions or locally.
|
|
67
|
-
|
|
68
|
-
### Versioning Guidelines
|
|
69
|
-
|
|
70
|
-
- `patch`: for non-breaking changes/bugfixes and small updates.
|
|
71
|
-
- `minor`: for some new features, bug fixes, and other non-breaking changes.
|
|
72
|
-
- `major`: for breaking changes.
|
|
73
|
-
|
|
74
|
-
### Note on NPM token
|
|
75
|
-
|
|
76
|
-
Publishing via the GitHub Action requires that the `NPM_TOKEN` be set correctly in GitHub Actions secrets. This should be an npm token generated for a bot user on [the npm @automattic org](https://www.npmjs.com/settings/automattic) that has publish access to this repo.
|
|
77
|
-
|
|
78
|
-
### GitHub Actions (Preferred)
|
|
79
|
-
|
|
80
|
-
This is the preferred method for pushing out the latest release. The workflow runs a bunch of validations, generates a build, bump versions + tags, pushes out to npm, and bumps to the next dev version.
|
|
81
|
-
|
|
82
|
-
1. Initiate the [release process here](https://github.com/Automattic/vip-design-system/actions/workflows/npm-prepare-release.yml).
|
|
83
|
-
1. On the right-hand side, select "Run Workflow".
|
|
84
|
-
1. Pick your preferred version bump.
|
|
85
|
-
1. Click `Run Workflow`.
|
|
86
|
-
1. Wait for a pull request to appear. The pull request will update the version number and shall be assigned to you.
|
|
87
|
-
1. When ready, merge the pull request. This will lead to a new version to be [published on npmjs.com](https://www.npmjs.com/package/@automattic/vip-design-system).
|
|
88
|
-
1. Another pull request will be created to bump to a development version, also assigned to you. Merge it to finish the process.
|
|
89
|
-
|
|
90
|
-
### Local
|
|
91
|
-
|
|
92
|
-
Follow these steps to publish locally:
|
|
93
|
-
|
|
94
|
-
1. Make sure you have NPM access to our @automattic organization. Ask for #vip-platform-pâtisserie help in case you need it.
|
|
95
|
-
2. Pull all the changes to your local trunk. Make sure you have the latest trunk locally.
|
|
96
|
-
3. We follow the [https://semver.org/](https://semver.org/) versioning. You should run the specific version you are trying to publish:
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
npm version major|minor|patch
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
4. You should see a version bump in the `package.json` file.
|
|
103
|
-
5. Build the application:
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
npm run build
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
6. Publish the application
|
|
110
|
-
|
|
111
|
-
```
|
|
112
|
-
npm publish
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
Note: You need to have two-factor enabled in your npm account. The publish command will request a two-factor code to complete the publishing process. You can also add `--otp=CODE` to the `npm publish` command if you already have the code.
|
|
116
|
-
|
|
117
|
-
7. Push the tags to the repository and trunk updates.
|
|
118
|
-
|
|
119
|
-
```
|
|
120
|
-
git push --tags
|
|
121
|
-
git push origin trunk
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
8. For major versions or breaking changes, it's recommended to [create a RELEASE](https://github.com/Automattic/vip-design-system/releases) with the published tag.
|
|
125
|
-
|
|
126
|
-
Ps: Add a `BREAKING CHANGES` section to the release. This will avoid folks trying to figure out why their code is not working on the VIP Dashboard or any other system.
|
|
127
|
-
|
|
128
|
-
## Troubleshooting
|
|
129
|
-
|
|
130
|
-
### Dialog + Dropdown usage
|
|
131
|
-
|
|
132
|
-
If you are facing a Dialog overlaping a Dropdown content, add this CSS to your application:
|
|
133
|
-
|
|
134
|
-
```css
|
|
135
|
-
div[data-radix-popper-content-wrapper][data-aria-hidden='true'] {
|
|
136
|
-
opacity: 0;
|
|
137
|
-
}
|
|
138
|
-
```
|