Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/react-component/tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
zombieJ committed Aug 7, 2022
2 parents 429cf76 + 8291d0f commit 9e015ae
Show file tree
Hide file tree
Showing 14 changed files with 261 additions and 140 deletions.
17 changes: 11 additions & 6 deletions assets/panels.less
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@
&-holder {
flex: auto;
}
position: relative;

display: flex;
// display: flex;
width: 100%;

&-animated {
transition: margin 0.3s;
}
// &-animated {
// transition: margin 0.3s;
// }
}

&-tabpane {
width: 100%;
flex: none;
// flex: none;
// width: 100%;

&-hidden {
display: none;
}
}
}
3 changes: 3 additions & 0 deletions docs/demo/animated.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## animated

<code src="../examples/animated.tsx">
32 changes: 32 additions & 0 deletions docs/examples/animated.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@duration: 0.3s;

.switch {
&-appear,
&-enter {
transition: none;

&-start {
opacity: 0;
}

&-active {
opacity: 1;
transition: all @duration;
}
}

&-leave {
position: absolute;
transition: none;
inset: 0;

&-start {
opacity: 1;
}

&-active {
opacity: 0;
transition: all @duration;
}
}
}
50 changes: 50 additions & 0 deletions docs/examples/animated.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import Tabs from 'rc-tabs';
import type { CSSMotionProps } from 'rc-motion';
import '../../assets/index.less';
import './animated.less';

const motion: CSSMotionProps = {
motionName: 'switch',
motionAppear: false,
motionEnter: true,
motionLeave: true,
};

export default () => (
<React.StrictMode>
<Tabs
animated={{
tabPaneMotion: motion,
}}
items={[
{
label: 'Light',
key: 'light',
children: 'Light!',
style: {
height: 200,
background: 'rgba(255, 0, 0, 0.05)',
},
},
{
label: 'Bamboo',
key: 'bamboo',
children: 'Bamboo!',
style: {
height: 100,
background: 'rgba(0, 255, 0, 0.05)',
},
},
{
label: 'Cute',
key: 'cute',
children: 'Cute!',
style: {
background: 'rgba(0, 0, 255, 0.05)',
},
},
]}
/>
</React.StrictMode>
);
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = {
setupFiles: ['./tests/setup.js'],
snapshotSerializers: [require.resolve('enzyme-to-json/serializer')],
setupFilesAfterEnv: ['<rootDir>/tests/setupFilesAfterEnv.js'],
};
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
"prepublishOnly": "npm run lint && npm run test && npm run compile && np --yolo --no-publish"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^12.0.0",
"@types/classnames": "^2.2.10",
"@types/enzyme": "^3.10.5",
"@types/jest": "^25.2.3",
Expand Down Expand Up @@ -78,6 +80,7 @@
"classnames": "2.x",
"rc-dropdown": "~4.0.0",
"rc-menu": "~9.6.0",
"rc-motion": "^2.6.2",
"rc-resize-observer": "^1.0.0",
"rc-util": "^5.5.0"
},
Expand Down
71 changes: 22 additions & 49 deletions src/TabPanelList/TabPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,54 +20,27 @@ export interface TabPaneProps {
destroyInactiveTabPane?: boolean;
}

