Merge pull request #30879 from backstage/storybook
Merge all Storybook instances at the root level
This commit is contained in:
@@ -192,20 +192,14 @@ jobs:
|
||||
path: .cache/package-docs
|
||||
key: ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-${{ github.run_id }}
|
||||
|
||||
# Also build and upload storybook
|
||||
- name: storybook yarn install
|
||||
run: yarn install --immutable
|
||||
working-directory: storybook
|
||||
|
||||
- name: storybook build
|
||||
- name: Build Storybook
|
||||
run: yarn build-storybook
|
||||
working-directory: storybook
|
||||
|
||||
- name: storybook upload
|
||||
- name: Upload Storybook
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: storybook
|
||||
path: storybook/dist/
|
||||
path: dist-storybook
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
|
||||
@@ -192,20 +192,14 @@ jobs:
|
||||
path: .cache/package-docs
|
||||
key: ${{ runner.os }}-v${{ matrix.node-version }}-package-docs-next-${{ github.run_id }}
|
||||
|
||||
# Also build and upload storybook
|
||||
- name: storybook yarn install
|
||||
run: yarn install --immutable
|
||||
working-directory: storybook
|
||||
|
||||
- name: storybook build
|
||||
- name: Build Storybook
|
||||
run: yarn build-storybook
|
||||
working-directory: storybook
|
||||
|
||||
- name: storybook upload
|
||||
- name: Upload Storybook
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: storybook
|
||||
path: storybook/dist/
|
||||
path: dist-storybook
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/verify_storybook.yml'
|
||||
- 'storybook/**'
|
||||
- '.storybook/**'
|
||||
- 'packages/ui/src/**'
|
||||
- 'packages/config/src/**'
|
||||
- 'packages/theme/src/**'
|
||||
- 'packages/types/src/**'
|
||||
@@ -32,33 +33,30 @@ jobs:
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0 # Required to retrieve git history
|
||||
|
||||
- name: use node.js ${{ matrix.node-version }}
|
||||
- name: Use node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org/ # Needed for auth
|
||||
- name: yarn install
|
||||
|
||||
- name: Install dependencies
|
||||
uses: backstage/actions/yarn-install@b3c1841fd69e1658ac631afafd0fb140a2309024 # v0.6.17
|
||||
with:
|
||||
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
|
||||
- name: storybook yarn install
|
||||
run: yarn install --immutable
|
||||
working-directory: storybook
|
||||
|
||||
# Only for verification, the BUI one is what we upload to Chromatic
|
||||
- run: yarn build-storybook
|
||||
- name: Build Storybook
|
||||
run: yarn build-storybook
|
||||
|
||||
- run: yarn --cwd packages/ui build-storybook
|
||||
|
||||
- uses: chromaui/action@1cfa065cbdab28f6ca3afaeb3d761383076a35aa # v11
|
||||
- name: Deploy Storybook to Chromatic
|
||||
uses: chromaui/action@1cfa065cbdab28f6ca3afaeb3d761383076a35aa # v11
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# 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: packages/ui
|
||||
storybookBuildDir: storybook-static
|
||||
storybookBuildDir: dist-storybook
|
||||
|
||||
@@ -184,3 +184,6 @@ knip.json
|
||||
type-docs
|
||||
docs.json
|
||||
tsconfig.typedoc.tmp.json
|
||||
|
||||
# Storybook
|
||||
dist-storybook/
|
||||
@@ -2,10 +2,9 @@ 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.
|
||||
*/
|
||||
// This set of stories are the ones that we publish to backstage.io.
|
||||
const backstageCoreStories = [
|
||||
'packages/ui',
|
||||
'packages/core-components',
|
||||
'packages/app',
|
||||
'plugins/org',
|
||||
@@ -15,7 +14,7 @@ const backstageCoreStories = [
|
||||
'plugins/catalog-react',
|
||||
];
|
||||
|
||||
const rootPath = '../../';
|
||||
const rootPath = '../';
|
||||
const storiesSrcMdx = 'src/**/*.mdx';
|
||||
const storiesSrcGlob = 'src/**/*.stories.@(js|jsx|mjs|ts|tsx)';
|
||||
|
||||
@@ -27,10 +26,7 @@ const stories = backstageCoreStories.flatMap(element => [
|
||||
getStoriesPath(element, storiesSrcGlob),
|
||||
]);
|
||||
|
||||
/**
|
||||
* This function is used to resolve the absolute path of a package.
|
||||
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
|
||||
*/
|
||||
// Resolve absolute path of a package. Needed in monorepos.
|
||||
function getAbsolutePath(value: string): any {
|
||||
return dirname(require.resolve(join(value, 'package.json')));
|
||||
}
|
||||
@@ -40,7 +36,6 @@ const config: StorybookConfig = {
|
||||
addons: [
|
||||
getAbsolutePath('@storybook/addon-links'),
|
||||
getAbsolutePath('@storybook/addon-essentials'),
|
||||
getAbsolutePath('@chromatic-com/storybook'),
|
||||
getAbsolutePath('@storybook/addon-interactions'),
|
||||
getAbsolutePath('@storybook/addon-themes'),
|
||||
getAbsolutePath('@storybook/addon-storysource'),
|
||||
@@ -50,4 +45,5 @@ const config: StorybookConfig = {
|
||||
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;
|
||||
@@ -12,7 +12,7 @@
|
||||
--sb-content-padding-inline: 250px;
|
||||
}
|
||||
|
||||
[data-theme='dark'] {
|
||||
[data-theme-mode='dark'] {
|
||||
--sb-sidebar-bg: var(--bui-bg-surface-1);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
--sb-content-padding-inline: 258px;
|
||||
}
|
||||
|
||||
[data-theme-name='spotify'][data-theme='light'] {
|
||||
[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);
|
||||
@@ -211,7 +211,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme='light'][data-theme-name='spotify'] {
|
||||
[data-theme-mode='light'][data-theme-name='spotify'] {
|
||||
--bui-bg: var(--bui-gray-1);
|
||||
--bui-bg-surface-1: var(--bui-white);
|
||||
--bui-bg-surface-2: var(--bui-gray-2);
|
||||
@@ -243,7 +243,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme='dark'][data-theme-name='spotify'] {
|
||||
[data-theme-mode='dark'][data-theme-name='spotify'] {
|
||||
--bui-bg: var(--bui-black);
|
||||
--bui-bg-surface-1: var(--bui-gray-1);
|
||||
--bui-bg-surface-2: var(--bui-gray-2);
|
||||
@@ -23,7 +23,7 @@
|
||||
"@mdx-js/react": "^3.1.0",
|
||||
"@next/mdx": "15.3.4",
|
||||
"@remixicon/react": "^4.6.0",
|
||||
"@storybook/react": "^8.6.8",
|
||||
"@storybook/react": "^8.6.12",
|
||||
"@uiw/codemirror-themes": "^4.23.7",
|
||||
"@uiw/react-codemirror": "^4.23.7",
|
||||
"html-react-parser": "^5.2.5",
|
||||
@@ -34,7 +34,7 @@
|
||||
"react": "19.1.1",
|
||||
"react-dom": "19.1.1",
|
||||
"shiki": "^1.26.1",
|
||||
"storybook": "^8.6.8"
|
||||
"storybook": "^8.6.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mdx": "^2.0.13",
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -14,7 +14,7 @@ const config = {
|
||||
name: 'Main Styles',
|
||||
},
|
||||
{
|
||||
source: '.storybook/themes/spotify.css',
|
||||
source: '../../.storybook/themes/spotify.css',
|
||||
destination: 'theme-spotify.css',
|
||||
name: 'Spotify Theme',
|
||||
},
|
||||
|
||||
@@ -44,8 +44,8 @@ export default async function RootLayout({
|
||||
return (
|
||||
<html
|
||||
lang="en"
|
||||
data-theme="light"
|
||||
data-theme-name="default"
|
||||
data-theme-mode="light"
|
||||
data-theme-name="backstage"
|
||||
suppressHydrationWarning
|
||||
>
|
||||
<body>
|
||||
|
||||
@@ -13,8 +13,8 @@ even more straightforward.
|
||||
|
||||
## Light & Dark modes
|
||||
|
||||
By default, Backstage UI supports both light and dark modes using the `data-theme` attribute.
|
||||
The light theme is applied by default if no `data-theme` attribute is specified. To create
|
||||
By default, Backstage UI supports both light and dark modes using the `data-theme-mode` attribute.
|
||||
The light theme is applied by default if no `data-theme-mode` attribute is specified. To create
|
||||
a custom theme, you'll need to define both light and dark modes as outlined below. If
|
||||
only one mode is defined, the other will fall back to the default theme.
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .chip {
|
||||
[data-theme-mode='dark'] .chip {
|
||||
background-color: #2c2c2c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .chip.head {
|
||||
[data-theme-mode='dark'] .chip.head {
|
||||
background-color: #33405b;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .codeBlock {
|
||||
[data-theme-mode='dark'] .codeBlock {
|
||||
background-color: #121212;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .button {
|
||||
[data-theme-mode='dark'] .button {
|
||||
background-color: #2c2c2c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .previewContent {
|
||||
[data-theme-mode='dark'] .previewContent {
|
||||
background-image: radial-gradient(
|
||||
rgba(255, 255, 255, 0.18) 1px,
|
||||
transparent 0
|
||||
|
||||
@@ -13,7 +13,7 @@ import { Icon } from '@backstage/ui';
|
||||
import { usePlayground } from '@/utils/playground-context';
|
||||
|
||||
const themes = [
|
||||
{ name: 'Backstage', value: 'default' },
|
||||
{ name: 'Backstage', value: 'backstage' },
|
||||
{ name: 'Spotify', value: 'spotify' },
|
||||
{ name: 'Custom theme', value: 'custom' },
|
||||
];
|
||||
@@ -23,7 +23,7 @@ export const ThemeNameSelector = () => {
|
||||
|
||||
return (
|
||||
<Select
|
||||
selectedKey={selectedThemeName || 'default'}
|
||||
selectedKey={selectedThemeName || 'backstage'}
|
||||
onSelectionChange={setSelectedThemeName}
|
||||
>
|
||||
<Button className={styles.Select}>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
--surface-1: #f4f4f4;
|
||||
}
|
||||
|
||||
[data-theme='dark'] {
|
||||
[data-theme-mode='dark'] {
|
||||
--bg: #000;
|
||||
--panel: #181818;
|
||||
--panel-hover: #202020;
|
||||
@@ -54,8 +54,8 @@ iframe {
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .shiki,
|
||||
[data-theme='dark'] .shiki span {
|
||||
[data-theme-mode='dark'] .shiki,
|
||||
[data-theme-mode='dark'] .shiki span {
|
||||
color: var(--shiki-dark) !important;
|
||||
/* Optional, if you also want font styles */
|
||||
font-style: var(--shiki-dark-font-style) !important;
|
||||
|
||||
@@ -15,7 +15,7 @@ export const customTheme = `:root {
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme='dark'] {
|
||||
[data-theme-mode='dark'] {
|
||||
--bui-font-regular: system-ui;
|
||||
--bui-font-weight-regular: 400;
|
||||
--bui-font-weight-bold: 600;
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import { components } from './data';
|
||||
|
||||
type Theme = 'light' | 'dark';
|
||||
type ThemeName = 'legacy' | 'default' | 'custom';
|
||||
type ThemeName = 'backstage' | 'spotify';
|
||||
|
||||
// Create a context with an empty array as the default value
|
||||
const PlaygroundContext = createContext<{
|
||||
@@ -27,7 +27,7 @@ const PlaygroundContext = createContext<{
|
||||
setSelectedComponents: () => {},
|
||||
selectedTheme: 'light',
|
||||
setSelectedTheme: () => {},
|
||||
selectedThemeName: 'default',
|
||||
selectedThemeName: 'backstage',
|
||||
setSelectedThemeName: () => {},
|
||||
});
|
||||
|
||||
@@ -42,12 +42,12 @@ export const PlaygroundProvider = ({ children }: { children: ReactNode }) => {
|
||||
);
|
||||
const [selectedTheme, setSelectedTheme] = useState<Theme>('light');
|
||||
const [selectedThemeName, setSelectedThemeName] =
|
||||
useState<ThemeName>('default');
|
||||
useState<ThemeName>('backstage');
|
||||
|
||||
// Load saved theme from localStorage after hydration
|
||||
useEffect(() => {
|
||||
if (isBrowser) {
|
||||
const savedTheme = localStorage.getItem('theme') as Theme;
|
||||
const savedTheme = localStorage.getItem('theme-mode') as Theme;
|
||||
if (savedTheme) {
|
||||
setSelectedTheme(savedTheme);
|
||||
}
|
||||
@@ -67,10 +67,10 @@ export const PlaygroundProvider = ({ children }: { children: ReactNode }) => {
|
||||
useEffect(() => {
|
||||
if (isBrowser) {
|
||||
document.documentElement.setAttribute(
|
||||
'data-theme',
|
||||
'data-theme-mode',
|
||||
selectedTheme || 'light',
|
||||
);
|
||||
localStorage.setItem('theme', selectedTheme || 'light');
|
||||
localStorage.setItem('theme-mode', selectedTheme || 'light');
|
||||
}
|
||||
}, [selectedTheme, isBrowser]);
|
||||
|
||||
@@ -78,9 +78,9 @@ export const PlaygroundProvider = ({ children }: { children: ReactNode }) => {
|
||||
if (isBrowser) {
|
||||
document.documentElement.setAttribute(
|
||||
'data-theme-name',
|
||||
selectedThemeName || 'default',
|
||||
selectedThemeName || 'backstage',
|
||||
);
|
||||
localStorage.setItem('theme-name', selectedThemeName || 'default');
|
||||
localStorage.setItem('theme-name', selectedThemeName || 'backstage');
|
||||
}
|
||||
}, [selectedThemeName, isBrowser]);
|
||||
|
||||
|
||||
@@ -9,19 +9,19 @@ export type ThemeName = keyof typeof availableThemes;
|
||||
|
||||
export function switchTheme(themeName: ThemeName) {
|
||||
// Remove existing theme links
|
||||
const existingLinks = document.querySelectorAll('link[data-theme]');
|
||||
const existingLinks = document.querySelectorAll('link[data-theme-mode]');
|
||||
existingLinks.forEach(link => link.remove());
|
||||
|
||||
// Add new theme link
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = availableThemes[themeName];
|
||||
link.setAttribute('data-theme', themeName);
|
||||
link.setAttribute('data-theme-mode', themeName);
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
|
||||
export function getCurrentTheme(): ThemeName {
|
||||
const existingLink = document.querySelector('link[data-theme]');
|
||||
const existingLink = document.querySelector('link[data-theme-mode]');
|
||||
if (existingLink) {
|
||||
const href = existingLink.getAttribute('href');
|
||||
for (const [name, path] of Object.entries(availableThemes)) {
|
||||
|
||||
@@ -156,10 +156,10 @@ are separated out into their own folder, see further down.
|
||||
- [`integration/`](https://github.com/backstage/backstage/tree/master/packages/integration) -
|
||||
Common functionalities of integrations like GitHub, GitLab, etc.
|
||||
|
||||
- [`storybook/`](https://github.com/backstage/backstage/tree/master/storybook) -
|
||||
This folder contains only the Storybook config which helps visualize our
|
||||
reusable React components. Stories are within the core package, and are
|
||||
published in the [Backstage Storybook](https://backstage.io/storybook).
|
||||
- [`.storybook/`](https://github.com/backstage/backstage/tree/master/.storybook) -
|
||||
This folder contains the Storybook configuration which helps visualize our
|
||||
reusable React components. Stories are scanned from packages and plugins across
|
||||
the monorepo, and are published in the [Backstage Storybook](https://backstage.io/storybook).
|
||||
|
||||
- [`techdocs-node/`](https://github.com/backstage/backstage/tree/master/plugins/techdocs-node) -
|
||||
Common node.js functionalities for TechDocs, to be shared between
|
||||
|
||||
+12
-3
@@ -23,7 +23,7 @@
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"build-storybook": "yarn ./storybook run build-storybook",
|
||||
"build-storybook": "storybook build --output-dir dist-storybook",
|
||||
"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,34 +0,0 @@
|
||||
import type { StorybookConfig } from '@storybook/react-webpack5';
|
||||
import { join, dirname } from 'path';
|
||||
|
||||
/**
|
||||
* This function is used to resolve the absolute path of a package.
|
||||
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
|
||||
*/
|
||||
function getAbsolutePath(value: string): string {
|
||||
return dirname(require.resolve(join(value, 'package.json')));
|
||||
}
|
||||
const config: StorybookConfig = {
|
||||
stories: ['../src/components/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
||||
staticDirs: ['../static'],
|
||||
addons: [
|
||||
getAbsolutePath('@storybook/addon-webpack5-compiler-swc'),
|
||||
getAbsolutePath('@storybook/addon-essentials'),
|
||||
getAbsolutePath('@storybook/addon-interactions'),
|
||||
],
|
||||
framework: {
|
||||
name: getAbsolutePath('@storybook/react-webpack5'),
|
||||
options: {},
|
||||
},
|
||||
// https://storybook.js.org/docs/configure/integration/compilers#the-swc-compiler-doesnt-work-with-react
|
||||
swc: () => ({
|
||||
jsc: {
|
||||
transform: {
|
||||
react: {
|
||||
runtime: 'automatic',
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
export default config;
|
||||
@@ -1,153 +0,0 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import type { Decorator, Preview, ReactRenderer } from '@storybook/react';
|
||||
import { useGlobals } from '@storybook/preview-api';
|
||||
|
||||
// Default Backstage theme
|
||||
import '../src/css/styles.css';
|
||||
|
||||
// Custom mocked styles
|
||||
import '../src/css/storybook.css';
|
||||
|
||||
// Custom themes
|
||||
import './themes/spotify.css';
|
||||
|
||||
export const withThemes: Decorator = StoryFn => {
|
||||
const [globals] = useGlobals();
|
||||
const selectedTheme = globals.themeMode || 'light';
|
||||
const selectedThemeName = globals.themeName || 'default';
|
||||
|
||||
useEffect(() => {
|
||||
const htmlElement = document.documentElement;
|
||||
|
||||
// Remove any existing theme data attributes
|
||||
htmlElement.removeAttribute('data-theme');
|
||||
htmlElement.removeAttribute('data-theme-name');
|
||||
|
||||
// Add the selected theme data attribute
|
||||
htmlElement.setAttribute('data-theme', selectedTheme);
|
||||
htmlElement.setAttribute('data-theme-name', selectedThemeName);
|
||||
|
||||
// Cleanup on unmount
|
||||
return () => {
|
||||
htmlElement.removeAttribute('data-theme');
|
||||
htmlElement.removeAttribute('data-theme-name');
|
||||
};
|
||||
}, [selectedTheme, selectedThemeName]);
|
||||
|
||||
return <StoryFn />;
|
||||
};
|
||||
|
||||
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: 'default',
|
||||
toolbar: {
|
||||
icon: 'paintbrush',
|
||||
items: [
|
||||
{ value: 'default', title: 'Default (Backstage)' },
|
||||
{ value: 'spotify', title: 'Spotify' },
|
||||
],
|
||||
showName: true,
|
||||
dynamicTitle: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
initialGlobals: {
|
||||
themeMode: 'light',
|
||||
themeName: 'default',
|
||||
},
|
||||
parameters: {
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
backgrounds: {
|
||||
disable: true,
|
||||
},
|
||||
options: {
|
||||
storySort: {
|
||||
method: 'alphabetical',
|
||||
order: ['Core Concepts', 'Components'],
|
||||
},
|
||||
},
|
||||
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: [
|
||||
withThemes,
|
||||
Story => {
|
||||
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 <Story />;
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default preview;
|
||||
@@ -9182,7 +9182,7 @@
|
||||
--bui-animate-pulse: pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
[data-theme-mode="dark"] {
|
||||
--bui-gray-1: #191919;
|
||||
--bui-gray-2: #242424;
|
||||
--bui-gray-3: #373737;
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
],
|
||||
"scripts": {
|
||||
"build": "yarn build:app && yarn build:css",
|
||||
"build-storybook": "storybook build",
|
||||
"build:app": "backstage-cli package build",
|
||||
"build:css": "node scripts/build-css.mjs",
|
||||
"build:css:watch": "node scripts/build-css.mjs --watch",
|
||||
@@ -36,31 +35,22 @@
|
||||
"lint": "backstage-cli package lint",
|
||||
"prepack": "backstage-cli package prepack",
|
||||
"postpack": "backstage-cli package postpack",
|
||||
"start": "concurrently \"yarn build:css:watch\" \"yarn storybook\"",
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"test": "backstage-cli package test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@base-ui-components/react": "1.0.0-alpha.7",
|
||||
"@remixicon/react": "^4.6.0",
|
||||
"@storybook/test": "^8.6.12",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"clsx": "^2.1.1",
|
||||
"react-aria-components": "^1.10.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@storybook/addon-essentials": "^8.6.12",
|
||||
"@storybook/addon-interactions": "^8.6.12",
|
||||
"@storybook/addon-styling-webpack": "^1.0.1",
|
||||
"@storybook/addon-webpack5-compiler-swc": "^3.0.0",
|
||||
"@storybook/blocks": "^8.6.12",
|
||||
"@storybook/react": "^8.6.12",
|
||||
"@storybook/react-webpack5": "^8.6.12",
|
||||
"@storybook/test": "^8.6.12",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"chalk": "^5.4.1",
|
||||
"concurrently": "^9.2.0",
|
||||
"eslint-plugin-storybook": "^0.12.0",
|
||||
"glob": "^11.0.1",
|
||||
"globals": "^15.11.0",
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Avatar } from './index';
|
||||
import { Flex } from '../..';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Avatar',
|
||||
title: 'Backstage UI/Avatar',
|
||||
component: Avatar,
|
||||
} satisfies Meta<typeof Avatar>;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import { Box } from './Box';
|
||||
import { Flex } from '../Flex';
|
||||
|
||||
const meta = {
|
||||
title: 'Layout/Box',
|
||||
title: 'Backstage UI/Box',
|
||||
component: Box,
|
||||
argTypes: {
|
||||
as: {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Text } from '../Text';
|
||||
import { Icon } from '../Icon';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Button',
|
||||
title: 'Backstage UI/Button',
|
||||
component: Button,
|
||||
argTypes: {
|
||||
size: {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Text } from '../Text';
|
||||
import { Icon } from '../Icon';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/ButtonIcon',
|
||||
title: 'Backstage UI/ButtonIcon',
|
||||
component: ButtonIcon,
|
||||
argTypes: {
|
||||
size: {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Text } from '../Text';
|
||||
import { Icon } from '../Icon';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/ButtonLink',
|
||||
title: 'Backstage UI/ButtonLink',
|
||||
component: ButtonLink,
|
||||
argTypes: {
|
||||
size: {
|
||||
|
||||
@@ -25,7 +25,7 @@ export interface ListItem {
|
||||
}
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Card',
|
||||
title: 'Backstage UI/Card',
|
||||
component: Card,
|
||||
subcomponents: { CardHeader, CardBody, CardFooter },
|
||||
} satisfies Meta<typeof Card>;
|
||||
|
||||
@@ -20,7 +20,7 @@ import { Flex } from '../Flex';
|
||||
import { Text } from '../Text';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Checkbox',
|
||||
title: 'Backstage UI/Checkbox',
|
||||
component: Checkbox,
|
||||
} satisfies Meta<typeof Checkbox>;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import { Text } from '../Text';
|
||||
import { Icon } from '../Icon';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Collapsible',
|
||||
title: 'Backstage UI/Collapsible',
|
||||
component: Collapsible.Root,
|
||||
} satisfies Meta<typeof Collapsible.Root>;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Box } from '../Box/Box';
|
||||
import { Container } from './Container';
|
||||
|
||||
const meta = {
|
||||
title: 'Layout/Container',
|
||||
title: 'Backstage UI/Container',
|
||||
component: Container,
|
||||
parameters: {
|
||||
layout: 'fullscreen',
|
||||
|
||||
@@ -19,7 +19,7 @@ import { TextField, Input, Form } from 'react-aria-components';
|
||||
import { FieldError } from './FieldError';
|
||||
|
||||
const meta = {
|
||||
title: 'Forms/FieldError',
|
||||
title: 'Backstage UI/FieldError',
|
||||
component: FieldError,
|
||||
} satisfies Meta<typeof FieldError>;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { FieldLabel } from './FieldLabel';
|
||||
|
||||
const meta = {
|
||||
title: 'Forms/FieldLabel',
|
||||
title: 'Backstage UI/FieldLabel',
|
||||
component: FieldLabel,
|
||||
argTypes: {
|
||||
label: {
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Flex } from './Flex';
|
||||
import { Text } from '../Text';
|
||||
|
||||
const meta = {
|
||||
title: 'Layout/Flex',
|
||||
title: 'Backstage UI/Flex',
|
||||
component: Flex,
|
||||
argTypes: {
|
||||
align: {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Box } from '../Box/Box';
|
||||
import { Flex } from '../Flex';
|
||||
|
||||
const meta = {
|
||||
title: 'Layout/Grid',
|
||||
title: 'Backstage UI/Grid',
|
||||
component: Grid.Root,
|
||||
} satisfies Meta<typeof Grid>;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import {
|
||||
import { HeaderPageBreadcrumb } from '../HeaderPage/types';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Header',
|
||||
title: 'Backstage UI/Header',
|
||||
component: Header,
|
||||
parameters: {
|
||||
layout: 'fullscreen',
|
||||
|
||||
@@ -23,7 +23,7 @@ import { Container } from '../Container';
|
||||
import { Text } from '../Text';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/HeaderPage',
|
||||
title: 'Backstage UI/HeaderPage',
|
||||
component: HeaderPage,
|
||||
parameters: {
|
||||
layout: 'fullscreen',
|
||||
|
||||
@@ -20,7 +20,7 @@ import { IconProvider } from './provider';
|
||||
import { icons } from './icons';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Icon',
|
||||
title: 'Backstage UI/Icon',
|
||||
component: Icon,
|
||||
argTypes: {
|
||||
name: {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Text } from '../Text';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Link',
|
||||
title: 'Backstage UI/Link',
|
||||
component: Link,
|
||||
args: {
|
||||
children: 'Link',
|
||||
|
||||
@@ -20,7 +20,7 @@ import { Text, Icon, Button, Flex } from '../../index';
|
||||
import { useState } from 'react';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Menu',
|
||||
title: 'Backstage UI/Menu',
|
||||
component: Menu.Root,
|
||||
} satisfies Meta<typeof Menu.Root>;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { RadioGroup, Radio } from './RadioGroup';
|
||||
|
||||
const meta = {
|
||||
title: 'Forms/RadioGroup',
|
||||
title: 'Backstage UI/RadioGroup',
|
||||
component: RadioGroup,
|
||||
} satisfies Meta<typeof RadioGroup>;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import { ScrollArea } from './ScrollArea';
|
||||
import { Text } from '../Text/Text';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/ScrollArea',
|
||||
title: 'Backstage UI/ScrollArea',
|
||||
component: ScrollArea.Root,
|
||||
} satisfies Meta<typeof ScrollArea.Root>;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import { RiCactusLine } from '@remixicon/react';
|
||||
import { Button } from '../Button';
|
||||
|
||||
const meta = {
|
||||
title: 'Forms/SearchField',
|
||||
title: 'Backstage UI/SearchField',
|
||||
component: SearchField,
|
||||
argTypes: {
|
||||
isRequired: {
|
||||
|
||||
@@ -20,7 +20,7 @@ import { Form } from 'react-aria-components';
|
||||
import { RiCloudLine } from '@remixicon/react';
|
||||
|
||||
const meta = {
|
||||
title: 'Forms/Select',
|
||||
title: 'Backstage UI/Select',
|
||||
component: Select,
|
||||
} satisfies Meta<typeof Select>;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Skeleton } from './Skeleton';
|
||||
import { Flex } from '../Flex';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Skeleton',
|
||||
title: 'Backstage UI/Skeleton',
|
||||
component: Skeleton,
|
||||
argTypes: {
|
||||
rounded: {
|
||||
|
||||
@@ -18,7 +18,7 @@ import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Switch } from './Switch';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Switch',
|
||||
title: 'Backstage UI/Switch',
|
||||
component: Switch,
|
||||
} satisfies Meta<typeof Switch>;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import { RiCactusLine } from '@remixicon/react';
|
||||
import { TablePagination } from '../TablePagination';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Table',
|
||||
title: 'Backstage UI/Table',
|
||||
decorators: [
|
||||
(Story: StoryFn) => (
|
||||
<MemoryRouter>
|
||||
@@ -47,7 +47,7 @@ const meta = {
|
||||
|
||||
// Added this fix to fix Chromatic timeout error. This bug is due to rerendering the table with too many rows.
|
||||
// Work in progress to fix it here - https://github.com/backstage/backstage/pull/30687
|
||||
const data1 = data1Raw.slice(0, 25);
|
||||
const data1 = data1Raw.slice(0, 10);
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useArgs } from '@storybook/preview-api';
|
||||
// TODO: Bring useArgs() back when we update Storybook to 9
|
||||
// import { useArgs } from 'storybook/preview-api';
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { TablePagination } from './TablePagination';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/TablePagination',
|
||||
title: 'Backstage UI/TablePagination',
|
||||
component: TablePagination,
|
||||
argTypes: {
|
||||
offset: { control: 'number' },
|
||||
@@ -41,17 +42,17 @@ export const Default: Story = {
|
||||
rowCount: 100,
|
||||
},
|
||||
render: args => {
|
||||
const [{}, updateArgs] = useArgs();
|
||||
// const [{}, updateArgs] = useArgs();
|
||||
|
||||
return (
|
||||
<TablePagination
|
||||
{...args}
|
||||
setOffset={value => {
|
||||
updateArgs({ offset: value });
|
||||
}}
|
||||
setPageSize={value => {
|
||||
updateArgs({ pageSize: value });
|
||||
}}
|
||||
// setOffset={value => {
|
||||
// updateArgs({ offset: value });
|
||||
// }}
|
||||
// setPageSize={value => {
|
||||
// updateArgs({ pageSize: value });
|
||||
// }}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Box } from '../Box';
|
||||
import { Text } from '../Text';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Tabs',
|
||||
title: 'Backstage UI/Tabs',
|
||||
component: Tabs,
|
||||
} satisfies Meta<typeof Tabs>;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Text } from './Text';
|
||||
import { Flex } from '../Flex';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Text',
|
||||
title: 'Backstage UI/Text',
|
||||
component: Text,
|
||||
args: {
|
||||
children: 'Text',
|
||||
|
||||
@@ -22,7 +22,7 @@ import { Flex } from '../Flex';
|
||||
import { FieldLabel } from '../FieldLabel';
|
||||
|
||||
const meta = {
|
||||
title: 'Forms/TextField',
|
||||
title: 'Backstage UI/TextField',
|
||||
component: TextField,
|
||||
argTypes: {
|
||||
isRequired: {
|
||||
|
||||
@@ -20,7 +20,7 @@ import { TooltipTrigger, Tooltip } from './Tooltip';
|
||||
import { Button } from '../Button/Button';
|
||||
|
||||
const meta = {
|
||||
title: 'Components/Tooltip',
|
||||
title: 'Backstage UI/Tooltip',
|
||||
component: TooltipTrigger,
|
||||
parameters: { layout: 'centered' },
|
||||
argTypes: {
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
}
|
||||
|
||||
/* Dark theme tokens */
|
||||
[data-theme='dark'] {
|
||||
[data-theme-mode='dark'] {
|
||||
/* Gray scale */
|
||||
--bui-gray-1: #191919;
|
||||
--bui-gray-2: #242424;
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*storybook.log
|
||||
@@ -1,2 +0,0 @@
|
||||
registry=https://registry.npmjs.org/
|
||||
engine-strict=true
|
||||
@@ -1,53 +0,0 @@
|
||||
import { TestApiProvider } from '@backstage/test-utils';
|
||||
import { Content, AlertDisplay } from '@backstage/core-components';
|
||||
import { lightTheme, darkTheme } from '@backstage/theme';
|
||||
import { CssBaseline, ThemeProvider } from '@material-ui/core';
|
||||
import { apis } from './apis';
|
||||
import { withThemeFromJSXProvider } from '@storybook/addon-themes';
|
||||
|
||||
import type { Preview, ReactRenderer } from '@storybook/react';
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
darkMode: {
|
||||
current: 'light',
|
||||
},
|
||||
layout: 'fullscreen',
|
||||
},
|
||||
decorators: [
|
||||
withThemeFromJSXProvider<ReactRenderer>({
|
||||
themes: {
|
||||
Light: lightTheme,
|
||||
Dark: darkTheme,
|
||||
},
|
||||
defaultTheme: 'Light',
|
||||
Provider: ThemeProvider,
|
||||
GlobalStyles: CssBaseline,
|
||||
}),
|
||||
Story => (
|
||||
// @ts-ignore - TODO: Fix this
|
||||
<TestApiProvider apis={apis}>
|
||||
<AlertDisplay />
|
||||
<Content>
|
||||
<Story />
|
||||
</Content>
|
||||
</TestApiProvider>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
export default preview;
|
||||
|
||||
export const parameters = {
|
||||
options: {
|
||||
storySort: {
|
||||
order: ['Plugins', 'Layout', 'Navigation'],
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -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,45 +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.3.6",
|
||||
"react": "^18.0.2",
|
||||
"react-dom": "^18.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@chromatic-com/storybook": "^1.9.0",
|
||||
"@storybook/addon-essentials": "^8.3.5",
|
||||
"@storybook/addon-interactions": "^8.3.5",
|
||||
"@storybook/addon-links": "^8.3.5",
|
||||
"@storybook/addon-themes": "^8.3.6",
|
||||
"@storybook/blocks": "^8.3.5",
|
||||
"@storybook/react": "^8.3.5",
|
||||
"@storybook/react-vite": "^8.3.5",
|
||||
"@storybook/test": "^8.3.5",
|
||||
"@storybook/types": "^8.3.5",
|
||||
"@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.3.5",
|
||||
"typescript": "^5.5.3",
|
||||
"typescript-eslint": "^8.7.0",
|
||||
"vite": "^5.4.8"
|
||||
}
|
||||
}
|
||||
-5010
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user