1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

UXMultichain: update segmented tabs (#18283)

* update tabs to functional component

* updated Tabs to use Box

* updated css for tab

* updated css on home screen

* updated snapshot

* fixed defaultkey and active key value for new keys
This commit is contained in:
Nidhi Kumari 2023-04-03 23:27:14 +05:30 committed by GitHub
parent 01057f9824
commit 0614b3db68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 138 additions and 122 deletions

View File

@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import Dropdown from '../../dropdown';
import Box from '../../box';
export const DropdownTab = (props) => {
const {
@ -17,7 +18,8 @@ export const DropdownTab = (props) => {
} = props;
return (
<li
<Box
as="li"
className={classnames('tab', className, {
'tab--active': isActive,
[activeClassName]: activeClassName && isActive,
@ -33,7 +35,7 @@ export const DropdownTab = (props) => {
selectedOption={selectedOption}
onChange={onChange}
/>
</li>
</Box>
);
};

View File

@ -7,10 +7,7 @@
-moz-transform: translateZ(0);
&__list {
display: flex;
justify-content: flex-start;
border-bottom: 1px solid var(--color-border-default);
background-color: var(--color-background-default);
position: sticky;
top: 0;
z-index: 2;

View File

@ -1,11 +1,6 @@
.tab {
button {
cursor: pointer;
padding: 8px;
min-width: 50px;
text-align: center;
display: block;
width: 100%;
background-color: unset;
font-size: unset;
color: unset;

View File

@ -1,6 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import {
BLOCK_SIZES,
DISPLAY,
TEXT_ALIGN,
} from '../../../../helpers/constants/design-system';
import Box from '../../box';
const Tab = (props) => {
const {
@ -15,7 +21,8 @@ const Tab = (props) => {
} = props;
return (
<li
<Box
as="li"
className={classnames('tab', className, {
'tab--active': isActive,
[activeClassName]: activeClassName && isActive,
@ -27,8 +34,16 @@ const Tab = (props) => {
}}
key={tabKey}
>
<button>{name}</button>
</li>
<Box
as="button"
padding={2}
textAlign={TEXT_ALIGN.CENTER}
display={DISPLAY.BLOCK}
width={BLOCK_SIZES.FULL}
>
{name}
</Box>
</Box>
);
};

View File

@ -1,93 +1,26 @@
import React, { Component } from 'react';
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import Box from '../box';
import {
BackgroundColor,
DISPLAY,
JustifyContent,
} from '../../../helpers/constants/design-system';
export default class Tabs extends Component {
static defaultProps = {
defaultActiveTabKey: null,
onTabClick: null,
tabsClassName: undefined,
subHeader: null,
const Tabs = ({
defaultActiveTabKey,
onTabClick,
children,
tabsClassName,
subHeader,
}) => {
// This ignores any 'null' child elements that are a result of a conditional
// based on a feature flag setting.
const _getValidChildren = () => {
return React.Children.toArray(children).filter(Boolean);
};
static propTypes = {
defaultActiveTabKey: PropTypes.string,
onTabClick: PropTypes.func,
children: PropTypes.node.isRequired,
tabsClassName: PropTypes.string,
subHeader: PropTypes.node,
};
state = {
activeTabIndex: Math.max(
this._findChildByKey(this.props.defaultActiveTabKey),
0,
),
};
handleTabClick(tabIndex, tabKey) {
const { onTabClick } = this.props;
const { activeTabIndex } = this.state;
if (tabIndex !== activeTabIndex) {
this.setState(
{
activeTabIndex: tabIndex,
},
() => {
if (onTabClick) {
onTabClick(tabKey);
}
},
);
}
}
renderTabs() {
const numberOfTabs = React.Children.count(this._getValidChildren());
return React.Children.map(this._getValidChildren(), (child, index) => {
const tabKey = child?.props.tabKey;
return (
child &&
React.cloneElement(child, {
onClick: (idx) => this.handleTabClick(idx, tabKey),
tabIndex: index,
isActive: numberOfTabs > 1 && index === this.state.activeTabIndex,
})
);
});
}
renderActiveTabContent() {
const children = this._getValidChildren();
const { activeTabIndex } = this.state;
if (
(Array.isArray(children) && !children[activeTabIndex]) ||
(!Array.isArray(children) && activeTabIndex !== 0)
) {
throw new Error(`Tab at index '${activeTabIndex}' does not exist`);
}
return children[activeTabIndex]
? children[activeTabIndex].props.children
: children.props.children;
}
render() {
const { tabsClassName, subHeader } = this.props;
return (
<div className="tabs">
<ul className={classnames('tabs__list', tabsClassName)}>
{this.renderTabs()}
</ul>
{subHeader}
<div className="tabs__content">{this.renderActiveTabContent()}</div>
</div>
);
}
/**
* Returns the index of the child with the given key
*
@ -95,15 +28,74 @@ export default class Tabs extends Component {
* @returns {number} the index of the child with the given name
* @private
*/
_findChildByKey(tabKey) {
return this._getValidChildren().findIndex(
(c) => c?.props.tabKey === tabKey,
);
}
const _findChildByKey = (tabKey) => {
return _getValidChildren().findIndex((c) => c?.props.tabKey === tabKey);
};
// This ignores any 'null' child elements that are a result of a conditional
// based on a feature flag setting.
_getValidChildren() {
return React.Children.toArray(this.props.children).filter(Boolean);
}
}
const [activeTabIndex, setActiveTabIndex] = useState(() =>
Math.max(_findChildByKey(defaultActiveTabKey), 0),
);
const handleTabClick = (tabIndex, tabKey) => {
if (tabIndex !== activeTabIndex) {
setActiveTabIndex(tabIndex);
onTabClick?.(tabKey);
}
};
const renderTabs = () => {
const numberOfTabs = React.Children.count(_getValidChildren());
return React.Children.map(_getValidChildren(), (child, index) => {
const tabKey = child?.props.tabKey;
return (
child &&
React.cloneElement(child, {
onClick: (idx) => handleTabClick(idx, tabKey),
tabIndex: index,
isActive: numberOfTabs > 1 && index === activeTabIndex,
})
);
});
};
const renderActiveTabContent = () => {
const validChildren = _getValidChildren();
if (
(Array.isArray(validChildren) && !validChildren[activeTabIndex]) ||
(!Array.isArray(validChildren) && activeTabIndex !== 0)
) {
throw new Error(`Tab at index '${activeTabIndex}' does not exist`);
}
return validChildren[activeTabIndex]
? validChildren[activeTabIndex].props.children
: validChildren.props.children;
};
return (
<Box className="tabs">
<Box
as="ul"
display={DISPLAY.FLEX}
justifyContent={JustifyContent.flexStart}
backgroundColor={BackgroundColor.backgroundDefault}
className={classnames('tabs__list', tabsClassName)}
gap={1}
>
{renderTabs()}
</Box>
{subHeader}
<Box className="tabs__content">{renderActiveTabContent()}</Box>
</Box>
);
};
export default Tabs;
Tabs.propTypes = {
defaultActiveTabKey: PropTypes.string,
onTabClick: PropTypes.func,
children: PropTypes.node.isRequired,
tabsClassName: PropTypes.string,
subHeader: PropTypes.node,
};

View File

@ -17,6 +17,7 @@ export default {
},
},
onTabClick: { action: 'onTabClick' },
onChange: { action: 'onChange' },
},
args: {
tabs: [
@ -42,16 +43,24 @@ export const DefaultStory = (args) => {
onTabClick={args.onTabClick}
>
{args.tabs.map((tabProps, i) => renderTab(tabProps, i, args.t))}
</Tabs>
);
};
DefaultStory.storyName = 'Default';
export const DropdownStory = (args) => {
return (
<Tabs>
<DropdownTab
options={[
{ name: 'Insight Snap', value: 'Insight Snap' },
{ name: 'Tenderly Insight', value: 'Tenderly Insight' },
]}
onChange={args.onChange}
>
This is a dropdown Tab
</DropdownTab>
</Tabs>
);
};
DefaultStory.storyName = 'Default';

View File

@ -278,35 +278,41 @@ exports[`Confirm Transaction Base should match snapshot 1`] = `
</div>
</div>
<div
class="tabs"
class="box tabs box--flex-direction-row"
>
<ul
class="tabs__list"
class="box tabs__list box--display-flex box--gap-1 box--flex-direction-row box--justify-content-flex-start box--background-color-background-default"
>
<li
class="tab confirm-page-container-content__tab tab--active"
class="box tab confirm-page-container-content__tab tab--active box--flex-direction-row"
>
<button>
<button
class="box box--padding-2 box--display-block box--flex-direction-row box--text-align-center box--width-full"
>
Details
</button>
</li>
<li
class="tab confirm-page-container-content__tab"
class="box tab confirm-page-container-content__tab box--flex-direction-row"
>
<button>
<button
class="box box--padding-2 box--display-block box--flex-direction-row box--text-align-center box--width-full"
>
Data
</button>
</li>
<li
class="tab confirm-page-container-content__tab"
class="box tab confirm-page-container-content__tab box--flex-direction-row"
>
<button>
<button
class="box box--padding-2 box--display-block box--flex-direction-row box--text-align-center box--width-full"
>
Hex
</button>
</li>
</ul>
<div
class="tabs__content"
class="box tabs__content box--flex-direction-row"
>
<div
class="confirm-page-container-content__details"

View File

@ -23,7 +23,7 @@
// TODO: fix style import order so this isn't required to override specificity of `tab` class
&__main-view &__tabs {
border: none;
box-shadow: var(--shadow-size-xs) var(--color-shadow-default);
padding: 0 16px;
}
&__main-view &__tab {
@ -39,7 +39,7 @@
}
&__main-view &__tab button {
padding: 16px 8px;
padding: 8px;
}
&__connect-status-text {