Add ripple for Tabs. Fixes #377
parent
52f6c4adab
commit
792f8acc42
|
@ -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 };
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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.|
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue