1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-22 09:23:21 +01:00

Feat/18890/button ts update (#20492)

* button to TS migration

working demo

style props

broken mapping - need switch

working types file

working types

fix dependent imports of Button

variant mapping

working types

fix lint

fix test

fix ButtonSize issue on QuizContent

box fix

test if this works

fix button being used on QuizContent

fix button_variant import

readme fix

* fix button import

* fix primary button as anchor hover

* deprecated

* button to TS migration

fix lint

fix test

* fix rebase issue

* fix rebase issue

* lint fix
This commit is contained in:
Garrett Bear 2023-08-28 14:42:00 -07:00 committed by GitHub
parent c54212916b
commit 66292330fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 292 additions and 299 deletions

View File

@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
BUTTON_VARIANT,
ButtonVariant,
Button,
Box,
Modal,
@ -72,7 +72,7 @@ export default function ConfigureSnapPopup({
{t('configureSnapPopupLink')}
</Text>
<Button
variant={BUTTON_VARIANT.LINK}
variant={ButtonVariant.Link}
marginBottom={8}
onClick={() => {
global.platform.openTab({

View File

@ -60,8 +60,7 @@ export default function QuizContent({
key={idx}
size={btn.size}
onClick={btn.onClick}
label={btn.label}
variant={btn.variant}
variant={btn.variant as any}
width={BlockSize.Full}
data-testid={btn['data-testid']}
>

View File

@ -18,8 +18,8 @@ import { REVEAL_SEED_ROUTE } from '../../../../helpers/constants/routes';
import ZENDESK_URLS from '../../../../helpers/constants/zendesk-url';
import { useI18nContext } from '../../../../hooks/useI18nContext';
import {
BUTTON_SIZES,
BUTTON_VARIANT,
ButtonSize,
ButtonVariant,
Icon,
IconName,
IconSize,
@ -81,14 +81,14 @@ export default function SRPQuiz(props: any) {
{
label: t('srpSecurityQuizGetStarted'),
onClick: () => setStage(QuizStage.questionOne),
variant: BUTTON_VARIANT.PRIMARY,
size: BUTTON_SIZES.LG,
variant: ButtonVariant.Primary,
size: ButtonSize.Lg,
'data-testid': 'srp-quiz-get-started',
},
{
label: t('learnMoreUpperCase'),
onClick: openSupportArticle,
variant: BUTTON_VARIANT.LINK,
variant: ButtonVariant.Link,
'data-testid': 'srp-quiz-learn-more',
},
]}
@ -105,21 +105,21 @@ export default function SRPQuiz(props: any) {
{
label: t('srpSecurityQuizQuestionOneWrongAnswer'),
onClick: () => setStage(QuizStage.wrongAnswerQuestionOne),
variant: BUTTON_VARIANT.SECONDARY,
size: BUTTON_SIZES.LG,
variant: ButtonVariant.Secondary,
size: ButtonSize.Lg,
'data-testid': 'srp-quiz-wrong-answer',
},
{
label: t('srpSecurityQuizQuestionOneRightAnswer'),
onClick: () => setStage(QuizStage.rightAnswerQuestionOne),
variant: BUTTON_VARIANT.SECONDARY,
size: BUTTON_SIZES.LG,
variant: ButtonVariant.Secondary,
size: ButtonSize.Lg,
'data-testid': 'srp-quiz-right-answer',
},
{
label: t('learnMoreUpperCase'),
onClick: openSupportArticle,
variant: BUTTON_VARIANT.LINK,
variant: ButtonVariant.Link,
},
]}
/>
@ -137,14 +137,14 @@ export default function SRPQuiz(props: any) {
{
label: t('continue'),
onClick: () => setStage(QuizStage.questionTwo),
variant: BUTTON_VARIANT.PRIMARY,
size: BUTTON_SIZES.LG,
variant: ButtonVariant.Primary,
size: ButtonSize.Lg,
'data-testid': 'srp-quiz-continue',
},
{
label: t('learnMoreUpperCase'),
onClick: openSupportArticle,
variant: BUTTON_VARIANT.LINK,
variant: ButtonVariant.Link,
},
]}
/>
@ -162,14 +162,14 @@ export default function SRPQuiz(props: any) {
{
label: t('tryAgain'),
onClick: () => setStage(QuizStage.questionOne),
variant: BUTTON_VARIANT.PRIMARY,
size: BUTTON_SIZES.LG,
variant: ButtonVariant.Primary,
size: ButtonSize.Lg,
'data-testid': 'srp-quiz-try-again',
},
{
label: t('learnMoreUpperCase'),
onClick: openSupportArticle,
variant: BUTTON_VARIANT.LINK,
variant: ButtonVariant.Link,
},
]}
/>
@ -185,21 +185,21 @@ export default function SRPQuiz(props: any) {
{
label: t('srpSecurityQuizQuestionTwoRightAnswer'),
onClick: () => setStage(QuizStage.rightAnswerQuestionTwo),
variant: BUTTON_VARIANT.SECONDARY,
size: BUTTON_SIZES.LG,
variant: ButtonVariant.Secondary,
size: ButtonSize.Lg,
'data-testid': 'srp-quiz-right-answer',
},
{
label: t('srpSecurityQuizQuestionTwoWrongAnswer'),
onClick: () => setStage(QuizStage.wrongAnswerQuestionTwo),
variant: BUTTON_VARIANT.SECONDARY,
size: BUTTON_SIZES.LG,
variant: ButtonVariant.Secondary,
size: ButtonSize.Lg,
'data-testid': 'srp-quiz-wrong-answer',
},
{
label: t('learnMoreUpperCase'),
onClick: openSupportArticle,
variant: BUTTON_VARIANT.LINK,
variant: ButtonVariant.Link,
},
]}
/>
@ -217,14 +217,14 @@ export default function SRPQuiz(props: any) {
{
label: t('continue'),
onClick: () => history.push(REVEAL_SEED_ROUTE),
variant: BUTTON_VARIANT.PRIMARY,
size: BUTTON_SIZES.LG,
variant: ButtonVariant.Primary,
size: ButtonSize.Lg,
'data-testid': 'srp-quiz-continue',
},
{
label: t('learnMoreUpperCase'),
onClick: openSupportArticle,
variant: BUTTON_VARIANT.LINK,
variant: ButtonVariant.Link,
},
]}
/>
@ -242,14 +242,14 @@ export default function SRPQuiz(props: any) {
{
label: t('tryAgain'),
onClick: () => setStage(QuizStage.questionTwo),
variant: BUTTON_VARIANT.PRIMARY,
size: BUTTON_SIZES.LG,
variant: ButtonVariant.Primary,
size: ButtonSize.Lg,
'data-testid': 'srp-quiz-try-again',
},
{
label: t('learnMoreUpperCase'),
onClick: openSupportArticle,
variant: BUTTON_VARIANT.LINK,
variant: ButtonVariant.Link,
},
]}
/>

View File

@ -1,3 +1,5 @@
import { ButtonSize, ButtonVariant } from '../../component-library';
export enum QuizStage {
introduction = 'introduction',
questionOne = 'question_one',
@ -31,8 +33,8 @@ export interface IQuizInformationProps {
buttons: {
onClick: () => void;
label: string;
variant: string;
size?: string;
variant: ButtonVariant;
size?: ButtonSize;
'data-testid'?: string;
}[];
}

View File

@ -1,5 +1,5 @@
.mm-button-primary {
&:hover {
&:hover:not(&--disabled) {
color: var(--color-primary-inverse);
box-shadow: var(--component-button-primary-shadow);
}
@ -10,7 +10,7 @@
}
// Danger type
&--type-danger {
&--type-danger:not(&--disabled) {
&:hover {
color: var(--color-error-inverse);
box-shadow: var(--component-button-danger-shadow);

View File

@ -13,66 +13,53 @@ The `Button` is used for user actions. It unifies `ButtonPrimary`, `ButtonSecond
## Props
The `Button` accepts all props below as well as all [ButtonPrimary](/docs/components-componentlibrary-buttonprimary--default-story), [ButtonSecondary](/docs/components-componentlibrary-buttonsecondary--default-story), [ButtonLink](/docs/components-componentlibrary-buttonlink--default-story), and [Box](/docs/components-ui-box--default-story#props) component props
<ArgsTable of={Button} />
The `Button` accepts all [ButtonBase](/docs/components-componentlibrary-buttonbase--default-story#props) component props
<ArgsTable of={ButtonBase} />
The `Button` accepts all [ButtonPrimary](/docs/components-componentlibrary-buttonprimary--default-story), [ButtonSecondary](/docs/components-componentlibrary-buttonsecondary--default-story), [ButtonLink](/docs/components-componentlibrary-buttonlink--default-story), and [Box](/docs/components-ui-box--default-story#props) component props
<ArgsTable of={ButtonLink} />
### Variant
Use the `variant` prop and the `BUTTON_VARIANT` object from `./button.constants.js` to change the `Button` variant.
Use the `variant` prop and the `ButtonVariant` enum from `./ui/components/component-library` to change the `Button` variant.
Possible variants include:
- `BUTTON_VARIANT.PRIMARY`
- `BUTTON_VARIANT.SECONDARY`
- `BUTTON_VARIANT.LINK`
- `ButtonVariant.Primary` (default)
- `ButtonVariant.Secondary`
- `ButtonVariant.Link`
<Canvas>
<Story id="components-componentlibrary-button--variant" />
</Canvas>
```jsx
import { Button, BUTTON_VARIANT } from '../ui/component-library/button';
import { Button, ButtonVariant } from '../ui/component-library/button';
<Button variant={BUTTON_VARIANT.PRIMARY}>Button Primary</Button>
<Button variant={BUTTON_VARIANT.SECONDARY}>Button Secondary</Button>
<Button variant={BUTTON_VARIANT.LINK}>Button Link</Button>
<Button variant={ButtonVariant.Primary}>Button Primary</Button>
<Button variant={ButtonVariant.Secondary}>Button Secondary</Button>
<Button variant={ButtonVariant.Link}>Button Link</Button>
```
### Size
Use the `size` prop and the `Size` object from `./ui/helpers/constants/design-system.js` to change the size of `Button`. Defaults to `Size.MD`
Optional: `BUTTON_SIZES` from `./button` object can be used instead of `Size`.
Use the `size` prop and the `ButtonSize` enum from `./ui/components/component-library` to change the size of `Button`. Defaults to `Buttonsize.Md`
Possible sizes include:
- `Size.inherit` inherits the font-size of the parent element. For [ButtonLink](/docs/components-componentlibrary-buttonlink--default-story) uses only
- `Size.auto` inherits auto height, but keeps the same button font-size. For [ButtonLink](/docs/components-componentlibrary-buttonlink--default-story) uses only
- `Size.SM` 32px
- `Size.MD` 40px
- `Size.LG` 48px
- `Buttonsize.Inherit` inherits the font-size of the parent element. For [ButtonLink](/docs/components-componentlibrary-buttonlink--default-story) uses only
- `Buttonsize.Auto` inherits auto height, but keeps the same button font-size. For [ButtonLink](/docs/components-componentlibrary-buttonlink--default-story) uses only
- `Buttonsize.Sm` 32px
- `Buttonsize.Md` 40px
- `Buttonsize.Lg` 48px
<Canvas>
<Story id="components-componentlibrary-button--size-story" />
</Canvas>
```jsx
import { Size } from '../../../helpers/constants/design-system';
import { Button } from '../../component-library';
import { Button, ButtonSize } from '../../component-library';
<Button size={Size.inherit} />
<Button size={Size.SM} />
<Button size={Size.MD} />
<Button size={Size.LG} />
<Button size={Buttonsize.Inherit} />
<Button size={Buttonsize.Sm} />
<Button size={Buttonsize.Md} />
<Button size={Buttonsize.Lg} />
```
### Danger
@ -113,7 +100,6 @@ Use boolean `block` prop to quickly enable a full width block button
</Canvas>
```jsx
import { DISPLAY } from '../../../helpers/constants/design-system';
import { Button } from '../../component-library';
<Button>Default Button</Button>
@ -184,8 +170,7 @@ Use the [IconSearch](/story/components-componentlibrary-icon--default-story) sto
</Canvas>
```jsx
import { Button } from '../../component-library';
import { IconName } from '../icon';
import { Button, IconName } from '../../component-library';
<Button startIconName={IconName.AddSquare}>Button</Button>;
```
@ -195,8 +180,7 @@ import { IconName } from '../icon';
</Canvas>
```jsx
import { Button } from '../../component-library';
import { IconName } from '../icon';
import { Button, IconName } from '../../component-library';
<Button endIconName={IconName.Arrow2Right}>Button</Button>;
```

View File

@ -1,15 +0,0 @@
import { Size } from '../../../helpers/constants/design-system';
export const BUTTON_SIZES = {
SM: Size.SM,
MD: Size.MD,
LG: Size.LG,
INHERIT: Size.inherit,
AUTO: Size.auto,
};
export const BUTTON_VARIANT = {
PRIMARY: 'primary',
SECONDARY: 'secondary',
LINK: 'link',
};

View File

@ -1,34 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { ButtonPrimary } from '../button-primary';
import { ButtonSecondary } from '../button-secondary';
import { ButtonLink } from '../button-link';
import { BUTTON_VARIANT } from './button.constants';
export const Button = ({ variant, ...props }) => {
switch (variant) {
case BUTTON_VARIANT.PRIMARY:
return <ButtonPrimary {...props} />;
case BUTTON_VARIANT.SECONDARY:
return <ButtonSecondary {...props} />;
case BUTTON_VARIANT.LINK:
return <ButtonLink {...props} />;
default:
return <ButtonPrimary {...props} />;
}
};
Button.propTypes = {
/**
* Select the variant of Button.
* Possible values could be 'BUTTON_VARIANT.PRIMARY', 'BUTTON_VARIANT.SECONDARY', 'BUTTON_VARIANT.LINK'
* Button will default to `BUTTON_VARIANT.PRIMARY`
*/
variant: PropTypes.oneOf(Object.values(BUTTON_VARIANT)),
/**
* Button accepts all the props from ButtonPrimary (same props as ButtonSecondary & ButtonLink)
*/
...ButtonPrimary.propTypes,
};

View File

@ -1,39 +1,18 @@
import React from 'react';
import { StoryFn, Meta } from '@storybook/react';
import {
AlignItems,
DISPLAY,
FLEX_DIRECTION,
Size,
Display,
FlexDirection,
TextVariant,
} from '../../../helpers/constants/design-system';
import { IconName } from '..';
import { ButtonLinkSize } from '../button-link';
import Box from '../../ui/box/box';
import { Box, IconName } from '..';
import { Text } from '../text';
import README from './README.mdx';
import { Button, BUTTON_VARIANT } from '.';
const marginSizeControlOptions = [
undefined,
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
'auto',
];
import { Button, ButtonSize, ButtonVariant } from '.';
export default {
title: 'Components/ComponentLibrary/Button',
component: Button,
parameters: {
docs: {
@ -83,79 +62,54 @@ export default {
},
size: {
control: 'select',
options: Object.values(ButtonLinkSize),
options: Object.values(ButtonSize),
},
variant: {
options: Object.values(BUTTON_VARIANT),
options: Object.values(ButtonVariant),
control: 'select',
},
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: {
children: 'Button',
},
};
} as Meta<typeof Button>;
export const DefaultStory = (args) => <Button {...args} />;
const Template: StoryFn<typeof Button> = (args) => <Button {...args} />;
export const DefaultStory = Template.bind({});
DefaultStory.storyName = 'Default';
export const Variant = (args) => (
<Box display={DISPLAY.FLEX} gap={1}>
<Button variant={BUTTON_VARIANT.PRIMARY} {...args}>
Button Primary
</Button>
<Button variant={BUTTON_VARIANT.SECONDARY} {...args}>
Button Secondary
</Button>
<Button variant={BUTTON_VARIANT.LINK} {...args}>
Button Link
</Button>
export const Variant: StoryFn<typeof Button> = () => (
<Box display={Display.Flex} gap={1}>
<Button variant={ButtonVariant.Primary}>Button Primary</Button>
<Button variant={ButtonVariant.Secondary}>Button Secondary</Button>
<Button variant={ButtonVariant.Link}>Button Link</Button>
</Box>
);
export const SizeStory = (args) => (
export const SizeStory: StoryFn<typeof Button> = (args) => (
<>
<Box
display={DISPLAY.FLEX}
display={Display.Flex}
alignItems={AlignItems.baseline}
gap={1}
marginBottom={3}
>
<Button {...args} size={Size.SM}>
<Button {...args} variant={ButtonVariant.Primary} size={ButtonSize.Sm}>
Small Button
</Button>
<Button {...args} size={Size.MD}>
<Button {...args} size={ButtonSize.Md}>
Medium (Default) Button
</Button>
<Button {...args} size={Size.LG}>
<Button {...args} size={ButtonSize.Lg}>
Large Button
</Button>
<Button {...args} variant={BUTTON_VARIANT.LINK}>
<Button {...args} variant={ButtonVariant.Link}>
Auto ButtonLink
</Button>
</Box>
<Text variant={TextVariant.bodySm}>
<Button {...args} variant={BUTTON_VARIANT.LINK} size={Size.inherit}>
<Button {...args} variant={ButtonVariant.Link} size={ButtonSize.Inherit}>
Button Inherit
</Button>{' '}
inherits the font-size of the parent element. Inherit size only used for
@ -165,8 +119,8 @@ export const SizeStory = (args) => (
);
SizeStory.storyName = 'Size';
export const Danger = (args) => (
<Box display={DISPLAY.FLEX} gap={1}>
export const Danger: StoryFn<typeof Button> = (args) => (
<Box display={Display.Flex} gap={1}>
<Button {...args}>Normal</Button>
{/* Test Anchor tag to match exactly as button */}
<Button as="a" {...args} href="#" danger>
@ -175,13 +129,15 @@ export const Danger = (args) => (
</Box>
);
export const Href = (args) => <Button {...args}>Anchor Element</Button>;
export const Href: StoryFn<typeof Button> = (args) => (
<Button {...args}>Anchor Element</Button>
);
Href.args = {
href: '/metamask',
};
export const Block = (args) => (
export const Block: StoryFn<typeof Button> = (args) => (
<>
<Button {...args} marginBottom={2}>
Default Button
@ -192,8 +148,8 @@ export const Block = (args) => (
</>
);
export const As = (args) => (
<Box display={DISPLAY.FLEX} flexDirection={FLEX_DIRECTION.ROW} gap={2}>
export const As: StoryFn<typeof Button> = (args) => (
<Box display={Display.Flex} flexDirection={FlexDirection.Row} gap={2}>
<Button {...args}>Button Element</Button>
<Button as="a" href="#" {...args}>
Anchor Element
@ -201,26 +157,22 @@ export const As = (args) => (
</Box>
);
export const Disabled = (args) => <Button {...args}>Disabled Button</Button>;
export const Disabled = Template.bind({});
Disabled.args = {
disabled: true,
};
export const Loading = (args) => <Button {...args}>Loading Button</Button>;
export const Loading = Template.bind({});
Loading.args = {
loading: true,
};
export const StartIconName = (args) => (
<Button {...args} startIconName={IconName.AddSquare}>
Button
</Button>
);
export const StartIconName = Template.bind({});
StartIconName.args = {
startIconName: IconName.AddSquare,
};
export const EndIconName = (args) => (
<Button {...args} endIconName={IconName.Arrow2Right}>
Button
</Button>
);
export const EndIconName = Template.bind({});
EndIconName.args = {
endIconName: IconName.AddSquare,
};

View File

@ -2,8 +2,8 @@
import { render } from '@testing-library/react';
import React from 'react';
import { IconName } from '..';
import { BUTTON_SIZES, BUTTON_VARIANT } from './button.constants';
import { Button } from './button';
import { ButtonSize, ButtonVariant } from '.';
describe('Button', () => {
it('should render button element correctly', () => {
@ -47,30 +47,30 @@ describe('Button', () => {
const { getByTestId, container } = render(
<>
<Button
variant={BUTTON_VARIANT.PRIMARY}
data-testid={BUTTON_VARIANT.PRIMARY}
variant={ButtonVariant.Primary}
data-testid={ButtonVariant.Primary}
>
Button
</Button>
<Button
variant={BUTTON_VARIANT.SECONDARY}
data-testid={BUTTON_VARIANT.SECONDARY}
variant={ButtonVariant.Secondary}
data-testid={ButtonVariant.Secondary}
>
Button
</Button>
<Button variant={BUTTON_VARIANT.LINK} data-testid={BUTTON_VARIANT.LINK}>
<Button variant={ButtonVariant.Link} data-testid={ButtonVariant.Link}>
Button
</Button>
</>,
);
expect(getByTestId(BUTTON_VARIANT.PRIMARY)).toHaveClass(
`mm-button-${BUTTON_VARIANT.PRIMARY}`,
expect(getByTestId(ButtonVariant.Primary)).toHaveClass(
`mm-button-${ButtonVariant.Primary}`,
);
expect(getByTestId(BUTTON_VARIANT.SECONDARY)).toHaveClass(
`mm-button-${BUTTON_VARIANT.SECONDARY}`,
expect(getByTestId(ButtonVariant.Secondary)).toHaveClass(
`mm-button-${ButtonVariant.Secondary}`,
);
expect(getByTestId(BUTTON_VARIANT.LINK)).toHaveClass(
`mm-button-${BUTTON_VARIANT.LINK}`,
expect(getByTestId(ButtonVariant.Link)).toHaveClass(
`mm-button-${ButtonVariant.Link}`,
);
expect(container).toMatchSnapshot();
});
@ -79,34 +79,34 @@ describe('Button', () => {
const { getByTestId } = render(
<>
<Button
size={BUTTON_SIZES.INHERIT}
variant={BUTTON_VARIANT.LINK}
data-testid={BUTTON_SIZES.INHERIT}
variant={ButtonVariant.Link}
size={ButtonSize.Inherit}
data-testid={ButtonSize.Inherit}
>
Button {BUTTON_SIZES.INHERIT}
Button {ButtonSize.Inherit}
</Button>
<Button size={BUTTON_SIZES.SM} data-testid={BUTTON_SIZES.SM}>
Button {BUTTON_SIZES.SM}
<Button size={ButtonSize.Sm} data-testid={ButtonSize.Sm}>
Button {ButtonSize.Sm}
</Button>
<Button size={BUTTON_SIZES.MD} data-testid={BUTTON_SIZES.MD}>
Button {BUTTON_SIZES.MD}
<Button size={ButtonSize.Md} data-testid={ButtonSize.Md}>
Button {ButtonSize.Md}
</Button>
<Button size={BUTTON_SIZES.LG} data-testid={BUTTON_SIZES.LG}>
Button {BUTTON_SIZES.LG}
<Button size={ButtonSize.Lg} data-testid={ButtonSize.Lg}>
Button {ButtonSize.Lg}
</Button>
</>,
);
expect(getByTestId(BUTTON_SIZES.INHERIT)).toHaveClass(
`mm-button-link--size-${BUTTON_SIZES.INHERIT}`,
expect(getByTestId(ButtonSize.Inherit)).toHaveClass(
`mm-button-link--size-${ButtonSize.Inherit}`,
);
expect(getByTestId(BUTTON_SIZES.SM)).toHaveClass(
`mm-button-base--size-${BUTTON_SIZES.SM}`,
expect(getByTestId(ButtonSize.Sm)).toHaveClass(
`mm-button-base--size-${ButtonSize.Sm}`,
);
expect(getByTestId(BUTTON_SIZES.MD)).toHaveClass(
`mm-button-base--size-${BUTTON_SIZES.MD}`,
expect(getByTestId(ButtonSize.Md)).toHaveClass(
`mm-button-base--size-${ButtonSize.Md}`,
);
expect(getByTestId(BUTTON_SIZES.LG)).toHaveClass(
`mm-button-base--size-${BUTTON_SIZES.LG}`,
expect(getByTestId(ButtonSize.Lg)).toHaveClass(
`mm-button-base--size-${ButtonSize.Lg}`,
);
});

View File

@ -0,0 +1,35 @@
import React from 'react';
import type { PolymorphicRef } from '../box';
import { ButtonPrimary } from '../button-primary';
import { ButtonSecondary } from '../button-secondary';
import { ButtonLink } from '../button-link';
import type { ButtonPrimaryProps } from '../button-primary/button-primary.types';
import type { ButtonSecondaryProps } from '../button-secondary/button-secondary.types';
import type { ButtonLinkProps } from '../button-link/button-link.types';
import type { ButtonProps, ButtonComponent } from './button.types';
import { ButtonVariant } from './button.types';
export const Button: ButtonComponent = React.forwardRef(
<C extends React.ElementType = 'button' | 'a'>(
{ variant, ...props }: ButtonProps<C>,
ref?: PolymorphicRef<C>,
) => {
switch (variant) {
case ButtonVariant.Primary:
return (
<ButtonPrimary ref={ref} {...(props as ButtonPrimaryProps<C>)} />
);
case ButtonVariant.Secondary:
return (
<ButtonSecondary ref={ref} {...(props as ButtonSecondaryProps<C>)} />
);
case ButtonVariant.Link:
return <ButtonLink ref={ref} {...(props as ButtonLinkProps<C>)} />;
default:
return (
<ButtonPrimary ref={ref} {...(props as ButtonPrimaryProps<C>)} />
);
}
},
);

View File

@ -0,0 +1,46 @@
import type { PolymorphicComponentPropWithRef } from '../box';
import type { ButtonPrimaryStyleUtilityProps } from '../button-primary/button-primary.types';
import type { ButtonSecondaryStyleUtilityProps } from '../button-secondary/button-secondary.types';
import type { ButtonLinkStyleUtilityProps } from '../button-link/button-link.types';
export enum ButtonSize {
Sm = 'sm',
Md = 'md',
Lg = 'lg',
Inherit = 'inherit',
Auto = 'auto',
}
export enum ButtonVariant {
Primary = 'primary',
Secondary = 'secondary',
Link = 'link',
}
type ValidButtonSize = ButtonSize.Sm | ButtonSize.Md | ButtonSize.Lg;
type ButtonPropsByVariant = {
[ButtonVariant.Primary]: {
variant?: ButtonVariant.Primary;
size?: ValidButtonSize; // Allows for only ButtonSize.Sm, ButtonSize.Md, ButtonSize.Lg
} & Omit<ButtonPrimaryStyleUtilityProps, 'size'>;
[ButtonVariant.Secondary]: {
variant?: ButtonVariant.Secondary;
size?: ValidButtonSize; // Allows for only ButtonSize.Sm, ButtonSize.Md, ButtonSize.Lg
} & Omit<ButtonSecondaryStyleUtilityProps, 'size'>;
[ButtonVariant.Link]: {
variant?: ButtonVariant.Link;
size?: ButtonSize;
} & Omit<ButtonLinkStyleUtilityProps, 'size'>;
};
type ButtonPropsMap = {
[variant in ButtonVariant]: ButtonPropsByVariant[variant];
};
export type ButtonProps<C extends React.ElementType> =
PolymorphicComponentPropWithRef<C, ButtonPropsMap[ButtonVariant]>;
export type ButtonComponent = <C extends React.ElementType = 'button' | 'a'>(
props: ButtonProps<C>,
) => React.ReactElement | null;

View File

@ -1,2 +0,0 @@
export { Button } from './button';
export { BUTTON_VARIANT, BUTTON_SIZES } from './button.constants';

View File

@ -0,0 +1,23 @@
import { Size } from '../../../helpers/constants/design-system';
export { Button } from './button';
export { ButtonSize, ButtonVariant } from './button.types';
/**
* @deprecated `BUTTON_VARIANT` const has been deprecated in favor of the `ButtonVariant` enum which can still be imported from `ui/components/component-library`
*/
export const BUTTON_SIZES = {
SM: Size.SM,
MD: Size.MD,
LG: Size.LG,
INHERIT: Size.inherit,
AUTO: Size.auto,
};
/**
* @deprecated `BUTTON_SIZES` const has been deprecated in favor of the `ButtonSize` enum which can still be imported from `ui/components/component-library`
*/
export const BUTTON_VARIANT = {
PRIMARY: 'primary',
SECONDARY: 'secondary',
LINK: 'link',
};

View File

@ -3,7 +3,7 @@ import { StoryFn, Meta } from '@storybook/react';
import {
IconName,
Button,
BUTTON_SIZES,
ButtonSize,
ButtonIcon,
ButtonIconSize,
Text,
@ -206,7 +206,7 @@ export const UseCaseDemos = (args) => (
<Button
backgroundColor={BackgroundColor.successAlternative}
style={{ whiteSpace: 'nowrap' }}
size={BUTTON_SIZES.SM}
size={ButtonSize.Sm}
>
Unlock Now
</Button>
@ -247,10 +247,7 @@ export const UseCaseDemos = (args) => (
/>
}
endAccessory={
<Button
backgroundColor={BackgroundColor.goerli}
size={BUTTON_SIZES.SM}
>
<Button backgroundColor={BackgroundColor.goerli} size={ButtonSize.Sm}>
Download
</Button>
}
@ -272,7 +269,7 @@ export const UseCaseDemos = (args) => (
startAccessory={
<Button
backgroundColor={BackgroundColor.successAlternative}
size={BUTTON_SIZES.SM}
size={ButtonSize.Sm}
>
Unlock
</Button>

View File

@ -15,7 +15,13 @@ export {
BadgeWrapperAnchorElementShape,
} from './badge-wrapper';
export { Box } from './box';
export { Button, BUTTON_VARIANT, BUTTON_SIZES } from './button';
export {
Button,
ButtonVariant,
ButtonSize,
BUTTON_SIZES,
BUTTON_VARIANT,
} from './button';
export { ButtonBase, ButtonBaseSize } from './button-base';
export { ButtonIcon, ButtonIconSize } from './button-icon';
export { ButtonLink, ButtonLinkSize } from './button-link';

View File

@ -8,7 +8,7 @@ import {
TextVariant,
} from '../../../helpers/constants/design-system';
import { Button, Box, BUTTON_VARIANT } from '..';
import { Button, Box, ButtonVariant } from '..';
import { InputType } from './input.types';
import { Input } from './input';
@ -169,7 +169,7 @@ export const Ref = (args) => {
<Box display={Display.Flex}>
<Input {...args} ref={inputRef} value={value} onChange={handleOnChange} />
<Button
variant={BUTTON_VARIANT.PRIMARY}
variant={ButtonVariant.Primary}
marginLeft={1}
onClick={handleOnClick}
>

View File

@ -24,21 +24,21 @@ Use the `children` prop to render the content of `ModalContent`. The `ModalConte
```jsx
import React, { useState } from 'react';
import { Modal, ModalContent, ModalHeader, Text, Button, BUTTON_VARIANT } from '../../component-library';
import { Modal, ModalContent, ModalHeader, Text, Button, ButtonVariant } from '../../component-library';
const [show, setShow] = useState(false);
const handleOnClick = () => {
setShow(!show);
};
<Button variant={BUTTON_VARIANT.PRIMARY} onClick={handleOnClick}>
<Button variant={ButtonVariant.Primary} onClick={handleOnClick}>
Open
</Button>
<Modal isOpen={show} onClose={handleOnClick}>
<ModalContent {...args}>
<ModalHeader marginBottom={4}>Modal Header</ModalHeader>
<Text marginBottom={4}>Modal Content</Text>
<Button variant={BUTTON_VARIANT.PRIMARY} onClick={handleOnClick}>
<Button variant={ButtonVariant.Primary} onClick={handleOnClick}>
Close
</Button>
<LoremIpsum />
@ -65,7 +65,7 @@ import { DISPLAY } from '../../../helpers/constants/design-system';
import Box from '../../ui/box';
import { Modal, ModalContent, Text, Button, BUTTON_VARIANT } from '../../component-library';
import { Modal, ModalContent, Text, Button, ButtonVariant } from '../../component-library';
enum ModalContentSizeStoryOption {
Sm = 'sm',
@ -82,13 +82,13 @@ const handleOnClick = (size: ModalContentSizeStoryOption) => {
<Box display={DISPLAY.FLEX} gap={4}>
<Button
variant={BUTTON_VARIANT.SECONDARY}
variant={ButtonVariant.Secondary}
onClick={() => handleOnClick(ModalContentSizeStoryOption.Sm)}
>
Show sm size
</Button>
<Button
variant={BUTTON_VARIANT.SECONDARY}
variant={ButtonVariant.Secondary}
onClick={() => handleOnClick(ModalContentSizeStoryOption.ClassName)}
>
Show className

View File

@ -5,7 +5,7 @@ import Box from '../../ui/box';
import { DISPLAY } from '../../../helpers/constants/design-system';
import { BUTTON_VARIANT, Button, Text, Modal, ModalHeader } from '..';
import { ButtonVariant, Button, Text, Modal, ModalHeader } from '..';
import { ModalContent } from './modal-content';
import { ModalContentSize } from './modal-content.types';
@ -48,14 +48,14 @@ export const DefaultStory: ComponentStory<typeof ModalContent> = (args) => {
};
return (
<>
<Button variant={BUTTON_VARIANT.PRIMARY} onClick={handleOnClick}>
<Button variant={ButtonVariant.Primary} onClick={handleOnClick}>
Open
</Button>
<Modal isOpen={show} onClose={handleOnClick}>
<ModalContent {...args}>
<ModalHeader marginBottom={4}>Modal Header</ModalHeader>
<Text marginBottom={4}>Modal Content</Text>
<Button variant={BUTTON_VARIANT.PRIMARY} onClick={handleOnClick}>
<Button variant={ButtonVariant.Primary} onClick={handleOnClick}>
Close
</Button>
</ModalContent>
@ -73,7 +73,7 @@ export const Children: ComponentStory<typeof ModalContent> = (args) => {
};
return (
<>
<Button variant={BUTTON_VARIANT.PRIMARY} onClick={handleOnClick}>
<Button variant={ButtonVariant.Primary} onClick={handleOnClick}>
Open
</Button>
<Modal isOpen={show} onClose={handleOnClick}>
@ -84,7 +84,7 @@ export const Children: ComponentStory<typeof ModalContent> = (args) => {
</Text>
<Button
marginBottom={4}
variant={BUTTON_VARIANT.PRIMARY}
variant={ButtonVariant.Primary}
onClick={handleOnClick}
>
Close
@ -118,13 +118,13 @@ export const Size: ComponentStory<typeof ModalContent> = (args) => {
<>
<Box display={DISPLAY.FLEX} gap={4}>
<Button
variant={BUTTON_VARIANT.SECONDARY}
variant={ButtonVariant.Secondary}
onClick={() => handleOnClick(ModalContentSizeStoryOption.Sm)}
>
Show sm size
</Button>
<Button
variant={BUTTON_VARIANT.SECONDARY}
variant={ButtonVariant.Secondary}
onClick={() => handleOnClick(ModalContentSizeStoryOption.ClassName)}
>
Show className

View File

@ -99,9 +99,9 @@ Use the `startAccessory` prop to render a component in the startAccessory positi
</Canvas>
```jsx
import { ModalHeader, Button, BUTTON_SIZES } from '../../component-library';
import { ModalHeader, Button, ButtonSize } from '../../component-library';
<ModalHeader startAccessory={<Button size={BUTTON_SIZES.SM}>Demo</Button>}>
<ModalHeader startAccessory={<Button size={ButtonSize.Sm}>Demo</Button>}>
StartAccessory
</ModalHeader>;
```
@ -115,9 +115,9 @@ Use the `endAccessory` prop to render a component in the endAccessory position.
</Canvas>
```jsx
import { ModalHeader, Button, BUTTON_SIZES } from '../../component-library';
import { ModalHeader, Button, ButtonSize } from '../../component-library';
<ModalHeader endAccessory={<Button size={BUTTON_SIZES.SM}>Demo</Button>}>
<ModalHeader endAccessory={<Button size={ButtonSize.Sm}>Demo</Button>}>
EndAccessory
</ModalHeader>;
```

View File

@ -10,7 +10,7 @@ import {
JustifyContent,
} from '../../../helpers/constants/design-system';
import { AvatarAccount, BUTTON_SIZES, Button, Text } from '..';
import { AvatarAccount, ButtonSize, Button, Text } from '..';
import { ModalHeader } from './modal-header';
import README from './README.mdx';
@ -76,11 +76,11 @@ OnClose.args = {
export const StartAccessory = Template.bind({});
StartAccessory.args = {
children: 'StartAccessory demo',
startAccessory: <Button size={BUTTON_SIZES.SM}>Demo</Button>,
startAccessory: <Button size={ButtonSize.Sm}>Demo</Button>,
};
export const EndAccessory = Template.bind({});
EndAccessory.args = {
children: 'EndAccessory demo',
endAccessory: <Button size={BUTTON_SIZES.SM}>Demo</Button>,
endAccessory: <Button size={ButtonSize.Sm}>Demo</Button>,
};

View File

@ -99,9 +99,9 @@ Use the `startAccessory` prop to render a component in the startAccessory positi
</Canvas>
```jsx
import { PopoverHeader, Button, BUTTON_SIZES } from '../../component-library';
import { PopoverHeader, Button, ButtonSize } from '../../component-library';
<PopoverHeader startAccessory={<Button size={BUTTON_SIZES.SM}>Demo</Button>}>
<PopoverHeader startAccessory={<Button size={ButtonSize.Sm}>Demo</Button>}>
StartAccessory
</PopoverHeader>;
```
@ -115,9 +115,9 @@ Use the `endAccessory` prop to render a component in the endAccessory position.
</Canvas>
```jsx
import { PopoverHeader, Button, BUTTON_SIZES } from '../../component-library';
import { PopoverHeader, Button, ButtonSize } from '../../component-library';
<PopoverHeader endAccessory={<Button size={BUTTON_SIZES.SM}>Demo</Button>}>
<PopoverHeader endAccessory={<Button size={ButtonSize.Sm}>Demo</Button>}>
EndAccessory
</PopoverHeader>;
```

View File

@ -10,7 +10,7 @@ import {
JustifyContent,
} from '../../../helpers/constants/design-system';
import { AvatarAccount, BUTTON_SIZES, Button, Text } from '..';
import { AvatarAccount, ButtonSize, Button, Text } from '..';
import { PopoverHeader } from './popover-header';
import README from './README.mdx';
@ -76,11 +76,11 @@ OnClose.args = {
export const StartAccessory = Template.bind({});
StartAccessory.args = {
children: 'StartAccessory demo',
startAccessory: <Button size={BUTTON_SIZES.SM}>Demo</Button>,
startAccessory: <Button size={ButtonSize.Sm}>Demo</Button>,
};
export const EndAccessory = Template.bind({});
EndAccessory.args = {
children: 'EndAccessory demo',
endAccessory: <Button size={BUTTON_SIZES.SM}>Demo</Button>,
endAccessory: <Button size={ButtonSize.Sm}>Demo</Button>,
};

View File

@ -1,7 +1,7 @@
import { useArgs } from '@storybook/client-api';
import { StoryFn } from '@storybook/react';
import React from 'react';
import { BUTTON_VARIANT, Button } from '../../../components/component-library';
import { ButtonVariant, Button } from '../../../components/component-library';
import AddSnapAccountModal from '.';
const AddSnapAccountModalStory = {
@ -16,7 +16,7 @@ export const DefaultStory: StoryFn<typeof AddSnapAccountModal> = () => {
return (
<>
<Button
variant={BUTTON_VARIANT.PRIMARY}
variant={ButtonVariant.Primary}
onClick={() => updateArgs({ isShowingModal: true })}
>
Open modal

View File

@ -1,6 +1,6 @@
import React from 'react';
import {
BUTTON_VARIANT,
ButtonVariant,
Box,
Button,
Modal,
@ -53,7 +53,7 @@ export default function AddSnapAccountModal({
{t('addSnapAccountModalDescription')}
</Text>
<Button
variant={BUTTON_VARIANT.PRIMARY}
variant={ButtonVariant.Primary}
block
className="get-started_button"
data-testid="get-started-button"

View File

@ -3,7 +3,7 @@ import ConfigureSnapPopup, {
ConfigureSnapPopupType,
} from '../../../components/app/configure-snap-popup/configure-snap-popup';
import {
BUTTON_VARIANT,
ButtonVariant,
Box,
Button,
Icon,
@ -58,7 +58,7 @@ export const SnapDetailHeader = ({
marginBottom={4}
>
<Button
variant={BUTTON_VARIANT.LINK}
variant={ButtonVariant.Link}
marginRight={4}
onClick={() => history.back()}
>
@ -91,7 +91,7 @@ export const SnapDetailHeader = ({
<Box>
{isInstalled && updateAvailable && (
<Button
variant={BUTTON_VARIANT.PRIMARY}
variant={ButtonVariant.Primary}
marginRight={1}
onClick={() => {
setShowConfigPopoverType(ConfigureSnapPopupType.INSTALL);
@ -103,7 +103,7 @@ export const SnapDetailHeader = ({
)}
{isInstalled && (
<Button
variant={BUTTON_VARIANT.PRIMARY}
variant={ButtonVariant.Primary}
onClick={() => {
setShowConfigPopoverType(ConfigureSnapPopupType.CONFIGURE);
setShowConfigPopover(true);
@ -114,7 +114,7 @@ export const SnapDetailHeader = ({
)}
{!isInstalled && (
<Button
variant={BUTTON_VARIANT.PRIMARY}
variant={ButtonVariant.Primary}
onClick={() => {
setShowConfigPopoverType(ConfigureSnapPopupType.INSTALL);
setShowConfigPopover(true);

View File

@ -3,7 +3,7 @@ import { useSelector } from 'react-redux';
import { useHistory, useParams } from 'react-router-dom';
import semver from 'semver';
import {
BUTTON_VARIANT,
ButtonVariant,
Box,
Button,
Tag,
@ -111,7 +111,7 @@ export default function SnapAccountDetailPage() {
{currentSnap.auditUrls.map((auditLink, index) => {
return (
<Text key={`audit-link-${index}`}>
<Button variant={BUTTON_VARIANT.LINK} href={auditLink}>
<Button variant={ButtonVariant.Link} href={auditLink}>
{auditLink}
</Button>
</Text>
@ -127,7 +127,7 @@ export default function SnapAccountDetailPage() {
{isInstalled && (
<Box>
<Button
variant={BUTTON_VARIANT.LINK}
variant={ButtonVariant.Link}
onClick={() =>
history.push(
`${SNAPS_VIEW_ROUTE}/${encodeURIComponent(

View File

@ -4,7 +4,7 @@ import ConfigureSnapPopup, {
ConfigureSnapPopupType,
} from '../../../components/app/configure-snap-popup';
import {
BUTTON_VARIANT,
ButtonVariant,
Box,
Button,
Icon,
@ -91,7 +91,7 @@ export default function SnapCard({
{isInstalled ? (
<Button
data-testid="configure-snap-button"
variant={BUTTON_VARIANT.SECONDARY}
variant={ButtonVariant.Secondary}
onClick={() => setShowConfigPopover(true)}
>
{t('snapConfigure')}
@ -99,7 +99,7 @@ export default function SnapCard({
) : (
<Button
data-testid="install-snap-button"
variant={BUTTON_VARIANT.SECONDARY}
variant={ButtonVariant.Secondary}
onClick={() => {
history.push(`/add-snap-account/${id}`);
}}

View File

@ -21,9 +21,9 @@ import {
} from '../../../../shared/lib/ui-utils';
import SRPQuiz from '../../../components/app/srp-quiz-modal/SRPQuiz';
import {
Button,
BUTTON_SIZES,
Box,
Button,
Text,
} from '../../../components/component-library';
import TextField from '../../../components/ui/text-field';

View File

@ -1,7 +1,7 @@
import React from 'react';
import { StoryFn, Meta } from '@storybook/react';
import { useArgs } from '@storybook/client-api';
import { BUTTON_VARIANT, Button } from '../../../components/component-library';
import { ButtonVariant, Button } from '../../../components/component-library';
import SmartTransactionPopover from './smart-transactions-popover';
export default {
@ -20,7 +20,7 @@ export const DefaultStory: StoryFn<typeof SmartTransactionPopover> = () => {
return (
<>
<Button variant={BUTTON_VARIANT.PRIMARY} onClick={toggleModal}>
<Button variant={ButtonVariant.Primary} onClick={toggleModal}>
Open modal
</Button>
{isShowingModal && (

View File

@ -16,7 +16,7 @@ import {
Text,
Box,
Button,
BUTTON_VARIANT,
ButtonVariant,
} from '../../../components/component-library';
interface Props {
@ -80,7 +80,7 @@ export default function SmartTransactionsPopover({
</Text>
<Button
variant={BUTTON_VARIANT.PRIMARY}
variant={ButtonVariant.Primary}
onClick={onEnableSmartTransactionsClick}
width={BlockSize.Full}
>
@ -89,7 +89,7 @@ export default function SmartTransactionsPopover({
<Button
type="link"
variant={BUTTON_VARIANT.LINK}
variant={ButtonVariant.Link}
onClick={onCloseSmartTransactionsOptInPopover}
width={BlockSize.Full}
>