@atlaskit/storybook-addon-design-system 0.1.1 → 0.2.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,11 @@
1
1
  # @atlaskit/storybook-addon-design-system
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`068c9a0b770`](https://bitbucket.org/atlassian/atlassian-frontend/commits/068c9a0b770) - Refactors the storybook addon into a "tool addon"
8
+
3
9
  ## 0.1.1
4
10
 
5
11
  ### Patch Changes
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ Object.defineProperty(exports, "Tool", {
9
+ enumerable: true,
10
+ get: function get() {
11
+ return _tool.default;
12
+ }
13
+ });
14
+
15
+ var _tool = _interopRequireDefault(require("./tool"));
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+
7
+ Object.defineProperty(exports, "__esModule", {
8
+ value: true
9
+ });
10
+ exports.default = void 0;
11
+
12
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
13
+
14
+ var _react = _interopRequireWildcard(require("react"));
15
+
16
+ var _api = require("@storybook/api");
17
+
18
+ var _components = require("@storybook/components");
19
+
20
+ var _constants = require("../constants");
21
+
22
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
23
+
24
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
25
+
26
+ var themeOptions = [{
27
+ id: 'none',
28
+ title: 'Disable',
29
+ icon: 'cross'
30
+ }, {
31
+ id: 'light',
32
+ title: 'Light theme',
33
+ icon: 'circlehollow'
34
+ }, {
35
+ id: 'dark',
36
+ title: 'Dark theme',
37
+ icon: 'circle'
38
+ }, {
39
+ id: 'split',
40
+ title: 'Side by side',
41
+ icon: 'sidebar'
42
+ }, {
43
+ id: 'stack',
44
+ title: 'Stacked',
45
+ icon: 'bottombar'
46
+ }];
47
+ /**
48
+ * __Tool__
49
+ *
50
+ * ADS Toolbar UI, visible in the topbar of the storybook UI.
51
+ */
52
+
53
+ var Tool = function Tool() {
54
+ var _themeOptions$find;
55
+
56
+ var _useState = (0, _react.useState)(false),
57
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
58
+ isVisible = _useState2[0],
59
+ setIsVisible = _useState2[1];
60
+
61
+ var _useGlobals = (0, _api.useGlobals)(),
62
+ _useGlobals2 = (0, _slicedToArray2.default)(_useGlobals, 2),
63
+ adsTheme = _useGlobals2[0].adsTheme,
64
+ updateGlobals = _useGlobals2[1];
65
+
66
+ var setTheme = (0, _react.useCallback)(function (theme) {
67
+ return updateGlobals({
68
+ adsTheme: theme
69
+ });
70
+ }, [updateGlobals]);
71
+ return /*#__PURE__*/_react.default.createElement(_components.WithTooltip, {
72
+ placement: "top",
73
+ trigger: "click",
74
+ closeOnClick: true,
75
+ onVisibilityChange: setIsVisible,
76
+ tooltip: function tooltip(_ref) {
77
+ var onHide = _ref.onHide;
78
+ return /*#__PURE__*/_react.default.createElement(_components.TooltipLinkList, {
79
+ links: themeOptions.map(function (_ref2) {
80
+ var id = _ref2.id,
81
+ title = _ref2.title,
82
+ icon = _ref2.icon;
83
+
84
+ var Icon = /*#__PURE__*/_react.default.createElement(_components.Icons, {
85
+ style: {
86
+ opacity: 1
87
+ },
88
+ icon: icon
89
+ });
90
+
91
+ return {
92
+ id: id,
93
+ title: title,
94
+ active: adsTheme === id,
95
+ right: Icon,
96
+ onClick: function onClick() {
97
+ setTheme(id);
98
+ onHide();
99
+ }
100
+ };
101
+ })
102
+ });
103
+ }
104
+ }, /*#__PURE__*/_react.default.createElement(_components.IconButton, {
105
+ key: _constants.TOOL_ID,
106
+ active: isVisible,
107
+ title: "Apply ADS themes to your story"
108
+ }, /*#__PURE__*/_react.default.createElement(_components.Icons, {
109
+ icon: ((_themeOptions$find = themeOptions.find(function (_ref3) {
110
+ var id = _ref3.id;
111
+ return id === adsTheme;
112
+ })) === null || _themeOptions$find === void 0 ? void 0 : _themeOptions$find.icon) || 'circlehollow'
113
+ }), '\xa0ADS Theme'));
114
+ };
115
+
116
+ var _default = Tool;
117
+ exports.default = _default;
@@ -3,15 +3,13 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.PANEL_TITLE = exports.PANEL_ID = exports.EVENT_THEME_CHANGED = exports.DECORATOR_PARAM = exports.DECORATOR_ID = exports.ADDON_ID = void 0;
6
+ exports.TOOL_ID = exports.TITLE = exports.DECORATOR_PARAM = exports.DECORATOR_ID = exports.ADDON_ID = void 0;
7
7
  var ADDON_ID = 'ads-tokens';
8
8
  exports.ADDON_ID = ADDON_ID;
9
- var PANEL_ID = "".concat(ADDON_ID, "/panel");
10
- exports.PANEL_ID = PANEL_ID;
11
- var PANEL_TITLE = "Design Tokens";
12
- exports.PANEL_TITLE = PANEL_TITLE;
13
- var EVENT_THEME_CHANGED = "".concat(ADDON_ID, "/on-theme-change");
14
- exports.EVENT_THEME_CHANGED = EVENT_THEME_CHANGED;
9
+ var TOOL_ID = "".concat(ADDON_ID, "/tool");
10
+ exports.TOOL_ID = TOOL_ID;
11
+ var TITLE = 'Design Tokens';
12
+ exports.TITLE = TITLE;
15
13
  var DECORATOR_ID = 'withDesignTokens';
16
14
  exports.DECORATOR_ID = DECORATOR_ID;
17
15
  var DECORATOR_PARAM = 'DesignTokens';
@@ -1,50 +1,136 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+
3
7
  Object.defineProperty(exports, "__esModule", {
4
8
  value: true
5
9
  });
6
10
  exports.default = void 0;
7
11
 
12
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
+
14
+ var _react = _interopRequireWildcard(require("react"));
15
+
8
16
  var _addons = require("@storybook/addons");
9
17
 
18
+ var _tokens = require("@atlaskit/tokens");
19
+
20
+ require("@atlaskit/tokens/css/atlassian-light.css");
21
+
22
+ require("@atlaskit/tokens/css/atlassian-dark.css");
23
+
10
24
  var _constants = require("./constants");
11
25
 
12
- // // eslint-disable-next-line
13
- // import '../../../node_modules/@atlaskit/tokens/css/atlassian-light.css';
14
- // // eslint-disable-next-line
15
- // import '../../../node_modules/@atlaskit/tokens/css/atlassian-dark.css';
26
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
27
+
28
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
29
+
30
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
31
+
32
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
33
+
34
+ var splitColumnStyles = {
35
+ position: 'absolute',
36
+ boxSizing: 'border-box',
37
+ width: '50vw',
38
+ height: '100vh',
39
+ overflow: 'auto',
40
+ padding: '10px',
41
+ background: (0, _tokens.token)('color.background.default'),
42
+ color: (0, _tokens.token)('color.text.highEmphasis')
43
+ };
44
+ var stackColumnStyles = {
45
+ position: 'absolute',
46
+ boxSizing: 'border-box',
47
+ width: '100%',
48
+ height: '50%',
49
+ overflow: 'auto',
50
+ padding: '10px',
51
+ background: (0, _tokens.token)('color.background.default'),
52
+ color: (0, _tokens.token)('color.text.highEmphasis')
53
+ };
16
54
  var withDesignTokens = (0, _addons.makeDecorator)({
17
55
  name: _constants.DECORATOR_ID,
18
56
  parameterName: _constants.DECORATOR_PARAM,
19
57
  wrapper: function wrapper(storyFn, context) {
20
- // eslint-disable-next-line react-hooks/rules-of-hooks
58
+ var theme = context.globals.adsTheme; // eslint-disable-next-line react-hooks/rules-of-hooks
59
+
21
60
  (0, _addons.useEffect)(function () {
22
- var setTheme = function setTheme(theme) {
23
- if (!theme || theme === 'none') {
24
- delete document.documentElement.dataset.theme;
25
- return;
26
- } // HACK: Allows us to disable the light mode style since it uses root:
27
-
28
-
29
- if (theme === 'light') {
30
- document.querySelectorAll('style').forEach(function (el) {
31
- if (el.innerText.includes(':root, html[data-theme="light"]')) {
32
- el.innerText = el.textContent.replace(':root,', '');
33
- }
34
- });
61
+ document.querySelectorAll('style').forEach(function (el) {
62
+ if (el.innerText.includes(':root, html[data-theme="light"]')) {
63
+ // HACK: Allows us to disable the light mode style since it uses root:
64
+ el.innerText = el.textContent.replace(':root,', ''); // HACK: Allows us to apply the theme to children elements
65
+
66
+ el.innerText = el.textContent.replace('html[data-theme="light"]', 'html[data-theme="light"],.ads-theme-override[data-theme="light"]');
35
67
  }
68
+ });
69
+ document.querySelectorAll('style').forEach(function (el) {
70
+ if (el.innerText.includes('html[data-theme="dark"]')) {
71
+ // HACK: Allows us to apply the theme to children elements
72
+ el.innerText = el.textContent.replace('html[data-theme="dark"]', 'html[data-theme="dark"],.ads-theme-override[data-theme="dark"]');
73
+ }
74
+ });
75
+ }, [context.id]); // eslint-disable-next-line react-hooks/rules-of-hooks
76
+
77
+ (0, _addons.useEffect)(function () {
78
+ if (!theme || theme === 'none') {
79
+ delete document.documentElement.dataset.theme;
80
+ return;
81
+ }
82
+
83
+ document.documentElement.dataset.theme = theme;
84
+ }, [context.id, theme]);
85
+
86
+ function renderStory() {
87
+ var story = storyFn(context);
88
+
89
+ switch (theme) {
90
+ case 'split':
91
+ {
92
+ return /*#__PURE__*/_react.default.createElement(_react.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
93
+ className: "ads-theme-override",
94
+ "data-theme": "light",
95
+ style: _objectSpread(_objectSpread({}, splitColumnStyles), {}, {
96
+ inset: '0px 50vw 0px 0px'
97
+ })
98
+ }, story), /*#__PURE__*/_react.default.createElement("div", {
99
+ className: "ads-theme-override",
100
+ "data-theme": "dark",
101
+ style: _objectSpread(_objectSpread({}, splitColumnStyles), {}, {
102
+ inset: '0px 0px 0px 50vw'
103
+ })
104
+ }, story));
105
+ }
36
106
 
37
- document.documentElement.dataset.theme = theme;
38
- };
107
+ case 'stack':
108
+ {
109
+ return /*#__PURE__*/_react.default.createElement(_react.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
110
+ className: "ads-theme-override",
111
+ "data-theme": "light",
112
+ style: _objectSpread(_objectSpread({}, stackColumnStyles), {}, {
113
+ inset: '0px 0px 50% 0px'
114
+ })
115
+ }, story), /*#__PURE__*/_react.default.createElement("div", {
116
+ className: "ads-theme-override",
117
+ "data-theme": "dark",
118
+ style: _objectSpread(_objectSpread({}, stackColumnStyles), {}, {
119
+ inset: '50% 0px 0px 0px'
120
+ })
121
+ }, story));
122
+ }
39
123
 
40
- var channel = _addons.addons.getChannel();
124
+ default:
125
+ {
126
+ return /*#__PURE__*/_react.default.createElement("div", {
127
+ "data-theme": theme
128
+ }, story);
129
+ }
130
+ }
131
+ }
41
132
 
42
- channel.on(_constants.EVENT_THEME_CHANGED, setTheme);
43
- return function () {
44
- channel.off(_constants.EVENT_THEME_CHANGED, setTheme);
45
- };
46
- }, [context.id]);
47
- return storyFn(context);
133
+ return renderStory();
48
134
  }
49
135
  });
50
136
  var _default = withDesignTokens;
@@ -1,52 +1,19 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
5
- var _react = _interopRequireDefault(require("react"));
6
-
7
3
  var _addons = require("@storybook/addons");
8
4
 
9
- var _components = require("@storybook/components");
5
+ var _components = require("./components");
10
6
 
11
7
  var _constants = require("./constants");
12
8
 
13
- // eslint-disable-next-line import/no-extraneous-dependencies
14
- // eslint-disable-next-line import/no-extraneous-dependencies
15
- var TokensPanel = function TokensPanel(_ref) {
16
- var onThemeChange = _ref.onThemeChange;
17
- return /*#__PURE__*/_react.default.createElement("div", {
18
- style: {
19
- padding: '20px'
20
- }
21
- }, /*#__PURE__*/_react.default.createElement("h1", null, "ADS Design Tokens"), /*#__PURE__*/_react.default.createElement("select", {
22
- name: "theme",
23
- onChange: function onChange(event) {
24
- return onThemeChange(event.target.value);
25
- }
26
- }, /*#__PURE__*/_react.default.createElement("option", {
27
- value: "none"
28
- }, "Disable theme"), /*#__PURE__*/_react.default.createElement("option", {
29
- value: "light"
30
- }, "Light theme"), /*#__PURE__*/_react.default.createElement("option", {
31
- value: "dark"
32
- }, "Dark theme")));
33
- };
34
-
35
- _addons.addons.register(_constants.ADDON_ID, function (api) {
36
- _addons.addons.add(_constants.PANEL_ID, {
37
- type: _addons.types.PANEL,
38
- title: _constants.PANEL_TITLE,
39
- render: function render(_ref2) {
40
- var active = _ref2.active,
41
- key = _ref2.key;
42
- return /*#__PURE__*/_react.default.createElement(_components.AddonPanel, {
43
- active: active || false,
44
- key: key
45
- }, /*#__PURE__*/_react.default.createElement(TokensPanel, {
46
- onThemeChange: function onThemeChange(theme) {
47
- return api.emit(_constants.EVENT_THEME_CHANGED, theme);
48
- }
49
- }));
50
- }
9
+ _addons.addons.register(_constants.ADDON_ID, function () {
10
+ _addons.addons.add(_constants.TOOL_ID, {
11
+ type: _addons.types.TOOL,
12
+ title: _constants.TITLE,
13
+ match: function match(_ref) {
14
+ var viewMode = _ref.viewMode;
15
+ return !!(viewMode && viewMode.match(/^(story|docs)$/));
16
+ },
17
+ render: _components.Tool
51
18
  });
52
19
  });
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/storybook-addon-design-system",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1 @@
1
+ export { default as Tool } from './tool';
@@ -0,0 +1,84 @@
1
+ import React, { useCallback, useState } from 'react';
2
+ import { useGlobals } from '@storybook/api';
3
+ import { IconButton, Icons, TooltipLinkList, WithTooltip } from '@storybook/components';
4
+ import { TOOL_ID } from '../constants';
5
+ const themeOptions = [{
6
+ id: 'none',
7
+ title: 'Disable',
8
+ icon: 'cross'
9
+ }, {
10
+ id: 'light',
11
+ title: 'Light theme',
12
+ icon: 'circlehollow'
13
+ }, {
14
+ id: 'dark',
15
+ title: 'Dark theme',
16
+ icon: 'circle'
17
+ }, {
18
+ id: 'split',
19
+ title: 'Side by side',
20
+ icon: 'sidebar'
21
+ }, {
22
+ id: 'stack',
23
+ title: 'Stacked',
24
+ icon: 'bottombar'
25
+ }];
26
+ /**
27
+ * __Tool__
28
+ *
29
+ * ADS Toolbar UI, visible in the topbar of the storybook UI.
30
+ */
31
+
32
+ const Tool = () => {
33
+ var _themeOptions$find;
34
+
35
+ const [isVisible, setIsVisible] = useState(false);
36
+ const [{
37
+ adsTheme
38
+ }, updateGlobals] = useGlobals();
39
+ const setTheme = useCallback(theme => updateGlobals({
40
+ adsTheme: theme
41
+ }), [updateGlobals]);
42
+ return /*#__PURE__*/React.createElement(WithTooltip, {
43
+ placement: "top",
44
+ trigger: "click",
45
+ closeOnClick: true,
46
+ onVisibilityChange: setIsVisible,
47
+ tooltip: ({
48
+ onHide
49
+ }) => /*#__PURE__*/React.createElement(TooltipLinkList, {
50
+ links: themeOptions.map(({
51
+ id,
52
+ title,
53
+ icon
54
+ }) => {
55
+ const Icon = /*#__PURE__*/React.createElement(Icons, {
56
+ style: {
57
+ opacity: 1
58
+ },
59
+ icon: icon
60
+ });
61
+ return {
62
+ id,
63
+ title,
64
+ active: adsTheme === id,
65
+ right: Icon,
66
+ onClick: () => {
67
+ setTheme(id);
68
+ onHide();
69
+ }
70
+ };
71
+ })
72
+ })
73
+ }, /*#__PURE__*/React.createElement(IconButton, {
74
+ key: TOOL_ID,
75
+ active: isVisible,
76
+ title: "Apply ADS themes to your story"
77
+ }, /*#__PURE__*/React.createElement(Icons, {
78
+ icon: ((_themeOptions$find = themeOptions.find(({
79
+ id
80
+ }) => id === adsTheme)) === null || _themeOptions$find === void 0 ? void 0 : _themeOptions$find.icon) || 'circlehollow'
81
+ }), '\xa0ADS Theme'));
82
+ };
83
+
84
+ export default Tool;
@@ -1,6 +1,5 @@
1
1
  export const ADDON_ID = 'ads-tokens';
2
- export const PANEL_ID = `${ADDON_ID}/panel`;
3
- export const PANEL_TITLE = `Design Tokens`;
4
- export const EVENT_THEME_CHANGED = `${ADDON_ID}/on-theme-change`;
2
+ export const TOOL_ID = `${ADDON_ID}/tool`;
3
+ export const TITLE = 'Design Tokens';
5
4
  export const DECORATOR_ID = 'withDesignTokens';
6
5
  export const DECORATOR_PARAM = 'DesignTokens';
@@ -1,40 +1,111 @@
1
- import { addons, makeDecorator, useEffect } from '@storybook/addons'; // // eslint-disable-next-line
2
- // import '../../../node_modules/@atlaskit/tokens/css/atlassian-light.css';
3
- // // eslint-disable-next-line
4
- // import '../../../node_modules/@atlaskit/tokens/css/atlassian-dark.css';
1
+ import React, { Fragment } from 'react';
2
+ import { makeDecorator, useEffect } from '@storybook/addons';
3
+ import { token } from '@atlaskit/tokens'; // eslint-disable-next-line
5
4
 
6
- import { DECORATOR_ID, DECORATOR_PARAM, EVENT_THEME_CHANGED } from './constants';
5
+ import '@atlaskit/tokens/css/atlassian-light.css'; // eslint-disable-next-line
6
+
7
+ import '@atlaskit/tokens/css/atlassian-dark.css';
8
+ import { DECORATOR_ID, DECORATOR_PARAM } from './constants';
9
+ const splitColumnStyles = {
10
+ position: 'absolute',
11
+ boxSizing: 'border-box',
12
+ width: '50vw',
13
+ height: '100vh',
14
+ overflow: 'auto',
15
+ padding: '10px',
16
+ background: token('color.background.default'),
17
+ color: token('color.text.highEmphasis')
18
+ };
19
+ const stackColumnStyles = {
20
+ position: 'absolute',
21
+ boxSizing: 'border-box',
22
+ width: '100%',
23
+ height: '50%',
24
+ overflow: 'auto',
25
+ padding: '10px',
26
+ background: token('color.background.default'),
27
+ color: token('color.text.highEmphasis')
28
+ };
7
29
  const withDesignTokens = makeDecorator({
8
30
  name: DECORATOR_ID,
9
31
  parameterName: DECORATOR_PARAM,
10
32
  wrapper: (storyFn, context) => {
11
- // eslint-disable-next-line react-hooks/rules-of-hooks
33
+ const theme = context.globals.adsTheme; // eslint-disable-next-line react-hooks/rules-of-hooks
34
+
12
35
  useEffect(() => {
13
- const setTheme = theme => {
14
- if (!theme || theme === 'none') {
15
- delete document.documentElement.dataset.theme;
16
- return;
17
- } // HACK: Allows us to disable the light mode style since it uses root:
18
-
19
-
20
- if (theme === 'light') {
21
- document.querySelectorAll('style').forEach(el => {
22
- if (el.innerText.includes(':root, html[data-theme="light"]')) {
23
- el.innerText = el.textContent.replace(':root,', '');
24
- }
25
- });
36
+ document.querySelectorAll('style').forEach(el => {
37
+ if (el.innerText.includes(':root, html[data-theme="light"]')) {
38
+ // HACK: Allows us to disable the light mode style since it uses root:
39
+ el.innerText = el.textContent.replace(':root,', ''); // HACK: Allows us to apply the theme to children elements
40
+
41
+ el.innerText = el.textContent.replace('html[data-theme="light"]', 'html[data-theme="light"],.ads-theme-override[data-theme="light"]');
26
42
  }
43
+ });
44
+ document.querySelectorAll('style').forEach(el => {
45
+ if (el.innerText.includes('html[data-theme="dark"]')) {
46
+ // HACK: Allows us to apply the theme to children elements
47
+ el.innerText = el.textContent.replace('html[data-theme="dark"]', 'html[data-theme="dark"],.ads-theme-override[data-theme="dark"]');
48
+ }
49
+ });
50
+ }, [context.id]); // eslint-disable-next-line react-hooks/rules-of-hooks
51
+
52
+ useEffect(() => {
53
+ if (!theme || theme === 'none') {
54
+ delete document.documentElement.dataset.theme;
55
+ return;
56
+ }
57
+
58
+ document.documentElement.dataset.theme = theme;
59
+ }, [context.id, theme]);
60
+
61
+ function renderStory() {
62
+ const story = storyFn(context);
63
+
64
+ switch (theme) {
65
+ case 'split':
66
+ {
67
+ return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", {
68
+ className: "ads-theme-override",
69
+ "data-theme": "light",
70
+ style: { ...splitColumnStyles,
71
+ inset: '0px 50vw 0px 0px'
72
+ }
73
+ }, story), /*#__PURE__*/React.createElement("div", {
74
+ className: "ads-theme-override",
75
+ "data-theme": "dark",
76
+ style: { ...splitColumnStyles,
77
+ inset: '0px 0px 0px 50vw'
78
+ }
79
+ }, story));
80
+ }
81
+
82
+ case 'stack':
83
+ {
84
+ return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", {
85
+ className: "ads-theme-override",
86
+ "data-theme": "light",
87
+ style: { ...stackColumnStyles,
88
+ inset: '0px 0px 50% 0px'
89
+ }
90
+ }, story), /*#__PURE__*/React.createElement("div", {
91
+ className: "ads-theme-override",
92
+ "data-theme": "dark",
93
+ style: { ...stackColumnStyles,
94
+ inset: '50% 0px 0px 0px'
95
+ }
96
+ }, story));
97
+ }
27
98
 
28
- document.documentElement.dataset.theme = theme;
29
- };
99
+ default:
100
+ {
101
+ return /*#__PURE__*/React.createElement("div", {
102
+ "data-theme": theme
103
+ }, story);
104
+ }
105
+ }
106
+ }
30
107
 
31
- const channel = addons.getChannel();
32
- channel.on(EVENT_THEME_CHANGED, setTheme);
33
- return () => {
34
- channel.off(EVENT_THEME_CHANGED, setTheme);
35
- };
36
- }, [context.id]);
37
- return storyFn(context);
108
+ return renderStory();
38
109
  }