export default function TabPane({
prefixCls,
forceRender,
className,
style,
id,
active,
animated,
destroyInactiveTabPane,
tabKey,
children,
}: TabPaneProps) {
const [visited, setVisited] = React.useState(forceRender);
const TabPane = React.forwardRef<HTMLDivElement, TabPaneProps>(
({ prefixCls, className, style, id, active, tabKey, children }, ref) => {
return (
<div
id={id && `${id}-panel-${tabKey}`}
role="tabpanel"
tabIndex={active ? 0 : -1}
aria-labelledby={id && `${id}-tab-${tabKey}`}
aria-hidden={!active}
style={style}
className={classNames(prefixCls, active && `${prefixCls}-active`, className)}
ref={ref}
>
{children}
</div>
);
},
);

React.useEffect(() => {
if (active) {
setVisited(true);
} else if (destroyInactiveTabPane) {
setVisited(false);
}
}, [active, destroyInactiveTabPane]);

const mergedStyle: React.CSSProperties = {};
if (!active) {
if (animated) {
mergedStyle.visibility = 'hidden';
mergedStyle.height = 0;
mergedStyle.overflowY = 'hidden';
} else {
mergedStyle.display = 'none';
}
}

return (
<div
id={id && `${id}-panel-${tabKey}`}
role="tabpanel"
tabIndex={active ? 0 : -1}
aria-labelledby={id && `${id}-tab-${tabKey}`}
aria-hidden={!active}
style={{ ...mergedStyle, ...style }}
className={classNames(
`${prefixCls}-tabpane`,
active && `${prefixCls}-tabpane-active`,
className,
)}
>
{(active || visited || forceRender) && children}
</div>
);
if (process.env.NODE_ENV !== 'production') {
TabPane.displayName = 'TabPane';
}

export default TabPane;
57 changes: 37 additions & 20 deletions src/TabPanelList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import * as React from 'react';
import classNames from 'classnames';
import CSSMotion from 'rc-motion';
import TabContext from '../TabContext';
import type { TabPosition, AnimatedConfig } from '../interface';
import TabPane from './TabPane';

export interface TabPanelListProps {
activeKey: string;
id: string;
rtl: boolean;
animated?: AnimatedConfig;
tabPosition?: TabPosition;
destroyInactiveTabPane?: boolean;
Expand All @@ -18,38 +18,55 @@ export default function TabPanelList({
activeKey,
animated,
tabPosition,
rtl,
destroyInactiveTabPane,
}: TabPanelListProps) {
const { prefixCls, tabs } = React.useContext(TabContext);
const tabPaneAnimated = animated.tabPane;

const activeIndex = tabs.findIndex(tab => tab.key === activeKey);
const tabPanePrefixCls = `${prefixCls}-tabpane`;

return (
<div className={classNames(`${prefixCls}-content-holder`)}>
<div
className={classNames(`${prefixCls}-content`, `${prefixCls}-content-${tabPosition}`, {
[`${prefixCls}-content-animated`]: tabPaneAnimated,
})}
style={
activeIndex && tabPaneAnimated
? { [rtl ? 'marginRight' : 'marginLeft']: `-${activeIndex}00%` }
: null
}
>
{tabs.map(tab => (
<TabPane
{...tab}
prefixCls={prefixCls}
id={id}
tabKey={tab.key}
animated={tabPaneAnimated}
active={tab.key === activeKey}
destroyInactiveTabPane={destroyInactiveTabPane}
key={tab.key}
/>
))}
{tabs.map(
({ key, forceRender, style: paneStyle, className: paneClassName, ...restTabProps }) => {
const active = key === activeKey;

return (
<CSSMotion
key={key}
visible={active}
forceRender={forceRender}
removeOnLeave={!!destroyInactiveTabPane}
leavedClassName={`${tabPanePrefixCls}-hidden`}
{...animated.tabPaneMotion}
>
{({ style: motionStyle, className: motionClassName }, ref) => {
return (
<TabPane
{...restTabProps}
prefixCls={tabPanePrefixCls}
id={id}
tabKey={key}
animated={tabPaneAnimated}
active={active}
style={{
...paneStyle,
...motionStyle,
}}
className={classNames(paneClassName, motionClassName)}
ref={ref}
/>
);
}}
</CSSMotion>
);
},
)}
</div>
</div>
);
Expand Down
25 changes: 3 additions & 22 deletions src/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {
} from './interface';
import TabContext from './TabContext';
import TabNavListWrapper from './TabNavList/Wrapper';
import useAnimateConfig from './hooks/useAnimateConfig';

/**
* Should added antd:
Expand Down Expand Up @@ -79,10 +80,7 @@ function Tabs(
activeKey,
defaultActiveKey,
editable,
animated = {
inkBar: true,
tabPane: false,
},
animated,
tabPosition = 'top',
tabBarGutter,
tabBarStyle,
Expand All @@ -107,24 +105,7 @@ function Tabs(
);
const rtl = direction === 'rtl';

let mergedAnimated: AnimatedConfig | false;
if (animated === false) {
mergedAnimated = {
inkBar: false,
tabPane: false,
};
} else if (animated === true) {
mergedAnimated = {
inkBar: true,
tabPane: true,
};
} else {
mergedAnimated = {
inkBar: true,
tabPane: false,
...(typeof animated === 'object' ? animated : {}),
};
}
const mergedAnimated = useAnimateConfig(animated);

// ======================== Mobile ========================
const [mobile, setMobile] = useState(false);
Expand Down
Loading

0 comments on commit 9e015ae

Please sign in to comment.