@atlaskit/spotlight 0.0.18 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @atlaskit/spotlight
2
2
 
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`0bc8c3d1f15ee`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0bc8c3d1f15ee) -
8
+ Apply `flex-direction: row-reverse;` to `SpotlightControls` to make `SpotlightDismissControl` the
9
+ first focusable element in `Spotlight`.
10
+
11
+ ### Patch Changes
12
+
13
+ - [`6fa400e1910b7`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/6fa400e1910b7) -
14
+ Styling update to `PopoverContent` to set `z-index: 800` to ensure `Spotlight` displays correctly
15
+ on top of Atlassian layering elements.
16
+ - Updated dependencies
17
+
3
18
  ## 0.0.18
4
19
 
5
20
  ### Patch Changes
@@ -0,0 +1,73 @@
1
+ ---
2
+ order: 0
3
+ ---
4
+
5
+ import PlacementsExample from '../../examples/constellation/placements';
6
+ import SingleStepExample from '../../examples/constellation/single-step';
7
+ import MultipleStepsExample from '../../examples/constellation/multiple-steps';
8
+ import MediaExample from '../../examples/constellation/media';
9
+ import ControlsExample from '../../examples/constellation/controls';
10
+
11
+ ## Single Step
12
+
13
+ Ideally, spotlights should only have a single step so as not to overwhelm users with too much
14
+ information. Try and combine or eliminate tasks where possible. Dismiss functionality is required.
15
+ Don't force users to participate.
16
+
17
+ To show/hide the `Spotlight`, simply use a `useState` to control the `isVisible` prop on
18
+ `PopoverContent`. To position the `Spotlight`, use `PopoverProvider`, `PopoverTarget` and
19
+ `PopoverContent` and set the
20
+
21
+ <Example Component={SingleStepExample} packageName="@atlaskit/spinner" />
22
+
23
+ ## Multiple Steps/Tour
24
+
25
+ Multiple steps should be avoided if possible. Try and combine or eliminate steps where possible. If
26
+ multiple steps are required, preference managing the tour with a `useState`. As a last resort a
27
+ React context may be used. However, these contexts will often need to be wrapping the entire `App`
28
+ and therefore will cause the entire `App` to re-render every time a new spotlight step is shown.
29
+
30
+ <Example Component={MultipleStepsExample} packageName="@atlaskit/spinner" />
31
+
32
+ ## Placements
33
+
34
+ Spotlight placements are static — they do not change as the user scrolls, or if the `PopoverContent`
35
+ overflows out of the viewport. Make sure to choose a placement that ensures the `Spotlight` is
36
+ displayed in full.
37
+
38
+ By design `@atlaskit/spotlight` does not have a blanket, scroll-lock, focus-trap, or click-outside
39
+ to dismiss functionality. This is to ensure the user is not hijacked into the spotlight experience,
40
+ and can opt-in if they are interested.
41
+
42
+ <Example Component={PlacementsExample} packageName="@atlaskit/spinner" />
43
+
44
+ ## Media
45
+
46
+ Media is optional for a `Spotlight`. However if it is used it must be 295px width X 135px height.
47
+ This is to ensure correct reflow on smaller viewports.
48
+
49
+ Media can be an image, video, animation, or any other visual aid to communicate spotlight intent.
50
+
51
+ <Example Component={MediaExample} packageName="@atlaskit/spinner" />
52
+
53
+ ## Controls
54
+
55
+ `SpotlightDismissControl` is required for all `Spotlight` components. It **must** be the first
56
+ focusable element on the `Spotlight` card. This means that when defining the controls,
57
+ `SpotlightDismissControl` should appear first in the DOM order:
58
+
59
+ ```tsx
60
+ <SpotlighControls>
61
+ <SpotlightDismissControl />
62
+ <SpotlightShowMoreControl />
63
+ </SpotlighControls>
64
+ ```
65
+
66
+ Internally, `SpotlighControls` applies `flex-direction: row-reverse;` so that
67
+ `SpotlightDismissControl` visually displays after `SpotlightShowMoreControl` while maintaining
68
+ correct tabbing order.
69
+
70
+ `SpotlightShowMoreControl` is optional for `Spotlight` components. It should be used to allow users
71
+ to opt out of a spotlight experience, or understand why they are seeing the spotlight experience.
72
+
73
+ <Example Component={ControlsExample} packageName="@atlaskit/spinner" />
@@ -0,0 +1,104 @@
1
+ import { SingleStepSpotlightTable, MultiStepSpotlightTable } from '@af/design-system-docs-ui';
2
+
3
+ ## Usage
4
+
5
+ A spotlight focuses attention on a specific part of the UI, such as a button or icon, to educate
6
+ users about key features or workflows. Spotlights are most effective for onboarding new users,
7
+ driving feature discovery, or highlighting important changes. Use them sparingly — if your UI needs
8
+ frequent spotlights, consider simplifying the core experience instead.
9
+
10
+ ## Spotlight Scenarios
11
+
12
+ ### Top use cases
13
+
14
+ - **Onboarding new users**: Guide first-time users to essential features and workflows.
15
+ - **Feature discovery**: Help existing users learn about new or updated capabilities.
16
+
17
+ ### Growth use cases
18
+
19
+ - **Cross-flow, cross-join, co-use**: Use spotlights only when triggered by another message type
20
+ (e.g., a banner that asks for permission to “show me” before triggering a spotlight).
21
+
22
+ ### Unsupported use cases
23
+
24
+ - **Transactional**: Never use spotlights for transactional messages.
25
+
26
+ ## Guiding Principles
27
+
28
+ - **Use sparingly**: Spotlights are a Level 3 (Neutral Plus) attention component. Overuse can
29
+ distract and fatigue users.
30
+ - **One at a time**: Only show one spotlight at a time.
31
+ - **Dismissibility**: Always provide a dismiss option. Never force participation.
32
+ - **Step count**: Prefer single-step spotlights. For tours, keep flows short (2–3 steps max).
33
+ - **Orchestration**: Build spotlights with Post Office to avoid message collisions and enforce
34
+ fatigue rules (Atlassians Only).
35
+ - **Media**: Use media (images or video) only when it enhances understanding. Exclude media if the
36
+ spotlight already focuses attention effectively.
37
+
38
+ ## Anatomy & Specifications
39
+
40
+ ### Single Step Spotlight
41
+
42
+ <SingleStepSpotlightTable />
43
+ <br />
44
+
45
+ ### Multi Step Spotlight/Tour
46
+
47
+ <MultiStepSpotlightTable />
48
+ <br />
49
+
50
+ ## Visual Guidance
51
+
52
+ - **Complexity**: Match the visual complexity to the feature’s learning curve. Use text-only for
53
+ simple features, a single illustration for moderate complexity, and a narrative/motion for complex
54
+ flows.
55
+
56
+ - **Brand color**: Use solid backgrounds to focus attention. Limit to three brand colors per
57
+ composition.
58
+
59
+ - **Composition**: Highlight the focal point with size, color, and gesture lines. Use motion only if
60
+ it clarifies the feature.
61
+
62
+ ## Behavior
63
+
64
+ - **Entry points**: Spotlights should be triggered contextually and never interrupt core workflows.
65
+ For cross-product or promotional spotlights, use a less obtrusive entrypoint (like a banner)
66
+ first.
67
+
68
+ - **Tours**: Sequence steps logically. Keep flows short and focused.
69
+
70
+ ## Best Practices
71
+
72
+ - Use spotlights only when necessary to drive understanding or adoption.
73
+ - Sequence multi-step spotlights logically; aim for 2–3 steps max.
74
+ - Always allow users to dismiss or skip.
75
+ - Avoid competing with other in-product messages.
76
+ - Prefer embedded, contextual education over overlays.
77
+
78
+ ## Accessibility
79
+
80
+ - The headline is used as the accessible name for the spotlight dialog.
81
+ - Keep content concise and avoid motion that could be disruptive.
82
+ - Ensure the carat and spotlight are not truncated by the browser bounds.
83
+
84
+ ## Content Guidelines
85
+
86
+ ## Headline
87
+
88
+ - Required. Begin with an active verb where possible.
89
+ - Brief and direct; communicate the main benefit.
90
+ - Limit to one line and use sentence case.
91
+
92
+ ## Body
93
+
94
+ - Required. Briefly elaborate on the intent.
95
+ - Avoid repeating the headline verb.
96
+ - Two lines max. Focus on benefits and relevance.
97
+ - Reference only visible elements.
98
+
99
+ ## CTA
100
+
101
+ - Required. One clear next action.
102
+ - Avoid plan or feature names in CTAs.
103
+ - For tours: “Next”, “Back”, “Done”.
104
+ - For features: 1–3 words; “Done” is acceptable if no clear next action.
@@ -0,0 +1,3 @@
1
+
2
+ ._zulpu2gc{gap:var(--ds-space-100,8px)}._1e0c1txw{display:flex}
3
+ ._2lx21sbv{flex-direction:row-reverse}
@@ -1,3 +1,4 @@
1
+ /* index.tsx generated by @compiled/babel-plugin v0.36.1 */
1
2
  "use strict";
