Skip to content

Commit 431af2c

Browse files
committed
Bug 1805491 - create addon to show component status in Storybook r=tgiles,mstriemer
Differential Revision: https://phabricator.services.mozilla.com/D175931 UltraBlame original commit: 3c4b3e7a5169c3858d7298319656c715d544c3fe
1 parent dedb3a1 commit 431af2c

File tree

6 files changed

+176
-0
lines changed

6 files changed

+176
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
// eslint-disable-next-line no-unused-vars
6+
import React from "react";
7+
import { useParameter } from "@storybook/api";
8+
import {
9+
// eslint-disable-next-line no-unused-vars
10+
Badge,
11+
// eslint-disable-next-line no-unused-vars
12+
WithTooltip,
13+
// eslint-disable-next-line no-unused-vars
14+
TooltipMessage,
15+
// eslint-disable-next-line no-unused-vars
16+
IconButton,
17+
} from "@storybook/components";
18+
import { TOOL_ID, STATUS_PARAM_KEY } from "./constants.mjs";
19+
20+
const VALID_STATUS_MAP = {
21+
stable: {
22+
label: "Stable",
23+
badgeType: "positive",
24+
description:
25+
"This component is widely used in Firefox, in both the chrome and in-content pages.",
26+
},
27+
"in-development": {
28+
label: "In Development",
29+
badgeType: "warning",
30+
description:
31+
"This component is in active development and starting to be used in Firefox. It may not yet be usable in both the chrome and in-content pages.",
32+
},
33+
unstable: {
34+
label: "Unstable",
35+
badgeType: "negative",
36+
description:
37+
"This component is still in the early stages of development and may not be ready for general use in Firefox.",
38+
},
39+
};
40+
41+
/**
42+
* Displays a badge with the components status in the Storybook toolbar.
43+
*
44+
* Statuses are set via story parameters.
45+
* We support either passing `status: "statusType"` for using defaults or
46+
* `status: {
47+
type: "stable" | "in-development" | "unstable",
48+
description: "Your description here"
49+
links: [
50+
{
51+
title: "Link title",
52+
href: "www.example.com",
53+
},
54+
],
55+
}`
56+
* when we want to customize the description or add links.
57+
*/
58+
export const StatusIndicator = () => {
59+
let componentStatus = useParameter(STATUS_PARAM_KEY, null);
60+
let statusData = VALID_STATUS_MAP[componentStatus?.type ?? componentStatus];
61+
62+
if (!componentStatus || !statusData) {
63+
return "";
64+
}
65+
66+
// The tooltip message is added/removed from the DOM when visibility changes.
67+
// We need to update the aira-describedby button relationship accordingly.
68+
let onVisibilityChange = isVisible => {
69+
let button = document.getElementById("statusButton");
70+
if (isVisible) {
71+
button.setAttribute("aria-describedby", "statusMessage");
72+
} else {
73+
button.removeAttribute("aria-describedby");
74+
}
75+
};
76+
77+
let description = componentStatus.description || statusData.description;
78+
let links = componentStatus.links || [];
79+
80+
return (
81+
<WithTooltip
82+
key={TOOL_ID}
83+
placement="top"
84+
trigger="click"
85+
style={{
86+
display: "flex",
87+
}}
88+
onVisibilityChange={onVisibilityChange}
89+
tooltip={() => (
90+
<div id="statusMessage">
91+
<TooltipMessage
92+
title={statusData.label}
93+
desc={description}
94+
links={links}
95+
/>
96+
</div>
97+
)}
98+
>
99+
<IconButton
100+
id="statusButton"
101+
title={`Component status: ${statusData.label}`}
102+
>
103+
<Badge
104+
status={statusData.badgeType}
105+
style={{
106+
boxShadow: "currentColor 0 0 0 1px inset",
107+
}}
108+
>
109+
{statusData.label}
110+
</Badge>
111+
</IconButton>
112+
</WithTooltip>
113+
);
114+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
export const ADDON_ID = "addon-component-status";
6+
export const TOOL_ID = `${ADDON_ID}/statusIndicator`;
7+
export const STATUS_PARAM_KEY = "status";
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
3+
4+
5+
6+
7+
8+
9+
10+
11+
12+
function config(entry = []) {
13+
return [...entry, require.resolve("./preset/preview.mjs")];
14+
}
15+
16+
function managerEntries(entry = []) {
17+
return [...entry, require.resolve("./preset/manager.mjs")];
18+
}
19+
20+
module.exports = {
21+
managerEntries,
22+
config,
23+
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
/** This file handles registering the Storybook addon */
6+
7+
// eslint-disable-next-line no-unused-vars
8+
import React from "react";
9+
import { addons, types } from "@storybook/addons";
10+
import { ADDON_ID, TOOL_ID } from "../constants.mjs";
11+
import { StatusIndicator } from "../StatusIndicator.mjs";
12+
13+
addons.register(ADDON_ID, () => {
14+
addons.add(TOOL_ID, {
15+
type: types.TOOL,
16+
title: "Pseudo Localization",
17+
render: StatusIndicator,
18+
});
19+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
export const globalTypes = {
6+
componentStatus: {
7+
name: "Component status",
8+
description:
9+
"Provides a visual indicator of the component's readiness status.",
10+
defaultValue: "default",
11+
},
12+
};

browser/components/storybook/.storybook/main.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ module.exports = {
6161
},
6262
"@storybook/addon-a11y",
6363
path.resolve(__dirname, "addon-pseudo-localization"),
64+
path.resolve(__dirname, "addon-component-status"),
6465
],
6566
framework: "@storybook/web-components",
6667
webpackFinal: async (config, { configType }) => {

0 commit comments

Comments
 (0)