1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

Feat/18308/ds popover header component (#18489)

* add popover component

popperjs init

popperjs hook init

popper arrow styles

fix popover story

add popover positions constant

story testing

popover structure

popper placement

make forwardref

fix popover with TS updates

modifiers

createPortal

add useClickAway hook

newer popover component build

simplifed popperjs with toggle to show/hide

toggle popover

modal version

popover progress 65%

add hover functionality

hide folder

storybook demo

add close button props

working popover with arrow

title prop breaking

popover TS conversion

TS updates

update test

add test

add arrow test

add stories

remove unused hook

fix docs

add popoverheader

types fix

Fix typo: detetcted-tokens-link -> detected-tokens-link (#18408)

Typography to text (#18382)

* Typography to text

* Update README.md

* Update README.md

* minor changes in custom file

* minor change

* Resolved Conflict issues

---------

Co-authored-by: Nidhi Kumari <nidhi.kumari@consensys.net>

fix: Pass correct optimism chain id to gas estimation (#18478)

removes unnecessary images (#18484)

Fix firsttimeloaded logic (#18344)

* use session storage, instead of chrome.runtime.onStartup and globalThis, for firstTimeLoaded architecture

* Ensure account tracker accounts remain defined upon service worker restart

* lint fix

* Simplify code

* Only call browser.storage.session in mv3

* Only call browser.storage.session.set after resetStates in mv3

* fix metamask controller reset states unit tests

* fix test

* fix test

* Actually fix tests

* lint fix

[FLASK] More Snaps E2E Optimization and Delay Reductions (#18245)

* bip32 delay reduction

* asserts changed to waitFors in 32/44

* scrollTo change

* replaced delay for firefox flake

* more reduced delays

* more delay reductions and changes

* raise paralellism to 4 for snaps tests

* additional delay changes

* fixed update code

* removed comment

* removed another comment

Fix switch-ethereum-chain handler by passing configuration id to setA… (#18483)

* Fix switch-ethereum-chain handler by passing configuration id to setActiveNetwork

* fix e2e test

* Fix e2e tests

* Update test/e2e/tests/switch-custom-network.spec.js

Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com>

* Revert "Update test/e2e/tests/switch-custom-network.spec.js"

This reverts commit be533ff7f25e1fd42e951d9b817b8438035ae256.

---------

Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com>

Bumping notification id's to 18 & 19 (#18460)

* Popover header update with TS ButtonIcon

* update PopoverHeader types

* update using new Text enums

* readme fix

* direct file import

* remove forwardRef and add action argtypes

* remove console.logs

* add arg types and fix TS on HeaderBase

* george nits

* popover header snapshot update

---------

Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com>
This commit is contained in:
Garrett Bear 2023-04-19 10:36:01 -07:00 committed by GitHub
parent 1e5f481a51
commit 4e1a96b4ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 361 additions and 11 deletions

View File

@ -14,7 +14,7 @@ import {
AlignItems,
BackgroundColor,
TextVariant,
TEXT_ALIGN,
TextAlign,
} from '../../../helpers/constants/design-system';
import { HeaderBase } from './header-base';
import README from './README.mdx';
@ -37,7 +37,7 @@ export const DefaultStory = Template.bind({});
DefaultStory.args = {
children: (
<Text variant={TextVariant.headingSm} textAlign={TEXT_ALIGN.CENTER}>
<Text variant={TextVariant.headingSm} textAlign={TextAlign.Center}>
Title is sentence case no period
</Text>
),
@ -62,7 +62,7 @@ DefaultStory.storyName = 'Default';
export const Children = (args) => {
return (
<HeaderBase {...args}>
<Text variant={TextVariant.headingSm} textAlign={TEXT_ALIGN.CENTER}>
<Text variant={TextVariant.headingSm} textAlign={TextAlign.Center}>
Title is sentence case no period
</Text>
</HeaderBase>
@ -82,7 +82,7 @@ export const StartAccessory = (args) => {
}
{...args}
>
<Text variant={TextVariant.headingSm} textAlign={TEXT_ALIGN.CENTER}>
<Text variant={TextVariant.headingSm} textAlign={TextAlign.Center}>
Title is sentence case no period
</Text>
</HeaderBase>
@ -102,7 +102,7 @@ export const EndAccessory = (args) => {
}
{...args}
>
<Text variant={TextVariant.headingSm} textAlign={TEXT_ALIGN.CENTER}>
<Text variant={TextVariant.headingSm} textAlign={TextAlign.Center}>
Title is sentence case no period
</Text>
</HeaderBase>
@ -116,7 +116,7 @@ export const UseCaseDemos = (args) => (
<HeaderBase marginBottom={4} {...args}>
<Text
variant={TextVariant.headingSm}
textAlign={TEXT_ALIGN.CENTER}
textAlign={TextAlign.Center}
backgroundColor={BackgroundColor.primaryAlternative}
>
Title is sentence case no period
@ -139,7 +139,7 @@ export const UseCaseDemos = (args) => (
>
<Text
variant={TextVariant.headingSm}
textAlign={TEXT_ALIGN.CENTER}
textAlign={TextAlign.Center}
backgroundColor={BackgroundColor.primaryAlternative}
>
Title is sentence case no period
@ -162,7 +162,7 @@ export const UseCaseDemos = (args) => (
>
<Text
variant={TextVariant.headingSm}
textAlign={TEXT_ALIGN.CENTER}
textAlign={TextAlign.Center}
backgroundColor={BackgroundColor.primaryAlternative}
>
Title is sentence case no period
@ -193,7 +193,7 @@ export const UseCaseDemos = (args) => (
>
<Text
variant={TextVariant.headingSm}
textAlign={TEXT_ALIGN.CENTER}
textAlign={TextAlign.Center}
backgroundColor={BackgroundColor.primaryAlternative}
>
Title is sentence case no period
@ -225,7 +225,7 @@ export const UseCaseDemos = (args) => (
>
<Text
variant={TextVariant.headingSm}
textAlign={TEXT_ALIGN.CENTER}
textAlign={TextAlign.Center}
backgroundColor={BackgroundColor.primaryAlternative}
>
Title is sentence case no period
@ -260,7 +260,7 @@ export const UseCaseDemos = (args) => (
>
<Text
variant={TextVariant.headingSm}
textAlign={TEXT_ALIGN.CENTER}
textAlign={TextAlign.Center}
backgroundColor={BackgroundColor.primaryAlternative}
>
Title is sentence case no period

View File

@ -39,3 +39,4 @@ export { ModalOverlay } from './modal-overlay';
export { BannerBase } from './banner-base';
export { BannerAlert, BANNER_ALERT_SEVERITIES } from './banner-alert';
export { BannerTip, BannerTipLogoType } from './banner-tip';
export { PopoverHeader } from './popover-header';

View File

@ -0,0 +1,98 @@
import { Story, Canvas, ArgsTable } from '@storybook/addon-docs';
import { PopoverHeader } from './popover-header';
# PopoverHeader
PopoverHeader is built on top of [HeaderBase](/docs/components-componentlibrary-headerbase--default-story) component with the most common use case of a back button in the startAccessory position, title, and close button in the endAccessory position.
<Canvas>
<Story id="components-componentlibrary-popoverheader--default-story" />
</Canvas>
## Props
The `PopoverHeader` accepts all props below as well as all [Box](/docs/ui-components-ui-box-box-stories-js--default-story#props) component props
<ArgsTable of={PopoverHeader} />
### Children
Wrapping string content in the `PopoverHeader` component will be rendered in the center of the header with the default title `Text` component.
<Canvas>
<Story id="components-componentlibrary-popoverheader--children" />
</Canvas>
```jsx
import { PopoverHeader } from '../../component-library';
<PopoverHeader>Title is sentence case no period</PopoverHeader>;
```
### onBack
Use the onClick handler `onBack` prop to render the `ButtonIcon` back button in the startAccessory position.
Use the `backButtonProps` prop to pass additional props to the `ButtonIcon` back button.
<Canvas>
<Story id="components-componentlibrary-popoverheader--on-back" />
</Canvas>
```jsx
import { PopoverHeader } from '../../component-library';
<PopoverHeader onBack={() => console.log('Back button click')}>
OnBack Demo
</PopoverHeader>;
```
### onClose
Use the onClick handler `onClose` prop to render the `ButtonIcon` back button in the endAccessory position.
Use the `backButtonProps` prop to pass additional props to the `ButtonIcon` back button.
<Canvas>
<Story id="components-componentlibrary-popoverheader--on-close" />
</Canvas>
```jsx
import { PopoverHeader } from '../../component-library';
<PopoverHeader onClose={() => console.log('Back button click')}>
OnClose Demo
</PopoverHeader>;
```
### startAccessory
Use the `startAccessory` prop to render a component in the startAccessory position. This will override the default back `ButtonIcon`.
<Canvas>
<Story id="components-componentlibrary-popoverheader--start-accessory" />
</Canvas>
```jsx
import { PopoverHeader, Button, BUTTON_SIZES } from '../../component-library';
<PopoverHeader startAccessory={<Button size={BUTTON_SIZES.SM}>Demo</Button>}>
StartAccessory
</PopoverHeader>;
```
### endAccessory
Use the `endAccessory` prop to render a component in the endAccessory position. This will override the default close `ButtonIcon`.
<Canvas>
<Story id="components-componentlibrary-popoverheader--end-accessory" />
</Canvas>
```jsx
import { PopoverHeader, Button, BUTTON_SIZES } from '../../component-library';
<PopoverHeader endAccessory={<Button size={BUTTON_SIZES.SM}>Demo</Button>}>
EndAccessory
</PopoverHeader>;
```

View File

@ -0,0 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PopoverHeader should render PopoverHeader correctly 1`] = `
<div>
<div
class="box mm-header-base mm-popover-header box--display-flex box--flex-direction-row box--justify-content-space-between"
data-testid="popover-header"
>
<div
class="box mm-header-base__children box--flex-direction-row box--width-full"
>
<h4
class="box mm-text mm-text--heading-sm mm-text--text-align-center box--flex-direction-row box--color-text-default"
>
Popover Header
</h4>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,2 @@
export { PopoverHeader } from './popover-header';
export type { PopoverHeaderProps } from './popover-header.types';

View File

@ -0,0 +1,65 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { BUTTON_SIZES, Button } from '..';
import { PopoverHeader } from './popover-header';
import README from './README.mdx';
export default {
title: 'Components/ComponentLibrary/PopoverHeader',
component: PopoverHeader,
parameters: {
docs: {
page: README,
},
},
argTypes: {
children: { control: 'text' },
className: { control: 'text' },
onBack: { action: 'onBack' },
onClose: { action: 'onClose' },
},
args: {
children: 'PopoverHeader',
},
} as ComponentMeta<typeof PopoverHeader>;
const Template: ComponentStory<typeof PopoverHeader> = (args) => {
return <PopoverHeader {...args}>PopoverHeader</PopoverHeader>;
};
export const DefaultStory = Template.bind({});
DefaultStory.storyName = 'Default';
export const Children: ComponentStory<typeof PopoverHeader> = (args) => (
<PopoverHeader {...args} />
);
Children.args = {
children: 'PopoverHeader Title',
};
export const OnBack: ComponentStory<typeof PopoverHeader> = (args) => (
<PopoverHeader {...args}>OnBack Demo</PopoverHeader>
);
export const OnClose: ComponentStory<typeof PopoverHeader> = (args) => (
<PopoverHeader {...args}>OnClose Demo</PopoverHeader>
);
export const StartAccessory: ComponentStory<typeof PopoverHeader> = (args) => (
<PopoverHeader
startAccessory={<Button size={BUTTON_SIZES.SM}>Demo</Button>}
{...args}
>
StartAccessory
</PopoverHeader>
);
export const EndAccessory: ComponentStory<typeof PopoverHeader> = (args) => (
<PopoverHeader
endAccessory={<Button size={BUTTON_SIZES.SM}>Demo</Button>}
{...args}
>
EndAccessory
</PopoverHeader>
);

View File

@ -0,0 +1,61 @@
/* eslint-disable jest/require-top-level-describe */
import { render, fireEvent } from '@testing-library/react';
import React from 'react';
import { PopoverHeader } from './popover-header';
describe('PopoverHeader', () => {
it('should render PopoverHeader correctly', () => {
const { getByTestId, container } = render(
<PopoverHeader data-testid="popover-header">
Popover Header
</PopoverHeader>,
);
expect(getByTestId('popover-header')).toHaveClass('mm-popover-header');
expect(container).toMatchSnapshot();
});
it('should render popover header title', () => {
const { getByText } = render(
<PopoverHeader data-testid="popover-header">
Popover Header Test
</PopoverHeader>,
);
expect(getByText('Popover Header Test')).toBeDefined();
});
it('should render popover header back button', () => {
const onBackTest = jest.fn();
const { getByTestId } = render(
<PopoverHeader
data-testid="popover"
onBack={onBackTest}
backButtonProps={{ 'data-testid': 'back' }}
>
Popover
</PopoverHeader>,
);
const backButton = getByTestId('back');
fireEvent.click(backButton);
expect(onBackTest).toHaveBeenCalled();
});
it('should render popover header close button', () => {
const onCloseTest = jest.fn();
const { getByTestId } = render(
<PopoverHeader
data-testid="popover"
onClose={onCloseTest}
closeButtonProps={{ 'data-testid': 'close' }}
>
Popover
</PopoverHeader>,
);
const closeButton = getByTestId('close');
fireEvent.click(closeButton);
expect(onCloseTest).toHaveBeenCalled();
});
});

View File

@ -0,0 +1,61 @@
import React from 'react';
import classnames from 'classnames';
import { HeaderBase, Text, ButtonIcon, ButtonIconSize, IconName } from '..';
import {
TextVariant,
TextAlign,
} from '../../../helpers/constants/design-system';
import { useI18nContext } from '../../../hooks/useI18nContext';
import { PopoverHeaderProps } from '.';
export const PopoverHeader: React.FC<PopoverHeaderProps> = ({
children,
className = '',
startAccessory,
endAccessory,
onClose,
closeButtonProps,
onBack,
backButtonProps,
...props
}) => {
const t = useI18nContext();
return (
<HeaderBase
className={classnames('mm-popover-header', className)}
startAccessory={
startAccessory ||
(onBack && (
<ButtonIcon
iconName={IconName.ArrowLeft}
ariaLabel={t('back')}
size={ButtonIconSize.Sm}
onClick={onBack}
{...backButtonProps}
/>
))
}
endAccessory={
endAccessory ||
(onClose && (
<ButtonIcon
iconName={IconName.Close}
ariaLabel={t('close')}
size={ButtonIconSize.Sm}
onClick={onClose}
{...closeButtonProps}
/>
))
}
{...props}
>
{typeof children === 'string' ? (
<Text variant={TextVariant.headingSm} textAlign={TextAlign.Center}>
{children}
</Text>
) : (
children
)}
</HeaderBase>
);
};

View File

@ -0,0 +1,42 @@
import React from 'react';
import type { ButtonIconProps } from '../button-icon/button-icon.types';
import type { HeaderBaseProps } from '../header-base';
export interface PopoverHeaderProps extends HeaderBaseProps {
/**
* The contents within the PopoverHeader positioned middle (popular for title use case)
*/
children?: React.ReactNode;
/**
* Additional classNames to be added to the Popover component
*/
className?: string;
/**
* The onClick handler for the back `ButtonIcon`
* When passed this will allow for the back `ButtonIcon` to show
*/
onBack?: () => void;
/**
* The props to pass to the back `ButtonIcon`
*/
backButtonProps?: ButtonIconProps;
/**
* The start (left) content area of PopoverHeader
* Default to have the back `ButtonIcon` when `onBack` is passed, but passing a `startAccessory` will override this
*/
startAccessory?: React.ReactNode;
/**
* The onClick handler for the close `ButtonIcon`
* When passed this will allow for the close `ButtonIcon` to show
*/
onClose?: () => void;
/**
* The props to pass to the close `ButtonIcon`
*/
closeButtonProps?: ButtonIconProps;
/**
* The end (right) content area of PopoverHeader
* Default to have the close `ButtonIcon` when `onClose` is passed, but passing a `endAccessory` will override this
*/
endAccessory?: React.ReactNode;
}