UNPKG

@atlaskit/navigation-system

Version:

The latest navigation system for Atlassian apps.

134 lines (131 loc) • 6.56 kB
/* top-nav-end.tsx generated by @compiled/babel-plugin v3.0.2 */ import _extends from "@babel/runtime/helpers/extends"; import "./top-nav-end.compiled.css"; import { ax, ix } from "@compiled/react/runtime"; import React, { useState } from 'react'; // Compiled supports the inherited container-layout widths outside @atlaskit/css's bounded values. import { cx } from '@compiled/react'; import mergeRefs from '@atlaskit/ds-lib/merge-refs'; import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect'; import ShowMoreHorizontalIcon from '@atlaskit/icon/core/show-more-horizontal'; import { OpenLayerObserverNamespaceProvider } from '@atlaskit/layering/open-layer-observer-namespace-provider'; import { fg } from '@atlaskit/platform-feature-flags/fg'; import { Popup } from '@atlaskit/popup/popup'; import { UNSAFE_useMediaQuery as useMediaQuery } from '@atlaskit/primitives/compiled/use-media-query'; import { List } from '../../../components/list'; import { HasCustomThemeContext } from '../../top-nav-items/themed/has-custom-theme-context'; import { IconButton } from '../../top-nav-items/themed/icon-button'; import { openLayerObserverTopNavEndNamespace } from '../constants'; import { useTopNavBreakpoints } from './use-top-nav-breakpoints'; import { useTopNavEndFocus } from './use-top-nav-end-focus'; const containerStyles = { focusScope: "_1e0c1bgi", root: "_yyhy11wp _1e0c1txw _1bahh9n0 _1ul9zwfg", withPersistentItems: "_zulpu2gc _4cvr1h6o", container: "_1bsb14ik _1ul98ox3 _vchhusvi _10fph9n0 _1d2yioy8 _gltexl30 _15riwpqv", viewport: "_1d2y1ris _glte1ris _15rip2n4 _1gs5usvi _ndwch9n0" }; const listStyles = { root: "_zulp1b66 _4cvr1h6o _1e0c1txw", container: "_1e0c1cgg _181nz5ha", hideOnSmallViewport: "_1e0cglyw _181n1txw", popupContainer: "_1yt4u2gc" }; /** * __TopNavEnd__ * * Wrapper for the top navigation actions on the inline-end (right) side of the top navigation. * * On small viewports, the children will be placed inside a popup, and a button will be rendered to open the popup. * This is to prevent the actions from overflowing the top navigation. */ export function TopNavEnd({ children, persistentItems, label = 'Actions', showMoreButtonLabel = 'Show more' }) { var _breakpoints$belowSm; const breakpoints = useTopNavBreakpoints(); const hasContainerBreakpoints = breakpoints != null; const hasPersistentItems = fg('platform-dst-chat-panel-layout') && persistentItems != null; const [isOpen, setIsOpen] = useState(false); // Always setting to `false` for the initial render (will flip in an effect for mobile) const [isMobileViewport, setIsMobileViewport] = useState(false); // Note: `query` is a stable value between renders const query = useMediaQuery('below.sm', function onChange(event) { setIsMobileViewport(event.matches); // Container mode closes only when the effective layout changes below. // Keep the existing viewport behavior outside the rollout / provider. if (fg('platform-dst-chat-panel-layout')) { if (!hasContainerBreakpoints) { setIsOpen(false); } } else { setIsOpen(false); } }); useLayoutEffect(() => { var _query$matches; // The default is `false`, and desktop will remain as `false` (no re-render). // Mobile will flip from `false` to `true`. setIsMobileViewport((_query$matches = query === null || query === void 0 ? void 0 : query.matches) !== null && _query$matches !== void 0 ? _query$matches : false); }, [query]); const isMobile = (_breakpoints$belowSm = breakpoints === null || breakpoints === void 0 ? void 0 : breakpoints.belowSm) !== null && _breakpoints$belowSm !== void 0 ? _breakpoints$belowSm : isMobileViewport; const { actionsRef, triggerRef, onFocusCapture } = useTopNavEndFocus({ isMobile, enabled: fg('platform-dst-chat-panel-layout') }); useLayoutEffect(() => { if (fg('platform-dst-chat-panel-layout') && hasContainerBreakpoints) { setIsOpen(false); } }, [isMobile, hasContainerBreakpoints]); // The shared provider also covers the mobile overflow popup itself. Keep the // previous content-only namespace coverage when the layout gate is disabled. // The observer is not used when the top-layer gate is on, so no provider is needed. const actions = fg('platform-dst-chat-panel-layout') || fg('platform-dst-top-layer') ? children : /*#__PURE__*/React.createElement(OpenLayerObserverNamespaceProvider, { namespace: openLayerObserverTopNavEndNamespace }, children); const regularActions = isMobile ? /*#__PURE__*/React.createElement(Popup, { isOpen: isOpen, onClose: () => setIsOpen(false) // Top-layer popups need a role to register as a popup with the layer observer. , role: fg('platform-dst-chat-panel-layout') ? 'dialog' : undefined, label: fg('platform-dst-chat-panel-layout') ? label : undefined, placement: "bottom-start", shouldRenderToParent: true, content: () => /*#__PURE__*/React.createElement(HasCustomThemeContext.Provider, { value: false }, /*#__PURE__*/React.createElement(List, { ref: actionsRef, xcss: cx(listStyles.root, listStyles.popupContainer) }, actions)), trigger: triggerProps => /*#__PURE__*/React.createElement(IconButton, _extends({}, triggerProps, { ref: fg('platform-dst-chat-panel-layout') ? mergeRefs([triggerProps.ref, triggerRef]) : triggerProps.ref, label: showMoreButtonLabel, isSelected: isOpen, onClick: () => setIsOpen(!isOpen), icon: ShowMoreHorizontalIcon, isTooltipDisabled: false })) }) : /*#__PURE__*/React.createElement(List, { ref: actionsRef, xcss: cx(listStyles.root, fg('platform-dst-chat-panel-layout') ? listStyles.container : listStyles.hideOnSmallViewport) }, actions); const content = /*#__PURE__*/React.createElement("nav", { "aria-label": label, className: ax([containerStyles.root, fg('platform-dst-chat-panel-layout') ? containerStyles.container : containerStyles.viewport, hasPersistentItems && containerStyles.withPersistentItems]) }, fg('platform-dst-chat-panel-layout') ? /*#__PURE__*/React.createElement("div", { onFocusCapture: onFocusCapture, className: ax([containerStyles.focusScope]) }, regularActions) : regularActions, hasPersistentItems && persistentItems); return fg('platform-dst-chat-panel-layout') && !fg('platform-dst-top-layer') ? /*#__PURE__*/React.createElement(OpenLayerObserverNamespaceProvider, { namespace: openLayerObserverTopNavEndNamespace }, content) : content; }