diff --git a/ui/components/app/configure-snap-popup/configure-snap-popup.tsx b/ui/components/app/configure-snap-popup/configure-snap-popup.tsx index ac9b77129..b0bdd707a 100644 --- a/ui/components/app/configure-snap-popup/configure-snap-popup.tsx +++ b/ui/components/app/configure-snap-popup/configure-snap-popup.tsx @@ -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')} - - + + + ``` ### 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 ```jsx -import { Size } from '../../../helpers/constants/design-system'; -import { Button } from '../../component-library'; +import { Button, ButtonSize } from '../../component-library'; - @@ -184,8 +170,7 @@ Use the [IconSearch](/story/components-componentlibrary-icon--default-story) sto ```jsx -import { Button } from '../../component-library'; -import { IconName } from '../icon'; +import { Button, IconName } from '../../component-library'; ; ``` @@ -195,8 +180,7 @@ import { IconName } from '../icon'; ```jsx -import { Button } from '../../component-library'; -import { IconName } from '../icon'; +import { Button, IconName } from '../../component-library'; ; ``` diff --git a/ui/components/component-library/button/__snapshots__/button.test.js.snap b/ui/components/component-library/button/__snapshots__/button.test.tsx.snap similarity index 100% rename from ui/components/component-library/button/__snapshots__/button.test.js.snap rename to ui/components/component-library/button/__snapshots__/button.test.tsx.snap diff --git a/ui/components/component-library/button/button.constants.js b/ui/components/component-library/button/button.constants.js deleted file mode 100644 index b555bb11a..000000000 --- a/ui/components/component-library/button/button.constants.js +++ /dev/null @@ -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', -}; diff --git a/ui/components/component-library/button/button.js b/ui/components/component-library/button/button.js deleted file mode 100644 index 111a01458..000000000 --- a/ui/components/component-library/button/button.js +++ /dev/null @@ -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 ; - case BUTTON_VARIANT.SECONDARY: - return ; - case BUTTON_VARIANT.LINK: - return ; - default: - return ; - } -}; - -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, -}; diff --git a/ui/components/component-library/button/button.stories.js b/ui/components/component-library/button/button.stories.tsx similarity index 50% rename from ui/components/component-library/button/button.stories.js rename to ui/components/component-library/button/button.stories.tsx index cb908e4bb..421ee3a97 100644 --- a/ui/components/component-library/button/button.stories.js +++ b/ui/components/component-library/button/button.stories.tsx @@ -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; -export const DefaultStory = (args) => - - +export const Variant: StoryFn = () => ( + + + + ); -export const SizeStory = (args) => ( +export const SizeStory: StoryFn = (args) => ( <> - - - - - {' '} 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) => ( - +export const Danger: StoryFn = (args) => ( + {/* Test Anchor tag to match exactly as button */} ; +export const Href: StoryFn = (args) => ( + +); Href.args = { href: '/metamask', }; -export const Block = (args) => ( +export const Block: StoryFn = (args) => ( <> ; - +export const Disabled = Template.bind({}); Disabled.args = { disabled: true, }; -export const Loading = (args) => ; - +export const Loading = Template.bind({}); Loading.args = { loading: true, }; -export const StartIconName = (args) => ( - -); +export const StartIconName = Template.bind({}); +StartIconName.args = { + startIconName: IconName.AddSquare, +}; -export const EndIconName = (args) => ( - -); +export const EndIconName = Template.bind({}); +EndIconName.args = { + endIconName: IconName.AddSquare, +}; diff --git a/ui/components/component-library/button/button.test.js b/ui/components/component-library/button/button.test.tsx similarity index 69% rename from ui/components/component-library/button/button.test.js rename to ui/components/component-library/button/button.test.tsx index f612b4da6..84cd94df9 100644 --- a/ui/components/component-library/button/button.test.js +++ b/ui/components/component-library/button/button.test.tsx @@ -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( <> - , ); - 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( <> - - - , ); - 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}`, ); }); diff --git a/ui/components/component-library/button/button.tsx b/ui/components/component-library/button/button.tsx new file mode 100644 index 000000000..710c24e52 --- /dev/null +++ b/ui/components/component-library/button/button.tsx @@ -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( + ( + { variant, ...props }: ButtonProps, + ref?: PolymorphicRef, + ) => { + switch (variant) { + case ButtonVariant.Primary: + return ( + )} /> + ); + case ButtonVariant.Secondary: + return ( + )} /> + ); + case ButtonVariant.Link: + return )} />; + default: + return ( + )} /> + ); + } + }, +); diff --git a/ui/components/component-library/button/button.types.ts b/ui/components/component-library/button/button.types.ts new file mode 100644 index 000000000..f0477a65d --- /dev/null +++ b/ui/components/component-library/button/button.types.ts @@ -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; + [ButtonVariant.Secondary]: { + variant?: ButtonVariant.Secondary; + size?: ValidButtonSize; // Allows for only ButtonSize.Sm, ButtonSize.Md, ButtonSize.Lg + } & Omit; + [ButtonVariant.Link]: { + variant?: ButtonVariant.Link; + size?: ButtonSize; + } & Omit; +}; + +type ButtonPropsMap = { + [variant in ButtonVariant]: ButtonPropsByVariant[variant]; +}; + +export type ButtonProps = + PolymorphicComponentPropWithRef; + +export type ButtonComponent = ( + props: ButtonProps, +) => React.ReactElement | null; diff --git a/ui/components/component-library/button/index.js b/ui/components/component-library/button/index.js deleted file mode 100644 index fff8a29fe..000000000 --- a/ui/components/component-library/button/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export { Button } from './button'; -export { BUTTON_VARIANT, BUTTON_SIZES } from './button.constants'; diff --git a/ui/components/component-library/button/index.ts b/ui/components/component-library/button/index.ts new file mode 100644 index 000000000..8133ad863 --- /dev/null +++ b/ui/components/component-library/button/index.ts @@ -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', +}; diff --git a/ui/components/component-library/header-base/header-base.stories.tsx b/ui/components/component-library/header-base/header-base.stories.tsx index abe880dcf..e7f924755 100644 --- a/ui/components/component-library/header-base/header-base.stories.tsx +++ b/ui/components/component-library/header-base/header-base.stories.tsx @@ -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) => ( @@ -247,10 +247,7 @@ export const UseCaseDemos = (args) => ( /> } endAccessory={ - } @@ -272,7 +269,7 @@ export const UseCaseDemos = (args) => ( startAccessory={ diff --git a/ui/components/component-library/index.js b/ui/components/component-library/index.js index e2308d721..eb922c7d6 100644 --- a/ui/components/component-library/index.js +++ b/ui/components/component-library/index.js @@ -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'; diff --git a/ui/components/component-library/input/input.stories.tsx b/ui/components/component-library/input/input.stories.tsx index 676687350..ab4476f3a 100644 --- a/ui/components/component-library/input/input.stories.tsx +++ b/ui/components/component-library/input/input.stories.tsx @@ -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) => { Modal Header Modal Content - @@ -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) => { Modal Header Modal Content - @@ -73,7 +73,7 @@ export const Children: ComponentStory = (args) => { }; return ( <> - @@ -84,7 +84,7 @@ export const Children: ComponentStory = (args) => { }> +Demo}> StartAccessory ; ``` @@ -115,9 +115,9 @@ Use the `endAccessory` prop to render a component in the endAccessory position. ```jsx -import { ModalHeader, Button, BUTTON_SIZES } from '../../component-library'; +import { ModalHeader, Button, ButtonSize } from '../../component-library'; -Demo}> +Demo}> EndAccessory ; ``` diff --git a/ui/components/component-library/modal-header/modal-header.stories.tsx b/ui/components/component-library/modal-header/modal-header.stories.tsx index 299221ca5..676cf7d09 100644 --- a/ui/components/component-library/modal-header/modal-header.stories.tsx +++ b/ui/components/component-library/modal-header/modal-header.stories.tsx @@ -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: , + startAccessory: , }; export const EndAccessory = Template.bind({}); EndAccessory.args = { children: 'EndAccessory demo', - endAccessory: , + endAccessory: , }; diff --git a/ui/components/component-library/popover-header/README.mdx b/ui/components/component-library/popover-header/README.mdx index 0680c2b6a..e01a82751 100644 --- a/ui/components/component-library/popover-header/README.mdx +++ b/ui/components/component-library/popover-header/README.mdx @@ -99,9 +99,9 @@ Use the `startAccessory` prop to render a component in the startAccessory positi ```jsx -import { PopoverHeader, Button, BUTTON_SIZES } from '../../component-library'; +import { PopoverHeader, Button, ButtonSize } from '../../component-library'; -Demo}> +Demo}> StartAccessory ; ``` @@ -115,9 +115,9 @@ Use the `endAccessory` prop to render a component in the endAccessory position. ```jsx -import { PopoverHeader, Button, BUTTON_SIZES } from '../../component-library'; +import { PopoverHeader, Button, ButtonSize } from '../../component-library'; -Demo}> +Demo}> EndAccessory ; ``` diff --git a/ui/components/component-library/popover-header/popover-header.stories.tsx b/ui/components/component-library/popover-header/popover-header.stories.tsx index 92c188d81..9cdeaf10a 100644 --- a/ui/components/component-library/popover-header/popover-header.stories.tsx +++ b/ui/components/component-library/popover-header/popover-header.stories.tsx @@ -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: , + startAccessory: , }; export const EndAccessory = Template.bind({}); EndAccessory.args = { children: 'EndAccessory demo', - endAccessory: , + endAccessory: , }; diff --git a/ui/pages/keyring-snaps/add-snap-account-modal/add-snap-account-modal.stories.tsx b/ui/pages/keyring-snaps/add-snap-account-modal/add-snap-account-modal.stories.tsx index 2f5ef9f72..5c713b10e 100644 --- a/ui/pages/keyring-snaps/add-snap-account-modal/add-snap-account-modal.stories.tsx +++ b/ui/pages/keyring-snaps/add-snap-account-modal/add-snap-account-modal.stories.tsx @@ -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 = () => { return ( <> @@ -127,7 +127,7 @@ export default function SnapAccountDetailPage() { {isInstalled && ( {isShowingModal && ( diff --git a/ui/pages/swaps/prepare-swap-page/smart-transactions-popover.tsx b/ui/pages/swaps/prepare-swap-page/smart-transactions-popover.tsx index 38484fab4..5aa8cb011 100644 --- a/ui/pages/swaps/prepare-swap-page/smart-transactions-popover.tsx +++ b/ui/pages/swaps/prepare-swap-page/smart-transactions-popover.tsx @@ -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({