Skip to content

Commit

Permalink
feat: adds storybook (janus-idp#956)
Browse files Browse the repository at this point in the history
FLPATH-701

chore: address PR issues

Changes:
1. Removes the examples directory and related code.
2. Removes @storybook/addon-onboarding
3. Updates deps: @testing-library/jest-dom": "^5.17.0, @backstage/test-utils": "^1.4.4
4. Removes custom prettier config inside the storybook package
5. Fixes code-style issues

docs: updates Storybook's README file

chore: ignore .idea/ folder
  • Loading branch information
jkilzi authored Nov 24, 2023
1 parent 869fe5e commit 4dda929
Show file tree
Hide file tree
Showing 10 changed files with 3,413 additions and 131 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dist-scalprum
/plugins/*/dist-dynamic/*
!/plugins/*/dist-dynamic/package.json
!/plugins/*/dist-dynamic/yarn.lock
storybook-static

# Temporary change files created by Vim
*.swp
Expand All @@ -56,3 +57,5 @@ site

# build cache
.webpack-cache

.idea/
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
"preinstall": "npx only-allow yarn",
"start:backstage": "turbo run start:backstage",
"start:plugins": "turbo run start --filter=@janus-idp/*",
"start:storybook": "yarn --cwd packages/storybook start",
"build": "turbo run build",
"build:backstage": "turbo run build --filter=...{./packages/app} --filter=...{./packages/backend}",
"build:plugins": "turbo run build --filter=@janus-idp/*",
"build:storybook": "yarn --cwd packages/storybook build",
"tsc": "turbo run tsc",
"clean": "turbo run clean",
"test": "turbo run test",
Expand Down Expand Up @@ -42,8 +44,8 @@
"@semrel-extra/npm": "1.2.2",
"@spotify/prettier-config": "15.0.0",
"conventional-changelog-conventionalcommits": "6.1.0",
"husky": "8.0.3",
"eslint-plugin-jest": "27.4.2",
"husky": "8.0.3",
"lint-staged": "15.0.1",
"multi-semantic-release": "3.0.2",
"prettier": "3.0.3",
Expand Down
1 change: 1 addition & 0 deletions packages/storybook/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!.storybook
1 change: 1 addition & 0 deletions packages/storybook/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
25 changes: 25 additions & 0 deletions packages/storybook/.storybook/apis.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {
AlertApiForwarder,
ConfigReader,
ErrorAlerter,
ErrorApiForwarder,
LocalStorageFeatureFlags,
} from '@backstage/core-app-api';
import {
alertApiRef,
configApiRef,
errorApiRef,
featureFlagsApiRef,
} from '@backstage/core-plugin-api';

const configApi = new ConfigReader({});
const featureFlagsApi = new LocalStorageFeatureFlags();
const alertApi = new AlertApiForwarder();
const errorApi = new ErrorAlerter(alertApi, new ErrorApiForwarder());

export const apis = [
[configApiRef, configApi],
[featureFlagsApiRef, featureFlagsApi],
[alertApiRef, alertApi],
[errorApiRef, errorApi],
] as const;
128 changes: 128 additions & 0 deletions packages/storybook/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import type { StorybookConfig } from '@storybook/react-webpack5';
import type { Configuration } from 'webpack';

import { existsSync } from 'node:fs';
import { dirname, join, resolve } from 'node: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')));
}

function makeSwcLoaderOptionsWithSyntax(syntax: 'typescript' | 'ecmascript') {
return {
jsc: {
target: 'es2019',
parser: {
syntax,
tsx: true,
dynamicImport: true,
},
transform: {
react: {
runtime: 'automatic',
},
},
},
};
}

/**
* This function replaces `babel-loader` with `swc-loader` for handling `.[jt]sx?` files.
* @note The `babel-loader` configuration in Storybook doesn't support relatively
* new TypeScript features (e.g. the `satisfies` keyword). Although, using
* https://babeljs.io/docs/babel-plugin-transform-typescript can yield the same results, SWC is faster
* (source: https://swc.rs/blog/perf-swc-vs-babel) and it requires less configuration boilerplate.
*/
function replaceBabelLoaderWithSwcLoader(webpackConfig: Configuration) {
const indexOfRuleUsingBabelLoader = 2;
if (!webpackConfig.module)
throw new Error('Missing `module` property in Webpack configuration');
if (!webpackConfig.module.rules)
throw new Error('Missing `rules` property in Webpack configuration');

const { rules } = webpackConfig.module;
rules.splice(indexOfRuleUsingBabelLoader, 1);
rules.push(
{
test: /\.(tsx?)$/,
exclude: /node_modules/,
loader: require.resolve('swc-loader'),
options: makeSwcLoaderOptionsWithSyntax('typescript'),
},
{
test: /\.(jsx?)$/,
exclude: /node_modules/,
loader: require.resolve('swc-loader'),
options: makeSwcLoaderOptionsWithSyntax('ecmascript'),
},
);

return webpackConfig;
}

/**
* Calling storybook with no args renders all the stories in the plugins directory.
* This is OK if we are making a build of storybook, but for local development it doesn't scale well.
* This function allows passing storybook a specific plugins workspace, in order to render only the stories from that
* specific workspace.
* @example yarn start:storybook plugins/orchestrator
* @note The same applies for the `build` command (`yarn build:storybook <plugins/dir>`)
*/
function createConfig(args: string[]): StorybookConfig {
const lastCliArg = args.at(-1);
const rootDir = resolve(__dirname, '../../..');
const storiesFileExtensions = '*.stories.@(js|jsx|mjs|ts|tsx)';
const mdxFileExtensions = '*.mdx';
const pluginsDirNameRegExp = /plugins\/(\d|\w|\s|-|_)+/;
const storybookConfig: StorybookConfig = {
stories: [],
addons: [
getAbsolutePath('@storybook/addon-links'),
getAbsolutePath('@storybook/addon-essentials'),
getAbsolutePath('@storybook/addon-interactions'),
],
framework: {
name: getAbsolutePath(
'@storybook/react-webpack5',
) as '@storybook/react-webpack5',
options: {
fastRefresh: true,
},
},
docs: {
autodocs: 'tag',
},
core: {
disableTelemetry: true,
},
webpackFinal: async webpackConfig =>
replaceBabelLoaderWithSwcLoader(webpackConfig),
};

if (lastCliArg && pluginsDirNameRegExp.test(lastCliArg)) {
const pluginDir = join(rootDir, lastCliArg);
if (existsSync(pluginDir)) {
// Include only the stories in the given plugin workspace
storybookConfig.stories.push(
`${pluginDir}/src/**/${mdxFileExtensions}`,
`${pluginDir}/src/**/${storiesFileExtensions}`,
);
} else {
throw new Error(`${pluginDir} is not a plugin directory`);
}
} else {
// Include all the stories in the plugins workspace
storybookConfig.stories.push(
`${rootDir}/plugins/*/src/**/${mdxFileExtensions}`,
`${rootDir}/plugins/*/src/**/${storiesFileExtensions}`,
);
}

return storybookConfig;
}

export default createConfig(process.argv.slice(2));
38 changes: 38 additions & 0 deletions packages/storybook/.storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';

import { AlertDisplay } from '@backstage/core-components';
import { TestApiProvider } from '@backstage/test-utils';
import { darkTheme, lightTheme } from '@backstage/theme';

import { CssBaseline, ThemeProvider } from '@material-ui/core';
import type { Preview } from '@storybook/react';
import { useDarkMode } from 'storybook-dark-mode';

import { apis } from './apis';

const preview: Preview = {
decorators: [
Story => (
<TestApiProvider apis={apis}>
<ThemeProvider theme={useDarkMode() ? darkTheme : lightTheme}>
<CssBaseline>
<AlertDisplay />
<Story />
</CssBaseline>
</ThemeProvider>
</TestApiProvider>
),
],
parameters: {
layout: 'fullscreen',
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};

export default preview;
19 changes: 19 additions & 0 deletions packages/storybook/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Storybook

_This package was created through the Backstage CLI_.
It provides a playground for testing and developing UI components in isolation.

## Usage

From the root workspace run:

```sh
yarn start:storybook [plugins/<frontend-plugin-name>]
```

### Notes:

1. If no `plugins/<plugin-name>` is passed, the process will scan for stories inside each plugin workspace.
2. To make a build of Storybook use: `yarn build:storybook [plugins/<frontend-plugin-name>]`.
This command produces a directory called `packages/storybook/storybook-static`. This directory can be then rendered
using a static web server.
49 changes: 49 additions & 0 deletions packages/storybook/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"name": "storybook",
"version": "0.0.0",
"license": "Apache-2.0",
"private": true,
"backstage": {
"role": "frontend"
},
"sideEffects": false,
"scripts": {
"start": "storybook dev -p 6006",
"start:debug": "yarn start:storybook --debug-webpack",
"build": "storybook build",
"lint": "backstage-cli package lint",
"clean": "backstage-cli package clean"
},
"devDependencies": {
"@storybook/react-webpack5": "^7.5.3",
"@storybook/testing-library": "^0.2.2",
"@testing-library/jest-dom": "^5.17.0",
"@types/react": "^17",
"@types/react-dom": "^17",
"@swc/core": "^1.3.96",
"eslint-plugin-storybook": "^0.6.15",
"prop-types": "^15.8.1",
"swc-loader": "^0.2.3"
},
"dependencies": {
"@material-ui/core": "^4.12.4",
"@storybook/addon-controls": "^7.5.3",
"@storybook/addon-essentials": "^7.5.3",
"@storybook/addon-interactions": "^7.5.3",
"@storybook/addon-links": "^7.5.3",
"@storybook/blocks": "^7.5.3",
"@storybook/react": "^7.5.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"storybook": "^7.5.3",
"storybook-dark-mode": "^3.0.1"
},
"peerDependencies": {
"@backstage/cli": "*",
"@backstage/core-app-api": "*",
"@backstage/core-components": "*",
"@backstage/core-plugin-api": "*",
"@backstage/test-utils": "*",
"@backstage/theme": "*"
}
}
Loading

0 comments on commit 4dda929

Please sign in to comment.