@primer/react
Version:
An implementation of GitHub's Primer Design System using React
95 lines (88 loc) • 4.94 kB
JavaScript
'use strict';
var classnames = require('classnames');
var React = require('react');
var styled = require('styled-components');
var constants = require('../constants.js');
var useFocusZone = require('../hooks/useFocusZone.js');
var sx = require('../sx.js');
var _getGlobalFocusStyles = require('../_getGlobalFocusStyles.js');
var behaviors = require('@primer/behaviors');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var classnames__default = /*#__PURE__*/_interopDefault(classnames);
var React__default = /*#__PURE__*/_interopDefault(React);
var styled__default = /*#__PURE__*/_interopDefault(styled);
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__default.default.div.withConfig({
displayName: "TabNav__TabNavBase",
componentId: "sc-pwdi4r-0"
})(["", ""], sx.default);
const TabNavTabList = styled__default.default.div.withConfig({
displayName: "TabNav__TabNavTabList",
componentId: "sc-pwdi4r-1"
})(["display:flex;margin-bottom:-1px;overflow:auto;"]);
const TabNavNav = styled__default.default.nav.withConfig({
displayName: "TabNav__TabNavNav",
componentId: "sc-pwdi4r-2"
})(["margin-top:0;border-bottom:1px solid ", ";"], constants.get('colors.border.default'));
function TabNav({
children,
'aria-label': ariaLabel,
...rest
}) {
const customContainerRef = React.useRef(null);
// Detect if the TabNav is inside an ActionMenu.
const [isInsideMenu, setIsInsideMenu] = React.useState(false);
React__default.default.useEffect(() => {
if (customContainerRef.current) {
const menu = customContainerRef.current.closest('[role=menu]');
if (menu) {
setIsInsideMenu(true);
}
}
}, [customContainerRef]);
const customStrategy = React__default.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.useFocusZone({
containerRef: customContainerRef,
bindKeys: behaviors.FocusKeys.ArrowHorizontal | behaviors.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.default.createElement(TabNavBase, _extends({}, rest, {
ref: navRef
}), /*#__PURE__*/React__default.default.createElement(TabNavNav, {
"aria-label": ariaLabel
}, /*#__PURE__*/React__default.default.createElement(TabNavTabList, {
role: "tablist"
}, children)));
}
TabNav.displayName = "TabNav";
const TabNavLink = styled__default.default.a.attrs(props => ({
activeClassName: typeof props.to === 'string' ? 'selected' : undefined,
className: classnames__default.default(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:", ";}", ";"], constants.get('fontSizes.1'), constants.get('colors.fg.default'), _getGlobalFocusStyles('-6px'), constants.get('colors.fg.default'), constants.get('colors.fg.default'), constants.get('colors.border.default'), constants.get('radii.2'), constants.get('radii.2'), constants.get('colors.canvas.default'), sx.default);
TabNavLink.displayName = 'TabNav.Link';
var TabNav$1 = Object.assign(TabNav, {
Link: TabNavLink
});
module.exports = TabNav$1;