Add type parameter for TabNavHorizontal

The type indicates if tabs are links or buttons.
This commit is contained in:
Hannu Lyytikainen 2017-12-12 15:23:10 +02:00
parent 1a800e5fbf
commit b41c2f43c1
4 changed files with 92 additions and 17 deletions

View file

@ -22,7 +22,7 @@
}
}
.link {
.tabContent {
display: flex;
flex-direction: column;
justify-content: flex-end;
@ -51,7 +51,7 @@
}
}
.selectedLink {
.selectedTabContent {
border-bottom-color: var(--matterColorDark);
color: var(--matterColorDark);
}
@ -63,7 +63,7 @@
}
/* Dark skin */
.linkDarkSkin {
.tabContentDarkSkin {
color: var(--matterColorAnti);
&:hover {
@ -71,7 +71,7 @@
}
}
.selectedLinkDarkSkin {
.selectedTabContentDarkSkin {
border-bottom-color: var(--matterColorLight);
color: var(--matterColorLight);
}

View file

@ -1,17 +1,30 @@
import TabNavHorizontal from './TabNavHorizontal';
import { TYPE_BUTTON, TYPE_LINK } from './TabNavHorizontal';
const selfLinkProps = {
name: 'StyleguideComponent',
params: { component: 'TabNavHorizontal' },
};
export const Empty = {
export const LinkTabs = {
component: TabNavHorizontal,
props: {
tabs: [
{ text: 'Normal', linkProps: selfLinkProps },
{ text: 'Selected', linkProps: selfLinkProps, selected: true },
],
type: TYPE_LINK,
},
group: 'navigation',
};
const noop = () => {};
export const ButtonTabs = {
component: TabNavHorizontal,
props: {
tabs: [{ text: 'Normal', onClick: noop }, { text: 'Selected', onClick: noop, selected: true }],
type: TYPE_BUTTON,
},
group: 'navigation',
};

View file

@ -1,26 +1,82 @@
/**
* A horizontal tab bar.
*
* Tabs can be of links or buttons, denoted by the type param
* which accepts values 'link' and 'button'.
*
* The required tab params vary based on the main component type. For
* link tab bar linkProps is required for the tabs. For a button type
* of tab bar onClick function is required.
*
* By default the type of TabNavHorizontal is 'link'.
*/
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { NamedLink } from '../../components';
import { InlineTextButton, NamedLink } from '../../components';
import css from './TabNavHorizontal.css';
export const LIGHT_SKIN = 'light';
export const DARK_SKIN = 'dark';
const Tab = props => {
export const TYPE_LINK = 'link';
export const TYPE_BUTTON = 'button';
const { arrayOf, bool, func, node, object, oneOf, string } = PropTypes;
const ButtonTab = props => {
const { className, disabled, text, selected, onClick, isDark } = props;
const darkSkinClasses = isDark
? classNames(css.tabContentDarkSkin, {
[css.selectedTabContentDarkSkin]: selected,
[css.disabledDarkSkin]: disabled,
})
: null;
const buttonClasses = classNames(
css.tabContent,
{
[css.selectedTabContent]: selected,
[css.disabled]: disabled,
},
darkSkinClasses
);
return (
<div className={className}>
<InlineTextButton className={buttonClasses} onClick={onClick}>
{text}
</InlineTextButton>
</div>
);
};
ButtonTab.defaultProps = { className: null, disabled: false, selected: false };
ButtonTab.propTypes = {
className: string,
text: node.isRequired,
disabled: bool,
selected: bool,
onClick: func.isRequired,
isDark: bool.isRequired,
};
const LinkTab = props => {
const { className, disabled, text, selected, linkProps, isDark } = props;
const darkSkinClasses = isDark
? classNames(css.linkDarkSkin, {
[css.selectedLinkDarkSkin]: selected,
? classNames(css.tabContentDarkSkin, {
[css.selectedTabContentDarkSkin]: selected,
[css.disabledDarkSkin]: disabled,
})
: null;
const linkClasses = classNames(
css.link,
css.tabContent,
{
[css.selectedLink]: selected,
[css.selectedTabContent]: selected,
[css.disabled]: disabled,
},
darkSkinClasses
@ -35,11 +91,9 @@ const Tab = props => {
);
};
Tab.defaultProps = { className: null, disabled: false, selected: false };
LinkTab.defaultProps = { className: null, disabled: false, selected: false };
const { arrayOf, bool, node, object, oneOf, string } = PropTypes;
Tab.propTypes = {
LinkTab.propTypes = {
className: string,
text: node.isRequired,
disabled: bool,
@ -49,15 +103,20 @@ Tab.propTypes = {
};
const TabNavHorizontal = props => {
const { className, rootClassName, tabRootClassName, tabs, skin } = props;
const { className, rootClassName, tabRootClassName, tabs, skin, type } = props;
const isDark = skin === DARK_SKIN;
const isButton = type === TYPE_BUTTON;
const classes = classNames(rootClassName || css.root, { [css.darkSkin]: isDark }, className);
const tabClasses = tabRootClassName || css.tab;
return (
<nav className={classes}>
{tabs.map((tab, index) => {
const key = typeof tab.text === 'string' ? tab.text : index;
return <Tab key={key} className={tabClasses} {...tab} isDark={isDark} />;
return isButton ? (
<ButtonTab key={key} className={tabClasses} {...tab} isDark={isDark} />
) : (
<LinkTab key={key} className={tabClasses} {...tab} isDark={isDark} />
);
})}
</nav>
);
@ -69,6 +128,7 @@ TabNavHorizontal.defaultProps = {
tabRootClassName: null,
tabClassName: null,
skin: LIGHT_SKIN,
type: TYPE_LINK,
};
TabNavHorizontal.propTypes = {
@ -77,6 +137,7 @@ TabNavHorizontal.propTypes = {
tabRootClassName: string,
tabs: arrayOf(object).isRequired,
skin: oneOf([LIGHT_SKIN, DARK_SKIN]),
type: oneOf([TYPE_LINK, TYPE_BUTTON]),
};
export default TabNavHorizontal;

View file

@ -74,6 +74,7 @@ exports[`AuthenticationPageComponent matches snapshot 1`] = `
},
]
}
type="link"
/>
<ReduxForm
inProgress={false}