├── .nvmrc ├── .eslintignore ├── .shellcheckrc ├── manager.js ├── src ├── constants.js ├── components │ ├── StatusDot.jsx │ └── StatusTag.jsx ├── defaults.js ├── getStatusConfigs.js └── manager.jsx ├── prettier.config.cjs ├── lint-staged.config.cjs ├── screenshot.png ├── stylelint.config.js ├── commitlint.config.cjs ├── .husky ├── pre-commit └── commit-msg ├── .vscode └── settings.json ├── .editorconfig ├── .eslintrc.cjs ├── .storybook ├── local-preset.js ├── preview.js ├── manager.js └── main.js ├── stories ├── Header.stories.jsx ├── Page.stories.jsx ├── header.css ├── Button.jsx ├── button.css ├── Button.stories.jsx ├── assets │ ├── direction.svg │ ├── flow.svg │ ├── code-brackets.svg │ ├── comments.svg │ ├── repo.svg │ ├── plugin.svg │ ├── stackalt.svg │ └── colors.svg ├── page.css ├── Header.jsx ├── Page.jsx └── Introduction.mdx ├── .github ├── semantic.yml ├── workflows │ ├── release.yml │ └── ci.yml └── mergify.yml ├── release.config.cjs ├── LICENSE ├── Migration.md ├── tsup.config.js ├── .gitignore ├── package.json ├── Readme.md └── CHANGELOG.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 22.14.0 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/** 2 | -------------------------------------------------------------------------------- /.shellcheckrc: -------------------------------------------------------------------------------- 1 | disable=SC1091 2 | -------------------------------------------------------------------------------- /manager.js: -------------------------------------------------------------------------------- 1 | import './dist/manager.js'; 2 | -------------------------------------------------------------------------------- /src/constants.js: -------------------------------------------------------------------------------- 1 | export const ADDON_ID = 'status'; 2 | -------------------------------------------------------------------------------- /prettier.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | }; 4 | -------------------------------------------------------------------------------- /lint-staged.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { '*.{ts,tsx,js,jsx,yml,yaml,json}': 'eslint --fix' }; 2 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etchteam/storybook-addon-status/HEAD/screenshot.png -------------------------------------------------------------------------------- /stylelint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@etchteam/stylelint-config'], 3 | }; 4 | -------------------------------------------------------------------------------- /commitlint.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | }; 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no-install -- lint-staged 5 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no -- commitlint --edit "${1}" 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": false, 3 | "editor.codeActionsOnSave": { 4 | "source.fixAll.eslint": "explicit" 5 | }, 6 | "eslint.format.enable": true, 7 | } 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@etchteam'], 3 | rules: { 4 | '@next/next/no-html-link-for-pages': 0, 5 | // Storybook/tsup uses the import React... 6 | 'import/default': 0, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /.storybook/local-preset.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url'; 2 | 3 | /** 4 | * to load the built addon in this test Storybook 5 | */ 6 | export function managerEntries(entry = []) { 7 | return [...entry, fileURLToPath(import.meta.resolve('../dist/manager.js'))]; 8 | } 9 | -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | const preview = { 2 | parameters: { 3 | actions: { argTypesRegex: '^on[A-Z].*' }, 4 | controls: { 5 | matchers: { 6 | color: /(background|color)$/i, 7 | date: /Date$/, 8 | }, 9 | }, 10 | }, 11 | }; 12 | 13 | export default preview; 14 | -------------------------------------------------------------------------------- /.storybook/manager.js: -------------------------------------------------------------------------------- 1 | import { addons } from "storybook/manager-api"; 2 | 3 | addons.setConfig({ 4 | status: { 5 | statuses: { 6 | customStatus: { 7 | background: '#0000ff', 8 | color: '#ffffff', 9 | description: 'This component is stable and released', 10 | }, 11 | }, 12 | sidebarDots: 'multiple', // 'single' | 'multiple' | 'none'. 'single' is the default 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|ts|tsx)'], 3 | addons: [ 4 | '@storybook/addon-webpack5-compiler-swc', 5 | import.meta.resolve('./local-preset.js'), 6 | '@storybook/addon-docs' 7 | ], 8 | framework: { 9 | name: '@storybook/react-webpack5', 10 | options: {} 11 | }, 12 | docs: { 13 | autodocs: true 14 | } 15 | }; 16 | 17 | export default config; 18 | -------------------------------------------------------------------------------- /stories/Header.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Header from './Header'; 4 | 5 | export default { 6 | title: 'Example/Header', 7 | component: Header, 8 | tags: ['stable', 'releaseCandidate'], 9 | }; 10 | 11 | const Template = (args) =>
; 12 | 13 | export const LoggedIn = Template.bind({}); 14 | LoggedIn.args = { 15 | user: {}, 16 | }; 17 | 18 | export const LoggedOut = Template.bind({}); 19 | LoggedOut.args = {}; 20 | -------------------------------------------------------------------------------- /.github/semantic.yml: -------------------------------------------------------------------------------- 1 | # Always validate the PR title AND all the commits 2 | titleAndCommits: true 3 | # Allows use of Merge commits (eg on github: "Merge branch 'main' into feature/ride-unicorns") 4 | # this is only relevant when using commitsOnly: true (or titleAndCommits: true) 5 | allowMergeCommits: true 6 | # Allow use of Revert commits (eg on github: "Revert "feat: ride unicorns"") 7 | # this is only relevant when using commitsOnly: true (or titleAndCommits: true) 8 | allowRevertCommits: true 9 | -------------------------------------------------------------------------------- /src/components/StatusDot.jsx: -------------------------------------------------------------------------------- 1 | import { styled } from 'storybook/theming'; 2 | 3 | import { defaultStatuses, defaultBackground } from '../defaults'; 4 | 5 | const StatusDot = styled.span` 6 | align-self: center; 7 | background-color: ${({ background, type }) => 8 | background ?? 9 | (defaultStatuses[type] 10 | ? defaultStatuses[type].background 11 | : defaultBackground)}; 12 | border-radius: 100%; 13 | height: 6px; 14 | margin-left: 0.5em; 15 | user-select: none; 16 | width: 6px; 17 | `; 18 | 19 | export default StatusDot; 20 | -------------------------------------------------------------------------------- /stories/Page.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import * as HeaderStories from './Header.stories'; 4 | import Page from './Page'; 5 | 6 | export default { 7 | title: 'Example/Page', 8 | component: Page, 9 | tags: ['customStatus'], 10 | }; 11 | 12 | const Template = (args) => ; 13 | 14 | export const LoggedIn = Template.bind({}); 15 | LoggedIn.args = { 16 | ...HeaderStories.LoggedIn.args, 17 | }; 18 | 19 | export const LoggedOut = Template.bind({}); 20 | LoggedOut.args = { 21 | ...HeaderStories.LoggedOut.args, 22 | }; 23 | -------------------------------------------------------------------------------- /stories/header.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | align-items: center; 3 | border-bottom: 1px solid var(--header-border-color); 4 | display: flex; 5 | font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; 6 | justify-content: space-between; 7 | padding: 15px 20px; 8 | } 9 | 10 | svg { 11 | display: inline-block; 12 | vertical-align: top; 13 | } 14 | 15 | h1 { 16 | display: inline-block; 17 | font-size: 20px; 18 | font-weight: 900; 19 | line-height: 1; 20 | margin: 6px 0 6px 10px; 21 | vertical-align: top; 22 | } 23 | 24 | button + button { 25 | margin-left: 10px; 26 | } 27 | -------------------------------------------------------------------------------- /release.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | branches: ['main'], 3 | plugins: [ 4 | [ 5 | '@semantic-release/commit-analyzer', 6 | { 7 | preset: 'conventionalcommits', 8 | presetConfig: {}, 9 | }, 10 | ], 11 | [ 12 | '@semantic-release/release-notes-generator', 13 | { 14 | preset: 'conventionalcommits', 15 | }, 16 | ], 17 | '@semantic-release/changelog', 18 | [ 19 | '@semantic-release/npm', 20 | { 21 | npmPublish: true, 22 | }, 23 | ], 24 | '@semantic-release/github', 25 | 26 | // NOTE: this plugin must be last to ensure all updated files are committed 27 | '@semantic-release/git', 28 | ], 29 | }; 30 | -------------------------------------------------------------------------------- /stories/Button.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './button.css'; 3 | 4 | /** 5 | * Primary UI component for user interaction 6 | */ 7 | const Button = ({ 8 | primary = false, 9 | size = 'medium', 10 | backgroundColor = 'pink', 11 | label = 'Button', 12 | ...props 13 | }) => { 14 | const mode = primary 15 | ? 'storybook-button--primary' 16 | : 'storybook-button--secondary'; 17 | return ( 18 | 28 | ); 29 | }; 30 | 31 | export default Button; 32 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Release 3 | on: 4 | push: 5 | branches: 6 | - main 7 | env: 8 | HUSKY: 0 9 | jobs: 10 | publish: 11 | name: Publish 12 | runs-on: ubuntu-latest 13 | if: "! contains(toJSON(github.event.commits.*.message), '[skip ci]')" 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | persist-credentials: false 19 | - uses: actions/setup-node@v4 20 | with: 21 | node-version-file: .nvmrc 22 | cache: npm 23 | - run: npm ci 24 | - name: Publish 25 | env: 26 | GH_TOKEN: ${{ secrets.GH_TOKEN }} 27 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 28 | run: npm run release 29 | -------------------------------------------------------------------------------- /src/defaults.js: -------------------------------------------------------------------------------- 1 | export const defaultBackground = '#2f2f2f'; 2 | export const defaultColor = '#ffffff'; 3 | 4 | export const defaultStatus = { 5 | color: defaultColor, 6 | background: defaultBackground, 7 | }; 8 | 9 | export const defaultStatuses = { 10 | beta: { 11 | color: '#ffffff', 12 | background: '#ec942c', 13 | description: 'The interface for this component may change', 14 | }, 15 | deprecated: { 16 | color: '#ffffff', 17 | background: '#f02c2c', 18 | description: 'This component will be removed in the next major version', 19 | }, 20 | stable: { 21 | color: '#ffffff', 22 | background: '#339902', 23 | description: 'This component is stable', 24 | }, 25 | releaseCandidate: { 26 | color: '#ffffff', 27 | background: '#a335ee', 28 | description: 'This component is a release candidate', 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /stories/button.css: -------------------------------------------------------------------------------- 1 | .storybook-button { 2 | border: 0; 3 | border-radius: 3em; 4 | cursor: pointer; 5 | display: inline-block; 6 | font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; 7 | font-weight: 700; 8 | line-height: 1; 9 | } 10 | 11 | .storybook-button--primary { 12 | background-color: var(--button-primary-background); 13 | color: var(--button-primary-color); 14 | } 15 | 16 | .storybook-button--secondary { 17 | background-color: var(--button-secondary-background); 18 | box-shadow: var(--button-secondary-box-shadow); 19 | color: var(--button-secondary-color); 20 | } 21 | 22 | .storybook-button--small { 23 | font-size: 12px; 24 | padding: 10px 16px; 25 | } 26 | 27 | .storybook-button--medium { 28 | font-size: 14px; 29 | padding: 11px 20px; 30 | } 31 | 32 | .storybook-button--large { 33 | font-size: 16px; 34 | padding: 12px 24px; 35 | } 36 | -------------------------------------------------------------------------------- /stories/Button.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Button from './Button'; 4 | 5 | export default { 6 | title: 'Example/Button', 7 | component: Button, 8 | argTypes: { 9 | backgroundColor: { control: 'color' }, 10 | }, 11 | tags: ['beta', 'customStatus'], 12 | parameters: { 13 | status: { 14 | type: { 15 | name: 'customStatus', 16 | url: 'http://www.url.com/custom', 17 | }, 18 | url: 'http://www.url.com/status', 19 | }, 20 | }, 21 | }; 22 | 23 | const Template = (args) =>
51 | ); 52 | 53 | export default Header; 54 | -------------------------------------------------------------------------------- /stories/assets/repo.svg: -------------------------------------------------------------------------------- 1 | illustration/repo -------------------------------------------------------------------------------- /stories/assets/plugin.svg: -------------------------------------------------------------------------------- 1 | illustration/plugin -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Storybook build outputs 86 | storybook-static 87 | 88 | # Gatsby files 89 | .cache/ 90 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 91 | # https://nextjs.org/blog/next-9-1#public-directory-support 92 | # public 93 | 94 | # vuepress build output 95 | .vuepress/dist 96 | 97 | # Serverless directories 98 | .serverless/ 99 | 100 | # FuseBox cache 101 | .fusebox/ 102 | 103 | # DynamoDB Local files 104 | .dynamodb/ 105 | 106 | # TernJS port file 107 | .tern-port 108 | 109 | ts3.5 110 | -------------------------------------------------------------------------------- /stories/assets/stackalt.svg: -------------------------------------------------------------------------------- 1 | illustration/stackalt -------------------------------------------------------------------------------- /src/components/StatusTag.jsx: -------------------------------------------------------------------------------- 1 | import startCase from 'lodash/startCase'; 2 | import React from 'react'; 3 | import { useParameter, useStorybookApi, addons } from 'storybook/manager-api'; 4 | import { styled, css } from 'storybook/theming'; 5 | 6 | import { ADDON_ID } from '../constants'; 7 | import { defaultStatuses, defaultBackground, defaultColor } from '../defaults'; 8 | import { getStatusConfigs } from '../getStatusConfigs'; 9 | 10 | const tagStyles = css` 11 | align-self: center; 12 | border-radius: 0.25em; 13 | padding: 0 0.5em; 14 | text-decoration: none; 15 | user-select: none; 16 | font-size: 11px; 17 | text-transform: uppercase; 18 | line-height: 20px; 19 | font-weight: 700; 20 | padding: 0 0.5em; 21 | `; 22 | 23 | const LinkTag = styled.a` 24 | ${tagStyles} 25 | `; 26 | 27 | const TextTag = styled.span` 28 | ${tagStyles} 29 | `; 30 | 31 | const StatusTag = () => { 32 | const api = useStorybookApi(); 33 | const tags = api.getCurrentStoryData()?.tags ?? []; 34 | 35 | const parameters = useParameter(ADDON_ID, null); 36 | const customConfigs = addons.getConfig()?.[ADDON_ID]?.statuses; 37 | 38 | const statusConfigs = getStatusConfigs({ 39 | tags, 40 | parameters, 41 | customConfigs, 42 | }); 43 | 44 | if (!statusConfigs?.length) { 45 | return null; 46 | } 47 | 48 | return ( 49 | <> 50 | {statusConfigs.map((statusConfig) => { 51 | const { background, color, description } = statusConfig.status; 52 | const statusUrl = statusConfig.url; 53 | const label = startCase(statusConfig.label); 54 | 55 | const style = { 56 | color: 57 | color ?? 58 | (defaultStatuses[label] 59 | ? defaultStatuses[label].color 60 | : defaultColor), 61 | backgroundColor: 62 | background ?? 63 | (defaultStatuses[label] 64 | ? defaultStatuses[label].background 65 | : defaultBackground), 66 | }; 67 | 68 | return statusUrl ? ( 69 | 75 | {label} 76 | 77 | ) : ( 78 | 79 | {label} 80 | 81 | ); 82 | })} 83 | 84 | ); 85 | }; 86 | 87 | export default StatusTag; 88 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@etchteam/storybook-addon-status", 3 | "version": "8.0.0", 4 | "description": "Add component status to the storybook UI", 5 | "type": "module", 6 | "main": "dist/manager.js", 7 | "exports": { 8 | "./manager": "./dist/manager.js", 9 | "./package.json": "./package.json" 10 | }, 11 | "files": [ 12 | "dist/**/*", 13 | "README.md", 14 | "manager.js" 15 | ], 16 | "scripts": { 17 | "prebuild": "node -e \"fs.rmSync('./dist', { recursive: true, force: true })\"", 18 | "prepare": "tsup", 19 | "storybook": "storybook dev -p 6006", 20 | "build-storybook": "storybook build", 21 | "release": "semantic-release" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/etchteam/storybook-addon-status.git" 26 | }, 27 | "keywords": [ 28 | "storybook", 29 | "addon", 30 | "status", 31 | "react", 32 | "storybook-addon", 33 | "organize", 34 | "popular" 35 | ], 36 | "author": "Etch ", 37 | "license": "MIT", 38 | "bugs": { 39 | "url": "https://github.com/etchteam/storybook-addon-status/issues" 40 | }, 41 | "homepage": "https://github.com/etchteam/storybook-addon-status#readme", 42 | "devDependencies": { 43 | "@commitlint/cli": "^19.3.0", 44 | "@commitlint/config-conventional": "^19.2.2", 45 | "@etchteam/eslint-config": "^1.10.0", 46 | "@semantic-release/changelog": "^6.0.3", 47 | "@semantic-release/commit-analyzer": "^11.1.0", 48 | "@semantic-release/git": "^10.0.1", 49 | "@semantic-release/github": "^9.2.6", 50 | "@semantic-release/npm": "^11.0.2", 51 | "@semantic-release/release-notes-generator": "^12.1.0", 52 | "@storybook/addon-docs": "10.0.0-rc.0", 53 | "@storybook/addon-webpack5-compiler-swc": "1.0.5", 54 | "@storybook/react-webpack5": "10.0.0-rc.0", 55 | "@swc/core": "1.8.0", 56 | "eslint": "^8.0.0", 57 | "eslint-plugin-storybook": "^0.8.0", 58 | "husky": "^9.0.11", 59 | "lint-staged": "^15.2.2", 60 | "prettier": "^3.2.5", 61 | "react": "^18.2.0", 62 | "react-dom": "^18.2.0", 63 | "semantic-release": "^23.0.0", 64 | "storybook": "10.0.0-rc.0", 65 | "swc-loader": "^0.2.6", 66 | "tsup": "^8.3.5" 67 | }, 68 | "publishConfig": { 69 | "access": "public" 70 | }, 71 | "storybook": { 72 | "icon": "https://pbs.twimg.com/profile_images/998947662287130625/7Ff1hOdQ_400x400.jpg", 73 | "displayName": "Status" 74 | }, 75 | "dependencies": { 76 | "lodash": "^4.17.21" 77 | }, 78 | "peerDependencies": { 79 | "storybook": "^10.0.0" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /stories/Page.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Header from './Header'; 4 | import './page.css'; 5 | 6 | const Page = ({ user, onLogin, onLogout, onCreateAccount }) => ( 7 |
8 |
14 | 15 |
16 |

Pages in Storybook

17 |

18 | We recommend building UIs with a{' '} 19 | 24 | component-driven 25 | {' '} 26 | process starting with atomic components and ending with pages. 27 |

28 |

29 | Render pages with mock data. This makes it easy to build and review page 30 | states without needing to navigate to them in your app. Here are some 31 | handy patterns for managing page data in Storybook: 32 |

33 |
    34 |
  • 35 | Use a higher-level connected component. Storybook helps you compose 36 | such data from the “args” of child component stories 37 |
  • 38 |
  • 39 | Assemble data in the page component from your services. You can mock 40 | these services out using Storybook. 41 |
  • 42 |
43 |

44 | Get a guided tutorial on component-driven development at{' '} 45 | 50 | Storybook tutorials 51 | 52 | . Read more in the{' '} 53 | 58 | docs 59 | 60 | . 61 |

62 |
63 | Tip Adjust the width of the canvas with the{' '} 64 | 70 | 71 | 76 | 77 | 78 | Viewports addon in the toolbar 79 |
80 |
81 |
82 | ); 83 | 84 | export default Page; 85 | -------------------------------------------------------------------------------- /src/getStatusConfigs.js: -------------------------------------------------------------------------------- 1 | import { defaultStatuses } from './defaults'; 2 | 3 | const combineTagsAndParameters = (tags, parameters) => { 4 | // If there are no parameter statuses, we only use the tags. 5 | if (!parameters) { 6 | return tags ?? []; 7 | } 8 | 9 | // If parameters is an array, there are multiple statuses. 10 | if (Array.isArray(parameters)) { 11 | return [...tags, ...parameters]; 12 | } 13 | 14 | // If parameters is a string or an object, it's a single status. 15 | if (typeof parameters === 'string' || typeof parameters === 'object') { 16 | return [...tags, parameters]; 17 | } 18 | 19 | // We shouldn't get here but if we do, return an empty array. 20 | return []; 21 | }; 22 | 23 | const filterStatuses = (statuses) => { 24 | const filteredStatuses = []; 25 | const existingNames = []; 26 | 27 | statuses.forEach((status) => { 28 | const name = typeof status === 'string' ? status : status.name; 29 | if (!existingNames.includes(name)) { 30 | filteredStatuses.push(status); 31 | existingNames.push(name); 32 | return; 33 | } 34 | // If the same status is defined in both tags and parameters, it should only be included once - 35 | // parameter statuses override tag statuses as they may contain additional information. 36 | if (status.name) { 37 | const index = existingNames.indexOf(name); 38 | if (index !== -1) { 39 | filteredStatuses[index] = status; 40 | } 41 | } 42 | }); 43 | 44 | return filteredStatuses; 45 | }; 46 | 47 | export const getStatusConfigs = ({ tags, parameters, customConfigs }) => { 48 | // If there are no statuses from either parameters or tags, return an empty array. 49 | if (!parameters && !tags?.length) { 50 | return []; 51 | } 52 | 53 | // Combine the tag and parameter statuses into a single array. 54 | const combinedStatuses = combineTagsAndParameters(tags, parameters?.type); 55 | 56 | // Filter out duplicate statuses based on their names. 57 | const statuses = filterStatuses(combinedStatuses); 58 | 59 | // Combine the default and custom status configs. 60 | // If there's no custom configs, try to use the status configs from parameters. 61 | const statusConfigMap = { 62 | ...defaultStatuses, 63 | ...(customConfigs || parameters?.statuses || {}), 64 | }; 65 | 66 | // Map the status names to their configurations. 67 | let statusConfigs = statuses.map((status) => { 68 | if (typeof status === 'string') { 69 | return { 70 | label: status, 71 | status: statusConfigMap[status], 72 | url: parameters?.url, 73 | }; 74 | } 75 | 76 | return { 77 | label: status.name, 78 | status: statusConfigMap[status.name], 79 | url: status.url, 80 | }; 81 | }); 82 | 83 | // Remove any missing status configurations 84 | statusConfigs = statusConfigs.filter((x) => x.status != null); 85 | 86 | return statusConfigs; 87 | }; 88 | -------------------------------------------------------------------------------- /src/manager.jsx: -------------------------------------------------------------------------------- 1 | import startCase from 'lodash/startCase'; 2 | import React from 'react'; 3 | import { addons, types } from 'storybook/manager-api'; 4 | 5 | import StatusDot from './components/StatusDot'; 6 | import StatusTag from './components/StatusTag'; 7 | import { ADDON_ID } from './constants'; 8 | import { getStatusConfigs } from './getStatusConfigs'; 9 | 10 | addons.register(ADDON_ID, (api) => { 11 | const addonsConfig = addons.getConfig(); 12 | const existingSidebarConfig = addonsConfig?.sidebar ?? {}; 13 | 14 | addons.add(ADDON_ID, { 15 | title: 'Status', 16 | type: types.TOOL, 17 | render: () => , 18 | }); 19 | 20 | const statusAddonConfig = addonsConfig?.[ADDON_ID] ?? {}; 21 | 22 | addons.setConfig({ 23 | sidebar: { 24 | ...existingSidebarConfig, 25 | renderLabel: (item) => { 26 | const { name, tags } = item; 27 | const isLeaf = ['root', 'group', 'story'].includes(item.type); 28 | 29 | try { 30 | const fallbackLabel = existingSidebarConfig?.renderLabel 31 | ? existingSidebarConfig.renderLabel(item) 32 | : name; 33 | 34 | const sidebarDotsConfig = statusAddonConfig?.sidebarDots; 35 | 36 | if (sidebarDotsConfig === 'none') { 37 | return fallbackLabel; 38 | } 39 | 40 | const parameters = api.getParameters(item.id, ADDON_ID); 41 | 42 | // item can be a Root | Group | Story 43 | if (!isLeaf || (tags.length === 0 && !parameters?.type)) { 44 | return fallbackLabel; 45 | } 46 | 47 | // Get custom status configurations from the current story's parameters. 48 | // This will include any custom statuses defined in manager.js, preview.js or story parameters. 49 | // However custom statuses from story parameters will only be available in the sidebar 50 | // when viewing that story. This is a storybook limitation: 51 | // https://github.com/storybookjs/storybook/discussions/24022 52 | const customConfigs = 53 | statusAddonConfig?.statuses || 54 | api.getCurrentStoryData().parameters?.status?.statuses; 55 | 56 | let statusConfigs = getStatusConfigs({ 57 | tags, 58 | parameters, 59 | customConfigs, 60 | }); 61 | 62 | if (statusConfigs.length === 0) { 63 | return fallbackLabel; 64 | } 65 | 66 | if (sidebarDotsConfig !== 'multiple') { 67 | statusConfigs = [statusConfigs[0]]; 68 | } 69 | 70 | return ( 71 | <> 72 | {fallbackLabel} 73 | {statusConfigs.map((statusConfig) => { 74 | const { 75 | label: statusName, 76 | status: { background, description }, 77 | } = statusConfig; 78 | 79 | return ( 80 | 86 | ); 87 | })} 88 | 89 | ); 90 | } catch (error) { 91 | return name; 92 | } 93 | }, 94 | }, 95 | }); 96 | }); 97 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Storybook Addon Status 2 | 3 | Storybook Status Addon can be used to add a component status label in [Storybook](https://storybook.js.org). 4 | 5 | ![React Storybook Screenshot](https://raw.githubusercontent.com/etchteam/storybook-addon-status/master/screenshot.png) 6 | 7 | ## Installation 8 | 9 | ```sh 10 | npm install @etchteam/storybook-addon-status --save-dev 11 | ``` 12 | 13 | ## Configuration 14 | 15 | Then create a file called `main.js` in your storybook config. 16 | 17 | Add the following content to it: 18 | 19 | ```js 20 | export default { 21 | addons: ['@etchteam/storybook-addon-status'], 22 | }; 23 | ``` 24 | 25 | 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. 26 | 27 | ```js 28 | import { addons } from "storybook/manager-api"; 29 | 30 | addons.setConfig({ 31 | status: { 32 | statuses: { 33 | released: { 34 | background: '#0000ff', 35 | color: '#ffffff', 36 | description: 'This component is stable and released', 37 | }, 38 | }, 39 | sidebarDots: 'single', // 'single' | 'multiple' | 'none'. 'single' is the default 40 | }, 41 | }); 42 | ``` 43 | 44 | **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. 45 | 46 | **NOTE:** Each key will be used as the label for the status and will convert camelCase to words. 47 | 48 | ## Story Usage 49 | 50 | There are two ways to add statuses to your stories: 51 | 52 | 1. [Tags](#tags) (new, recommended) 53 | 2. [Story parameters](#story-parameters) (legacy) 54 | 55 | You can also use [both methods together](#combined-method) to get the benefits of both at once. 56 | 57 | ### Tags 58 | 59 | Storybook's built-in [tag system](https://storybook.js.org/docs/writing-stories/tags) can now be used to add statuses to your stories. 60 | 61 | Just add an array of status names to the `tags` property: 62 | 63 | ```js 64 | 65 | export default { 66 | title: 'BetterSoftwareLink', 67 | tags: ['beta'], // 'beta' | 'stable' | 'deprecated' | 'releaseCandidate' | your own custom status 68 | }; 69 | ``` 70 | 71 | This can be used for the built-in statuses, as well as any custom statuses defined in `manager.js`. Only these tags will appear as statuses - if they are not built-in or have a definition in `manager.js`, they will be ignored by the addon. This means that status tags can be used alongside tags for other purposes. 72 | 73 | Using tags to define statuses means that stories can also be [filtered](https://storybook.js.org/docs/writing-stories/tags#filtering-by-custom-tags) by status. 74 | 75 | ### Story parameters 76 | 77 | The alternative (legacy) way to add statuses to stories is to add them to the `status` property of the story parameters: 78 | 79 | ```js 80 | 81 | export default { 82 | title: 'BetterSoftwareLink', 83 | parameters: { 84 | status: { 85 | type: 'beta', // 'beta' | 'stable' | 'deprecated' | 'releaseCandidate' 86 | url: 'http://www.url.com/status', // Optional: will make the tag a link 87 | statuses: {...} // Optional: add custom status configurations for this story here 88 | } 89 | }, 90 | }; 91 | ``` 92 | 93 | `type` also accepts an object with `name` and `url` keys, or an array of strings and/or objects for multiple statuses. 94 | 95 | If not specifically set, every status uses `status.url` as the linked Url. 96 | 97 | ```js 98 | export default { 99 | parameters: { 100 | status: { 101 | type: [ 102 | 'beta', 103 | 'released', 104 | 'myCustomStatus', 105 | { 106 | name: 'stable', 107 | url: 'http://www.url.com/stable' 108 | } 109 | ], 110 | url: 'http://www.url.com/status' 111 | }, 112 | }, 113 | } 114 | ``` 115 | 116 | Setting statuses via the story parameters allows more customisation on a story-by-story basis, but at the expense of sidebar filtering. Additionally, using this method means that the status dot(s) in the sidebar only shows for the story that is currently being viewed - this is a [known limitation](https://github.com/storybookjs/storybook/discussions/24022#discussioncomment-12737532) of the way Storybook works. 117 | 118 | ### Combined method 119 | 120 | For the best of both worlds, tag and story parameter statuses can be used together. This gives you the ability to filter by status in the sidebar, see sidebar dots for all stories at once, and to customise statuses within a story. 121 | 122 | To do this, add all the statuses for the story to the `tags` array in the story definition. Then, add any statuses that need customisation (e.g. for a URL or custom style) to the story parameters' `status` property. 123 | 124 | Both sets of statuses will be combined and de-duplicated. 125 | 126 | ```js 127 | 128 | export default { 129 | title: 'BetterSoftwareLink', 130 | tags: ['beta', 'customStoryStatus'] 131 | parameters: { 132 | status: { 133 | type: { 134 | name: 'customStoryStatus', 135 | url: 'http://www.url.com/custom', 136 | }, 137 | url: 'http://www.url.com/status', 138 | statuses: { 139 | customStoryStatus: { 140 | background: '#0000ff', 141 | color: '#ffffff', 142 | description: 'This is a custom status configuration for this story only', 143 | } 144 | } 145 | }, 146 | }, 147 | }; 148 | ``` 149 | 150 | **NOTE:** The sidebar dot(s) for a status with custom styles added in a particular story will only work while you are viewing that story. This is a [known limitation](https://github.com/storybookjs/storybook/discussions/24022#discussioncomment-12737532) of the way Storybook works. We recommend [defining custom status styles globally](#configuration) in `preview.js` wherever possible instead. 151 | 152 | ## Migration guide 153 | 154 | Need to [update your major version](Migration.md)? 155 | 156 | --- 157 | 158 | Made with ☕ at [Etch](https://etch.co) 159 | -------------------------------------------------------------------------------- /stories/Introduction.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs/blocks'; 2 | import Code from './assets/code-brackets.svg'; 3 | import Colors from './assets/colors.svg'; 4 | import Comments from './assets/comments.svg'; 5 | import Direction from './assets/direction.svg'; 6 | import Flow from './assets/flow.svg'; 7 | import Plugin from './assets/plugin.svg'; 8 | import Repo from './assets/repo.svg'; 9 | import StackAlt from './assets/stackalt.svg'; 10 | 11 | 12 | 13 | 116 | 117 | # Welcome to Storybook 118 | 119 | Storybook helps you build UI components in isolation from your app's business logic, data, and context. 120 | That makes it easy to develop hard-to-reach states. Save these UI states as **stories** to revisit during development, testing, or QA. 121 | 122 | Browse example stories now by navigating to them in the sidebar. 123 | View their code in the `src/stories` directory to learn how they work. 124 | We recommend building UIs with a [**component-driven**](https://componentdriven.org) process starting with atomic components and ending with pages. 125 | 126 |
Configure
127 | 128 |
129 | 130 | plugin 131 | 132 | 133 | Presets for popular tools 134 | Easy setup for TypeScript, SCSS and more. 135 | 136 | 137 | 138 | 139 | Build 140 | 141 | 142 | Build configuration 143 | How to customize webpack and Babel 144 | 145 | 146 | 147 | 148 | colors 149 | 150 | 151 | Styling 152 | How to load and configure CSS libraries 153 | 154 | 155 | 156 | 157 | flow 158 | 159 | 160 | Data 161 | Providers and mocking for data libraries 162 | 163 | 164 |
165 | 166 |
Learn
167 | 168 |
169 | 170 | repo 171 | 172 | 173 | Storybook documentation 174 | Configure, customize, and extend 175 | 176 | 177 | 178 | 179 | direction 180 | 181 | 182 | In-depth guides 183 | Best practices from leading teams 184 | 185 | 186 | 187 | 188 | code 189 | 190 | 191 | GitHub project 192 | View the source and add issues 193 | 194 | 195 | 196 | 197 | comments 198 | 199 | 200 | Discord chat 201 | Chat with maintainers and the community 202 | 203 | 204 |
205 | 206 |
207 | TipEdit the Markdown in{' '} 208 | src/stories/Introduction.stories.mdx 209 |
210 | -------------------------------------------------------------------------------- /stories/assets/colors.svg: -------------------------------------------------------------------------------- 1 | illustration/colors -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [8.0.0](https://github.com/etchteam/storybook-addon-status/compare/v7.0.1...v8.0.0) (2025-10-28) 2 | 3 | 4 | ### ⚠ BREAKING CHANGES 5 | 6 | * storybook v10 support 7 | 8 | ### Features 9 | 10 | * storybook v10 support ([83027e7](https://github.com/etchteam/storybook-addon-status/commit/83027e7045c4dad89d2702ffb61deae6015a8779)) 11 | 12 | ## [7.0.1](https://github.com/etchteam/storybook-addon-status/compare/v7.0.0...v7.0.1) (2025-07-09) 13 | 14 | 15 | ### Bug Fixes 16 | 17 | * merge existing sidebar config with addon config ([d34c1e5](https://github.com/etchteam/storybook-addon-status/commit/d34c1e5c1ac679e613a69dca5690ce23c07d3bb0)) 18 | 19 | ## [7.0.0](https://github.com/etchteam/storybook-addon-status/compare/v6.0.0...v7.0.0) (2025-07-08) 20 | 21 | 22 | ### ⚠ BREAKING CHANGES 23 | 24 | * new way to set story statuses 25 | * Storybook packages have been consolidated/moved/deleted 26 | 27 | ### Features 28 | 29 | * show all statuses in sidebar ([9a2153c](https://github.com/etchteam/storybook-addon-status/commit/9a2153c0d5d3a55b81f099d5d8071c059f78cadb)) 30 | * sidebar dots config and show single dot by default ([add0276](https://github.com/etchteam/storybook-addon-status/commit/add0276203336d0d36730c6c60b21ad9939e7eeb)) 31 | * update browser target list ([3ec6a3d](https://github.com/etchteam/storybook-addon-status/commit/3ec6a3d12de2ffaf13c68a3bad31a2a46ff90675)) 32 | * update dependencies for storybook v9 ([2f731c6](https://github.com/etchteam/storybook-addon-status/commit/2f731c6885a221121305b55cdedd82f24981291d)) 33 | * use storybook tags to set statuses ([2bf03f8](https://github.com/etchteam/storybook-addon-status/commit/2bf03f8d441bcb3534bed60d1eb864f13e3aa7a5)) 34 | 35 | ## [6.0.0](https://github.com/etchteam/storybook-addon-status/compare/v5.0.0...v6.0.0) (2025-05-30) 36 | 37 | 38 | ### ⚠ BREAKING CHANGES 39 | 40 | * Storybook packages have been consolidated/moved/deleted 41 | 42 | ### Features 43 | 44 | * update browser target list ([3b1413c](https://github.com/etchteam/storybook-addon-status/commit/3b1413c6546e4a15ad6d68eccb4231ce0a2baadd)) 45 | * update dependencies for storybook v9 ([27cbf9e](https://github.com/etchteam/storybook-addon-status/commit/27cbf9ee599949c2a2cac53e7b4a71a63887aed4)) 46 | 47 | ## [5.0.0](https://github.com/etchteam/storybook-addon-status/compare/v4.2.2...v5.0.0) (2024-05-28) 48 | 49 | 50 | ### ⚠ BREAKING CHANGES 51 | 52 | * dependencies and peer dependencies removed 53 | these are now part of storybook global packages 54 | 55 | ### Features 56 | 57 | * add .nvmrc ([f8070cc](https://github.com/etchteam/storybook-addon-status/commit/f8070ccb8746e8649b9f414fa401d011798b404f)) 58 | * add basic ci ([9c15342](https://github.com/etchteam/storybook-addon-status/commit/9c1534226d35078cf7d0e461edbb4c866fcf448d)) 59 | * add nvmrc ([1e1fa7b](https://github.com/etchteam/storybook-addon-status/commit/1e1fa7b306007ffadf3bf96bb58b974086fe1163)) 60 | * add our own lint script ([0b0ad01](https://github.com/etchteam/storybook-addon-status/commit/0b0ad0137fbe76cbff95e8026e546712a5c9a6b1)) 61 | * add stylelint ([48367f2](https://github.com/etchteam/storybook-addon-status/commit/48367f2ea4644342400b0bdc1c4acbb49972bf4b)) 62 | * ignore dist ([95d57f8](https://github.com/etchteam/storybook-addon-status/commit/95d57f8b78039aa4a9257173157fd258d3cd2e17)) 63 | * improve linting setup ([e8b3f57](https://github.com/etchteam/storybook-addon-status/commit/e8b3f57b9500d7ecc0050cdf9f1edd75903e6259)) 64 | * migrate to our linter ([94c983c](https://github.com/etchteam/storybook-addon-status/commit/94c983c450e80e2fbd8e35193381f021252928eb)) 65 | * remove unnecessary storybook packages ([1902181](https://github.com/etchteam/storybook-addon-status/commit/1902181ab21600861a08711df38ad723255a8b9d)) 66 | * storybook 8 support ([e454c70](https://github.com/etchteam/storybook-addon-status/commit/e454c708a672915697dc88a0acff00c0454ca19c)) 67 | * update base branch ([b8312a2](https://github.com/etchteam/storybook-addon-status/commit/b8312a2351bb2b4cb595a4108755ae4679a0c516)) 68 | * upgrade to node 20 ([1629dbd](https://github.com/etchteam/storybook-addon-status/commit/1629dbdf5fb9ddd08812341746b7ddd4e7c1d448)) 69 | * use optional chaining ([3013680](https://github.com/etchteam/storybook-addon-status/commit/3013680babeb1328dda4482ec1e03568a0304bab)) 70 | 71 | 72 | ### Bug Fixes 73 | 74 | * add double quotes to prevent globbing and word splitting ([5d95dde](https://github.com/etchteam/storybook-addon-status/commit/5d95ddea4d8d979062e5adb7a8217564e9ca8e33)) 75 | * add husky install step to prepare ([a793af6](https://github.com/etchteam/storybook-addon-status/commit/a793af6798de9af569feb9f6777cb6aeebebb5c3)) 76 | * add node preset ([486dbe1](https://github.com/etchteam/storybook-addon-status/commit/486dbe1ee1634b1ce2108ad0ddc419e2157eb171)) 77 | * broken package json ([a81da55](https://github.com/etchteam/storybook-addon-status/commit/a81da55f89c8765e3eb58047807f1f6929fad79d)) 78 | * correctly set up commit lint hook ([d58d54d](https://github.com/etchteam/storybook-addon-status/commit/d58d54d0ac4842e97c7dc5ee2c053d26930d8d4a)) 79 | * disable https://www.shellcheck.net/wiki/SC1091 ([cf98b4c](https://github.com/etchteam/storybook-addon-status/commit/cf98b4c9e5b42839dba71b115d395304998f6213)) 80 | * handle removal of isLead ([0a630da](https://github.com/etchteam/storybook-addon-status/commit/0a630da8c3a11dc8a98a78a21ce5ee2096a2b8d6)) 81 | * ignore log files ([7381ed5](https://github.com/etchteam/storybook-addon-status/commit/7381ed58998c4a259a615d984c2cfd83c8f94e7f)) 82 | * linter cleanup ([bb63a2d](https://github.com/etchteam/storybook-addon-status/commit/bb63a2dfccfe3c27fb471f4c858031f2f48416cb)) 83 | * package lock ([eb34b7f](https://github.com/etchteam/storybook-addon-status/commit/eb34b7f58b7d307fffb8c00d7ce18c7e3ae3084d)) 84 | * remove vscode ts checks ([f0a43cd](https://github.com/etchteam/storybook-addon-status/commit/f0a43cd21bcff3409629b3e0c9e6d1f34d38bce3)) 85 | * status dot never appearing ([03ea3fb](https://github.com/etchteam/storybook-addon-status/commit/03ea3fbe9500486df8a2ab16987975e54591b466)) 86 | * storybook v7 support and codebase simplification ([ca62dad](https://github.com/etchteam/storybook-addon-status/commit/ca62dadd9973a2a455399bc6ccfb9aeb401ff96e)) 87 | * use smart quotes ([23593cc](https://github.com/etchteam/storybook-addon-status/commit/23593cc71100ba90c9dab7972c431ffaa300db2a)) 88 | 89 | 90 | ### Reverts 91 | 92 | * debug ([ad746dd](https://github.com/etchteam/storybook-addon-status/commit/ad746ddcb45947a3f138ef33bc9bee96dd502db3)) 93 | 94 | ## 1.0.0 (2024-05-28) 95 | 96 | 97 | ### ⚠ BREAKING CHANGES 98 | 99 | * dependencies and peer dependencies removed 100 | these are now part of storybook global packages 101 | 102 | ### Features 103 | 104 | * add .nvmrc ([f8070cc](https://github.com/etchteam/storybook-addon-status/commit/f8070ccb8746e8649b9f414fa401d011798b404f)) 105 | * add basic ci ([9c15342](https://github.com/etchteam/storybook-addon-status/commit/9c1534226d35078cf7d0e461edbb4c866fcf448d)) 106 | * add nvmrc ([1e1fa7b](https://github.com/etchteam/storybook-addon-status/commit/1e1fa7b306007ffadf3bf96bb58b974086fe1163)) 107 | * add our own lint script ([0b0ad01](https://github.com/etchteam/storybook-addon-status/commit/0b0ad0137fbe76cbff95e8026e546712a5c9a6b1)) 108 | * Add screenshot to docs ([7462efe](https://github.com/etchteam/storybook-addon-status/commit/7462efea5c308539433d1df37f39fbae9c7de3fc)) 109 | * add stylelint ([48367f2](https://github.com/etchteam/storybook-addon-status/commit/48367f2ea4644342400b0bdc1c4acbb49972bf4b)) 110 | * better linting and sidebar status labels ([a56d732](https://github.com/etchteam/storybook-addon-status/commit/a56d7320a0e5538ee99293006979643f7c5b0c86)) 111 | * Custom status maps fixes [#2](https://github.com/etchteam/storybook-addon-status/issues/2) ([ce90b44](https://github.com/etchteam/storybook-addon-status/commit/ce90b44b7dc0e64f38ac0fdb8d9fc5c8f758161f)) 112 | * ignore dist ([95d57f8](https://github.com/etchteam/storybook-addon-status/commit/95d57f8b78039aa4a9257173157fd258d3cd2e17)) 113 | * improve linting setup ([e8b3f57](https://github.com/etchteam/storybook-addon-status/commit/e8b3f57b9500d7ecc0050cdf9f1edd75903e6259)) 114 | * migrate to our linter ([94c983c](https://github.com/etchteam/storybook-addon-status/commit/94c983c450e80e2fbd8e35193381f021252928eb)) 115 | * remove unnecessary storybook packages ([1902181](https://github.com/etchteam/storybook-addon-status/commit/1902181ab21600861a08711df38ad723255a8b9d)) 116 | * Screenshot image ([fe518e5](https://github.com/etchteam/storybook-addon-status/commit/fe518e5865e4bd4998f12bae6d7d85249d393e27)) 117 | * statusLink and extend default statuses ([9d3573b](https://github.com/etchteam/storybook-addon-status/commit/9d3573b8250b0ea3f4ad6fc73327c3726c963748)) 118 | * storybook 8 support ([e454c70](https://github.com/etchteam/storybook-addon-status/commit/e454c708a672915697dc88a0acff00c0454ca19c)) 119 | * update base branch ([b8312a2](https://github.com/etchteam/storybook-addon-status/commit/b8312a2351bb2b4cb595a4108755ae4679a0c516)) 120 | * upgrade to node 20 ([1629dbd](https://github.com/etchteam/storybook-addon-status/commit/1629dbdf5fb9ddd08812341746b7ddd4e7c1d448)) 121 | * use optional chaining ([3013680](https://github.com/etchteam/storybook-addon-status/commit/3013680babeb1328dda4482ec1e03568a0304bab)) 122 | 123 | 124 | ### Bug Fixes 125 | 126 | * add double quotes to prevent globbing and word splitting ([5d95dde](https://github.com/etchteam/storybook-addon-status/commit/5d95ddea4d8d979062e5adb7a8217564e9ca8e33)) 127 | * add husky install step to prepare ([a793af6](https://github.com/etchteam/storybook-addon-status/commit/a793af6798de9af569feb9f6777cb6aeebebb5c3)) 128 | * add node preset ([486dbe1](https://github.com/etchteam/storybook-addon-status/commit/486dbe1ee1634b1ce2108ad0ddc419e2157eb171)) 129 | * broken package json ([a81da55](https://github.com/etchteam/storybook-addon-status/commit/a81da55f89c8765e3eb58047807f1f6929fad79d)) 130 | * correctly set up commit lint hook ([d58d54d](https://github.com/etchteam/storybook-addon-status/commit/d58d54d0ac4842e97c7dc5ee2c053d26930d8d4a)) 131 | * disable https://www.shellcheck.net/wiki/SC1091 ([cf98b4c](https://github.com/etchteam/storybook-addon-status/commit/cf98b4c9e5b42839dba71b115d395304998f6213)) 132 | * forgot a console ([591c10a](https://github.com/etchteam/storybook-addon-status/commit/591c10ad1ba13910490e0a63811efbf8fcebe0f3)) 133 | * forgot to add last new types ([74fa364](https://github.com/etchteam/storybook-addon-status/commit/74fa36499e6977432b2bc799b1e4818b8a28b189)) 134 | * had to run a fresh install for package-lock ([fedb7c1](https://github.com/etchteam/storybook-addon-status/commit/fedb7c155637caf7adfd72bd36f934fdc23af6a9)) 135 | * handle removal of isLead ([0a630da](https://github.com/etchteam/storybook-addon-status/commit/0a630da8c3a11dc8a98a78a21ce5ee2096a2b8d6)) 136 | * ignore log files ([7381ed5](https://github.com/etchteam/storybook-addon-status/commit/7381ed58998c4a259a615d984c2cfd83c8f94e7f)) 137 | * linter cleanup ([bb63a2d](https://github.com/etchteam/storybook-addon-status/commit/bb63a2dfccfe3c27fb471f4c858031f2f48416cb)) 138 | * package lock ([eb34b7f](https://github.com/etchteam/storybook-addon-status/commit/eb34b7f58b7d307fffb8c00d7ce18c7e3ae3084d)) 139 | * Remove console log fixes [#14](https://github.com/etchteam/storybook-addon-status/issues/14) ([52c573d](https://github.com/etchteam/storybook-addon-status/commit/52c573de0453dca8113fca62f62426e3642fe775)) 140 | * status dot never appearing ([03ea3fb](https://github.com/etchteam/storybook-addon-status/commit/03ea3fbe9500486df8a2ab16987975e54591b466)) 141 | * storybook v7 support and codebase simplification ([ca62dad](https://github.com/etchteam/storybook-addon-status/commit/ca62dadd9973a2a455399bc6ccfb9aeb401ff96e)) 142 | * support react 18 ([6631f4e](https://github.com/etchteam/storybook-addon-status/commit/6631f4eb417c379edfaf296573d27a60ce16e5e9)) 143 | * TS and linting ([eda3d4e](https://github.com/etchteam/storybook-addon-status/commit/eda3d4ead600d9e4efde0f35d23334cd554c82a4)) 144 | * updated storybook to 6.2.9 and changed parameters and added typesafety ([07bbfd2](https://github.com/etchteam/storybook-addon-status/commit/07bbfd23f81c2a6aba2d6870f23914718de75a0c)) 145 | * use smart quotes ([23593cc](https://github.com/etchteam/storybook-addon-status/commit/23593cc71100ba90c9dab7972c431ffaa300db2a)) 146 | * using preset now for loading ([0981464](https://github.com/etchteam/storybook-addon-status/commit/0981464123bd14936e9a3428fc6ea2049974a141)) 147 | 148 | 149 | ### Reverts 150 | 151 | * debug ([ad746dd](https://github.com/etchteam/storybook-addon-status/commit/ad746ddcb45947a3f138ef33bc9bee96dd502db3)) 152 | --------------------------------------------------------------------------------