Add ripple for Tabs. Fixes #377

old
Javi Velasco 2017-01-21 13:03:38 +01:00
parent 52f6c4adab
commit 792f8acc42
6 changed files with 79 additions and 61 deletions

View File

@ -3,70 +3,80 @@ import classnames from 'classnames';
import { FontIcon } from '../font_icon';
import { themr } from 'react-css-themr';
import { TABS } from '../identifiers.js';
import rippleFactory from '../ripple/Ripple.js';
class Tab extends Component {
static propTypes = {
active: PropTypes.bool,
activeClassName: PropTypes.string,
className: PropTypes.string,
disabled: PropTypes.bool,
hidden: PropTypes.bool,
icon: PropTypes.node,
index: PropTypes.number,
label: PropTypes.node,
onActive: PropTypes.func,
onClick: PropTypes.func,
theme: PropTypes.shape({
active: PropTypes.string,
disabled: PropTypes.string,
hidden: PropTypes.string,
label: PropTypes.string,
withIcon: PropTypes.string,
withText: PropTypes.string
})
};
const factory = (ripple) => {
class Tab extends Component {
static propTypes = {
active: PropTypes.bool,
activeClassName: PropTypes.string,
children: PropTypes.node,
className: PropTypes.string,
disabled: PropTypes.bool,
hidden: PropTypes.bool,
icon: PropTypes.node,
index: PropTypes.number,
label: PropTypes.node,
onActive: PropTypes.func,
onClick: PropTypes.func,
theme: PropTypes.shape({
active: PropTypes.string,
disabled: PropTypes.string,
hidden: PropTypes.string,
label: PropTypes.string,
rippleWrapper: PropTypes.string,
withIcon: PropTypes.string,
withText: PropTypes.string
})
};
static defaultProps = {
active: false,
className: '',
disabled: false,
hidden: false
};
static defaultProps = {
active: false,
className: '',
disabled: false,
hidden: false
};
componentDidUpdate (prevProps) {
if (!prevProps.active && this.props.active && this.props.onActive) {
this.props.onActive();
componentDidUpdate (prevProps) {
if (!prevProps.active && this.props.active && this.props.onActive) {
this.props.onActive();
}
}
handleClick = (event) => {
if (!this.props.disabled && this.props.onClick) {
this.props.onClick(event, this.props.index);
}
};
render () {
const {
index, onActive, // eslint-disable-line
active, activeClassName, children, className, disabled, hidden, label, icon, theme, ...other
} = this.props;
const _className = classnames(theme.label, {
[theme.active]: active,
[theme.hidden]: hidden,
[theme.withText]: label,
[theme.withIcon]: icon,
[theme.disabled]: disabled,
[activeClassName]: active
}, className);
return (
<label {...other} data-react-toolbox='tab' className={_className} onClick={this.handleClick}>
{icon && <FontIcon className={theme.icon} value={icon}/>}
{label}
{children}
</label>
);
}
}
handleClick = (event) => {
if (!this.props.disabled && this.props.onClick) {
this.props.onClick(event, this.props.index);
}
};
render () {
const {
index, onActive, // eslint-disable-line
active, activeClassName, className, disabled, hidden, label, icon, theme, ...other
} = this.props;
const _className = classnames(theme.label, {
[theme.active]: active,
[theme.hidden]: hidden,
[theme.withText]: label,
[theme.withIcon]: icon,
[theme.disabled]: disabled,
[activeClassName]: active
}, className);
return (
<label {...other} data-react-toolbox='tab' className={_className} onClick={this.handleClick}>
{icon && <FontIcon className={theme.icon} value={icon}/>}
{label}
</label>
);
}
}
return ripple(Tab);
};
const Tab = factory(rippleFactory({ centered: false }));
export default themr(TABS)(Tab);
export { factory as tabFactory };
export { Tab };

View File

@ -137,6 +137,7 @@ const factory = (Tab, TabContent, FontIcon) => {
renderHeaders (headers) {
return headers.map((item, idx) => {
return React.cloneElement(item, {
children: null,
key: idx,
index: idx,
theme: this.props.theme,

View File

@ -2,13 +2,14 @@ import { themr } from 'react-css-themr';
import { TABS } from '../identifiers.js';
import { tabsFactory } from './Tabs.js';
import { TabContent } from './TabContent.js';
import { Tab } from './Tab.js';
import { tabFactory } from './Tab.js';
import themedRippleFactory from '../ripple';
import FontIcon from '../font_icon/FontIcon.js';
import theme from './theme.css';
const applyTheme = (Component) => themr(TABS, theme)(Component);
const ThemedTabContent = applyTheme(TabContent);
const ThemedTab = applyTheme(Tab);
const ThemedTab = applyTheme(tabFactory(themedRippleFactory({ centered: false })));
const ThemedTabs = applyTheme(tabsFactory(ThemedTab, ThemedTabContent, FontIcon));
export { ThemedTab as Tab };

View File

@ -116,3 +116,4 @@ It is required to provide either a label or an icon (or both).
| `disabled` | Added to the navigation tab element in case it's disabled.|
| `hidden` | Added to the navigation tab element in case it's hidden.|
| `label` | Added to the navigation tab element in case it's active.|
| `rippleWrapper` | Used for the ripple wrapper element.|

View File

@ -43,11 +43,16 @@
font-weight: var(--font-weight-semi-bold);
line-height: 1;
padding: var(--tab-label-v-padding) var(--tab-label-h-padding);
position: relative;
text-transform: uppercase;
transition-duration: var(--animation-duration);
transition-property: box-shadow, color;
transition-timing-function: var(--animation-curve-default);
& > .rippleWrapper {
overflow: hidden;
}
&.active {
color: var(--tab-text-color);
}

View File

@ -30,7 +30,7 @@ class TabsTest extends React.Component {
<h5>Tabs</h5>
<p>This tabs can be disabled or hidden</p>
<Tabs disableAnimatedBottomBorder index={this.state.index} onChange={this.handleTabChange}>
<Tab label='Primary'><small>Primary content</small></Tab>
<Tab ripple={false} label='Primary'><small>Primary content (no ripple)</small></Tab>
<Tab label='Secondary' onActive={this.handleActive}><small>Secondary content</small></Tab>
<Tab label='Third' disabled><small>Disabled content</small></Tab>
<Tab label='Fourth' hidden><small>Fourth content hidden</small></Tab>