Skip to content

Instantly share code, notes, and snippets.

@pettaysergey
Created November 22, 2018 14:06
Show Gist options
  • Select an option

  • Save pettaysergey/2619c29ff41c97178c369abb69777428 to your computer and use it in GitHub Desktop.

Select an option

Save pettaysergey/2619c29ff41c97178c369abb69777428 to your computer and use it in GitHub Desktop.
Code
import * as React from 'react';
import cx from 'classnames';
import * as styles from './styles.scss';
import { utils } from '@shared/utils';
import { TabBody, ITabBodyProps } from './TabBody';
import { TabHead, ITabHeadProps } from './TabHead';
import { Tab, ITabProps } from './Tab';
interface IProps {
active?: string;
className?: string;
onTabChange?: (e: React.SyntheticEvent, id: string) => void;
}
interface IState {
active: string;
}
export class Tabs extends React.PureComponent<IProps, IState> {
public static Item = Tab;
static getDerivedStateFromProps(props: IProps, state: IState) {
if (props.active && props.active !== state.active) {
return { ...state, active: props.active };
}
return state;
}
state = { active: '' };
constructor(props) {
super(props);
this.initState();
}
private initState() {
const tabs = this.getTabs();
this.state.active = this.props.active ? this.props.active : tabs[0].props.id;
}
private getTabs() {
return utils.render.getNodeArray<ITabProps>(this.props.children, Tab);
}
private getHeader(tab: React.ReactElement<ITabProps>) {
return utils.render.getChild<ITabHeadProps>(tab, TabHead);
}
private getBody(tab: React.ReactElement<ITabProps>) {
return utils.render.getChild<ITabBodyProps>(tab, TabBody);
}
private onSetTab = (e: React.SyntheticEvent) => {
const id = e.currentTarget.id;
if (id !== this.state.active) {
this.setState({ active: id }, () => {
this.props.onTabChange && this.props.onTabChange(e, id);
});
}
};
renderHeaders(tabs: React.ReactElement<ITabProps>[]) {
return tabs.map((tab) => {
const header = this.getHeader(tab);
const isActive = tab.props.id === this.state.active;
const Wrapper = header.props.wrapper ? header.props.wrapper : 'div';
return (
<Wrapper
key={tab.props.id}
className={cx(styles.tabHead, header.props.className, isActive && header.props.activeClassName, {
[styles.tabHeadActive]: isActive,
[styles.tabHeadDisable]: tab.props.disabled,
})}
disabled={tab.props.disabled}
id={tab.props.id}
onClick={this.onSetTab}
>
{header}
</Wrapper>
);
});
}
renderBody(tabs: React.ReactElement<ITabProps>[]) {
const { active } = this.state;
const tab = tabs.find((t) => t.props.id === active);
if (tab) {
return this.getBody(tab);
}
return null;
}
render() {
const tabs = this.getTabs();
return (
<div className={cx(this.props.className)}>
<div className={styles.header}>{this.renderHeaders(tabs)}</div>
{this.renderBody(tabs)}
</div>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment