mdc-react
Version:
Material Components for the web implemented in React
75 lines (59 loc) • 2.49 kB
JSX
import { forwardRef, useContext, useImperativeHandle, useRef } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { useUpdatedSync } from '../hooks';
import { indicatorCssClasses as cssClasses } from './constants';
import TabContext from './context';
const TabIndicator = forwardRef(({
icon,
active = false,
fade = false,
underline = !icon,
...props
}, ref) => {
const { previousTab } = useContext(TabContext);
const rootRef = useRef();
const contentRef = useRef();
useImperativeHandle(ref, () => rootRef.current);
useUpdatedSync(() => {
if (fade || !active || !previousTab) return;
const activeIndicator = rootRef.current;
const previousIndicator = previousTab.querySelector('.mdc-tab-indicator');
const previousIndicatorClientRect = previousIndicator.getBoundingClientRect();
const activeIndicatorClientRect = activeIndicator.getBoundingClientRect();
const xPosition = previousIndicatorClientRect.left - activeIndicatorClientRect.left;
const widthDelta = previousIndicatorClientRect.width / activeIndicatorClientRect.width;
rootRef.current.classList.add(cssClasses.NO_TRANSITION);
contentRef.current.style.transform = `translateX(${xPosition}px) scaleX(${widthDelta})`;
// Force repaint before updating classes and transform to ensure the transform properly takes effect
contentRef.current.getBoundingClientRect();
rootRef.current.classList.remove(cssClasses.NO_TRANSITION);
contentRef.current.style.transform = '';
}, [fade, active]);
const rootClassNames = classnames(cssClasses.ROOT, {
[cssClasses.ACTIVE]: active,
[cssClasses.FADE]: fade
});
const contentClassNames = classnames(cssClasses.CONTENT, {
[cssClasses.CONTENT_ICON]: icon,
[cssClasses.CONTENT_UNDERLINE]: underline
});
return (
<span ref={rootRef} className={rootClassNames} {...props}>
<span
ref={contentRef}
className={contentClassNames}
>
{icon}
</span>
</span>
);
});
TabIndicator.displayName = 'MDCTabIndicator';
TabIndicator.propTypes = {
icon: PropTypes.node,
active: PropTypes.bool,
fade: PropTypes.bool,
underline: PropTypes.bool
};
export default TabIndicator;