UNPKG

vcc-ui

Version:

A React library for building user interfaces at Volvo Cars

266 lines (265 loc) 7.62 kB
import _extends from "@babel/runtime/helpers/extends"; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck import PropTypes from 'prop-types'; import React, { createContext, forwardRef, useContext, useRef, useState } from 'react'; import { useTheme } from '../../styling/use-theme'; import { Block } from '../block'; import { Click } from '../click'; import { Flex } from '../flex'; import { Icon } from '../icon'; import { Inline } from '../inline'; import { KeyboardNavigationProvider, useKeyboardNavigation } from '../nav'; export const TabNavContext = /*#__PURE__*/createContext({}); const styles = { nav: _ref => { let { theme, reverseOut } = _ref; return { flexDirection: 'row', borderBottomStyle: 'solid', borderBottomWidth: 1, borderBottomColor: reverseOut ? theme.color.primitive.grey100 : theme.color.ornament.divider, backgroundColor: reverseOut ? theme.color.primitive.grey100 : theme.color.background.secondary, lineHeight: 1.3 }; }, scrollContainer: { flex: '0 1 auto', overflowY: 'hidden', overflowX: 'auto', msOverflowY: 'hidden', msOverflowX: 'auto', msOverflowStyle: 'none', '::-webkit-scrollbar': { display: 'none' } }, itemContainer: { flexDirection: 'row', padding: '0 0 0 19px', '> button:focus-visible': { outlineOffset: -2 } }, stickyLeft: _ref2 => { let { isCentered } = _ref2; return { flexShrink: 0, flexBasis: 0, flexGrow: isCentered ? 1 : 0, msFlex: '1 0 auto', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center' }; }, stickyRight: { flexShrink: 0, flexBasis: 0, flexGrow: 1, msFlex: '1 0 auto', alignItems: 'center', justifyContent: 'flex-end', flexDirection: 'row' }, border: _ref3 => { let { animatedMargin, duration, theme } = _ref3; return { width: 0, height: duration === 0 ? 0 : 3, marginRight: '0 !important', backgroundColor: theme.color.ornament.highlight, transitionProperty: `margin-${animatedMargin}, width`, transitionTimingFunction: 'ease-out', transitionDuration: duration + 'ms' }; }, backButton: _ref4 => { let { reverseOut, showBackButtonOn = [], theme } = _ref4; return { fontSize: 15, padding: '16px 10px 19px', verticalAlign: 'middle', fontWeight: 300, fontFamily: theme.fontTypes.NOVUM, whiteSpace: 'nowrap', flexShrink: '0', color: reverseOut ? theme.color.primitive.white : theme.color.foreground.primary, display: showBackButtonOn.some(size => size === 's') ? 'inline' : 'none', '> img': { marginRight: 8, transitionProperty: 'transform', transitionTimingFunction: 'ease-out', transitionDuration: '0.3s', transform: 'translate(0, 1px)' }, ':hover > img': { transform: 'translate(-5px, 1px)' }, [theme.breakpoints.onlyM]: { display: showBackButtonOn.some(size => size === 'm') ? 'inline' : 'none' }, [theme.breakpoints.fromL]: { display: showBackButtonOn.some(size => size === 'l') ? 'inline' : 'none' } }; }, backButtonText: _ref5 => { let { theme } = _ref5; return { [theme.breakpoints.onlyS]: { display: 'none' } }; } }; function BackButton(_ref6) { let { backButtonConfig = {}, showBackButtonOn, reverseOut } = _ref6; const theme = useTheme(); const { href, clickHandler, text } = backButtonConfig; const keyboardNavigationProps = useKeyboardNavigation(); const styleProps = { theme, reverseOut, showBackButtonOn }; return /*#__PURE__*/React.createElement(Click, _extends({ onClick: clickHandler ? clickHandler : () => {}, href: href }, keyboardNavigationProps, { extend: styles.backButton(styleProps) }), /*#__PURE__*/React.createElement(Icon, { type: "navigation-chevronback-12", color: reverseOut ? 'inverted' : 'action' }), /*#__PURE__*/React.createElement(Inline, { extend: styles.backButtonText }, text || '')); } function TabNavBorder() { const { borderRef, duration } = useContext(TabNavContext); const theme = useTheme(); const animatedMargin = theme.direction === 'rtl' ? 'right' : 'left'; return /*#__PURE__*/React.createElement(Block, { ref: borderRef, extend: styles.border({ animatedMargin, duration, theme }) }); } /** * @deprecated Use `<nav>` element instead. See [TabNav](https://developer.volvocars.com/design-system/web/?path=/docs/components-tabs--docs) */ export const TabNav = /*#__PURE__*/forwardRef((_ref7, ref) => { let { children, duration = 160, enableLineTransition = false, textAlign = 'center', stickyChildrenLeft = null, stickyChildrenRight = null, showBackButtonOn = ['s', 'm', 'l'], backButton: backButtonConfig = {}, 'aria-label': ariaLabel } = _ref7; const [active, setActive] = useState(false); const scrollRef = useRef(null); const borderRef = useRef(null); const theme = useTheme(); const isCentered = textAlign === 'center'; const backButtonVisible = !!(backButtonConfig.clickHandler || backButtonConfig.href); const styleProps = { theme, isCentered }; const context = { active, setActive, scrollRef, borderRef, duration: enableLineTransition ? duration : 0 }; return /*#__PURE__*/React.createElement(Flex, { as: "nav", ref: ref, extend: styles.nav(styleProps) }, /*#__PURE__*/React.createElement(KeyboardNavigationProvider, null, /*#__PURE__*/React.createElement(Flex, { extend: styles.stickyLeft(styleProps) }, backButtonVisible ? /*#__PURE__*/React.createElement(BackButton, { backButtonConfig: backButtonConfig, showBackButtonOn: showBackButtonOn }) : null, stickyChildrenLeft), /*#__PURE__*/React.createElement(TabNavContext.Provider, { value: context }, /*#__PURE__*/React.createElement(Flex, { ref: scrollRef, extend: styles.scrollContainer }, /*#__PURE__*/React.createElement(Flex, { extend: styles.itemContainer, role: "tablist", "aria-label": ariaLabel }, /*#__PURE__*/React.createElement(Flex, { extend: { paddingRight: 1 } }), children, /*#__PURE__*/React.createElement(Flex, { extend: { paddingRight: 1 } })), /*#__PURE__*/React.createElement(TabNavBorder, null))), /*#__PURE__*/React.createElement(Flex, { extend: styles.stickyRight }, stickyChildrenRight))); }); TabNav.displayName = 'TabNav'; TabNav.propTypes = { /** Text-align: left or center */ textAlign: PropTypes.oneOf(['center', 'left']), /** Back button text, href, click handler */ backButton: PropTypes.shape({ text: PropTypes.string, href: PropTypes.string, clickHandler: PropTypes.func }), /** A JSX node */ // @ts-ignore children: PropTypes.node, /** A JSX node sticky to the left */ // @ts-ignore stickyChildrenLeft: PropTypes.node, /** A JSX node sticky to the right */ // @ts-ignore stickyChildrenRight: PropTypes.node, /** Which viewports to show the back button on */ showBackButtonOn: PropTypes.arrayOf(PropTypes.oneOf(['s', 'm', 'l'])), /** Enable fancy transition when changing active tabs */ enableLineTransition: PropTypes.bool, /** Set duration of lineTransition animation */ duration: PropTypes.number, 'aria-label': PropTypes.string };