2
3
 
3
4
  var _typeof = require("@babel/runtime/helpers/typeof");
@@ -5,9 +6,14 @@ Object.defineProperty(exports, "__esModule", {
5
6
  value: true
6
7
  });
7
8
  exports.SpotlightControls = void 0;
9
+ require("./index.compiled.css");
8
10
  var _react = _interopRequireWildcard(require("react"));
9
- var _compiled = require("@atlaskit/primitives/compiled");
11
+ var React = _react;
12
+ var _runtime = require("@compiled/react/runtime");
10
13
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
14
+ var styles = {
15
+ root: "_zulpu2gc _1e0c1txw _2lx21sbv"
16
+ };
11
17
  /**
12
18
  * __Spotlight controls__
13
19
  *
@@ -16,10 +22,10 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
16
22
  var SpotlightControls = exports.SpotlightControls = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
17
23
  var testId = _ref.testId,
18
24
  children = _ref.children;
19
- return /*#__PURE__*/_react.default.createElement(_compiled.Flex, {
20
- testId: testId,
25
+ return /*#__PURE__*/React.createElement("div", {
26
+ "data-testid": testId,
21
27
  ref: ref,
22
- gap: "space.100",
23
- role: "group"
28
+ role: "group",
29
+ className: (0, _runtime.ax)([styles.root])
24
30
  }, children);
25
31
  });
