Last active
July 3, 2019 08:44
-
-
Save DubiousS/4b3aeb43c5ef9bbca2d686ca0ba2c7ff to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as React from 'react'; | |
| export type ITabIndex = number | string; | |
| export interface ITabsContext { | |
| selectedIndex: ITabIndex; | |
| selectTab(index: ITabIndex): void; | |
| } | |
| export const { Provider, Consumer } = React.createContext<ITabsContext>({ | |
| selectedIndex: 0, | |
| selectTab: () => undefined, | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import cn from 'classnames'; | |
| import * as React from 'react'; | |
| import { Consumer, Provider } from 'contexts/tab-context'; | |
| import styles from './TabsStyles.scss'; | |
| import { ITabIndex, ITabsContext } from 'contexts/tab-context'; | |
| interface ITabsProps { | |
| children: React.ReactNode; | |
| initalIndex?: ITabIndex; | |
| } | |
| interface IPanelProps { | |
| index: number; | |
| enableReinitialize?: boolean; | |
| hidden?: boolean; | |
| children: React.ReactNode; | |
| className?: string; | |
| } | |
| interface IListProps { | |
| children: React.ReactNode; | |
| className?: string; | |
| } | |
| interface ITabProps { | |
| index: number; | |
| className?: string; | |
| activeClassName?: string; | |
| hidden?: boolean; | |
| disabledClassName?: string; | |
| disabled?: boolean; | |
| children: React.ReactNode; | |
| } | |
| interface ITabsState { | |
| selectedTab: ITabIndex; | |
| } | |
| class TabsComponent extends React.Component<ITabsProps, ITabsState> { | |
| constructor(props: ITabsProps) { | |
| super(props); | |
| this.state = { | |
| selectedTab: this.props.initalIndex, | |
| }; | |
| } | |
| public static defaultProps = { | |
| initalIndex: 0, | |
| }; | |
| public static Tab: React.FC<ITabProps> = ({ | |
| children, | |
| index, | |
| activeClassName, | |
| disabledClassName, | |
| disabled, | |
| hidden, | |
| className, | |
| }): React.ReactElement<ITabProps> => ( | |
| <Consumer> | |
| {({ selectedIndex, selectTab }: ITabsContext) => { | |
| const isActive = selectedIndex === index; | |
| return !hidden && ( | |
| <ul | |
| className={cn(styles.tabsTab, { | |
| [className]: className, | |
| [activeClassName]: !disabled && isActive, | |
| [disabledClassName]: disabled, | |
| [styles.tabsTabActive]: !disabled && isActive, | |
| [styles.tabsTabDisabled]: disabled, | |
| })} | |
| onClick={() => !disabled && selectTab(index)} | |
| > | |
| {children} | |
| </ul> | |
| ); | |
| }} | |
| </Consumer> | |
| ) | |
| public static List: React.FC<IListProps> = ({ | |
| children, | |
| className, | |
| }): React.ReactElement<IListProps> => ( | |
| <li | |
| className={cn(styles.tabsList, { | |
| [className]: className, | |
| })} | |
| > | |
| {children} | |
| </li> | |
| ) | |
| public static Panel: React.FC<IPanelProps> = ({ | |
| index, | |
| children, | |
| className, | |
| enableReinitialize, | |
| hidden, | |
| }): React.ReactElement<ITabsState> => ( | |
| <Consumer> | |
| {({ selectedIndex }: ITabsContext) => { | |
| const isActive = index === selectedIndex && !hidden; | |
| return !hidden && !enableReinitialize | |
| ? ( | |
| <span | |
| className={cn({ | |
| [className]: className, | |
| [styles.tabsPanelHidden]: !isActive, | |
| })} | |
| > | |
| {children} | |
| </span> | |
| ) | |
| : isActive && ( | |
| <span | |
| className={cn({ | |
| [className]: className, | |
| })} | |
| > | |
| {children} | |
| </span> | |
| ); | |
| }} | |
| </Consumer> | |
| ) | |
| private selectTab = (index: ITabIndex) => { | |
| this.setState({ | |
| selectedTab: index, | |
| }); | |
| } | |
| public render(): React.ReactNode { | |
| return ( | |
| <Provider | |
| value={{ | |
| selectedIndex: this.state.selectedTab, | |
| selectTab: this.selectTab, | |
| }} | |
| > | |
| {this.props.children} | |
| </Provider> | |
| ); | |
| } | |
| } | |
| TabsComponent.List.displayName = 'TabList'; | |
| TabsComponent.Tab.displayName = 'Tab'; | |
| TabsComponent.Tab.defaultProps = { | |
| disabled: false, | |
| hidden: false, | |
| className: '', | |
| activeClassName: '', | |
| disabledClassName: '', | |
| }; | |
| TabsComponent.Panel.displayName = 'TabPanel'; | |
| TabsComponent.Panel.defaultProps = { | |
| className: '', | |
| enableReinitialize: false, | |
| hidden: false, | |
| }; | |
| export default TabsComponent; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @import '~assets/styles/variables'; | |
| @import '~assets/styles/color'; | |
| .tabs { | |
| &List { | |
| display: flex; | |
| } | |
| &PanelHidden { | |
| position: fixed; | |
| width: 0; | |
| height: 0; | |
| opacity: 0; | |
| } | |
| &Tab { | |
| display: block; | |
| border-bottom: 1px solid transparent; | |
| transition: $defaultAnimationTime; | |
| padding: 5px; | |
| cursor: pointer; | |
| &Active { | |
| border-bottom: 1px solid $two; | |
| } | |
| &Disabled { | |
| opacity: 0.8; | |
| cursor: auto; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment