vcc-ui
Version:
VCC UI is a collection of React UI Components that can be used for developing front-end applications at Volvo Car Corporation.
128 lines (115 loc) • 2.97 kB
JavaScript
import React, { useContext, useEffect, useRef } from "react";
import PropTypes from "prop-types";
import { useFela } from "react-fela";
import { Click } from "../click";
import { LineTransitionContext } from "../tab-nav";
import { getThemeStyle } from "../../get-theme-style";
const styles = ({
isActive,
reverseOut,
hasLineTransition,
theme: {
colors: { grey1, primary, white }
}
}) => ({
display: "inline-flex",
alignItems: "center",
color: reverseOut ? white : grey1,
fontSize: 15,
height: 55,
textAlign: "left",
fontWeight: 200,
letterSpacing: 0.3,
margin: "0 20px 0 0",
backgroundColor: reverseOut ? grey1 : "none",
":last-child": {
margin: 0
},
transition: "color 200ms ease-out",
":hover": {
color: reverseOut ? white : primary
},
":focus": {
outline: "none",
color: reverseOut ? white : primary
},
extend: [
{
condition: isActive,
style: {
color: reverseOut ? white : primary
}
},
{
condition: !hasLineTransition,
style: {
borderBottom: "3px solid transparent",
":hover": {
borderBottom: `3px solid ${reverseOut ? white : primary}`
},
":focus": {
borderBottom: `3px solid ${reverseOut ? white : primary}`
}
}
},
{
condition: !hasLineTransition && isActive,
style: {
borderBottom: `3px solid ${reverseOut ? white : primary}`
}
}
]
});
export function TabNavItem({ children, index, isActive, variant, ...props }) {
const { theme } = useFela();
const reverseOut = variant === "dark";
const { updateDimensions } = useContext(LineTransitionContext);
const ref = useRef();
useEffect(() => {
if (updateDimensions && ref.current) {
const { width } = ref.current
? ref.current.getBoundingClientRect()
: { width: 0 };
const x = ref.current ? ref.current.offsetLeft : 0;
updateDimensions(index, { width, x });
}
}, []);
const styleProps = {
isActive,
reverseOut,
hasLineTransition: !!updateDimensions,
theme
};
if (styleProps.hasLineTransition && typeof index !== "number") {
// Index property is passed down only to direct descendants of <TabNav> and is required for line transitions to work as intended.
// If <TabNavItem>s are not direct descendants of <TabNav> an index will need to be passed down manually.
// eslint-disable-next-line no-console
console.warn(
"TabNavItem is not a direct descendant of TabNav. Please provide an index to each TabNavItem to enable line transitions."
);
return null;
}
return (
<Click
extend={{
...styles(styleProps),
...getThemeStyle("tabNavItem", theme, styleProps)
}}
{...props}
innerRef={ref}
>
{children}
</Click>
);
}
TabNavItem.propTypes = {
children: PropTypes.node,
/** Indicate if the TabNavItem is in an active state */
isActive: PropTypes.bool,
/** Dark text on light background, or vice versa */
variant: PropTypes.oneOf(["light", "dark"])
};
TabNavItem.defaultProps = {
isActive: false,
variant: "light"
};