Skip to content

Commit

Permalink
feat: Add Tabs support css-in-js and custom animate
Browse files Browse the repository at this point in the history
#Close #11
  • Loading branch information
myxvisual committed Aug 8, 2017
1 parent 9119657 commit a598741
Showing 1 changed file with 75 additions and 26 deletions.
101 changes: 75 additions & 26 deletions src/Tabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ export interface DataProps {
* Custom set render `Tab Title` method.
*/
renderTitle?: (title?: string) => React.ReactNode;
/**
* If true, will add animate to tabs in out.
*/
useAnimate?: boolean;
/**
* Set tabs animate mode.
*/
animateMode?: "in" | "out" | "in-out";
/**
* Set tabs animate speed.
*/
animateSpeed?: number;
/**
* Set tab animate enter style.
*/
animateEnterStyle?: React.CSSProperties;
/**
* Set tab animate leave style.
*/
animateLeaveStyle?: React.CSSProperties;
}

export interface TabsProps extends DataProps, React.HTMLAttributes<HTMLDivElement> {}
Expand All @@ -37,7 +57,18 @@ export interface TabsState {

export class Tabs extends React.Component<TabsProps, TabsState> {
static defaultProps: TabsProps = {
renderTitle: (title: string) => title
renderTitle: (title: string) => title,
useAnimate: true,
animateMode: "in",
animateSpeed: 500,
animateEnterStyle: {
transform: "translateX(0)",
opacity: 1
},
animateLeaveStyle: {
transform: "translateX(100%)",
opacity: 0
}
};

state: TabsState = {
Expand Down Expand Up @@ -65,53 +96,65 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
children,
tabStyle,
renderTitle,
useAnimate,
animateMode,
animateSpeed,
animateEnterStyle,
animateLeaveStyle,
className,
style,
...attributes
} = this.props;
const { theme } = this.context;
const { tabFocusIndex } = this.state;
const styles = getStyles(this);

const childrenArray = React.Children.toArray(children);
const isAvailableArray = childrenArray && childrenArray.length > 0;
const tabs: Tab[] | false = isAvailableArray && childrenArray.filter((child: any) => child.type === Tab) as any;
const currTab: Tab | false = tabs && tabs[tabFocusIndex] as any;
const tabTitle = currTab && currTab.props.title;

const inlineStyles = getStyles(this);
const styles = theme.prepareStyles({
className: "tabs",
styles: inlineStyles
});

const normalRender = (
<div key={`${tabFocusIndex}`} {...styles.tabStyle}>
{currTab}
</div>
);

return (
<div
{...attributes}
style={styles.root}
style={styles.root.style}
className={styles.root.className}
>
<div style={styles.titles}>
<div {...styles.titles}>
{tabs && tabs.map((tab, index) => (
<span
style={index === tabFocusIndex ? {
...styles.title,
...styles.titleFocus
} : styles.title}
{...(index === tabFocusIndex ? styles.titleFocus : styles.title)}
key={`${index}`}
onClick={() => this.setState({ tabFocusIndex: index })}
>
{renderTitle(tab.props.title || `Tabs Items ${index + 1}`)}
</span>
))}
</div>
<CustomAnimate
leaveStyle={{
transform: "translateX(100%)",
opacity: 1
}}
enterStyle={{
transform: "translateX(0)",
opacity: 1
}}
wrapperStyle={{ width: "100%", height: "100%" }}
appearAnimate={false}
>
<div key={`${tabFocusIndex}`} style={styles.tabStyle}>
{currTab}
</div>
</CustomAnimate>
{useAnimate ? (
<CustomAnimate
mode={animateMode}
speed={animateSpeed}
enterStyle={animateEnterStyle}
leaveStyle={animateLeaveStyle}
wrapperStyle={{ width: "100%", height: "100%" }}
appearAnimate={false}
>
{normalRender}
</CustomAnimate>
) : normalRender}
</div>
);
}
Expand Down Expand Up @@ -156,12 +199,18 @@ function getStyles(Tabs: Tabs): {
fontWeight: "lighter",
cursor: "pointer",
fontSize: 18,
padding: 4,
marginRight: 4,
padding: "4px 12px",
transition: "all .25s",
...tabTitleStyle
}),
titleFocus: prefixStyle({
color: theme.baseHigh,
fontWeight: "lighter",
cursor: "pointer",
fontSize: 18,
padding: "4px 12px",
transition: "all .25s",
...tabTitleStyle,
borderBottom: `2px solid ${theme.accent}`,
...tabTitleFocusStyle
}),
Expand Down

0 comments on commit a598741

Please sign in to comment.