UNPKG

@atlaskit/onboarding

Version:

An onboarding spotlight introduces new features to users through focused messages or multi-step tours.

135 lines (133 loc) 4.34 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; import React, { Component } from 'react'; import FocusLock from 'react-focus-lock'; import { Popper } from '@atlaskit/popper/main'; import { Box } from '@atlaskit/primitives/compiled'; import { DialogImage } from '../styled/dialog'; import SpotlightCard from './spotlight-card'; import ValueChanged from './value-changed'; /** * __Spotlight dialog__ * * An onboarding spotlight introduces new features to users through focused messages or multi-step tours. * * - [Examples](https://atlassian.design/components/onboarding/examples) * - [Code](https://atlassian.design/components/onboarding/code) * - [Usage](https://atlassian.design/components/onboarding/usage) */ // eslint-disable-next-line @repo/internal/react/no-class-components class SpotlightDialogComponent extends Component { constructor(...args) { super(...args); _defineProperty(this, "state", { focusLockDisabled: true }); } componentDidMount() { this.focusLockTimeoutId = window.setTimeout(() => { // we delay the enabling of the focus lock to avoid the scroll position // jumping around in some situations this.setState({ focusLockDisabled: false }); }, 200); } componentWillUnmount() { window.clearTimeout(this.focusLockTimeoutId); } render() { const { actions, actionsBeforeElement, children, dialogPlacement, dialogWidth, footer, header, heading, headingAfterElement, image, label = 'Introducing new feature', titleId, targetNode, testId } = this.props; const { focusLockDisabled } = this.state; const dialogLabel = !heading && !titleId ? label : undefined; const dialogLabelledBy = titleId || (heading ? 'spotlight-dialog-label' : undefined); const translatedPlacement = dialogPlacement ? { 'top left': 'top-start', 'top center': 'top', 'top right': 'top-end', 'right top': 'right-start', 'right middle': 'right', 'right bottom': 'right-end', 'bottom left': 'bottom-start', 'bottom center': 'bottom', 'bottom right': 'bottom-end', 'left top': 'left-start', 'left middle': 'left', 'left bottom': 'left-end' }[dialogPlacement] : undefined; // If there's no room on either side of the popper, it will extend off-screen. // This looks buggy when scroll-lock and focus is placed on the dialog, so we // customise popper so it overflows the spotlight instead with altAxis=true. const modifiers = [{ name: 'preventOverflow', options: { padding: 5, rootBoundary: 'document', altAxis: true, tether: false } }]; return /*#__PURE__*/React.createElement(Popper, { modifiers: modifiers, referenceElement: targetNode, placement: translatedPlacement }, ({ ref, style, update }) => /*#__PURE__*/React.createElement(ValueChanged, { value: dialogWidth, onChange: update }, /*#__PURE__*/React.createElement(FocusLock, { disabled: focusLockDisabled, returnFocus: false, autoFocus: true }, /*#__PURE__*/React.createElement(Box, { style: style, ref: ref, "aria-modal": true, role: "dialog", "aria-label": dialogLabel, "aria-labelledby": dialogLabelledBy, testId: `${testId}-container` }, /*#__PURE__*/React.createElement(SpotlightCard, { testId: testId, width: dialogWidth, actions: actions, actionsBeforeElement: actionsBeforeElement, image: image && /*#__PURE__*/React.createElement(DialogImage, { alt: heading, src: image }), components: { Header: header, Footer: footer }, heading: heading, headingId: "spotlight-dialog-label", headingAfterElement: headingAfterElement // This should be heading level 1 since this is technically a modal, including a focus lock on the modal window. // But because it is not a _true_ modal, we are setting it to `2` until that is fixed. , headingLevel: 2 }, children))))); } } // eslint-disable-next-line @repo/internal/react/require-jsdoc export default SpotlightDialogComponent;