mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Adding BaseIcon
UI component (#15609)
* Adding BaseIcon component * Updates to styles, docs and proptypes * Updating box props link
This commit is contained in:
parent
6e0f130168
commit
fc23cff03c
77
ui/components/component-library/base-icon/README.mdx
Normal file
77
ui/components/component-library/base-icon/README.mdx
Normal file
@ -0,0 +1,77 @@
|
||||
import { Story, Canvas, ArgsTable } from '@storybook/addon-docs';
|
||||
|
||||
import { BaseIcon } from './base-icon';
|
||||
|
||||
### This is a base component. It should not be used in your feature code directly but as a "base" for other UI components
|
||||
|
||||
# BaseIcon
|
||||
|
||||
The `BaseIcon` is the base component for all icons. It is used in conjunction with a script to create all icons it should not be used directly.
|
||||
|
||||
<Canvas>
|
||||
<Story id="ui-components-component-library-base-icon-base-icon-stories-js--default-story" />
|
||||
</Canvas>
|
||||
|
||||
## Props
|
||||
|
||||
The `BaseIcon` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story#props) component props
|
||||
|
||||
<ArgsTable of={BaseIcon} />
|
||||
|
||||
### Size
|
||||
|
||||
Use the `size` prop and the `SIZES` object from `./ui/helpers/constants/design-system.js` to change the size of `BaseIcon`. Defaults to `SIZES.SM`
|
||||
|
||||
Possible sizes include:
|
||||
|
||||
- `SIZES.XXS` 10px
|
||||
- `SIZES.XS` 12px
|
||||
- `SIZES.SM` 16px
|
||||
- `SIZES.MD` 20px
|
||||
- `SIZES.LG` 24px
|
||||
- `SIZES.XL` 32px
|
||||
|
||||
<Canvas>
|
||||
<Story id="ui-components-component-library-base-icon-base-icon-stories-js--size" />
|
||||
</Canvas>
|
||||
|
||||
```jsx
|
||||
import { SIZES } from '../../../helpers/constants/design-system';
|
||||
import { BaseIcon } from '../ui/component-library';
|
||||
|
||||
<BaseIcon size={SIZES.XXS} />
|
||||
<BaseIcon size={SIZES.XS} />
|
||||
<BaseIcon size={SIZES.SM} />
|
||||
<BaseIcon size={SIZES.MD} />
|
||||
<BaseIcon size={SIZES.LG} />
|
||||
<BaseIcon size={SIZES.XL} />
|
||||
```
|
||||
|
||||
### Color
|
||||
|
||||
Use the `color` prop and the `COLORS` object from `./ui/helpers/constants/design-system.js` to change the color of `BaseIcon`. Defaults to `COLORS.INHERIT` which will use the text color of the parent element. This is useful for inline icons.
|
||||
|
||||
<Canvas>
|
||||
<Story id="ui-components-component-library-base-icon-base-icon-stories-js--color" />
|
||||
</Canvas>
|
||||
|
||||
```jsx
|
||||
import { COLORS } from '../../../helpers/constants/design-system';
|
||||
import { BaseIcon } from '../ui/component-library';
|
||||
|
||||
<BaseIcon color={COLORS.INHERIT} />
|
||||
<BaseIcon color={COLORS.ICON_DEFAULT} />
|
||||
<BaseIcon color={COLORS.ICON_ALTERNATIVE} />
|
||||
<BaseIcon color={COLORS.ICON_MUTED} />
|
||||
<BaseIcon color={COLORS.OVERLAY_INVERSE} />
|
||||
<BaseIcon color={COLORS.PRIMARY_DEFAULT} />
|
||||
<BaseIcon color={COLORS.PRIMARY_INVERSE} />
|
||||
<BaseIcon color={COLORS.ERROR_DEFAULT} />
|
||||
<BaseIcon color={COLORS.ERROR_INVERSE} />
|
||||
<BaseIcon color={COLORS.SUCCESS_DEFAULT} />
|
||||
<BaseIcon color={COLORS.SUCCESS_INVERSE} />
|
||||
<BaseIcon color={COLORS.WARNING_DEFAULT} />
|
||||
<BaseIcon color={COLORS.WARNING_INVERSE} />
|
||||
<BaseIcon color={COLORS.INFO_DEFAULT} />
|
||||
<BaseIcon color={COLORS.INFO_INVERSE} />
|
||||
```
|
56
ui/components/component-library/base-icon/base-icon.js
Normal file
56
ui/components/component-library/base-icon/base-icon.js
Normal file
@ -0,0 +1,56 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import Box from '../../ui/box/box';
|
||||
|
||||
import {
|
||||
SIZES,
|
||||
COLORS,
|
||||
ICON_COLORS,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
|
||||
export const BaseIcon = ({
|
||||
className,
|
||||
size = SIZES.MD,
|
||||
color = COLORS.INHERIT,
|
||||
children,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<Box
|
||||
as="svg"
|
||||
viewBox="0 0 512 512"
|
||||
className={classnames(className, 'base-icon', `base-icon--size-${size}`)}
|
||||
color={color}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
BaseIcon.propTypes = {
|
||||
/**
|
||||
* The size of the BaseIcon.
|
||||
* Possible values could be 'SIZES.XXS', 'SIZES.XS', 'SIZES.SM', 'SIZES.MD', 'SIZES.LG', 'SIZES.XL',
|
||||
* Default value is 'SIZES.MD'.
|
||||
*/
|
||||
size: PropTypes.oneOf(Object.values(SIZES)),
|
||||
/**
|
||||
* The color of the icon.
|
||||
* Defaults to COLORS.INHERIT.
|
||||
*/
|
||||
color: PropTypes.oneOf(Object.values(ICON_COLORS)),
|
||||
/**
|
||||
* An additional className to apply to the icon.
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
/**
|
||||
* The <path> to the icon.
|
||||
*/
|
||||
children: PropTypes.node,
|
||||
/**
|
||||
* BaseIcon accepts all the props from Box
|
||||
*/
|
||||
...Box.propTypes,
|
||||
};
|
33
ui/components/component-library/base-icon/base-icon.scss
Normal file
33
ui/components/component-library/base-icon/base-icon.scss
Normal file
@ -0,0 +1,33 @@
|
||||
.base-icon {
|
||||
--icon-size: var(--size, 16px);
|
||||
|
||||
&--size-xxs {
|
||||
--size: 10px;
|
||||
}
|
||||
|
||||
&--size-xs {
|
||||
--size: 12px;
|
||||
}
|
||||
|
||||
&--size-sm {
|
||||
--size: 16px;
|
||||
}
|
||||
|
||||
&--size-md {
|
||||
--size: 20px;
|
||||
}
|
||||
|
||||
&--size-lg {
|
||||
--size: 24px;
|
||||
}
|
||||
|
||||
&--size-xl {
|
||||
--size: 32px;
|
||||
}
|
||||
|
||||
font-size: var(--icon-size);
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
fill: currentColor;
|
||||
}
|
176
ui/components/component-library/base-icon/base-icon.stories.js
Normal file
176
ui/components/component-library/base-icon/base-icon.stories.js
Normal file
@ -0,0 +1,176 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
SIZES,
|
||||
ALIGN_ITEMS,
|
||||
DISPLAY,
|
||||
COLORS,
|
||||
ICON_COLORS,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import Box from '../../ui/box/box';
|
||||
|
||||
import { BaseIcon } from './base-icon';
|
||||
import README from './README.mdx';
|
||||
|
||||
const marginSizeControlOptions = [
|
||||
undefined,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
'auto',
|
||||
];
|
||||
|
||||
export default {
|
||||
title: 'Components/ComponentLibrary/BaseIcon',
|
||||
id: __filename,
|
||||
component: BaseIcon,
|
||||
parameters: {
|
||||
docs: {
|
||||
page: README,
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
size: {
|
||||
control: 'select',
|
||||
options: Object.values(SIZES),
|
||||
},
|
||||
color: {
|
||||
control: 'select',
|
||||
options: Object.values(ICON_COLORS),
|
||||
},
|
||||
className: {
|
||||
control: 'text',
|
||||
},
|
||||
marginTop: {
|
||||
options: marginSizeControlOptions,
|
||||
control: 'select',
|
||||
table: { category: 'box props' },
|
||||
},
|
||||
marginRight: {
|
||||
options: marginSizeControlOptions,
|
||||
control: 'select',
|
||||
table: { category: 'box props' },
|
||||
},
|
||||
marginBottom: {
|
||||
options: marginSizeControlOptions,
|
||||
control: 'select',
|
||||
table: { category: 'box props' },
|
||||
},
|
||||
marginLeft: {
|
||||
options: marginSizeControlOptions,
|
||||
control: 'select',
|
||||
table: { category: 'box props' },
|
||||
},
|
||||
},
|
||||
args: {
|
||||
color: COLORS.INHERIT,
|
||||
size: SIZES.MD,
|
||||
children: (
|
||||
<path d="M259 16l204 112 3 3c1 1 2 2 2 3 1 1 1 3 1 4 1 1 1 2 1 3l-2 224c0 5-3 10-7 13L261 496c-3 1-5 2-8 2h-1c-3 0-5-1-8-2L49 380c-5-2-7-7-7-12V141c0-5 2-10 7-13 1 0 1-1 2-1L245 16c5-2 10-2 14 0zm182 150l-175 97 1 195 172-101zm-370 0v190l2 2c0 1 1 2 1 3l163 97V261zm331 170c3-5 9-7 14-4l6 3c5 3 6 9 4 14-2 4-6 6-9 6-2 0-4-1-5-2l-6-3c-5-3-7-9-4-14zm-305-4c5-3 12-1 14 4 3 4 2 11-3 14l-6 3c-2 1-3 1-5 1-4 0-7-2-9-5-3-5-1-11 4-14zm265-18c3-5 9-7 14-4l6 3c5 3 7 9 4 14-2 3-6 5-9 5-2 0-4 0-5-1l-6-3c-5-3-7-9-4-14zm-226-5c5-3 11-1 14 4s1 11-4 14l-5 4c-2 0-4 1-5 1-4 0-7-2-9-5-3-5-1-12 3-14zm186-18c3-5 9-7 14-4l6 3c5 3 7 10 4 14-2 4-5 6-9 6-2 0-4-1-5-2l-6-3c-5-3-7-9-4-14zm-147-4c5-3 11-1 14 4s1 11-4 14l-5 3c-2 1-4 2-6 2-3 0-7-2-9-6-2-5-1-11 4-14zm107-18c3-5 10-7 14-4l6 3c5 3 7 9 4 14-2 3-5 5-9 5-2 0-3 0-5-1l-6-3c-5-3-6-9-4-14zm-69-4c5-3 12-2 15 3 2 5 1 12-4 15l-6 3c-1 1-3 1-5 1-3 0-7-2-9-5-3-5-1-11 4-14zm39-220L87 140l166 95 173-94zm0 150c6 0 11 4 11 10v6c0 6-5 11-11 11-5 0-10-5-10-11v-6c0-6 5-10 10-10zm0-45c6 0 11 4 11 10v6c0 6-5 11-11 11-5 0-10-5-10-11v-6c0-6 5-10 10-10zm0-45c6 0 11 4 11 10v7c0 5-5 10-11 10-5 0-10-5-10-10v-7c0-6 5-10 10-10zm0-45c6 0 11 5 11 10v7c0 5-5 10-11 10-5 0-10-5-10-10v-7c0-5 5-10 10-10z" />
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const DefaultStory = (args) => <BaseIcon {...args} />;
|
||||
|
||||
DefaultStory.storyName = 'Default';
|
||||
|
||||
export const Size = (args) => (
|
||||
<Box display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.BASELINE} gap={1}>
|
||||
<BaseIcon {...args} size={SIZES.XXS} />
|
||||
<BaseIcon {...args} size={SIZES.XS} />
|
||||
<BaseIcon {...args} size={SIZES.SM} />
|
||||
<BaseIcon {...args} size={SIZES.MD} />
|
||||
<BaseIcon {...args} size={SIZES.LG} />
|
||||
<BaseIcon {...args} size={SIZES.XL} />
|
||||
</Box>
|
||||
);
|
||||
|
||||
export const Color = (args) => (
|
||||
<Box display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.BASELINE}>
|
||||
<Box padding={1} display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.CENTER}>
|
||||
<BaseIcon {...args} color={COLORS.INHERIT} />
|
||||
</Box>
|
||||
<Box padding={1} display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.CENTER}>
|
||||
<BaseIcon {...args} color={COLORS.ICON_DEFAULT} />
|
||||
</Box>
|
||||
<Box padding={1} display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.CENTER}>
|
||||
<BaseIcon {...args} color={COLORS.ICON_ALTERNATIVE} />
|
||||
</Box>
|
||||
<Box padding={1} display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.CENTER}>
|
||||
<BaseIcon {...args} color={COLORS.ICON_MUTED} />
|
||||
</Box>
|
||||
<Box
|
||||
padding={1}
|
||||
display={DISPLAY.FLEX}
|
||||
alignItems={ALIGN_ITEMS.CENTER}
|
||||
backgroundColor={COLORS.OVERLAY_DEFAULT}
|
||||
>
|
||||
<BaseIcon {...args} color={COLORS.OVERLAY_INVERSE} />
|
||||
</Box>
|
||||
<Box padding={1} display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.CENTER}>
|
||||
<BaseIcon {...args} color={COLORS.PRIMARY_DEFAULT} />
|
||||
</Box>
|
||||
<Box
|
||||
padding={1}
|
||||
display={DISPLAY.FLEX}
|
||||
alignItems={ALIGN_ITEMS.CENTER}
|
||||
backgroundColor={COLORS.PRIMARY_DEFAULT}
|
||||
>
|
||||
<BaseIcon {...args} color={COLORS.PRIMARY_INVERSE} />
|
||||
</Box>
|
||||
<Box padding={1} display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.CENTER}>
|
||||
<BaseIcon {...args} color={COLORS.ERROR_DEFAULT} />
|
||||
</Box>
|
||||
<Box
|
||||
padding={1}
|
||||
display={DISPLAY.FLEX}
|
||||
alignItems={ALIGN_ITEMS.CENTER}
|
||||
backgroundColor={COLORS.ERROR_DEFAULT}
|
||||
>
|
||||
<BaseIcon {...args} color={COLORS.ERROR_INVERSE} />
|
||||
</Box>
|
||||
<Box padding={1} display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.CENTER}>
|
||||
<BaseIcon {...args} color={COLORS.SUCCESS_DEFAULT} />
|
||||
</Box>
|
||||
<Box
|
||||
padding={1}
|
||||
display={DISPLAY.FLEX}
|
||||
alignItems={ALIGN_ITEMS.CENTER}
|
||||
backgroundColor={COLORS.SUCCESS_DEFAULT}
|
||||
>
|
||||
<BaseIcon {...args} color={COLORS.SUCCESS_INVERSE} />
|
||||
</Box>
|
||||
<Box padding={1} display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.CENTER}>
|
||||
<BaseIcon {...args} color={COLORS.WARNING_DEFAULT} />
|
||||
</Box>
|
||||
<Box
|
||||
padding={1}
|
||||
display={DISPLAY.FLEX}
|
||||
alignItems={ALIGN_ITEMS.CENTER}
|
||||
backgroundColor={COLORS.WARNING_DEFAULT}
|
||||
>
|
||||
<BaseIcon {...args} color={COLORS.WARNING_INVERSE} />
|
||||
</Box>
|
||||
<Box padding={1} display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.CENTER}>
|
||||
<BaseIcon {...args} color={COLORS.INFO_DEFAULT} />
|
||||
</Box>
|
||||
<Box
|
||||
padding={1}
|
||||
display={DISPLAY.FLEX}
|
||||
alignItems={ALIGN_ITEMS.CENTER}
|
||||
backgroundColor={COLORS.INFO_DEFAULT}
|
||||
>
|
||||
<BaseIcon {...args} color={COLORS.INFO_INVERSE} />
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
64
ui/components/component-library/base-icon/base-icon.test.js
Normal file
64
ui/components/component-library/base-icon/base-icon.test.js
Normal file
@ -0,0 +1,64 @@
|
||||
/* eslint-disable jest/require-top-level-describe */
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { SIZES, COLORS } from '../../../helpers/constants/design-system';
|
||||
import { BaseIcon } from './base-icon';
|
||||
|
||||
describe('BaseIcon', () => {
|
||||
it('should render correctly', () => {
|
||||
const { getByTestId, container } = render(
|
||||
<BaseIcon data-testid="base-icon" />,
|
||||
);
|
||||
expect(getByTestId('base-icon')).toBeDefined();
|
||||
expect(container.querySelector('svg')).toBeDefined();
|
||||
});
|
||||
it('should render with different size classes', () => {
|
||||
const { getByTestId } = render(
|
||||
<>
|
||||
<BaseIcon size={SIZES.XXS} data-testid="base-icon-xxs" />
|
||||
<BaseIcon size={SIZES.XS} data-testid="base-icon-xs" />
|
||||
<BaseIcon size={SIZES.SM} data-testid="base-icon-sm" />
|
||||
<BaseIcon size={SIZES.MD} data-testid="base-icon-md" />
|
||||
<BaseIcon size={SIZES.LG} data-testid="base-icon-lg" />
|
||||
<BaseIcon size={SIZES.XL} data-testid="base-icon-xl" />
|
||||
</>,
|
||||
);
|
||||
expect(getByTestId('base-icon-xxs')).toHaveClass('base-icon--size-xxs');
|
||||
expect(getByTestId('base-icon-xs')).toHaveClass('base-icon--size-xs');
|
||||
expect(getByTestId('base-icon-sm')).toHaveClass('base-icon--size-sm');
|
||||
expect(getByTestId('base-icon-md')).toHaveClass('base-icon--size-md');
|
||||
expect(getByTestId('base-icon-lg')).toHaveClass('base-icon--size-lg');
|
||||
expect(getByTestId('base-icon-xl')).toHaveClass('base-icon--size-xl');
|
||||
});
|
||||
it('should render with icon colors', () => {
|
||||
const { getByTestId } = render(
|
||||
<>
|
||||
<BaseIcon data-testid="base-icon-color-inherit" />
|
||||
<BaseIcon
|
||||
color={COLORS.ICON_DEFAULT}
|
||||
data-testid="base-icon-color-default"
|
||||
/>
|
||||
<BaseIcon
|
||||
color={COLORS.ICON_ALTERNATIVE}
|
||||
data-testid="base-icon-color-alternative"
|
||||
/>
|
||||
<BaseIcon
|
||||
color={COLORS.ICON_MUTED}
|
||||
data-testid="base-icon-color-muted"
|
||||
/>
|
||||
</>,
|
||||
);
|
||||
expect(getByTestId('base-icon-color-inherit')).toHaveClass(
|
||||
'box--color-inherit',
|
||||
);
|
||||
expect(getByTestId('base-icon-color-default')).toHaveClass(
|
||||
'box--color-icon-default',
|
||||
);
|
||||
expect(getByTestId('base-icon-color-alternative')).toHaveClass(
|
||||
'box--color-icon-alternative',
|
||||
);
|
||||
expect(getByTestId('base-icon-color-muted')).toHaveClass(
|
||||
'box--color-icon-muted',
|
||||
);
|
||||
});
|
||||
});
|
1
ui/components/component-library/base-icon/index.js
Normal file
1
ui/components/component-library/base-icon/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { BaseIcon } from './base-icon';
|
@ -1,2 +1,3 @@
|
||||
/** Please import your files in alphabetical order **/
|
||||
@import 'base-avatar/base-avatar';
|
||||
@import 'base-icon/base-icon';
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
BACKGROUND_COLORS,
|
||||
BORDER_COLORS,
|
||||
TEXT_COLORS,
|
||||
ICON_COLORS,
|
||||
DISPLAY,
|
||||
JUSTIFY_CONTENT,
|
||||
SIZES,
|
||||
@ -28,6 +29,7 @@ export const ValidBackgroundColors = PropTypes.oneOf(
|
||||
);
|
||||
export const ValidBorderColors = PropTypes.oneOf(Object.values(BORDER_COLORS));
|
||||
export const ValidTextColors = PropTypes.oneOf(Object.values(TEXT_COLORS));
|
||||
export const ValidIconColors = PropTypes.oneOf(Object.values(ICON_COLORS));
|
||||
|
||||
const ArrayOfValidSizes = PropTypes.arrayOf(ValidSize);
|
||||
export const MultipleSizes = PropTypes.oneOfType([
|
||||
@ -54,9 +56,12 @@ export const MultipleBackgroundColors = PropTypes.oneOfType([
|
||||
]);
|
||||
|
||||
const ArrayOfValidTextColors = PropTypes.arrayOf(ValidTextColors);
|
||||
const ArrayOfValidIconColors = PropTypes.arrayOf(ValidIconColors);
|
||||
export const MultipleTextColors = PropTypes.oneOfType([
|
||||
ValidTextColors,
|
||||
ArrayOfValidTextColors,
|
||||
ValidIconColors,
|
||||
ArrayOfValidIconColors,
|
||||
]);
|
||||
|
||||
function isValidSize(type, value) {
|
||||
|
@ -126,6 +126,25 @@ export const TEXT_COLORS = pick(COLORS, [
|
||||
'INFO_INVERSE',
|
||||
'INHERIT',
|
||||
]);
|
||||
|
||||
export const ICON_COLORS = pick(COLORS, [
|
||||
'ICON_DEFAULT',
|
||||
'ICON_ALTERNATIVE',
|
||||
'ICON_MUTED',
|
||||
'OVERLAY_INVERSE',
|
||||
'PRIMARY_DEFAULT',
|
||||
'PRIMARY_INVERSE',
|
||||
'ERROR_DEFAULT',
|
||||
'ERROR_INVERSE',
|
||||
'SUCCESS_DEFAULT',
|
||||
'SUCCESS_INVERSE',
|
||||
'WARNING_DEFAULT',
|
||||
'WARNING_INVERSE',
|
||||
'INFO_DEFAULT',
|
||||
'INFO_INVERSE',
|
||||
'INHERIT',
|
||||
]);
|
||||
|
||||
export const TYPOGRAPHY = {
|
||||
H1: 'h1',
|
||||
H2: 'h2',
|
||||
|
Loading…
Reference in New Issue
Block a user