@@ -1,3 +1,4 @@
1
+ ._1pby1fw0{z-index:700}
1
2
  ._3um015vq{visibility:hidden}
2
3
  ._3um0ewfl{visibility:visible}
3
4
  ._lcxv1wug{pointer-events:auto}
@@ -14,6 +14,9 @@ var _popper = require("@atlaskit/popper");
14
14
  var _context = require("../../controllers/context");
15
15
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
16
16
  var styles = {
17
+ root: "_1pby1fw0"
18
+ };
19
+ var visibilityStyles = {
17
20
  visible: "_lcxv1wug _3um0ewfl",
18
21
  hidden: "_lcxvglyw _3um015vq"
19
22
  };
@@ -69,7 +72,7 @@ var PopoverContent = exports.PopoverContent = function PopoverContent(_ref) {
69
72
  return /*#__PURE__*/React.createElement("div", {
70
73
  ref: ref,
71
74
  style: style,
72
- className: (0, _runtime.ax)([styles[visibility]])
75
+ className: (0, _runtime.ax)([styles.root, visibilityStyles[visibility]])
73
76
  }, children);
74
77
  });
75
78
  };
@@ -0,0 +1,3 @@
1
+
2
+ ._zulpu2gc{gap:var(--ds-space-100,8px)}._1e0c1txw{display:flex}
3
+ ._2lx21sbv{flex-direction:row-reverse}
@@ -1,5 +1,11 @@
1
- import React, { forwardRef } from 'react';
2
- import { Flex } from '@atlaskit/primitives/compiled';
1
+ /* index.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ import "./index.compiled.css";
3
+ import * as React from 'react';
4
+ import { ax, ix } from "@compiled/react/runtime";
5
+ import { forwardRef } from 'react';
6
+ const styles = {
7
+ root: "_zulpu2gc _1e0c1txw _2lx21sbv"
8
+ };
3
9
  /**
4
10
  * __Spotlight controls__
5
11
  *
@@ -9,10 +15,10 @@ export const SpotlightControls = /*#__PURE__*/forwardRef(({
9
15
  testId,
10
16
  children
11
17
  }, ref) => {
12
- return /*#__PURE__*/React.createElement(Flex, {
13
- testId: testId,
18
+ return /*#__PURE__*/React.createElement("div", {
19
+ "data-testid": testId,
14
20
  ref: ref,
15
- gap: "space.100",
16
- role: "group"
21
+ role: "group",
22
+ className: ax([styles.root])
17
23
  }, children);
18
24
  });
@@ -1,3 +1,4 @@
1
+ ._1pby1fw0{z-index:700}
1
2
  ._3um015vq{visibility:hidden}
2
3
  ._3um0ewfl{visibility:visible}
3
4
  ._lcxv1wug{pointer-events:auto}
@@ -6,6 +6,9 @@ import { useContext, useEffect } from 'react';
6
6
  import { Popper } from '@atlaskit/popper';
7
7
  import { SpotlightContext } from '../../controllers/context';
8
8
  const styles = {
9
+ root: "_1pby1fw0"
10
+ };
11
+ const visibilityStyles = {
9
12
  visible: "_lcxv1wug _3um0ewfl",
10
13
  hidden: "_lcxvglyw _3um015vq"
11
14
  };
@@ -62,6 +65,6 @@ export const PopoverContent = ({
62
65
  }) => /*#__PURE__*/React.createElement("div", {
63
66
  ref: ref,
64
67
  style: style,
65
- className: ax([styles[visibility]])
68
+ className: ax([styles.root, visibilityStyles[visibility]])
66
69
  }, children));
67
70
  };
