Skip to content

Commit a598741

Browse files
committed
feat: Add Tabs support css-in-js and custom animate
#Close #11
1 parent 9119657 commit a598741

File tree

1 file changed

+75
-26
lines changed

1 file changed

+75
-26
lines changed

src/Tabs/index.tsx

Lines changed: 75 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,26 @@ export interface DataProps {
2727
* Custom set render `Tab Title` method.
2828
*/
2929
renderTitle?: (title?: string) => React.ReactNode;
30+
/**
31+
* If true, will add animate to tabs in out.
32+
*/
33+
useAnimate?: boolean;
34+
/**
35+
* Set tabs animate mode.
36+
*/
37+
animateMode?: "in" | "out" | "in-out";
38+
/**
39+
* Set tabs animate speed.
40+
*/
41+
animateSpeed?: number;
42+
/**
43+
* Set tab animate enter style.
44+
*/
45+
animateEnterStyle?: React.CSSProperties;
46+
/**
47+
* Set tab animate leave style.
48+
*/
49+
animateLeaveStyle?: React.CSSProperties;
3050
}
3151

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

3858
export class Tabs extends React.Component<TabsProps, TabsState> {
3959
static defaultProps: TabsProps = {
40-
renderTitle: (title: string) => title
60+
renderTitle: (title: string) => title,
61+
useAnimate: true,
62+
animateMode: "in",
63+
animateSpeed: 500,
64+
animateEnterStyle: {
65+
transform: "translateX(0)",
66+
opacity: 1
67+
},
68+
animateLeaveStyle: {
69+
transform: "translateX(100%)",
70+
opacity: 0
71+
}
4172
};
4273

4374
state: TabsState = {
@@ -65,53 +96,65 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
6596
children,
6697
tabStyle,
6798
renderTitle,
99+
useAnimate,
100+
animateMode,
101+
animateSpeed,
102+
animateEnterStyle,
103+
animateLeaveStyle,
104+
className,
105+
style,
68106
...attributes
69107
} = this.props;
70108
const { theme } = this.context;
71109
const { tabFocusIndex } = this.state;
72-
const styles = getStyles(this);
73110

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

117+
const inlineStyles = getStyles(this);
118+
const styles = theme.prepareStyles({
119+
className: "tabs",
120+
styles: inlineStyles
121+
});
122+
123+
const normalRender = (
124+
<div key={`${tabFocusIndex}`} {...styles.tabStyle}>
125+
{currTab}
126+
</div>
127+
);
128+
80129
return (
81130
<div
82131
{...attributes}
83-
style={styles.root}
132+
style={styles.root.style}
133+
className={styles.root.className}
84134
>
85-
<div style={styles.titles}>
135+
<div {...styles.titles}>
86136
{tabs && tabs.map((tab, index) => (
87137
<span
88-
style={index === tabFocusIndex ? {
89-
...styles.title,
90-
...styles.titleFocus
91-
} : styles.title}
138+
{...(index === tabFocusIndex ? styles.titleFocus : styles.title)}
92139
key={`${index}`}
93140
onClick={() => this.setState({ tabFocusIndex: index })}
94141
>
95142
{renderTitle(tab.props.title || `Tabs Items ${index + 1}`)}
96143
</span>
97144
))}
98145
</div>
99-
<CustomAnimate
100-
leaveStyle={{
101-
transform: "translateX(100%)",
102-
opacity: 1
103-
}}
104-
enterStyle={{
105-
transform: "translateX(0)",
106-
opacity: 1
107-
}}
108-
wrapperStyle={{ width: "100%", height: "100%" }}
109-
appearAnimate={false}
110-
>
111-
<div key={`${tabFocusIndex}`} style={styles.tabStyle}>
112-
{currTab}
113-
</div>
114-
</CustomAnimate>
146+
{useAnimate ? (
147+
<CustomAnimate
148+
mode={animateMode}
149+
speed={animateSpeed}
150+
enterStyle={animateEnterStyle}
151+
leaveStyle={animateLeaveStyle}
152+
wrapperStyle={{ width: "100%", height: "100%" }}
153+
appearAnimate={false}
154+
>
155+
{normalRender}
156+
</CustomAnimate>
157+
) : normalRender}
115158
</div>
116159
);
117160
}
@@ -156,12 +199,18 @@ function getStyles(Tabs: Tabs): {
156199
fontWeight: "lighter",
157200
cursor: "pointer",
158201
fontSize: 18,
159-
padding: 4,
160-
marginRight: 4,
202+
padding: "4px 12px",
161203
transition: "all .25s",
162204
...tabTitleStyle
163205
}),
164206
titleFocus: prefixStyle({
207+
color: theme.baseHigh,
208+
fontWeight: "lighter",
209+
cursor: "pointer",
210+
fontSize: 18,
211+
padding: "4px 12px",
212+
transition: "all .25s",
213+
...tabTitleStyle,
165214
borderBottom: `2px solid ${theme.accent}`,
166215
...tabTitleFocusStyle
167216
}),

0 commit comments

Comments
 (0)