diff --git a/.storybook/manager.js b/.storybook/manager.js
index c67c2bf..c1f6b43 100644
--- a/.storybook/manager.js
+++ b/.storybook/manager.js
@@ -9,6 +9,8 @@ addons.setConfig({
description: 'This component is stable and released',
},
},
+ // 'single' | 'multiple' | 'none'. When set, takes precedence over sidebarDots.
+ sidebarTags: 'multiple',
sidebarDots: 'multiple', // 'single' | 'multiple' | 'none'. 'single' is the default
},
});
diff --git a/Readme.md b/Readme.md
index 2bfc708..6f29a90 100644
--- a/Readme.md
+++ b/Readme.md
@@ -22,7 +22,7 @@ export default {
};
```
-In `manager.js` you can globally configure custom status configurations, or overwrite the built in "beta", "deprecated", "stable" & "releaseCandidate". You can also change how status dots will appear in the sidebar with the `sidebarDots` prop.
+In `manager.js` you can globally configure custom status configurations, or overwrite the built in "beta", "deprecated", "stable" & "releaseCandidate". You can also change how statuses appear in the sidebar with the `sidebarDots` and `sidebarTags` props.
```js
import { addons } from "storybook/manager-api";
@@ -37,10 +37,15 @@ addons.setConfig({
},
},
sidebarDots: 'single', // 'single' | 'multiple' | 'none'. 'single' is the default
+ sidebarTags: 'single', // 'single' | 'multiple' | 'none'. When set, overrides sidebarDots and renders full status tags in the sidebar instead of dots.
},
});
```
+By default the sidebar shows a small coloured dot next to each story. Setting `sidebarTags` to `'single'` or `'multiple'` switches the sidebar to render the full status tag — the same colour and label as the toolbar tag, but slightly smaller. `sidebarTags: 'none'` hides the indicator entirely (and overrides `sidebarDots`). When `sidebarTags` is not set, `sidebarDots` keeps its existing behaviour.
+
+**Note:** Status URLs are intentionally not used by sidebar tags — clicking a story row in the sidebar should always navigate to that story. Use the toolbar tag (which still renders as a link) to follow the URL.
+
**IMPORTANT:** The addon was previously configured using parameters in `preview.js`. This will still work as before, however newer features such as sidebar dot customisation are not available.
**NOTE:** Each key will be used as the label for the status and will convert camelCase to words.
diff --git a/src/components/SidebarStatusTag.jsx b/src/components/SidebarStatusTag.jsx
new file mode 100644
index 0000000..940180b
--- /dev/null
+++ b/src/components/SidebarStatusTag.jsx
@@ -0,0 +1,13 @@
+import React from 'react';
+
+import StatusTagBase from './StatusTagBase';
+
+const SidebarStatusTag = ({ statusConfig }) => (
+
+);
+
+export default SidebarStatusTag;
diff --git a/src/components/StatusDot.jsx b/src/components/StatusDot.jsx
index 5ec99c9..52d0a3e 100644
--- a/src/components/StatusDot.jsx
+++ b/src/components/StatusDot.jsx
@@ -11,7 +11,6 @@ const StatusDot = styled.span`
: defaultBackground)};
border-radius: 100%;
height: 6px;
- margin-left: 0.5em;
user-select: none;
width: 6px;
`;
diff --git a/src/components/StatusTag.jsx b/src/components/StatusTag.jsx
index ac15287..b5dcfd1 100644
--- a/src/components/StatusTag.jsx
+++ b/src/components/StatusTag.jsx
@@ -1,32 +1,10 @@
-import startCase from 'lodash/startCase';
import React from 'react';
import { useParameter, useStorybookApi, addons } from 'storybook/manager-api';
-import { styled, css } from 'storybook/theming';
import { ADDON_ID } from '../constants';
-import { defaultStatuses, defaultBackground, defaultColor } from '../defaults';
import { getStatusConfigs } from '../getStatusConfigs';
-const tagStyles = css`
- align-self: center;
- border-radius: 0.25em;
- padding: 0 0.5em;
- text-decoration: none;
- user-select: none;
- font-size: 11px;
- text-transform: uppercase;
- line-height: 20px;
- font-weight: 700;
- padding: 0 0.5em;
-`;
-
-const LinkTag = styled.a`
- ${tagStyles}
-`;
-
-const TextTag = styled.span`
- ${tagStyles}
-`;
+import StatusTagBase from './StatusTagBase';
const StatusTag = () => {
const api = useStorybookApi();
@@ -47,39 +25,15 @@ const StatusTag = () => {
return (
<>
- {statusConfigs.map((statusConfig) => {
- const { background, color, description } = statusConfig.status;
- const statusUrl = statusConfig.url;
- const label = startCase(statusConfig.label);
-
- const style = {
- color:
- color ??
- (defaultStatuses[label]
- ? defaultStatuses[label].color
- : defaultColor),
- backgroundColor:
- background ??
- (defaultStatuses[label]
- ? defaultStatuses[label].background
- : defaultBackground),
- };
-
- return statusUrl ? (
-
- {label}
-
- ) : (
-
- {label}
-
- );
- })}
+ {statusConfigs.map((statusConfig) => (
+
+ ))}
>
);
};
diff --git a/src/components/StatusTagBase.jsx b/src/components/StatusTagBase.jsx
new file mode 100644
index 0000000..11f4c0a
--- /dev/null
+++ b/src/components/StatusTagBase.jsx
@@ -0,0 +1,75 @@
+import startCase from 'lodash/startCase';
+import React from 'react';
+import { styled, css } from 'storybook/theming';
+
+import { defaultStatuses, defaultBackground, defaultColor } from '../defaults';
+
+const baseStyles = css`
+ align-self: center;
+ border-radius: 0.25em;
+ font-weight: 700;
+ text-decoration: none;
+ text-transform: uppercase;
+ user-select: none;
+`;
+
+const toolbarStyles = css`
+ font-size: 11px;
+ line-height: 20px;
+ padding: 0 0.5em;
+`;
+
+const sidebarStyles = css`
+ font-size: 10px;
+ line-height: 16px;
+ padding: 0 0.4em;
+`;
+
+const variantStyles = ({ variant }) =>
+ variant === 'sidebar' ? sidebarStyles : toolbarStyles;
+
+const LinkTag = styled.a`
+ ${baseStyles}
+ ${variantStyles}
+`;
+
+const TextTag = styled.span`
+ ${baseStyles}
+ ${variantStyles}
+`;
+
+const StatusTagBase = ({ label, status, url, variant = 'toolbar' }) => {
+ const resolvedColor =
+ status?.color ??
+ (defaultStatuses[label] ? defaultStatuses[label].color : defaultColor);
+ const resolvedBackground =
+ status?.background ??
+ (defaultStatuses[label]
+ ? defaultStatuses[label].background
+ : defaultBackground);
+
+ const style = {
+ color: resolvedColor,
+ backgroundColor: resolvedBackground,
+ };
+
+ const description = status?.description;
+ const displayLabel = startCase(label);
+ const isLink = variant === 'toolbar' && !!url;
+
+ if (isLink) {
+ return (
+
+ {displayLabel}
+
+ );
+ }
+
+ return (
+
+ {displayLabel}
+
+ );
+};
+
+export default StatusTagBase;
diff --git a/src/manager.jsx b/src/manager.jsx
index 3cd0343..09c3ac3 100644
--- a/src/manager.jsx
+++ b/src/manager.jsx
@@ -2,6 +2,7 @@ import startCase from 'lodash/startCase';
import React from 'react';
import { addons, types } from 'storybook/manager-api';
+import SidebarStatusTag from './components/SidebarStatusTag';
import StatusDot from './components/StatusDot';
import StatusTag from './components/StatusTag';
import { ADDON_ID } from './constants';
@@ -31,9 +32,18 @@ addons.register(ADDON_ID, (api) => {
? existingSidebarConfig.renderLabel(item)
: name;
+ const sidebarTagsConfig = statusAddonConfig?.sidebarTags;
const sidebarDotsConfig = statusAddonConfig?.sidebarDots;
- if (sidebarDotsConfig === 'none') {
+ // sidebarTags, when set, fully overrides sidebarDots.
+ const isTagMode =
+ sidebarTagsConfig === 'single' || sidebarTagsConfig === 'multiple';
+
+ if (sidebarTagsConfig === 'none') {
+ return fallbackLabel;
+ }
+
+ if (sidebarTagsConfig === undefined && sidebarDotsConfig === 'none') {
return fallbackLabel;
}
@@ -63,7 +73,11 @@ addons.register(ADDON_ID, (api) => {
return fallbackLabel;
}
- if (sidebarDotsConfig !== 'multiple') {
+ const showMultiple = isTagMode
+ ? sidebarTagsConfig === 'multiple'
+ : sidebarDotsConfig === 'multiple';
+
+ if (!showMultiple) {
statusConfigs = [statusConfigs[0]];
}
@@ -71,6 +85,15 @@ addons.register(ADDON_ID, (api) => {
<>
{fallbackLabel}
{statusConfigs.map((statusConfig) => {
+ if (isTagMode) {
+ return (
+
+ );
+ }
+
const {
label: statusName,
status: { background, description },