From 092189cb5b344a7746f2e02bca45d8edc5f407bd Mon Sep 17 00:00:00 2001 From: George Marshall Date: Wed, 10 Aug 2022 12:42:42 -0700 Subject: [PATCH] Adding polymorphic 'as' prop to Box component and updating Typography component to use the same (#15518) * Adding polymorphic as prop to Box component * Updating Typography component to use 'as' as the polymorphic prop instead of 'tag' * Fixing linting --- .../app/create-new-vault/create-new-vault.js | 2 +- .../edit-gas-display-education.component.js | 8 +-- .../edit-gas-display.component.js | 10 +--- .../snap-settings-card/snap-settings-card.js | 4 +- .../snaps-authorship-pill.js | 4 +- .../recovery-phrase-reminder.js | 2 +- ui/components/ui/box/README.mdx | 25 +++++--- ui/components/ui/box/box.js | 11 +++- ui/components/ui/box/box.stories.js | 20 +++++++ ui/components/ui/box/box.test.js | 18 ++++++ ui/components/ui/chip/chip.js | 2 +- .../ui/confusable/confusable.component.js | 2 +- .../ui/definition-list/definition-list.js | 4 +- .../numeric-input/numeric-input.component.js | 2 +- ui/components/ui/typography/README.mdx | 47 +++++++++------ ui/components/ui/typography/typography.js | 8 +-- .../ui/typography/typography.stories.js | 35 +++++++---- .../ui/typography/typography.test.js | 58 +++++++++---------- .../seed-phrase-intro.component.js | 6 +- .../secure-your-wallet/secure-your-wallet.js | 12 ++-- .../flask/snap-install/snap-install.js | 2 +- .../flask/snap-update/snap-update.js | 4 +- .../awaiting-signatures.js | 6 +- ui/pages/swaps/build-quote/build-quote.js | 6 +- ui/pages/swaps/fee-card/fee-card.js | 2 +- 25 files changed, 188 insertions(+), 112 deletions(-) diff --git a/ui/components/app/create-new-vault/create-new-vault.js b/ui/components/app/create-new-vault/create-new-vault.js index 126854308..054279328 100644 --- a/ui/components/app/create-new-vault/create-new-vault.js +++ b/ui/components/app/create-new-vault/create-new-vault.js @@ -146,7 +146,7 @@ export default function CreateNewVault({ className="create-new-vault__terms-label" htmlFor="create-new-vault__terms-checkbox" > - {termsOfUse} + {termsOfUse} ) : null} diff --git a/ui/components/app/edit-gas-display-education/edit-gas-display-education.component.js b/ui/components/app/edit-gas-display-education/edit-gas-display-education.component.js index 0433f9a10..2287f07e9 100644 --- a/ui/components/app/edit-gas-display-education/edit-gas-display-education.component.js +++ b/ui/components/app/edit-gas-display-education/edit-gas-display-education.component.js @@ -15,7 +15,7 @@ export default function EditGasDisplayEducation() { return (
@@ -29,7 +29,7 @@ export default function EditGasDisplayEducation() { {t('editGasHigh')} @@ -43,7 +43,7 @@ export default function EditGasDisplayEducation() { {t('editGasMedium')} @@ -57,7 +57,7 @@ export default function EditGasDisplayEducation() { {t('editGasLow')} diff --git a/ui/components/app/edit-gas-display/edit-gas-display.component.js b/ui/components/app/edit-gas-display/edit-gas-display.component.js index 5818b86f1..c81abab58 100644 --- a/ui/components/app/edit-gas-display/edit-gas-display.component.js +++ b/ui/components/app/edit-gas-display/edit-gas-display.component.js @@ -196,17 +196,13 @@ export default function EditGasDisplay({ supportsEIP1559 && estimatedMaximumFiat !== undefined && ( <> - + {t('editGasSubTextFeeLabel')} - + {estimatedMaximumFiat} - + {`(${estimatedMaximumNative})`} diff --git a/ui/components/app/flask/snap-settings-card/snap-settings-card.js b/ui/components/app/flask/snap-settings-card/snap-settings-card.js index 210e38c9b..c529fa41a 100644 --- a/ui/components/app/flask/snap-settings-card/snap-settings-card.js +++ b/ui/components/app/flask/snap-settings-card/snap-settings-card.js @@ -161,7 +161,7 @@ const SnapSettingsCard = ({ color={COLORS.TEXT_MUTED} variant={TYPOGRAPHY.H8} fontWeight={FONT_WEIGHT.NORMAL} - tag="span" + as="span" className="snap-settings-card__date-added" > {`${ @@ -177,7 +177,7 @@ const SnapSettingsCard = ({ variant={TYPOGRAPHY.H7} fontWeight={FONT_WEIGHT.NORMAL} align={TEXT_ALIGN.CENTER} - tag="span" + as="span" className="snap-settings-card__version" > {t('shorthandVersion', [version])} diff --git a/ui/components/app/flask/snaps-authorship-pill/snaps-authorship-pill.js b/ui/components/app/flask/snaps-authorship-pill/snaps-authorship-pill.js index 456387dc0..a2da8c5c7 100644 --- a/ui/components/app/flask/snaps-authorship-pill/snaps-authorship-pill.js +++ b/ui/components/app/flask/snaps-authorship-pill/snaps-authorship-pill.js @@ -54,7 +54,7 @@ const SnapsAuthorshipPill = ({ snapId, version, className }) => { color={COLORS.PRIMARY_INVERSE} variant={TYPOGRAPHY.H7} align={TEXT_ALIGN.CENTER} - tag="span" + as="span" className="version" > {t('shorthandVersion', [version])} @@ -67,7 +67,7 @@ const SnapsAuthorshipPill = ({ snapId, version, className }) => { diff --git a/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js b/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js index 570d7c2a1..0e27136bb 100644 --- a/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js +++ b/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js @@ -47,7 +47,7 @@ export default function RecoveryPhraseReminder({ onConfirm, hasBackedUp }) {
  • diff --git a/ui/components/ui/box/README.mdx b/ui/components/ui/box/README.mdx index 1f82a5d22..5d2df0bba 100644 --- a/ui/components/ui/box/README.mdx +++ b/ui/components/ui/box/README.mdx @@ -42,6 +42,7 @@ Box is a utility component that can be used for layout or as a base for other UI | borderWidth | 0, 1, 2, 4, 6, 8, 9, 10, 12 or array of numbers [1, 2] | - | | borderRadius | [SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L74-L81) values or array of [SIZES](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L74-L81) values | - | | borderStyle | [BORDER_STYLE](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L83-L88) values or array of [BORDER_STYLE](https://github.com/MetaMask/metamask-extension/blob/develop/ui/helpers/constants/design-system.js#L83-L88) values | - | +| as | The polymorphic `as` prop allows you to change the root HTML element of the Box component. Defaults to 'div' | 'div' | ## Usage @@ -134,14 +135,10 @@ import Box from '../ui/box'; Use the `backgroundColor` prop along with the `COLORS` object from `ui/helpers/constants/design-system.js` to change background color. The `backgroundColor` prop accepts [responsive props](#responsive-props) in the form of array props. -````jsx - -**NOTE**: The `` and `` color combinations above follow our design system color rules and should cover most general UI applications. Click "Show code" to see the code example. Do not use the [deprecated colors](#deprecated-colors) - Example of importing `COLORS` object with `Box` component ```jsx @@ -151,7 +148,7 @@ import Box from '../ui/box'; COLORS.BACKGROUND_DEFAULT ; -```` +``` ### Border Color @@ -161,8 +158,6 @@ Use the `borderColor` prop along with the `COLORS` object from `ui/helpers/const -**NOTE**: The `` and `` color combinations above follow our design system color rules and should cover most general UI applications. Click "Show code" to see the code example. Do not use the [deprecated colors](#deprecated-colors) - Example of importing `COLORS` object with `Box` component ```jsx @@ -236,3 +231,19 @@ import Box from '../ui/box'; ; ``` + +### As + +Use the `as` prop to change the root html element of the Box component + + + + + +```jsx +import Box from '../../ui/box'; + +ul +li +button +``` diff --git a/ui/components/ui/box/box.js b/ui/components/ui/box/box.js index 8484172d2..09c4c0f39 100644 --- a/ui/components/ui/box/box.js +++ b/ui/components/ui/box/box.js @@ -227,6 +227,7 @@ export default function Box({ children, className, backgroundColor, + as = 'div', ...props }) { const boxClassName = classnames( @@ -284,10 +285,11 @@ export default function Box({ if (typeof children === 'function') { return children(boxClassName); } + const Component = as; return ( -
    + {children} -
    + ); } @@ -351,4 +353,9 @@ Box.propTypes = { ]), backgroundColor: MultipleBackgroundColors, className: PropTypes.string, + /** + * The polymorphic `as` prop allows you to change the root HTML element of the Box component + * Defaults to 'div' + */ + as: PropTypes.string, }; diff --git a/ui/components/ui/box/box.stories.js b/ui/components/ui/box/box.stories.js index e30e97db8..ea50b0e23 100644 --- a/ui/components/ui/box/box.stories.js +++ b/ui/components/ui/box/box.stories.js @@ -166,6 +166,10 @@ export default { control: 'select', table: { category: 'padding' }, }, + as: { + control: 'select', + options: ['div', 'ul', 'li', 'span', 'a', 'button'], + }, }, }; @@ -406,3 +410,19 @@ export const ResponsiveProps = () => { ); }; + +export const As = (args) => { + return ( + <> + + You can change the root element of the Box component using the as prop. + Inspect the below elements to see the underlying HTML elements + + div(default) + ul + li + button + header + + ); +}; diff --git a/ui/components/ui/box/box.test.js b/ui/components/ui/box/box.test.js index aabb49c32..c2b87bffb 100644 --- a/ui/components/ui/box/box.test.js +++ b/ui/components/ui/box/box.test.js @@ -729,4 +729,22 @@ describe('Box', () => { expect(getByText('Box content')).toHaveClass('box--lg:height-min'); }); }); + describe('polymorphic "as" prop', () => { + it('should render the Box with different html root elements', () => { + const { container } = render( + <> + Box as div (default) + Box as ul + Box as button + , + ); + expect(container.querySelector('div')).toHaveTextContent( + 'Box as div (default)', + ); + expect(container.querySelector('ul')).toHaveTextContent('Box as ul'); + expect(container.querySelector('button')).toHaveTextContent( + 'Box as button', + ); + }); + }); }); diff --git a/ui/components/ui/chip/chip.js b/ui/components/ui/chip/chip.js index fa217e31d..40d8e75e5 100644 --- a/ui/components/ui/chip/chip.js +++ b/ui/components/ui/chip/chip.js @@ -55,7 +55,7 @@ export default function Chip({ diff --git a/ui/components/ui/confusable/confusable.component.js b/ui/components/ui/confusable/confusable.component.js index 6e1ac6b40..b91d93e92 100644 --- a/ui/components/ui/confusable/confusable.component.js +++ b/ui/components/ui/confusable/confusable.component.js @@ -18,7 +18,7 @@ const Confusable = ({ input }) => { return ( {term} {tooltips[term] && ( @@ -62,7 +62,7 @@ export default function DefinitionList({ }} className="definition-list__definition" overflowWrap={OVERFLOW_WRAP.BREAK_WORD} - tag="dd" + as="dd" > {definition} diff --git a/ui/components/ui/numeric-input/numeric-input.component.js b/ui/components/ui/numeric-input/numeric-input.component.js index a072b288c..55e87f7f0 100644 --- a/ui/components/ui/numeric-input/numeric-input.component.js +++ b/ui/components/ui/numeric-input/numeric-input.component.js @@ -47,7 +47,7 @@ export default function NumericInput({ {detailText} diff --git a/ui/components/ui/typography/README.mdx b/ui/components/ui/typography/README.mdx index 86af7631a..43d5ef96a 100644 --- a/ui/components/ui/typography/README.mdx +++ b/ui/components/ui/typography/README.mdx @@ -215,50 +215,63 @@ import { OVERFLOW_WRAP } from '../../../helpers/constants/design-system';
; ``` -### Tag +### As -Use the `tag` prop to change the root html element of the Typography component +Use the `as` prop to change the root html element of the Typography component - + ```jsx // If importing from ui/components/app/[YOUR_COMPONENT]/ directory import Typography from '../../ui/typography'; -dd -div -dt -em -h1 -h2 -h3 -h4 -h5 -h6 -li -p -span -strong +dd +div +dt +em +h1 +h2 +h3 +h4 +h5 +h6 +li +p +span +strong ``` Renders the html: ```html
dd
+
div
+
dt
+ em +

h1

+

h2

+

h3

+

h4

+
h5
+
h6
+
  • li
  • +

    p

    + span + strong ``` diff --git a/ui/components/ui/typography/typography.js b/ui/components/ui/typography/typography.js index d3342e4cb..9c2498ede 100644 --- a/ui/components/ui/typography/typography.js +++ b/ui/components/ui/typography/typography.js @@ -57,7 +57,7 @@ export default function Typography({ align, overflowWrap, title, - tag, + as, margin, marginTop = 1, marginRight, @@ -67,7 +67,7 @@ export default function Typography({ className, children, }) { - let Tag = tag ?? variant; + let Tag = as ?? variant; let strongTagFontWeight; if (Tag === 'strong') { @@ -147,9 +147,9 @@ Typography.propTypes = { */ overflowWrap: PropTypes.oneOf(Object.values(OVERFLOW_WRAP)), /** - * Changes the root html element tag of the Typography component. + * Changes the root html element of the Typography component. */ - tag: PropTypes.oneOf(ValidTags), + as: PropTypes.oneOf(ValidTags), /** * Adds margin to the Typography component should use valid size */ diff --git a/ui/components/ui/typography/typography.stories.js b/ui/components/ui/typography/typography.stories.js index d36024ba4..dbfd9b2dc 100644 --- a/ui/components/ui/typography/typography.stories.js +++ b/ui/components/ui/typography/typography.stories.js @@ -6,7 +6,9 @@ import { TEXT_ALIGN, TYPOGRAPHY, OVERFLOW_WRAP, + DISPLAY, } from '../../../helpers/constants/design-system'; +import Box from '../box'; import { ValidColors, ValidTags } from './typography'; @@ -49,7 +51,7 @@ export default { control: { type: 'select' }, options: Object.values(OVERFLOW_WRAP), }, - tag: { + as: { control: { type: 'select' }, options: ValidTags, }, @@ -249,18 +251,27 @@ export const OverflowWrap = (args) => ( ); -export const Tag = (args) => ( +export const As = (args) => ( <> - {Object.values(ValidTags).map((tag) => ( - - {tag} - - ))} + + You can change the root element of the Typography component using the as + prop. Inspect the below elements to see the underlying HTML elements + + + {Object.values(ValidTags).map((as) => ( + + {as} + + ))} + ); diff --git a/ui/components/ui/typography/typography.test.js b/ui/components/ui/typography/typography.test.js index d8b259b85..98ad4bd32 100644 --- a/ui/components/ui/typography/typography.test.js +++ b/ui/components/ui/typography/typography.test.js @@ -7,52 +7,52 @@ describe('Typography', () => { const { getByText } = render(Test type); expect(getByText('Test type')).toBeDefined(); }); - it('should render the Typography with correct html tags', () => { + it('should render the Typography with correct html elements', () => { const { getByText, container } = render( <> - p tag - h1 tag - h2 tag - h3 tag - h4 tag - h5 tag - h6 tag - span tag - strong tag - em tag - li tag - div tag - dt tag - dd tag + p + h1 + h2 + h3 + h4 + h5 + h6 + span + strong + em + li + div + dt + dd , ); expect(container.querySelector('p')).toBeDefined(); - expect(getByText('p tag')).toBeDefined(); + expect(getByText('p')).toBeDefined(); expect(container.querySelector('h1')).toBeDefined(); - expect(getByText('h1 tag')).toBeDefined(); + expect(getByText('h1')).toBeDefined(); expect(container.querySelector('h2')).toBeDefined(); - expect(getByText('h2 tag')).toBeDefined(); + expect(getByText('h2')).toBeDefined(); expect(container.querySelector('h3')).toBeDefined(); - expect(getByText('h3 tag')).toBeDefined(); + expect(getByText('h3')).toBeDefined(); expect(container.querySelector('h4')).toBeDefined(); - expect(getByText('h4 tag')).toBeDefined(); + expect(getByText('h4')).toBeDefined(); expect(container.querySelector('h5')).toBeDefined(); - expect(getByText('h5 tag')).toBeDefined(); + expect(getByText('h5')).toBeDefined(); expect(container.querySelector('h6')).toBeDefined(); - expect(getByText('h6 tag')).toBeDefined(); + expect(getByText('h6')).toBeDefined(); expect(container.querySelector('span')).toBeDefined(); - expect(getByText('span tag')).toBeDefined(); + expect(getByText('span')).toBeDefined(); expect(container.querySelector('strong')).toBeDefined(); - expect(getByText('strong tag')).toBeDefined(); + expect(getByText('strong')).toBeDefined(); expect(container.querySelector('em')).toBeDefined(); - expect(getByText('em tag')).toBeDefined(); + expect(getByText('em')).toBeDefined(); expect(container.querySelector('li')).toBeDefined(); - expect(getByText('li tag')).toBeDefined(); + expect(getByText('li')).toBeDefined(); expect(container.querySelector('div')).toBeDefined(); - expect(getByText('div tag')).toBeDefined(); + expect(getByText('div')).toBeDefined(); expect(container.querySelector('dt')).toBeDefined(); - expect(getByText('dt tag')).toBeDefined(); + expect(getByText('dt')).toBeDefined(); expect(container.querySelector('dd')).toBeDefined(); - expect(getByText('dd tag')).toBeDefined(); + expect(getByText('dd')).toBeDefined(); }); }); diff --git a/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/seed-phrase-intro.component.js b/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/seed-phrase-intro.component.js index fd95d11f2..841b13fe1 100644 --- a/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/seed-phrase-intro.component.js +++ b/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/seed-phrase-intro.component.js @@ -97,7 +97,7 @@ export default function SeedPhraseIntro() { > {t('seedPhraseIntroSidebarTitleOne')} - + {t('seedPhraseIntroSidebarCopyOne')} {t('seedPhraseIntroSidebarTitleThree')} - + {t('seedPhraseIntroSidebarCopyTwo')} - + {t('seedPhraseIntroSidebarCopyThree')} diff --git a/ui/pages/permissions-connect/flask/snap-install/snap-install.js b/ui/pages/permissions-connect/flask/snap-install/snap-install.js index 2d7a7aab1..565f1c27b 100644 --- a/ui/pages/permissions-connect/flask/snap-install/snap-install.js +++ b/ui/pages/permissions-connect/flask/snap-install/snap-install.js @@ -77,7 +77,7 @@ export default function SnapInstall({ padding: [4, 4, 0, 4], }} variant={TYPOGRAPHY.H7} - tag="span" + as="span" > {t('snapRequestsPermission')} diff --git a/ui/pages/permissions-connect/flask/snap-update/snap-update.js b/ui/pages/permissions-connect/flask/snap-update/snap-update.js index 1ac883da0..d3f7d52fb 100644 --- a/ui/pages/permissions-connect/flask/snap-update/snap-update.js +++ b/ui/pages/permissions-connect/flask/snap-update/snap-update.js @@ -76,7 +76,7 @@ export default function SnapUpdate({ padding: [4, 4, 0, 4], }} variant={TYPOGRAPHY.H7} - tag="span" + as="span" > {t('snapUpdateExplanation', [`${request.metadata.dappOrigin}`])} @@ -85,7 +85,7 @@ export default function SnapUpdate({ padding: [2, 4, 0, 4], }} variant={TYPOGRAPHY.H7} - tag="span" + as="span" > {t('snapRequestsPermission')} diff --git a/ui/pages/swaps/awaiting-signatures/awaiting-signatures.js b/ui/pages/swaps/awaiting-signatures/awaiting-signatures.js index 73aaa9e74..c72f5355d 100644 --- a/ui/pages/swaps/awaiting-signatures/awaiting-signatures.js +++ b/ui/pages/swaps/awaiting-signatures/awaiting-signatures.js @@ -111,7 +111,7 @@ export default function AwaitingSignatures() { {t('swapAllowSwappingOf', [ @@ -123,14 +123,14 @@ export default function AwaitingSignatures() { {t('swapFromTo', [ {sourceTokenInfo?.symbol} , diff --git a/ui/pages/swaps/build-quote/build-quote.js b/ui/pages/swaps/build-quote/build-quote.js index 6bbac7e08..af4ba4aa6 100644 --- a/ui/pages/swaps/build-quote/build-quote.js +++ b/ui/pages/swaps/build-quote/build-quote.js @@ -626,7 +626,7 @@ export default function BuildQuote({ {t('stxDescription')} {t('stxBenefit4')} @@ -652,7 +652,7 @@ export default function BuildQuote({ > {t('stxSubDescription')}