@@ -0,0 +1,3 @@
1
+
2
+ ._zulpu2gc{gap:var(--ds-space-100,8px)}._1e0c1txw{display:flex}
3
+ ._2lx21sbv{flex-direction:row-reverse}
@@ -1,5 +1,11 @@
1
- import React, { forwardRef } from 'react';
2
- import { Flex } from '@atlaskit/primitives/compiled';
1
+ /* index.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ import "./index.compiled.css";
3
+ import * as React from 'react';
4
+ import { ax, ix } from "@compiled/react/runtime";
5
+ import { forwardRef } from 'react';
6
+ var styles = {
7
+ root: "_zulpu2gc _1e0c1txw _2lx21sbv"
8
+ };
3
9
  /**
4
10
  * __Spotlight controls__
5
11
  *
@@ -8,10 +14,10 @@ import { Flex } from '@atlaskit/primitives/compiled';
8
14
  export var SpotlightControls = /*#__PURE__*/forwardRef(function (_ref, ref) {
9
15
  var testId = _ref.testId,
10
16
  children = _ref.children;
11
- return /*#__PURE__*/React.createElement(Flex, {
12
- testId: testId,
17
+ return /*#__PURE__*/React.createElement("div", {
18
+ "data-testid": testId,
13
19
  ref: ref,
14
- gap: "space.100",
15
- role: "group"
20
+ role: "group",
21
+ className: ax([styles.root])
16
22
  }, children);
17
23
  });
@@ -1,3 +1,4 @@
1
+ ._1pby1fw0{z-index:700}
1
2
  ._3um015vq{visibility:hidden}
2
3
  ._3um0ewfl{visibility:visible}
3
4
  ._lcxv1wug{pointer-events:auto}
@@ -6,6 +6,9 @@ import { useContext, useEffect } from 'react';
6
6
  import { Popper } from '@atlaskit/popper';
7
7
  import { SpotlightContext } from '../../controllers/context';
8
8
  var styles = {
9
+ root: "_1pby1fw0"
10
+ };
11
+ var visibilityStyles = {
9
12
  visible: "_lcxv1wug _3um0ewfl",
10
13
  hidden: "_lcxvglyw _3um015vq"
11
14
  };
@@ -61,7 +64,7 @@ export var PopoverContent = function PopoverContent(_ref) {
61
64
  return /*#__PURE__*/React.createElement("div", {
62
65
  ref: ref,
63
66
  style: style,
64
- className: ax([styles[visibility]])
67
+ className: ax([styles.root, visibilityStyles[visibility]])
65
68
  }, children);
66
69
  });
67
70
  };
