Move Storybook to the root
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -4,7 +4,7 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/verify_storybook.yml'
|
||||
- 'storybook/**'
|
||||
- '.storybook/**'
|
||||
- 'packages/ui/src/**'
|
||||
- 'packages/config/src/**'
|
||||
- 'packages/theme/src/**'
|
||||
@@ -49,15 +49,6 @@ jobs:
|
||||
with:
|
||||
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
|
||||
|
||||
- name: Clean up storybook conflicting files
|
||||
run: |
|
||||
rm -rf storybook/node_modules
|
||||
echo "" > storybook/yarn.lock
|
||||
|
||||
- name: Install Storybook dependencies
|
||||
run: yarn install --immutable
|
||||
working-directory: storybook
|
||||
|
||||
- name: Build Storybook
|
||||
run: yarn build-storybook
|
||||
|
||||
@@ -68,5 +59,4 @@ jobs:
|
||||
# projectToken intentionally shared to allow collaborators to run Chromatic on forks
|
||||
# https://www.chromatic.com/docs/custom-ci-provider#run-chromatic-on-external-forks-of-open-source-projects
|
||||
projectToken: chpt_dab72dc0f97d55b
|
||||
workingDir: storybook
|
||||
storybookBuildDir: dist
|
||||
storybookBuildDir: storybook-static
|
||||
|
||||
@@ -184,3 +184,6 @@ knip.json
|
||||
type-docs
|
||||
docs.json
|
||||
tsconfig.typedoc.tmp.json
|
||||
|
||||
# Storybook
|
||||
storybook-static/
|
||||
@@ -0,0 +1,49 @@
|
||||
import type { StorybookConfig } from '@storybook/react-vite';
|
||||
|
||||
import { join, dirname, posix } from 'path';
|
||||
|
||||
// This set of stories are the ones that we publish to backstage.io.
|
||||
const backstageCoreStories = [
|
||||
'packages/ui',
|
||||
'packages/core-components',
|
||||
'packages/app',
|
||||
'plugins/org',
|
||||
'plugins/search',
|
||||
'plugins/search-react',
|
||||
'plugins/home',
|
||||
'plugins/catalog-react',
|
||||
];
|
||||
|
||||
const rootPath = '../';
|
||||
const storiesSrcMdx = 'src/**/*.mdx';
|
||||
const storiesSrcGlob = 'src/**/*.stories.@(js|jsx|mjs|ts|tsx)';
|
||||
|
||||
const getStoriesPath = (element: string, pattern: string) =>
|
||||
posix.join(rootPath, element, pattern);
|
||||
|
||||
const stories = backstageCoreStories.flatMap(element => [
|
||||
getStoriesPath(element, storiesSrcMdx),
|
||||
getStoriesPath(element, storiesSrcGlob),
|
||||
]);
|
||||
|
||||
// Resolve absolute path of a package. Needed in monorepos.
|
||||
function getAbsolutePath(value: string): any {
|
||||
return dirname(require.resolve(join(value, 'package.json')));
|
||||
}
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories,
|
||||
addons: [
|
||||
getAbsolutePath('@storybook/addon-links'),
|
||||
getAbsolutePath('@storybook/addon-essentials'),
|
||||
getAbsolutePath('@storybook/addon-interactions'),
|
||||
getAbsolutePath('@storybook/addon-themes'),
|
||||
getAbsolutePath('@storybook/addon-storysource'),
|
||||
],
|
||||
framework: {
|
||||
name: getAbsolutePath('@storybook/react-vite'),
|
||||
options: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -0,0 +1,126 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { TestApiProvider } from '@backstage/test-utils';
|
||||
import { Content, AlertDisplay } from '@backstage/core-components';
|
||||
import { apis } from './support/apis';
|
||||
import type { Decorator, Preview } from '@storybook/react';
|
||||
import { useGlobals } from '@storybook/preview-api';
|
||||
import { UnifiedThemeProvider, themes } from '@backstage/theme';
|
||||
|
||||
// Default Backstage theme CSS (from packages/ui)
|
||||
import '../packages/ui/src/css/styles.css';
|
||||
|
||||
// Custom Storybook chrome/styles
|
||||
import './storybook.css';
|
||||
|
||||
// Custom themes
|
||||
import './themes/spotify.css';
|
||||
|
||||
const preview: Preview = {
|
||||
globalTypes: {
|
||||
themeMode: {
|
||||
name: 'Theme Mode',
|
||||
description: 'Global theme mode for components',
|
||||
defaultValue: 'light',
|
||||
toolbar: {
|
||||
icon: 'circlehollow',
|
||||
items: [
|
||||
{ value: 'light', icon: 'circlehollow', title: 'Light' },
|
||||
{ value: 'dark', icon: 'circle', title: 'Dark' },
|
||||
],
|
||||
showName: true,
|
||||
dynamicTitle: true,
|
||||
},
|
||||
},
|
||||
themeName: {
|
||||
name: 'Theme Name',
|
||||
description: 'Global theme name for components',
|
||||
defaultValue: 'backstage',
|
||||
toolbar: {
|
||||
icon: 'paintbrush',
|
||||
items: [
|
||||
{ value: 'backstage', title: 'Backstage' },
|
||||
{ value: 'spotify', title: 'Spotify' },
|
||||
],
|
||||
showName: true,
|
||||
dynamicTitle: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
initialGlobals: {
|
||||
themeMode: 'light',
|
||||
themeName: 'backstage',
|
||||
},
|
||||
parameters: {
|
||||
layout: 'fullscreen',
|
||||
backgrounds: {
|
||||
disable: true,
|
||||
},
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
options: {
|
||||
storySort: {
|
||||
order: ['Backstage UI', 'Plugins', 'Layout', 'Navigation'],
|
||||
},
|
||||
},
|
||||
viewport: {
|
||||
viewports: {
|
||||
initial: {
|
||||
name: 'Initial',
|
||||
styles: { width: '320px', height: '100%' },
|
||||
},
|
||||
xs: { name: 'Extra Small', styles: { width: '640px', height: '100%' } },
|
||||
sm: { name: 'Small', styles: { width: '768px', height: '100%' } },
|
||||
md: { name: 'Medium', styles: { width: '1024px', height: '100%' } },
|
||||
lg: { name: 'Large', styles: { width: '1280px', height: '100%' } },
|
||||
xl: {
|
||||
name: 'Extra Large',
|
||||
styles: { width: '1536px', height: '100%' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
decorators: [
|
||||
Story => {
|
||||
const [globals] = useGlobals();
|
||||
const selectedTheme =
|
||||
globals.themeMode === 'light' ? themes.light : themes.dark;
|
||||
const selectedThemeMode = globals.themeMode || 'light';
|
||||
const selectedThemeName = globals.themeName || 'backstage';
|
||||
|
||||
useEffect(() => {
|
||||
document.body.removeAttribute('data-theme-mode');
|
||||
document.body.removeAttribute('data-theme-name');
|
||||
document.body.setAttribute('data-theme-mode', selectedThemeMode);
|
||||
document.body.setAttribute('data-theme-name', selectedThemeName);
|
||||
return () => {
|
||||
document.body.removeAttribute('data-theme-mode');
|
||||
document.body.removeAttribute('data-theme-name');
|
||||
};
|
||||
}, [selectedTheme, selectedThemeName]);
|
||||
|
||||
document.body.style.backgroundColor = 'var(--bui-bg)';
|
||||
const docsStoryElements = document.getElementsByClassName('docs-story');
|
||||
Array.from(docsStoryElements).forEach(element => {
|
||||
(element as HTMLElement).style.backgroundColor = 'var(--bui-bg)';
|
||||
});
|
||||
|
||||
return (
|
||||
<UnifiedThemeProvider theme={selectedTheme}>
|
||||
{/* @ts-ignore */}
|
||||
<TestApiProvider apis={apis}>
|
||||
<AlertDisplay />
|
||||
<Content>
|
||||
<Story />
|
||||
</Content>
|
||||
</TestApiProvider>
|
||||
</UnifiedThemeProvider>
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default preview;
|
||||
@@ -0,0 +1,38 @@
|
||||
:root {
|
||||
--sb-panel-radius: 0;
|
||||
--sb-panel-top: 0;
|
||||
--sb-panel-bottom: 0;
|
||||
--sb-panel-left: 0;
|
||||
--sb-panel-right: 0;
|
||||
--sb-sidebar-border: none;
|
||||
--sb-sidebar-border-right: 1px solid var(--bui-border);
|
||||
--sb-sidebar-bg: #000;
|
||||
--sb-options-border: none;
|
||||
--sb-options-border-left: 1px solid var(--bui-border);
|
||||
--sb-content-padding-inline: 250px;
|
||||
}
|
||||
|
||||
[data-theme-mode='dark'] {
|
||||
--sb-sidebar-bg: var(--bui-bg-surface-1);
|
||||
}
|
||||
|
||||
[data-theme-name='spotify'] {
|
||||
--sb-panel-radius: var(--bui-radius-3);
|
||||
--sb-panel-top: 8px;
|
||||
--sb-panel-bottom: 8px;
|
||||
--sb-panel-left: 8px;
|
||||
--sb-panel-right: 8px;
|
||||
--sb-sidebar-border: none;
|
||||
--sb-sidebar-border-right: none;
|
||||
--sb-sidebar-bg: var(--bui-bg-surface-1);
|
||||
--sb-options-border: none;
|
||||
--sb-options-border-left: none;
|
||||
--sb-content-padding-inline: 258px;
|
||||
}
|
||||
|
||||
[data-theme-name='spotify'][data-theme-mode='light'] {
|
||||
--sb-sidebar-border: 1px solid var(--bui-border);
|
||||
--sb-sidebar-border-right: 1px solid var(--bui-border);
|
||||
--sb-options-border: 1px solid var(--bui-border);
|
||||
--sb-options-border-left: 1px solid var(--bui-border);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import {
|
||||
AlertApiForwarder,
|
||||
ErrorAlerter,
|
||||
ErrorApiForwarder,
|
||||
GithubAuth,
|
||||
GitlabAuth,
|
||||
GoogleAuth,
|
||||
OAuthRequestManager,
|
||||
OktaAuth,
|
||||
ConfigReader,
|
||||
LocalStorageFeatureFlags,
|
||||
} from '@backstage/core-app-api';
|
||||
|
||||
import {
|
||||
alertApiRef,
|
||||
errorApiRef,
|
||||
githubAuthApiRef,
|
||||
gitlabAuthApiRef,
|
||||
googleAuthApiRef,
|
||||
identityApiRef,
|
||||
oauthRequestApiRef,
|
||||
oktaAuthApiRef,
|
||||
configApiRef,
|
||||
featureFlagsApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
import { translationApiRef } from '@backstage/core-plugin-api/alpha';
|
||||
import { MockTranslationApi } from '@backstage/test-utils/alpha';
|
||||
|
||||
const configApi = new ConfigReader({});
|
||||
const featureFlagsApi = new LocalStorageFeatureFlags();
|
||||
const alertApi = new AlertApiForwarder();
|
||||
const errorApi = new ErrorAlerter(alertApi, new ErrorApiForwarder());
|
||||
const identityApi = {
|
||||
getUserId: () => 'guest',
|
||||
getProfile: () => ({ email: 'guest@example.com' }),
|
||||
getIdToken: () => undefined,
|
||||
signOut: async () => {},
|
||||
};
|
||||
const oauthRequestApi = new OAuthRequestManager();
|
||||
const googleAuthApi = GoogleAuth.create({
|
||||
apiOrigin: 'http://localhost:7007',
|
||||
basePath: '/auth/',
|
||||
oauthRequestApi,
|
||||
});
|
||||
const githubAuthApi = GithubAuth.create({
|
||||
apiOrigin: 'http://localhost:7007',
|
||||
basePath: '/auth/',
|
||||
oauthRequestApi,
|
||||
});
|
||||
const gitlabAuthApi = GitlabAuth.create({
|
||||
apiOrigin: 'http://localhost:7007',
|
||||
basePath: '/auth/',
|
||||
oauthRequestApi,
|
||||
});
|
||||
const oktaAuthApi = OktaAuth.create({
|
||||
apiOrigin: 'http://localhost:7007',
|
||||
basePath: '/auth/',
|
||||
oauthRequestApi,
|
||||
});
|
||||
const translationApi = MockTranslationApi.create();
|
||||
|
||||
export const apis = [
|
||||
[configApiRef, configApi],
|
||||
[featureFlagsApiRef, featureFlagsApi],
|
||||
[alertApiRef, alertApi],
|
||||
[errorApiRef, errorApi],
|
||||
[identityApiRef, identityApi],
|
||||
[oauthRequestApiRef, oauthRequestApi],
|
||||
[googleAuthApiRef, googleAuthApi],
|
||||
[githubAuthApiRef, githubAuthApi],
|
||||
[gitlabAuthApiRef, gitlabAuthApi],
|
||||
[oktaAuthApiRef, oktaAuthApi],
|
||||
[translationApiRef, translationApi],
|
||||
];
|
||||
@@ -0,0 +1 @@
|
||||
/* Placeholder for custom Spotify-like theme tweaks applied to the Storybook chrome */
|
||||
+12
-3
@@ -23,7 +23,7 @@
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"build-storybook": "yarn ./storybook run build-storybook",
|
||||
"build-storybook": "storybook build --output-dir storybook-static",
|
||||
"build:all": "backstage-cli repo build --all",
|
||||
"build:api-docs": "LANG=en_EN yarn build:api-reports --docs --exclude 'plugins/@(adr|adr-backend|adr-common|airbrake|airbrake-backend|allure|analytics-module-ga|analytics-module-ga4|analytics-module-newrelic-browser|apache-airflow|api-docs|api-docs-module-protoc-gen-doc|apollo-explorer|app-visualizer|azure-devops|azure-devops-backend|azure-devops-common|azure-sites|azure-sites-backend|azure-sites-common|badges|badges-backend|bazaar|bazaar-backend|bitbucket-cloud-common|bitrise|catalog-graph|catalog-graphql|catalog-import|catalog-unprocessed-entities|cicd-statistics|cicd-statistics-module-gitlab|circleci|cloudbuild|code-climate|code-coverage|code-coverage-backend|codescene|config-schema|cost-insights|cost-insights-common|dynatrace|entity-feedback|entity-feedback-backend|entity-feedback-common|entity-validation|example-todo-list|example-todo-list-backend|example-todo-list-common|firehydrant|fossa|gcalendar|gcp-projects|git-release-manager|github-actions|github-deployments|github-issues|github-pull-requests-board|gitops-profiles|gocd|graphiql|graphql-backend|graphql-voyager|ilert|jenkins|jenkins-backend|jenkins-common|kafka|kafka-backend|lighthouse|lighthouse-backend|lighthouse-common|linguist|linguist-backend|linguist-common|microsoft-calendar|newrelic|newrelic-dashboard|nomad|nomad-backend|octopus-deploy|opencost|pagerduty|periskop|periskop-backend|playlist|playlist-backend|playlist-common|proxy-backend|puppetdb|rollbar|rollbar-backend|sentry|shortcuts|splunk-on-call|stack-overflow|stack-overflow-backend|stackstorm|tech-radar|tech-radar-2|todo|todo-backend|xcmetrics)'",
|
||||
"build:api-reports": "yarn build:api-reports:only --tsc",
|
||||
@@ -55,7 +55,7 @@
|
||||
"start-backend": "echo \"Use 'yarn start example-backend' instead\"",
|
||||
"start:microsite": "cd microsite/ && yarn start",
|
||||
"start:next": "yarn start example-app-next example-backend",
|
||||
"storybook": "yarn ./storybook run storybook",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"sync-issue-templates": "node ./.github/ISSUE_TEMPLATE/sync.js",
|
||||
"techdocs-cli": "node scripts/techdocs-cli.js",
|
||||
"techdocs-cli:dev": "cross-env TECHDOCS_CLI_DEV_MODE=true node scripts/techdocs-cli.js",
|
||||
@@ -129,6 +129,13 @@
|
||||
"@octokit/rest": "^19.0.3",
|
||||
"@playwright/test": "^1.32.3",
|
||||
"@spotify/eslint-plugin": "^15.0.0",
|
||||
"@storybook/addon-essentials": "^8.6.12",
|
||||
"@storybook/addon-interactions": "^8.6.12",
|
||||
"@storybook/addon-links": "^8.6.12",
|
||||
"@storybook/addon-storysource": "^8.6.12",
|
||||
"@storybook/addon-themes": "^8.6.12",
|
||||
"@storybook/react": "^8.6.12",
|
||||
"@storybook/react-vite": "^8.6.12",
|
||||
"@techdocs/cli": "workspace:*",
|
||||
"@types/cacheable-request": "^8.3.6",
|
||||
"@types/memjs": "^1.3.3",
|
||||
@@ -153,8 +160,10 @@
|
||||
"shx": "^0.4.0",
|
||||
"sloc": "^0.3.1",
|
||||
"sort-package-json": "^2.8.0",
|
||||
"storybook": "^8.6.12",
|
||||
"typedoc": "^0.28.0",
|
||||
"typescript": "~5.7.0"
|
||||
"typescript": "~5.7.0",
|
||||
"vite": "^7.1.2"
|
||||
},
|
||||
"packageManager": "yarn@4.8.1",
|
||||
"engines": {
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# storybook
|
||||
|
||||
## 0.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/core-plugin-api@0.6.0
|
||||
- @backstage/test-utils@0.2.3
|
||||
- @backstage/core-app-api@0.5.0
|
||||
|
||||
## 0.2.2-next.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/core-plugin-api@0.6.0-next.0
|
||||
- @backstage/core-app-api@0.5.0-next.0
|
||||
- @backstage/test-utils@0.2.3-next.0
|
||||
|
||||
## 0.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/test-utils@0.2.2
|
||||
- @backstage/core-plugin-api@0.5.0
|
||||
- @backstage/core-app-api@0.4.0
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ae5983387]
|
||||
- Updated dependencies [0d4459c08]
|
||||
- @backstage/theme@0.2.0
|
||||
@@ -1,17 +0,0 @@
|
||||
# storybook
|
||||
|
||||
This package provides a Storybook build for Backstage. See https://backstage.io/storybook/.
|
||||
|
||||
## Usage
|
||||
|
||||
To run the storybook locally, call `yarn storybook` in repo root. This will show the default set of stories that we publish to https://backstage.io/storybook
|
||||
|
||||
If you want to show stories other than the default set, you can pass one or more package paths as an argument when calling storybook, for example:
|
||||
|
||||
```sh
|
||||
yarn storybook plugins/search
|
||||
```
|
||||
|
||||
## Why is this not part of `@backstage/core-components`?
|
||||
|
||||
This separate storybook package exists because of dependency conflicts with `@backstage/cli`. It uses `nohoist` to avoid the conflicts, and since you can only use that in private packages it has to be separated out of `@backstage/core-components`.
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"name": "backstage-storybook",
|
||||
"version": "0.2.2",
|
||||
"description": "Storybook build for components package",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build-storybook": "storybook build --output-dir dist",
|
||||
"storybook": "storybook dev -p 6006"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"plugin:storybook/recommended"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addon-storysource": "^8.6.12",
|
||||
"react": "^18.0.2",
|
||||
"react-dom": "^18.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chromatic-com/storybook": "^1.9.0",
|
||||
"@storybook/addon-essentials": "^8.6.12",
|
||||
"@storybook/addon-interactions": "^8.6.12",
|
||||
"@storybook/addon-links": "^8.6.12",
|
||||
"@storybook/addon-themes": "^8.6.12",
|
||||
"@storybook/react": "^8.6.12",
|
||||
"@storybook/react-vite": "^8.6.12",
|
||||
"@storybook/test": "^8.6.12",
|
||||
"@storybook/types": "^8.6.12",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
||||
"@typescript-eslint/parser": "^5.0.0",
|
||||
"eslint": "^9.11.1",
|
||||
"eslint-plugin-storybook": "^0.12.0",
|
||||
"globals": "^15.9.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"storybook": "^8.6.12",
|
||||
"typescript": "^5.5.3",
|
||||
"typescript-eslint": "^8.7.0",
|
||||
"vite": "^5.4.8"
|
||||
}
|
||||
}
|
||||
-5009
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user