UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

87 lines (83 loc) 4.4 kB
import classnames from 'classnames'; import React__default, { useRef, useState } from 'react'; import styled from 'styled-components'; import { get } from '../constants.js'; import { useFocusZone } from '../hooks/useFocusZone.js'; import sx from '../sx.js'; import getGlobalFocusStyles from '../_getGlobalFocusStyles.js'; import { FocusKeys } from '@primer/behaviors'; function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } const ITEM_CLASS = 'TabNav-item'; const SELECTED_CLASS = 'selected'; const TabNavBase = styled.div.withConfig({ displayName: "TabNav__TabNavBase", componentId: "sc-pwdi4r-0" })(["", ""], sx); const TabNavTabList = styled.div.withConfig({ displayName: "TabNav__TabNavTabList", componentId: "sc-pwdi4r-1" })(["display:flex;margin-bottom:-1px;overflow:auto;"]); const TabNavNav = styled.nav.withConfig({ displayName: "TabNav__TabNavNav", componentId: "sc-pwdi4r-2" })(["margin-top:0;border-bottom:1px solid ", ";"], get('colors.border.default')); function TabNav({ children, 'aria-label': ariaLabel, ...rest }) { const customContainerRef = useRef(null); // Detect if the TabNav is inside an ActionMenu. const [isInsideMenu, setIsInsideMenu] = useState(false); React__default.useEffect(() => { if (customContainerRef.current) { const menu = customContainerRef.current.closest('[role=menu]'); if (menu) { setIsInsideMenu(true); } } }, [customContainerRef]); const customStrategy = React__default.useCallback(() => { var _customContainerRef$c, _customContainerRef$c2, _ref; const selectedTab = (_customContainerRef$c = customContainerRef.current) === null || _customContainerRef$c === void 0 ? void 0 : _customContainerRef$c.querySelector('[role=tab][aria-selected=true]'); const firstTab = (_customContainerRef$c2 = customContainerRef.current) === null || _customContainerRef$c2 === void 0 ? void 0 : _customContainerRef$c2.querySelector('[role=tab]'); return (_ref = selectedTab !== null && selectedTab !== void 0 ? selectedTab : firstTab) !== null && _ref !== void 0 ? _ref : undefined; }, [customContainerRef]); const { containerRef: navRef } = useFocusZone({ containerRef: customContainerRef, bindKeys: FocusKeys.ArrowHorizontal | FocusKeys.HomeAndEnd, focusOutBehavior: 'wrap', // Use 'previous' strategy when inside an ActionMenu to avoid // conflicting with the ActionMenu's focus zone. // // WARNING: We don't recommend using TabNav inside an ActionMenu. // This is a workaround to avoid breaking existing code. focusInStrategy: isInsideMenu ? 'previous' : customStrategy, focusableElementFilter: element => element.getAttribute('role') === 'tab' }, [isInsideMenu]); return /*#__PURE__*/React__default.createElement(TabNavBase, _extends({}, rest, { ref: navRef }), /*#__PURE__*/React__default.createElement(TabNavNav, { "aria-label": ariaLabel }, /*#__PURE__*/React__default.createElement(TabNavTabList, { role: "tablist" }, children))); } TabNav.displayName = "TabNav"; const TabNavLink = styled.a.attrs(props => ({ activeClassName: typeof props.to === 'string' ? 'selected' : undefined, className: classnames(ITEM_CLASS, props.selected && SELECTED_CLASS, props.className), role: 'tab', 'aria-selected': !!props.selected, tabIndex: -1 })).withConfig({ displayName: "TabNav__TabNavLink", componentId: "sc-pwdi4r-3" })(["padding:8px 12px;font-size:", ";line-height:20px;color:", ";text-decoration:none;background-color:transparent;border:1px solid transparent;border-bottom:0;", ";&:hover,&:focus{color:", ";text-decoration:none;}&.selected{color:", ";border-color:", ";border-top-right-radius:", ";border-top-left-radius:", ";background-color:", ";}", ";"], get('fontSizes.1'), get('colors.fg.default'), getGlobalFocusStyles('-6px'), get('colors.fg.default'), get('colors.fg.default'), get('colors.border.default'), get('radii.2'), get('radii.2'), get('colors.canvas.default'), sx); TabNavLink.displayName = 'TabNav.Link'; var TabNav$1 = Object.assign(TabNav, { Link: TabNavLink }); export { TabNav$1 as default };