@@ -1,4 +1,8 @@
1
- import React, { type ReactNode } from 'react';
1
+ /**
2
+ * @jsxRuntime classic
3
+ * @jsx jsx
4
+ */
5
+ import { type ReactNode } from 'react';
2
6
  export interface SpotlightControlsProps {
3
7
  /**
4
8
  * A `testId` prop is provided for specified elements, which is a unique
@@ -16,4 +20,4 @@ export interface SpotlightControlsProps {
16
20
  *
17
21
  * `SpotlightControls` groups spotlight control components.
18
22
  */
19
- export declare const SpotlightControls: React.ForwardRefExoticComponent<SpotlightControlsProps & React.RefAttributes<HTMLDivElement>>;
23
+ export declare const SpotlightControls: import("react").ForwardRefExoticComponent<SpotlightControlsProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @jsxRuntime classic
3
- * @jsx jsx
4
- */
2
+ * @jsxRuntime classic
3
+ * @jsx jsx
4
+ */
5
5
  import { type ReactNode } from 'react';
6
6
  /**
7
7
  * __Target__
@@ -1,4 +1,8 @@
1
- import React, { type ReactNode } from 'react';
1
+ /**
2
+ * @jsxRuntime classic
3
+ * @jsx jsx
4
+ */
5
+ import { type ReactNode } from 'react';
2
6
  export interface SpotlightControlsProps {
3
7
  /**
4
8
  * A `testId` prop is provided for specified elements, which is a unique
@@ -16,4 +20,4 @@ export interface SpotlightControlsProps {
16
20
  *
17
21
  * `SpotlightControls` groups spotlight control components.
18
22
  */
19
- export declare const SpotlightControls: React.ForwardRefExoticComponent<SpotlightControlsProps & React.RefAttributes<HTMLDivElement>>;
23
+ export declare const SpotlightControls: import("react").ForwardRefExoticComponent<SpotlightControlsProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -1,7 +1,7 @@
1
1
  /**
2
- * @jsxRuntime classic
3
- * @jsx jsx
4
- */
2
+ * @jsxRuntime classic
3
+ * @jsx jsx
4
+ */
5
5
  import { type ReactNode } from 'react';
6
6
  /**
7
7
  * __Target__
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/spotlight",
3
- "version": "0.0.18",
3
+ "version": "0.1.0",
4
4
  "description": "A spotlight introduces users to various points of interest across Atlassian through focused messages or multi-step tours.",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -48,7 +48,6 @@
48
48
  "@af/visual-regression": "workspace:^",
49
49
  "@atlaskit/dropdown-menu": "^16.3.0",
50
50
  "@atlaskit/ssr": "workspace:^",
51
- "@atlaskit/visual-regression": "workspace:^",
52
51
  "@testing-library/react": "^13.4.0",
53
52
  "react-dom": "^18.2.0"
54
53
  },