39
110
  });
40
111
  export default withDesignTokens;
@@ -1,39 +1,13 @@
1
- import React from 'react'; // eslint-disable-next-line import/no-extraneous-dependencies
2
-
3
- import { addons, types } from '@storybook/addons'; // eslint-disable-next-line import/no-extraneous-dependencies
4
-
5
- import { AddonPanel } from '@storybook/components';
6
- import { ADDON_ID, EVENT_THEME_CHANGED, PANEL_ID, PANEL_TITLE } from './constants';
7
-
8
- const TokensPanel = ({
9
- onThemeChange
10
- }) => /*#__PURE__*/React.createElement("div", {
11
- style: {
12
- padding: '20px'
13
- }
14
- }, /*#__PURE__*/React.createElement("h1", null, "ADS Design Tokens"), /*#__PURE__*/React.createElement("select", {
15
- name: "theme",
16
- onChange: event => onThemeChange(event.target.value)
17
- }, /*#__PURE__*/React.createElement("option", {
18
- value: "none"
19
- }, "Disable theme"), /*#__PURE__*/React.createElement("option", {
20
- value: "light"
21
- }, "Light theme"), /*#__PURE__*/React.createElement("option", {
22
- value: "dark"
23
- }, "Dark theme")));
24
-
25
- addons.register(ADDON_ID, api => {
26
- addons.add(PANEL_ID, {
27
- type: types.PANEL,
28
- title: PANEL_TITLE,
29
- render: ({
30
- active,
31
- key
32
- }) => /*#__PURE__*/React.createElement(AddonPanel, {
33
- active: active || false,
34
- key: key
35
- }, /*#__PURE__*/React.createElement(TokensPanel, {
36
- onThemeChange: theme => api.emit(EVENT_THEME_CHANGED, theme)
37
- }))
1
+ import { addons, types } from '@storybook/addons';
2
+ import { Tool } from './components';
3
+ import { ADDON_ID, TITLE, TOOL_ID } from './constants';
4
+ addons.register(ADDON_ID, () => {
5
+ addons.add(TOOL_ID, {
6
+ type: types.TOOL,
7
+ title: TITLE,
8
+ match: ({
9
+ viewMode
10
+ }) => !!(viewMode && viewMode.match(/^(story|docs)$/)),
11
+ render: Tool
38
12
  });
39
13
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/storybook-addon-design-system",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1 @@
1
+ export { default as Tool } from './tool';
@@ -0,0 +1,94 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import React, { useCallback, useState } from 'react';
3
+ import { useGlobals } from '@storybook/api';
4
+ import { IconButton, Icons, TooltipLinkList, WithTooltip } from '@storybook/components';
5
+ import { TOOL_ID } from '../constants';
6
+ var themeOptions = [{
7
+ id: 'none',
8
+ title: 'Disable',
9
+ icon: 'cross'
10
+ }, {
11
+ id: 'light',
12
+ title: 'Light theme',
13
+ icon: 'circlehollow'
14
+ }, {
15
+ id: 'dark',
16
+ title: 'Dark theme',
17
+ icon: 'circle'
18
+ }, {
19
+ id: 'split',
20
+ title: 'Side by side',
21
+ icon: 'sidebar'
22
+ }, {
23
+ id: 'stack',
24
+ title: 'Stacked',
25
+ icon: 'bottombar'
26
+ }];
27
+ /**
28
+ * __Tool__
29
+ *
30
+ * ADS Toolbar UI, visible in the topbar of the storybook UI.
31
+ */
32
+
33
+ var Tool = function Tool() {
34
+ var _themeOptions$find;
35
+
36
+ var _useState = useState(false),
37
+ _useState2 = _slicedToArray(_useState, 2),
38
+ isVisible = _useState2[0],
39
+ setIsVisible = _useState2[1];
40
+
41
+ var _useGlobals = useGlobals(),
42
+ _useGlobals2 = _slicedToArray(_useGlobals, 2),
43
+ adsTheme = _useGlobals2[0].adsTheme,
44
+ updateGlobals = _useGlobals2[1];
45
+
46
+ var setTheme = useCallback(function (theme) {
47
+ return updateGlobals({
48
+ adsTheme: theme
49
+ });
50
+ }, [updateGlobals]);
51
+ return /*#__PURE__*/React.createElement(WithTooltip, {
52
+ placement: "top",
53
+ trigger: "click",
54
+ closeOnClick: true,
55
+ onVisibilityChange: setIsVisible,
56
+ tooltip: function tooltip(_ref) {
57
+ var onHide = _ref.onHide;
58
+ return /*#__PURE__*/React.createElement(TooltipLinkList, {
59
+ links: themeOptions.map(function (_ref2) {
60
+ var id = _ref2.id,
61
+ title = _ref2.title,
62
+ icon = _ref2.icon;
63
+ var Icon = /*#__PURE__*/React.createElement(Icons, {
64
+ style: {
65
+ opacity: 1
66
+ },
67
+ icon: icon
68
+ });
69
+ return {
70
+ id: id,
71
+ title: title,
72
+ active: adsTheme === id,
73
+ right: Icon,
74
+ onClick: function onClick() {
75
+ setTheme(id);
76
+ onHide();
77
+ }
78
+ };
79
+ })
80
+ });
81
+ }
82
+ }, /*#__PURE__*/React.createElement(IconButton, {
83
+ key: TOOL_ID,
84
+ active: isVisible,
85
+ title: "Apply ADS themes to your story"
86
+ }, /*#__PURE__*/React.createElement(Icons, {
87
+ icon: ((_themeOptions$find = themeOptions.find(function (_ref3) {
88
+ var id = _ref3.id;
89
+ return id === adsTheme;
90
+ })) === null || _themeOptions$find === void 0 ? void 0 : _themeOptions$find.icon) || 'circlehollow'
91
+ }), '\xa0ADS Theme'));
92
+ };
93
+
94
+ export default Tool;
@@ -1,6 +1,5 @@
1
1
  export var ADDON_ID = 'ads-tokens';
2
- export var PANEL_ID = "".concat(ADDON_ID, "/panel");
3
- export var PANEL_TITLE = "Design Tokens";
4
- export var EVENT_THEME_CHANGED = "".concat(ADDON_ID, "/on-theme-change");
2
+ export var TOOL_ID = "".concat(ADDON_ID, "/tool");
3
+ export var TITLE = 'Design Tokens';
5
4
  export var DECORATOR_ID = 'withDesignTokens';
6
5
  export var DECORATOR_PARAM = 'DesignTokens';
@@ -1,40 +1,117 @@
1
- import { addons, makeDecorator, useEffect } from '@storybook/addons'; // // eslint-disable-next-line
2
- // import '../../../node_modules/@atlaskit/tokens/css/atlassian-light.css';
3
- // // eslint-disable-next-line
4
- // import '../../../node_modules/@atlaskit/tokens/css/atlassian-dark.css';
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
5
2
 
6
- import { DECORATOR_ID, DECORATOR_PARAM, EVENT_THEME_CHANGED } from './constants';
3
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
4
+
5
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
6
+
7
+ import React, { Fragment } from 'react';
8
+ import { makeDecorator, useEffect } from '@storybook/addons';
9
+ import { token } from '@atlaskit/tokens'; // eslint-disable-next-line
10
+
11
+ import '@atlaskit/tokens/css/atlassian-light.css'; // eslint-disable-next-line
12
+
13
+ import '@atlaskit/tokens/css/atlassian-dark.css';
14
+ import { DECORATOR_ID, DECORATOR_PARAM } from './constants';
15
+ var splitColumnStyles = {
16
+ position: 'absolute',
17
+ boxSizing: 'border-box',
18
+ width: '50vw',
19
+ height: '100vh',
20
+ overflow: 'auto',
21
+ padding: '10px',
22
+ background: token('color.background.default'),
23
+ color: token('color.text.highEmphasis')
24
+ };
25
+ var stackColumnStyles = {
26
+ position: 'absolute',
27
+ boxSizing: 'border-box',
28
+ width: '100%',
29
+ height: '50%',
30
+ overflow: 'auto',
31
+ padding: '10px',
32
+ background: token('color.background.default'),
33
+ color: token('color.text.highEmphasis')
34
+ };
7
35
  var withDesignTokens = makeDecorator({
8
36
  name: DECORATOR_ID,
9
37
  parameterName: DECORATOR_PARAM,
10
38
  wrapper: function wrapper(storyFn, context) {
11
- // eslint-disable-next-line react-hooks/rules-of-hooks
39
+ var theme = context.globals.adsTheme; // eslint-disable-next-line react-hooks/rules-of-hooks
40
+
12
41
  useEffect(function () {
13
- var setTheme = function setTheme(theme) {
14
- if (!theme || theme === 'none') {
15
- delete document.documentElement.dataset.theme;
16
- return;
17
- } // HACK: Allows us to disable the light mode style since it uses root:
18
-
19
-
20
- if (theme === 'light') {
21
- document.querySelectorAll('style').forEach(function (el) {
22
- if (el.innerText.includes(':root, html[data-theme="light"]')) {
23
- el.innerText = el.textContent.replace(':root,', '');
24
- }
25
- });
42
+ document.querySelectorAll('style').forEach(function (el) {
43
+ if (el.innerText.includes(':root, html[data-theme="light"]')) {
44
+ // HACK: Allows us to disable the light mode style since it uses root:
45
+ el.innerText = el.textContent.replace(':root,', ''); // HACK: Allows us to apply the theme to children elements
46
+
47
+ el.innerText = el.textContent.replace('html[data-theme="light"]', 'html[data-theme="light"],.ads-theme-override[data-theme="light"]');
48
+ }
49
+ });
50
+ document.querySelectorAll('style').forEach(function (el) {
51
+ if (el.innerText.includes('html[data-theme="dark"]')) {
52
+ // HACK: Allows us to apply the theme to children elements
53
+ el.innerText = el.textContent.replace('html[data-theme="dark"]', 'html[data-theme="dark"],.ads-theme-override[data-theme="dark"]');
26
54
  }
55
+ });
56
+ }, [context.id]); // eslint-disable-next-line react-hooks/rules-of-hooks
57
+
58
+ useEffect(function () {
59
+ if (!theme || theme === 'none') {
60
+ delete document.documentElement.dataset.theme;
61
+ return;
62
+ }
63
+
64
+ document.documentElement.dataset.theme = theme;
65
+ }, [context.id, theme]);
66
+
67
+ function renderStory() {
68
+ var story = storyFn(context);
69
+
70
+ switch (theme) {
71
+ case 'split':
72
+ {
73
+ return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", {
74
+ className: "ads-theme-override",
75
+ "data-theme": "light",
76
+ style: _objectSpread(_objectSpread({}, splitColumnStyles), {}, {
77
+ inset: '0px 50vw 0px 0px'
78
+ })
79
+ }, story), /*#__PURE__*/React.createElement("div", {
80
+ className: "ads-theme-override",
81
+ "data-theme": "dark",
82
+ style: _objectSpread(_objectSpread({}, splitColumnStyles), {}, {
83
+ inset: '0px 0px 0px 50vw'
84
+ })
85
+ }, story));
86
+ }
87
+
88
+ case 'stack':
89
+ {
90
+ return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement("div", {
91
+ className: "ads-theme-override",
92
+ "data-theme": "light",
93
+ style: _objectSpread(_objectSpread({}, stackColumnStyles), {}, {
94
+ inset: '0px 0px 50% 0px'
95
+ })
96
+ }, story), /*#__PURE__*/React.createElement("div", {
97
+ className: "ads-theme-override",
98
+ "data-theme": "dark",
99
+ style: _objectSpread(_objectSpread({}, stackColumnStyles), {}, {
100
+ inset: '50% 0px 0px 0px'
101
+ })
102
+ }, story));
103
+ }
27
104
 
28
- document.documentElement.dataset.theme = theme;
29
- };
105
+ default:
106
+ {
107
+ return /*#__PURE__*/React.createElement("div", {
108
+ "data-theme": theme
109
+ }, story);
110
+ }
111
+ }
112
+ }
30
113
 
31
- var channel = addons.getChannel();
32
- channel.on(EVENT_THEME_CHANGED, setTheme);
33
- return function () {
34
- channel.off(EVENT_THEME_CHANGED, setTheme);
35
- };
36
- }, [context.id]);
37
- return storyFn(context);
114
+ return renderStory();
38
115
  }
39
116
  });
40
117
  export default withDesignTokens;
@@ -1,45 +1,14 @@
1
- import React from 'react'; // eslint-disable-next-line import/no-extraneous-dependencies
2
-
3
- import { addons, types } from '@storybook/addons'; // eslint-disable-next-line import/no-extraneous-dependencies
4
-
5
- import { AddonPanel } from '@storybook/components';
6
- import { ADDON_ID, EVENT_THEME_CHANGED, PANEL_ID, PANEL_TITLE } from './constants';
7
-
8
- var TokensPanel = function TokensPanel(_ref) {
9
- var onThemeChange = _ref.onThemeChange;
10
- return /*#__PURE__*/React.createElement("div", {
11
- style: {
12
- padding: '20px'
13
- }
14
- }, /*#__PURE__*/React.createElement("h1", null, "ADS Design Tokens"), /*#__PURE__*/React.createElement("select", {
15
- name: "theme",
16
- onChange: function onChange(event) {
17
- return onThemeChange(event.target.value);
18
- }
19
- }, /*#__PURE__*/React.createElement("option", {
20
- value: "none"
21
- }, "Disable theme"), /*#__PURE__*/React.createElement("option", {
22
- value: "light"
23
- }, "Light theme"), /*#__PURE__*/React.createElement("option", {
24
- value: "dark"
25
- }, "Dark theme")));
26
- };
27
-
28
- addons.register(ADDON_ID, function (api) {
29
- addons.add(PANEL_ID, {
30
- type: types.PANEL,
31
- title: PANEL_TITLE,
32
- render: function render(_ref2) {
33
- var active = _ref2.active,
34
- key = _ref2.key;
35
- return /*#__PURE__*/React.createElement(AddonPanel, {
36
- active: active || false,
37
- key: key
38
- }, /*#__PURE__*/React.createElement(TokensPanel, {
39
- onThemeChange: function onThemeChange(theme) {
40
- return api.emit(EVENT_THEME_CHANGED, theme);
41
- }
42
- }));
43
- }
1
+ import { addons, types } from '@storybook/addons';
2
+ import { Tool } from './components';
3
+ import { ADDON_ID, TITLE, TOOL_ID } from './constants';
4
+ addons.register(ADDON_ID, function () {
5
+ addons.add(TOOL_ID, {
6
+ type: types.TOOL,
7
+ title: TITLE,
8
+ match: function match(_ref) {
9
+ var viewMode = _ref.viewMode;
10
+ return !!(viewMode && viewMode.match(/^(story|docs)$/));
11
+ },
12
+ render: Tool
44
13
  });
45
14
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/storybook-addon-design-system",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1 @@
1
+ export { default as Tool } from './tool';
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ /**
3
+ * __Tool__
4
+ *
5
+ * ADS Toolbar UI, visible in the topbar of the storybook UI.
6
+ */
7
+ declare const Tool: () => JSX.Element;
8
+ export default Tool;
@@ -1,6 +1,5 @@
1
1
  export declare const ADDON_ID = "ads-tokens";
2
- export declare const PANEL_ID: string;
3
- export declare const PANEL_TITLE = "Design Tokens";
4
- export declare const EVENT_THEME_CHANGED: string;
2
+ export declare const TOOL_ID: string;
3
+ export declare const TITLE = "Design Tokens";
5
4
  export declare const DECORATOR_ID = "withDesignTokens";
6
5
  export declare const DECORATOR_PARAM = "DesignTokens";
@@ -1,2 +1,4 @@
1
+ import '@atlaskit/tokens/css/atlassian-light.css';
2
+ import '@atlaskit/tokens/css/atlassian-dark.css';
1
3
  declare const withDesignTokens: (...args: any) => any;
2
4
  export default withDesignTokens;
@@ -0,0 +1 @@
1
+ export declare type Themes = 'light' | 'dark' | 'none' | 'split' | 'stack';
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@atlaskit/storybook-addon-design-system",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
+ "description": "Design token storybook addon",
4
5
  "author": "Atlassian Pty Ltd",
5
6
  "publishConfig": {
6
7
  "registry": "https://registry.npmjs.org/"
@@ -20,8 +21,10 @@
20
21
  ".": "./src/index.tsx"
21
22
  },
22
23
  "dependencies": {
24
+ "@atlaskit/tokens": "^0.4.0",
23
25
  "@babel/runtime": "^7.0.0",
24
26
  "@storybook/addons": "^6.4.0",
27
+ "@storybook/api": "^6.4.0",
25
28
  "@storybook/components": "^6.4.0"
26
29
  },
27
30
  "devDependencies": {