diff --git a/.storybook/Decorator.tsx b/.storybook/Decorator.tsx deleted file mode 100644 index 95ed2ba7..00000000 --- a/.storybook/Decorator.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React, { FC, ReactNode } from 'react' -import { createUseStyles } from 'react-jss' -import { ThemeType, themes } from '../src/components/assets/styles/themes' -import cn from 'classnames' -const { dark } = ThemeType - -const useStyles = createUseStyles({ - '@global': { - [`.${dark} .decorator`]: { - backgroundColor: themes[dark].background.secondary - } - }, - decorator: { - padding: '1rem' - } -}) - -export interface DecoratorProps { - children: ReactNode - classes?: string[] -} - -const Decorator: FC = ({ - children, - classes = [] -}: DecoratorProps) => { - const decoratorClasses = useStyles() - - return ( -
- {children} -
- ) -} - -export default Decorator diff --git a/.storybook/__tests__/Decorator.test.tsx b/.storybook/__tests__/Decorator.test.tsx deleted file mode 100644 index 34f5525f..00000000 --- a/.storybook/__tests__/Decorator.test.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react' -import Decorator, { DecoratorProps } from '../Decorator' -import { shallow, ShallowWrapper } from 'enzyme' - -let wrapper: ShallowWrapper - -describe('Decorator', () => { - it('renders', () => { - wrapper = shallow(Decorator) - - expect(wrapper).toHaveLength(1) - }) -}) diff --git a/src/__snapshots__/storybook.test.ts.snap b/src/__snapshots__/storybook.test.ts.snap index c40339d2..c2f46dfe 100644 --- a/src/__snapshots__/storybook.test.ts.snap +++ b/src/__snapshots__/storybook.test.ts.snap @@ -249,24 +249,20 @@ exports[`Storyshots Input Default 1`] = ` className="storyWrapper-0-2-2" >
-
- -
+
`; @@ -276,24 +272,20 @@ exports[`Storyshots Input Error 1`] = ` className="storyWrapper-0-2-2" >
-
- -
+
`; @@ -303,24 +295,20 @@ exports[`Storyshots Input Full Width 1`] = ` className="storyWrapper-0-2-2" >
-
- -
+
`; @@ -330,20 +318,16 @@ exports[`Storyshots Input Loading 1`] = ` className="storyWrapper-0-2-2" >
-
- -   - -
+   +
@@ -354,24 +338,20 @@ exports[`Storyshots Input Placeholder 1`] = ` className="storyWrapper-0-2-2" >
-
- -
+
`; @@ -637,6 +617,44 @@ exports[`Storyshots Radio Group Default 1`] = ` `; +exports[`Storyshots Radio Group Loading 1`] = ` +
+
+
+ +   + +
+
+ +   + +
+
+ +   + +
+
+
+`; + exports[`Storyshots Radio Group Partially Disabled 1`] = `
Lorem @@ -928,10 +946,10 @@ exports[`Storyshots Select Icon 1`] = ` className="storyWrapper-0-2-2" >
  @@ -1148,27 +1166,27 @@ exports[`Storyshots Skeleton Count 1`] = ` className="storyWrapper-0-2-2" >           @@ -1180,7 +1198,7 @@ exports[`Storyshots Skeleton Default 1`] = ` className="storyWrapper-0-2-2" >   diff --git a/src/components/Form/FieldLabel/index.tsx b/src/components/Form/FieldLabel/index.tsx index 388f89c1..d8ced9af 100644 --- a/src/components/Form/FieldLabel/index.tsx +++ b/src/components/Form/FieldLabel/index.tsx @@ -38,7 +38,7 @@ const FieldLabel: FC = ({
{loading ? : label} diff --git a/src/components/Form/Form.stories.tsx b/src/components/Form/Form.stories.tsx index 98a04dd0..572bcc7e 100644 --- a/src/components/Form/Form.stories.tsx +++ b/src/components/Form/Form.stories.tsx @@ -1,5 +1,4 @@ import { basicOptions } from '../RadioGroup/fixtures/sample_options' -import Decorator from '../../../.storybook/Decorator' import { iconOptions } from '../Select/fixtures/sample_options' import React from 'react' import treeData from '../Tree/fixtures/0_sample_data' @@ -12,13 +11,6 @@ export default { onSubmit: { control: { disable: true } } }, component: Form, - decorators: [ - (ComponentStory: Story) => ( - - - - ) - ], parameters: { // disabled because shallow rendering gives warning, but FormTree only works with shallow render storyshots: { disable: true } @@ -63,3 +55,6 @@ const Template: Story> = (args: FormProps) => ( ) export const Default = Template.bind({}) + +export const Loading = Template.bind({}) +Loading.args = { loading: true } diff --git a/src/components/Input/Input.stories.tsx b/src/components/Input/Input.stories.tsx index 0e9a187b..54ea78d1 100644 --- a/src/components/Input/Input.stories.tsx +++ b/src/components/Input/Input.stories.tsx @@ -1,4 +1,3 @@ -import Decorator from '../../../.storybook/Decorator' import React from 'react' import { Input, InputProps } from './index' import { Meta, Story } from '@storybook/react/types-6-0' @@ -9,13 +8,6 @@ export default { value: { control: { disable: true } } }, component: Input, - decorators: [ - (ComponentStory: Story) => ( - - - - ) - ], title: 'Input' } as Meta diff --git a/src/components/Input/index.tsx b/src/components/Input/index.tsx index 5201b739..ac04f846 100644 --- a/src/components/Input/index.tsx +++ b/src/components/Input/index.tsx @@ -3,7 +3,6 @@ import { Input as AntDInput } from 'antd' import { BaseFormElementProps } from '../types' import cn from 'classnames' import { createUseStyles } from 'react-jss' -import { generateInputStyles } from './utils' import { getDataTestAttributeProp } from '../utils' import { Skeleton } from '../Skeleton' import { ThemeType } from '../assets/styles/themes' @@ -11,23 +10,24 @@ import { defaultFieldWidth, fieldErrorStyles } from '../assets/styles/styleguide' +import { generateInputSkeletonStyles, generateInputStyles } from './utils' import React, { FC } from 'react' const { dark, light } = ThemeType const useStyles = createUseStyles({ - '@global': { - ...fieldErrorStyles['@global'], - [`.${dark} input`]: generateInputStyles(dark), - input: generateInputStyles(light) - }, container: { width: props => (props.fullWidth ? '100%' : defaultFieldWidth) }, - input: { - border: '1px solid #DEDEDF', - borderRadius: '4px', - padding: '6px 14px' + inputSkeleton: generateInputSkeletonStyles(light), + // eslint-disable-next-line sort-keys + '@global': { + ...fieldErrorStyles['@global'], + [`.${dark}`]: { + '& $input': generateInputStyles(dark), + '& $inputSkeleton': generateInputSkeletonStyles(dark) + }, + input: generateInputStyles(light) } }) @@ -36,7 +36,7 @@ const InputSkeleton: FC = (props: InputProps) => { return (
-
+
diff --git a/src/components/Input/utils.ts b/src/components/Input/utils.ts index 7688f823..505cc3d6 100644 --- a/src/components/Input/utils.ts +++ b/src/components/Input/utils.ts @@ -1,5 +1,8 @@ -import { fieldErrorStyles } from '../assets/styles/styleguide' -import { themedStyles, ThemeType } from '../assets/styles/themes' +import { + borderRadius, + fieldErrorStyles +} from 'components/assets/styles/styleguide' +import { themedStyles, ThemeType } from 'components/assets/styles/themes' export const generateInputStyles = (themeType: ThemeType) => { const { base, disabled, error, focus, hover, placeholder } = themedStyles[ @@ -31,3 +34,13 @@ export const generateInputStyles = (themeType: ThemeType) => { '&.ant-input.error': { ...fieldErrorStyles.error, border: error.border } } } + +export const generateInputSkeletonStyles = (themeType: ThemeType) => { + const { loading } = themedStyles[themeType] + + return { + border: loading.border, + borderRadius: borderRadius, + padding: '6px 14px' + } +} diff --git a/src/components/RadioGroup/RadioGroup.stories.tsx b/src/components/RadioGroup/RadioGroup.stories.tsx index 3efd33a7..3828dfb8 100644 --- a/src/components/RadioGroup/RadioGroup.stories.tsx +++ b/src/components/RadioGroup/RadioGroup.stories.tsx @@ -28,3 +28,6 @@ Default.args = { options: basicOptions } export const PartiallyDisabled = Template.bind({}) PartiallyDisabled.args = { options: basicOptionsDisabled } + +export const Loading = Template.bind({}) +Loading.args = { loading: true, options: basicOptions } diff --git a/src/components/RadioGroup/index.tsx b/src/components/RadioGroup/index.tsx index a872d526..92ae7454 100644 --- a/src/components/RadioGroup/index.tsx +++ b/src/components/RadioGroup/index.tsx @@ -2,22 +2,28 @@ import 'antd/lib/radio/style/index.css' import { Radio as AntDRadio } from 'antd' import { CommonComponentProps } from '../types' import { createUseStyles } from 'react-jss' +import { generateRadioSkeletonStyles } from './utils' import { Skeleton } from '../Skeleton' -import { skeletonButtonBorderColor } from '../assets/styles/styleguide' +import { ThemeType } from 'components/assets/styles/themes' import times from 'lodash/times' import { getDataTestAttributeProp, TAG } from '../utils' import React, { ChangeEventHandler, FC } from 'react' +const { dark, light } = ThemeType + const useStyles = createUseStyles({ - button: { - border: `1px solid ${skeletonButtonBorderColor}`, - display: 'flex' - }, container: { display: 'flex' }, skeleton: { borderRadius: 'unset' + }, + skeletonButton: generateRadioSkeletonStyles(light), + // eslint-disable-next-line sort-keys + '@global': { + [`.${dark}`]: { + '& $skeletonButton': generateRadioSkeletonStyles(dark) + } } }) @@ -29,7 +35,7 @@ const RadioGroupSkeleton: FC = ({ return (
{times(options.length, i => ( -
+
{ + const { loading } = themedStyles[themeType] + + return { + border: loading.border, + borderRadius: borderRadius, + display: 'flex', + margin: '0 1px' + } +} diff --git a/src/components/Skeleton/index.tsx b/src/components/Skeleton/index.tsx index 41f241cc..310e222f 100644 --- a/src/components/Skeleton/index.tsx +++ b/src/components/Skeleton/index.tsx @@ -1,26 +1,44 @@ +import { borderRadius } from 'components/assets/styles/styleguide' import cn from 'classnames' import { createUseStyles } from 'react-jss' import React, { FC } from 'react' +import { themes, ThemeType } from 'components/assets/styles/themes' + +const { light, dark } = ThemeType + +const generatePartialSkeletonStyles = (themeType: ThemeType) => { + const { primary, secondary } = themes[themeType].state.loading + + return { + backgroundColor: primary, + backgroundImage: `linear-gradient(90deg, ${primary}, ${secondary} , ${primary})` + } +} const useStyles = createUseStyles({ - '@global': { - '@keyframes skeleton': { - '0%': { backgroundPosition: '-200px 0' }, - '100%': { backgroundPosition: 'calc(200px + 100%) 0' } - } - }, container: { + ...generatePartialSkeletonStyles(light), animation: props => `skeleton ${props.duration}s ease-in-out infinite`, - backgroundColor: '#EEEEEE', - backgroundImage: 'linear-gradient(90deg, #EEEEEE, #F5F5F5, #EEEEEE)', backgroundRepeat: 'no-repeat', backgroundSize: '200px 100%', - borderRadius: props => (props.circle ? '50%' : '4px'), + borderRadius: props => (props.circle ? '50%' : borderRadius), display: props => (props.count > 1 ? 'block' : 'inline-block'), height: props => (props.height ? props.height : '100%'), lineHeight: 1, marginBottom: props => (props.count > 1 ? 5 : 0), - width: props => (props.width ? `${props.width}px` : '100%') + width: props => (props.width ? props.width : '100%') + }, + // eslint-disable-next-line sort-keys + '@global': { + '@keyframes skeleton': { + '0%': { backgroundPosition: '-200px 0' }, + '100%': { backgroundPosition: 'calc(200px + 100%) 0' } + }, + [`.${dark}`]: { + '& $container': { + ...generatePartialSkeletonStyles(dark) + } + } } }) diff --git a/src/components/assets/styles/colors.ts b/src/components/assets/styles/colors.ts index b6b69efe..6dbe06db 100644 --- a/src/components/assets/styles/colors.ts +++ b/src/components/assets/styles/colors.ts @@ -72,7 +72,7 @@ export interface ColorsType { greens: { base: string } oranges: { base: string } reds: { base: string } - whites: { base: string } + whites: { 'darken-5': string; base: string } } const colors: ColorsType = { @@ -81,7 +81,7 @@ const colors: ColorsType = { greens: { base: green }, oranges: { base: orange }, reds: { base: red }, - whites: { base: white } + whites: { base: white, 'darken-5': manipulateColor(white, 5, shade) } } export default colors diff --git a/src/components/assets/styles/styleguide.ts b/src/components/assets/styles/styleguide.ts index e565c70f..8623751f 100644 --- a/src/components/assets/styles/styleguide.ts +++ b/src/components/assets/styles/styleguide.ts @@ -1,5 +1,6 @@ import colors from './colors' +export const borderRadius = 4 export const defaultFieldWidth = '300px' export const fieldErrorStyles = { '@global': { @@ -16,9 +17,7 @@ export const fieldErrorStyles = { } export const fontSizeRegular = '14px' export const linkColor = '#1EA7FD' -export const skeletonButtonBorderColor = '#DFDFDF' export * from './themes' - /* eslint-disable sort-keys */ export const styleguide = { colors, diff --git a/src/components/assets/styles/themes.ts b/src/components/assets/styles/themes.ts index 4e332198..a5f77b01 100644 --- a/src/components/assets/styles/themes.ts +++ b/src/components/assets/styles/themes.ts @@ -1,5 +1,4 @@ import colors from './colors' -import { ColorManipulationTypes, manipulateColor } from 'components/utils' const { blacks, blues, greens, oranges, reds, whites } = colors @@ -8,71 +7,82 @@ export enum ThemeType { light = 'light' } +const { dark, light } = ThemeType + export interface Theme { - action: { - active: string - disabled: string - } background: { primary: string secondary: string } border: string primary: string - error: string - success: string + state: { + active: string + disabled: string + error: string + hover: string + loading: { + primary: string + secondary: string + } + success: string + warning: string + } text: { disabled: string; primary: string } - warning: string } const lightPalette: Theme = { - action: { - active: blacks.base, - disabled: blacks['lighten-90'] // update when defined by Design - }, background: { primary: whites.base, secondary: blacks['lighten-90'] }, border: blacks['lighten-80'], - error: reds.base, + primary: blues.base, - success: greens.base, + state: { + active: blacks.base, + disabled: blacks['lighten-90'], // update when defined by Design + error: reds.base, + hover: blacks['lighten-30'], + loading: { + primary: blacks['lighten-90'], + secondary: whites['darken-5'] + }, + success: greens.base, + warning: oranges.base + }, text: { disabled: blacks['lighten-70'], // update when defined by Design primary: blacks['lighten-30'] - }, - warning: oranges.base + } } const darkPalette: Theme = { - action: { - active: whites.base, - disabled: blacks['lighten-20'] // update when defined by Design - }, background: { primary: blacks.base, secondary: blacks['darken-20'] }, - border: blacks['darken-20'], - error: reds.base, + border: blacks['lighten-20'], primary: blues.base, - success: greens.base, + state: { + active: whites.base, + disabled: blacks['lighten-10'], // update when defined by Design + error: reds.base, + hover: blacks['lighten-60'], + loading: { + primary: blacks['lighten-10'], + secondary: blacks['lighten-20'] + }, + success: greens.base, + warning: oranges.base + }, text: { disabled: blacks['lighten-20'], // update when defined by Design primary: blacks['lighten-50'] - }, - warning: oranges.base + } } -const generateThemedStyles = ({ - action, - background, - border, - error, - primary, - text -}: Theme) => { +const generateThemedStyles = ({ state, background, border, text }: Theme) => { const base = { backgroundColor: background.primary, borderColor: border, @@ -80,32 +90,40 @@ const generateThemedStyles = ({ } const disabled = { - backgroundColor: action.disabled, + backgroundColor: state.disabled, color: text.disabled } const errorStyles = { - border: `1px solid ${error}` + border: `1px solid ${state.error}` } const hover = { - borderColor: blues['lighten-10'] // update when defined by Design + borderColor: state.hover } const focus = { ...hover, - boxShadow: `0px 0px 4px ${manipulateColor( - primary, - 50, - ColorManipulationTypes.fade - )}` // update when defined by Design + boxShadow: 'none' + } + + const loading = { + border: `1px solid ${state.loading.primary}` } const placeholder = { color: text.disabled // update when defined by Design } - return { base, disabled, error: errorStyles, focus, hover, placeholder } + return { + base, + disabled, + error: errorStyles, + focus, + hover, + loading, + placeholder + } } export const themes = { @@ -113,8 +131,6 @@ export const themes = { [ThemeType.light]: lightPalette } -const { dark, light } = ThemeType - export const themedStyles = { [ThemeType.dark]: generateThemedStyles(themes[dark]), [ThemeType.light]: generateThemedStyles(themes[light])