diff --git a/test/e2e/tests/add-account.spec.js b/test/e2e/tests/add-account.spec.js index dc10beb5653a..226c8bda950b 100644 --- a/test/e2e/tests/add-account.spec.js +++ b/test/e2e/tests/add-account.spec.js @@ -242,7 +242,7 @@ describe('Add account', function () { // enter private key', await driver.fill('#private-key-box', testPrivateKey); - await driver.clickElement({ text: 'Import', tag: 'span' }); + await driver.clickElement({ text: 'Import', tag: 'button' }); // should show the correct account name const importedAccountName = await driver.findElement( diff --git a/test/e2e/tests/failing-contract.spec.js b/test/e2e/tests/failing-contract.spec.js index b3f9bb5c0085..3391d878ee65 100644 --- a/test/e2e/tests/failing-contract.spec.js +++ b/test/e2e/tests/failing-contract.spec.js @@ -63,7 +63,7 @@ describe('Failing contract interaction ', function () { // dismiss warning and confirm the transaction await driver.clickElement({ text: 'I want to proceed anyway', - tag: 'span', + tag: 'button', }); await driver.clickElement({ text: 'Confirm', tag: 'button' }); await driver.waitUntilXWindowHandles(2); @@ -149,7 +149,7 @@ describe('Failing contract interaction on non-EIP1559 network', function () { // dismiss warning and confirm the transaction await driver.clickElement({ text: 'I want to proceed anyway', - tag: 'span', + tag: 'button', }); await driver.clickElement({ text: 'Confirm', tag: 'button' }); await driver.waitUntilXWindowHandles(2); diff --git a/test/e2e/tests/from-import-ui.spec.js b/test/e2e/tests/from-import-ui.spec.js index 6a931835152b..e56882c05728 100644 --- a/test/e2e/tests/from-import-ui.spec.js +++ b/test/e2e/tests/from-import-ui.spec.js @@ -212,7 +212,7 @@ describe('MetaMask Import UI', function () { // enter private key', await driver.fill('#private-key-box', testPrivateKey1); - await driver.clickElement({ text: 'Import', tag: 'span' }); + await driver.clickElement({ text: 'Import', tag: 'button' }); // should show the correct account name const importedAccountName = await driver.findElement( @@ -239,7 +239,7 @@ describe('MetaMask Import UI', function () { await driver.clickElement({ text: 'Import account', tag: 'div' }); // enter private key await driver.fill('#private-key-box', testPrivateKey2); - await driver.clickElement({ text: 'Import', tag: 'span' }); + await driver.clickElement({ text: 'Import', tag: 'button' }); // should see new account in account menu const importedAccount2Name = await driver.findElement( @@ -330,7 +330,7 @@ describe('MetaMask Import UI', function () { await driver.fill('#json-password-box', 'foobarbazqux'); - await driver.clickElement({ text: 'Import', tag: 'span' }); + await driver.clickElement({ text: 'Import', tag: 'button' }); // should show the correct account name const importedAccountName = await driver.findElement( @@ -392,7 +392,7 @@ describe('MetaMask Import UI', function () { // enter private key', await driver.fill('#private-key-box', testPrivateKey); - await driver.clickElement({ text: 'Import', tag: 'span' }); + await driver.clickElement({ text: 'Import', tag: 'button' }); // error should occur await driver.waitForSelector({ diff --git a/ui/components/component-library/button-base/README.mdx b/ui/components/component-library/button-base/README.mdx index 2390323792a3..f18d98636efa 100644 --- a/ui/components/component-library/button-base/README.mdx +++ b/ui/components/component-library/button-base/README.mdx @@ -102,7 +102,9 @@ import { ButtonBase } from '../../component-library'; When an `externalLink` prop is passed it will change the element to an anchor(`a`) tag and add the `target="_blank"` and `rel="noopener noreferrer"` attributes. + + ```jsx import { ButtonBase } from '../../component-library'; @@ -168,7 +170,7 @@ import { ICON_NAMES } from '../icon'; ### RTL -For RTL language support use the `textProps` prop to pass a `textDirection` prop. +For RTL language support use the `textDirection` prop. @@ -187,11 +189,28 @@ import { ButtonBase, ICON_NAMES } from '../../component-library'; Button Demo >; ``` + +### Ellipsis + +Use the boolean `ellipsis` prop to change the if the `ButtonBase` component to have an ellipsis. + +Note: this should only be used for dynamic/user generated content or addresses. Generally, button text should be succinct and only contain one or two words. + + + + + +```jsx +import { ButtonBase } from '../../component-library'; + + + This is long text example without ellipsis + This is long text example with ellipsis +; +``` diff --git a/ui/components/component-library/button-base/__snapshots__/button-base.test.js.snap b/ui/components/component-library/button-base/__snapshots__/button-base.test.js.snap index 6dc5bfbcf11d..9e3221f01a85 100644 --- a/ui/components/component-library/button-base/__snapshots__/button-base.test.js.snap +++ b/ui/components/component-library/button-base/__snapshots__/button-base.test.js.snap @@ -3,17 +3,13 @@ exports[`ButtonBase should render anchor element correctly by href and externalLink, href target and rel exist 1`] = ` - - Button Base - + Button Base `; @@ -21,14 +17,10 @@ exports[`ButtonBase should render anchor element correctly by href and externalL exports[`ButtonBase should render button element correctly and match snapshot 1`] = ` - - Button base - + Button base `; diff --git a/ui/components/component-library/button-base/button-base.js b/ui/components/component-library/button-base/button-base.js index 1a870284ad29..c79a757e91b5 100644 --- a/ui/components/component-library/button-base/button-base.js +++ b/ui/components/component-library/button-base/button-base.js @@ -15,6 +15,7 @@ import { Size, BorderRadius, BackgroundColor, + IconColor, } from '../../../helpers/constants/design-system'; import { BUTTON_BASE_SIZES } from './button-base.constants'; @@ -24,6 +25,7 @@ export const ButtonBase = ({ children, className, href, + ellipsis = false, externalLink, size = BUTTON_BASE_SIZES.MD, startIconName, @@ -34,6 +36,7 @@ export const ButtonBase = ({ disabled, iconLoadingProps, textProps, + color = TextColor.textDefault, ...props }) => { const Tag = href ? 'a' : as; @@ -42,13 +45,14 @@ export const ButtonBase = ({ props.rel = 'noopener noreferrer'; } return ( - - - {startIconName && ( - - )} - {children} - {endIconName && ( - - )} - + {startIconName && ( + + )} + {/* + * If children is a string and doesn't need truncation or loading + * prevent html bloat by rendering just the string + * otherwise render with wrapper to allow truncation or loading + */} + {typeof children === 'string' && !ellipsis && !loading ? ( + children + ) : ( + + {children} + + )} + {endIconName && ( + + )} {loading && ( )} - + ); }; @@ -126,6 +150,10 @@ ButtonBase.propTypes = { * When an `href` prop is passed, ButtonBase will automatically change the root element to be an `a` (anchor) tag */ href: PropTypes.string, + /** + * Used for long strings that can be cut off... + */ + ellipsis: PropTypes.bool, /** * Boolean indicating if the link targets external content, it will cause the link to open in a new tab */ diff --git a/ui/components/component-library/button-base/button-base.scss b/ui/components/component-library/button-base/button-base.scss index 42e6d24a9db7..6b4e249c2542 100644 --- a/ui/components/component-library/button-base/button-base.scss +++ b/ui/components/component-library/button-base/button-base.scss @@ -6,18 +6,13 @@ vertical-align: middle; user-select: none; - &:active, - &:hover { - color: var(--color-text-default); - } - &--block { display: block; width: 100%; } - &__content { - height: 100%; + &--ellipsis { + max-width: 100%; } &--size-sm { @@ -36,10 +31,6 @@ cursor: not-allowed; } - &--loading &__content { - color: transparent; - } - &--disabled, &:disabled { opacity: 0.3; diff --git a/ui/components/component-library/button-base/button-base.stories.js b/ui/components/component-library/button-base/button-base.stories.js index ffb512783106..0a4afed2c247 100644 --- a/ui/components/component-library/button-base/button-base.stories.js +++ b/ui/components/component-library/button-base/button-base.stories.js @@ -1,6 +1,7 @@ import React from 'react'; import { AlignItems, + Color, DISPLAY, FLEX_DIRECTION, Size, @@ -199,11 +200,18 @@ export const Rtl = (args) => ( {...args} startIconName={ICON_NAMES.ADD_SQUARE} endIconName={ICON_NAMES.ARROW_2_RIGHT} - textProps={{ - textDirection: TEXT_DIRECTIONS.RIGHT_TO_LEFT, - }} + textDirection={TEXT_DIRECTIONS.RIGHT_TO_LEFT} > Button Demo ); + +export const Ellipsis = (args) => ( + + Example without ellipsis + + Example with ellipsis + + +); diff --git a/ui/components/component-library/button-link/README.mdx b/ui/components/component-library/button-link/README.mdx index 292190b07731..4850161adc80 100644 --- a/ui/components/component-library/button-link/README.mdx +++ b/ui/components/component-library/button-link/README.mdx @@ -67,7 +67,7 @@ import { ButtonLink, Text, TextVariant } from '../../component-library'; - Inherits the font-size of the parent element and example with textProps override for a success color. + Inherits the font-size of the parent element and example with override for a success color. Learn more ``` @@ -103,7 +103,7 @@ import { ButtonLink } from '../../component-library'; ### External Link -When an `externalLink` prop is passed it adds the `target="_blank"` and `rel="noopener noreferrer"` attributes. +When an `externalLink` prop is passed it adds the `target="_blank"` and `rel="noopener noreferrer"` attributes. `rel="noreferrer noopener"` is used in links to prevent security vulnerabilities that can be exploited by malicious websites. It disables the window.opener property and prevents the new page from sending the referrer information, providing an additional layer of security. diff --git a/ui/components/component-library/button-link/__snapshots__/button-link.test.js.snap b/ui/components/component-library/button-link/__snapshots__/button-link.test.js.snap index f62717f6cd73..1a5c0af51d6b 100644 --- a/ui/components/component-library/button-link/__snapshots__/button-link.test.js.snap +++ b/ui/components/component-library/button-link/__snapshots__/button-link.test.js.snap @@ -3,14 +3,10 @@ exports[`ButtonLink should render button element correctly 1`] = ` - - Button Link - + Button Link `; diff --git a/ui/components/component-library/button-link/button-link.js b/ui/components/component-library/button-link/button-link.js index aa77a788ad7b..c7d7dd14fe47 100644 --- a/ui/components/component-library/button-link/button-link.js +++ b/ui/components/component-library/button-link/button-link.js @@ -3,26 +3,25 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import { ButtonBase } from '../button-base'; -import { Text } from '../text'; import { BackgroundColor, Color, Size, - TextVariant, } from '../../../helpers/constants/design-system'; import { BUTTON_LINK_SIZES } from './button-link.constants'; export const ButtonLink = ({ className, danger, + disabled, size = Size.auto, - textProps, ...props }) => { return ( ); }; @@ -62,15 +54,15 @@ ButtonLink.propTypes = { * Boolean to change button type to Danger when true */ danger: PropTypes.bool, + /** + * Boolean to disable button + */ + disabled: PropTypes.bool, /** * Possible size values: 'SIZES.AUTO'(auto), 'SIZES.SM'(32px), 'SIZES.MD'(40px), 'SIZES.LG'(48px), 'SIZES.INHERIT'(inherits parents font-size) * Default value is 'SIZES.AUTO'. */ size: PropTypes.oneOf(Object.values(BUTTON_LINK_SIZES)), - /** - * textProps accepts all the props from Text component - */ - textProps: PropTypes.shape(Text.PropTypes), /** * ButtonLink accepts all the props from ButtonBase */ diff --git a/ui/components/component-library/button-link/button-link.scss b/ui/components/component-library/button-link/button-link.scss index 5c8a4c10b89f..30e40042c672 100644 --- a/ui/components/component-library/button-link/button-link.scss +++ b/ui/components/component-library/button-link/button-link.scss @@ -1,17 +1,14 @@ .mm-button-link { &:hover { - color: var(--color-primary-default); opacity: 0.5; } &:active { - color: var(--color-primary-default); opacity: 0.5; } &--disabled { &:hover { - color: var(--color-primary-default); opacity: 0.3; } diff --git a/ui/components/component-library/button-link/button-link.stories.js b/ui/components/component-library/button-link/button-link.stories.js index b97d8de36735..bda5a27f4083 100644 --- a/ui/components/component-library/button-link/button-link.stories.js +++ b/ui/components/component-library/button-link/button-link.stories.js @@ -162,12 +162,12 @@ export const SizeStory = (args) => ( - Inherits the font-size of the parent element and example with textProps - override for a success color.{' '} + Inherits the font-size of the parent element and example with override for + a success color.{' '} Learn more diff --git a/ui/components/component-library/button-primary/__snapshots__/button-primary.test.js.snap b/ui/components/component-library/button-primary/__snapshots__/button-primary.test.js.snap index 8b0c03a89fca..8768e1c7c56d 100644 --- a/ui/components/component-library/button-primary/__snapshots__/button-primary.test.js.snap +++ b/ui/components/component-library/button-primary/__snapshots__/button-primary.test.js.snap @@ -3,14 +3,10 @@ exports[`ButtonPrimary should render button element correctly 1`] = ` - - Button Primary - + Button Primary `; diff --git a/ui/components/component-library/button-secondary/__snapshots__/button-secondary.test.js.snap b/ui/components/component-library/button-secondary/__snapshots__/button-secondary.test.js.snap index c6f9a31779c5..fcc63172f02d 100644 --- a/ui/components/component-library/button-secondary/__snapshots__/button-secondary.test.js.snap +++ b/ui/components/component-library/button-secondary/__snapshots__/button-secondary.test.js.snap @@ -3,14 +3,10 @@ exports[`ButtonSecondary should render button element correctly 1`] = ` - - Button Secondary - + Button Secondary `; diff --git a/ui/components/component-library/button/__snapshots__/button.test.js.snap b/ui/components/component-library/button/__snapshots__/button.test.js.snap index a0685c51a84e..7d795a179e20 100644 --- a/ui/components/component-library/button/__snapshots__/button.test.js.snap +++ b/ui/components/component-library/button/__snapshots__/button.test.js.snap @@ -3,14 +3,10 @@ exports[`Button should render button element correctly 1`] = ` - - Button - + Button `; @@ -18,34 +14,22 @@ exports[`Button should render button element correctly 1`] = ` exports[`Button should render with different button types 1`] = ` - - Button - + Button - - Button - + Button - - Button - + Button `; diff --git a/ui/helpers/constants/design-system.ts b/ui/helpers/constants/design-system.ts index c39e95f51378..a80999cbf56a 100644 --- a/ui/helpers/constants/design-system.ts +++ b/ui/helpers/constants/design-system.ts @@ -130,6 +130,7 @@ export enum TextColor { lineaTestnetInverse = 'lineatestnet-inverse', goerliInverse = 'goerli-inverse', sepoliaInverse = 'sepolia-inverse', + transparent = 'transparent', } export enum IconColor { diff --git a/ui/pages/keychains/__snapshots__/reveal-seed.test.js.snap b/ui/pages/keychains/__snapshots__/reveal-seed.test.js.snap index 0d97c028a221..5bf39129d3db 100644 --- a/ui/pages/keychains/__snapshots__/reveal-seed.test.js.snap +++ b/ui/pages/keychains/__snapshots__/reveal-seed.test.js.snap @@ -17,16 +17,12 @@ exports[`Reveal Seed Page should match snapshot 1`] = ` The - - Secret Recovery Phrase (SRP) - + Secret Recovery Phrase (SRP) provides - - non-custodial wallet - + non-custodial wallet . That means you're the owner of your SRP. @@ -112,23 +104,15 @@ exports[`Reveal Seed Page should match snapshot 1`] = ` class="box box--margin-top-auto box--display-flex box--gap-4 box--flex-direction-row" > - - Cancel - + Cancel - - Next - + Next