mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
* UX: Multichain: Account Menu List * Move to using stylesheet * Add hover state * Implement George's suggestions * Add connected site avatar * Add hardware tag * Create story for selected hardware item * Progress on the AccountListItemMenu * Add story for AccountListItemMenu * Better position the account menu * Fix AvatarFavicon missing name prop * Update menu options label to be account specific * Update text of 'View on Explorer' * Add AccountListMenu component * Move all items to multichain directory * Fix paths * Fix linting, use AvatarIcon * Add title and close button to account menu * Center the popover title * Add search functionality * Implementation WIP * Add MULTICHAIN feature flag * Add MULTICHAIN feature flag, add actions for menu items * Properly dispatch events * Fix search box padding * Fix sizing of menu item text * Fix isRequired * Fix alignment of the popover * Update label for hardware wallet items, add text for no search results * Update keyring retreival to remove account and add label * Fix storybook * Fix double link click issue, prevent wrapping of values * Use labelProps for tag variant * Restructure item menu story * Empower storybooks for all new components * Allow only 3 decimals for currencies * Avoid inline styles * Prefix classes with multichain, fix account-list-menu storybook * Close the accounts menu when account details is clicked * Restore tag.js * Create global file for multichain css * Add index file for multichain js * Update file paths * Ensure the block domain is present in menu * Add AccountListItem test * Add AccountListItemMenu tests * Show account connect to current dapp * Improve tests * Make avatar smaller * Add tooltip for account menu * Align icon better * Update snapshot * Rename files to DS standard * Add index files for export * Export all multichain components * Update snapshot * Remove embedded style in popover * Add comments for props, cleanup storybook * Improve test coverage * Improve test code quality * Remove border form avatar * Switch to using the ButtonLink iconName prop * Only show tooltip if character limit is reached * Restore prior search settings * Add test for tooltip
277 lines
6.4 KiB
JavaScript
277 lines
6.4 KiB
JavaScript
import React, { PureComponent } from 'react';
|
|
import ReactDOM from 'react-dom';
|
|
import PropTypes from 'prop-types';
|
|
import classnames from 'classnames';
|
|
import { useI18nContext } from '../../../hooks/useI18nContext';
|
|
import Box from '../box';
|
|
import {
|
|
AlignItems,
|
|
BackgroundColor,
|
|
FLEX_DIRECTION,
|
|
JustifyContent,
|
|
Color,
|
|
DISPLAY,
|
|
TextVariant,
|
|
Size,
|
|
BorderColor,
|
|
IconColor,
|
|
TEXT_ALIGN,
|
|
BLOCK_SIZES,
|
|
} from '../../../helpers/constants/design-system';
|
|
import {
|
|
ButtonIcon,
|
|
Text,
|
|
Icon,
|
|
ICON_NAMES,
|
|
ICON_SIZES,
|
|
} from '../../component-library';
|
|
|
|
const defaultHeaderProps = {
|
|
padding: [6, 4, 4],
|
|
display: 'flex',
|
|
flexDirection: FLEX_DIRECTION.COLUMN,
|
|
backgroundColor: BackgroundColor.backgroundDefault,
|
|
borderRadius: 'xl',
|
|
};
|
|
|
|
const defaultContentProps = {
|
|
display: 'flex',
|
|
flexDirection: FLEX_DIRECTION.COLUMN,
|
|
justifyContent: JustifyContent.flexStart,
|
|
alignItems: AlignItems.stretch,
|
|
borderRadius: 'xl',
|
|
};
|
|
|
|
const defaultFooterProps = {
|
|
display: 'flex',
|
|
justifyContent: JustifyContent.spaceBetween,
|
|
padding: [4, 6, 6],
|
|
};
|
|
|
|
const Popover = ({
|
|
title,
|
|
subtitle = '',
|
|
children,
|
|
footer,
|
|
footerClassName,
|
|
onBack,
|
|
onClose,
|
|
className,
|
|
contentClassName,
|
|
showArrow,
|
|
CustomBackground,
|
|
popoverRef,
|
|
showScrollDown,
|
|
onScrollDownButtonClick,
|
|
centerTitle,
|
|
headerProps = defaultHeaderProps,
|
|
contentProps = defaultContentProps,
|
|
footerProps = defaultFooterProps,
|
|
}) => {
|
|
const t = useI18nContext();
|
|
const showHeader = title || onBack || subtitle || onClose;
|
|
const Header = () => (
|
|
<Box
|
|
{...{ ...defaultHeaderProps, ...headerProps }}
|
|
className="popover-header"
|
|
>
|
|
<Box
|
|
display={DISPLAY.FLEX}
|
|
alignItems={AlignItems.center}
|
|
justifyContent={centerTitle ? null : JustifyContent.spaceBetween}
|
|
className={classnames('popover-header__title', {
|
|
'popover-header__title--center': centerTitle,
|
|
})}
|
|
marginBottom={2}
|
|
>
|
|
{onBack ? (
|
|
<ButtonIcon
|
|
iconName={ICON_NAMES.ARROW_LEFT}
|
|
ariaLabel={t('back')}
|
|
onClick={onBack}
|
|
color={Color.iconDefault}
|
|
size={Size.SM}
|
|
/>
|
|
) : null}
|
|
<Text
|
|
textAlign={centerTitle ? TEXT_ALIGN.CENTER : TEXT_ALIGN.START}
|
|
ellipsis
|
|
variant={TextVariant.headingSm}
|
|
as="h2"
|
|
width={BLOCK_SIZES.FULL}
|
|
>
|
|
{title}
|
|
</Text>
|
|
{onClose ? (
|
|
<ButtonIcon
|
|
iconName={ICON_NAMES.CLOSE}
|
|
ariaLabel={t('close')}
|
|
data-testid="popover-close"
|
|
onClick={onClose}
|
|
size={Size.SM}
|
|
/>
|
|
) : null}
|
|
</Box>
|
|
{subtitle ? <Text variant={TextVariant.bodySm}>{subtitle}</Text> : null}
|
|
</Box>
|
|
);
|
|
|
|
return (
|
|
<div className="popover-container">
|
|
{CustomBackground ? (
|
|
<CustomBackground onClose={onClose} />
|
|
) : (
|
|
<div className="popover-bg" onClick={onClose} />
|
|
)}
|
|
<section
|
|
className={classnames('popover-wrap', className)}
|
|
ref={popoverRef}
|
|
>
|
|
{showScrollDown ? (
|
|
<Box
|
|
display={DISPLAY.FLEX}
|
|
alignItems={AlignItems.center}
|
|
justifyContent={JustifyContent.center}
|
|
borderColor={BorderColor.borderDefault}
|
|
backgroundColor={BackgroundColor.backgroundDefault}
|
|
color={Color.iconDefault}
|
|
onClick={onScrollDownButtonClick}
|
|
className="whats-new-popup__scroll-button"
|
|
data-testid="whats-new-popup-scroll-button"
|
|
>
|
|
<Icon
|
|
name={ICON_NAMES.ARROW_DOWN}
|
|
color={IconColor.primaryDefault}
|
|
size={ICON_SIZES.MD}
|
|
aria-label={t('scrollDown')}
|
|
/>
|
|
</Box>
|
|
) : null}
|
|
{showArrow ? <div className="popover-arrow" /> : null}
|
|
{showHeader && <Header />}
|
|
{children ? (
|
|
<Box
|
|
className={classnames('popover-content', contentClassName)}
|
|
{...{ ...defaultContentProps, ...contentProps }}
|
|
>
|
|
{children}
|
|
</Box>
|
|
) : null}
|
|
{footer ? (
|
|
<Box
|
|
className={classnames('popover-footer', footerClassName)}
|
|
{...{ ...defaultFooterProps, ...footerProps }}
|
|
>
|
|
{footer}
|
|
</Box>
|
|
) : null}
|
|
</section>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
Popover.propTypes = {
|
|
/**
|
|
* Show title of the popover
|
|
*/
|
|
title: PropTypes.node,
|
|
/**
|
|
* Show subtitle label on popover
|
|
*/
|
|
subtitle: PropTypes.string,
|
|
/**
|
|
* Show children content could be react child or text
|
|
*/
|
|
children: PropTypes.node,
|
|
/**
|
|
* Show footer content could be react child or text
|
|
*/
|
|
footer: PropTypes.node,
|
|
/**
|
|
* Add custom CSS class for footer
|
|
*/
|
|
footerClassName: PropTypes.string,
|
|
/**
|
|
* onBack handler
|
|
*/
|
|
onBack: PropTypes.func,
|
|
/**
|
|
* onClose handler
|
|
*/
|
|
onClose: PropTypes.func,
|
|
CustomBackground: PropTypes.func,
|
|
/**
|
|
* Add custom CSS class for content
|
|
*/
|
|
contentClassName: PropTypes.string,
|
|
/**
|
|
* Add custom CSS class
|
|
*/
|
|
className: PropTypes.string,
|
|
/**
|
|
* Check if component would show arror
|
|
*/
|
|
showArrow: PropTypes.bool,
|
|
/**
|
|
* The ref of the popover-wrap element
|
|
*/
|
|
popoverRef: PropTypes.shape({
|
|
current: PropTypes.instanceOf(window.Element),
|
|
}),
|
|
/**
|
|
* Show title of the popover
|
|
*/
|
|
showScrollDown: PropTypes.bool,
|
|
/**
|
|
* ScrollDown handler
|
|
*/
|
|
onScrollDownButtonClick: PropTypes.func,
|
|
/**
|
|
* Check if use centered title
|
|
*/
|
|
centerTitle: PropTypes.bool,
|
|
/**
|
|
* Box props for the header
|
|
*/
|
|
headerProps: PropTypes.shape({ ...Box.propTypes }),
|
|
/**
|
|
* Box props for the content
|
|
*/
|
|
contentProps: PropTypes.shape({ ...Box.propTypes }),
|
|
/**
|
|
* Box props for the footer
|
|
*/
|
|
footerProps: PropTypes.shape({ ...Box.propTypes }),
|
|
};
|
|
|
|
export default class PopoverPortal extends PureComponent {
|
|
static propTypes = Popover.propTypes;
|
|
|
|
rootNode = document.getElementById('popover-content');
|
|
|
|
instanceNode = document.createElement('div');
|
|
|
|
componentDidMount() {
|
|
if (!this.rootNode) {
|
|
return;
|
|
}
|
|
|
|
this.rootNode.appendChild(this.instanceNode);
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
if (!this.rootNode) {
|
|
return;
|
|
}
|
|
|
|
this.rootNode.removeChild(this.instanceNode);
|
|
}
|
|
|
|
render() {
|
|
const children = <Popover {...this.props} />;
|
|
return this.rootNode
|
|
? ReactDOM.createPortal(children, this.instanceNode)
|
|
: children;
|
|
}
|
|
}
|