Skip to content

chore: add storybook to document available components #6921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .cursor/rules/storybook.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
description: Generate storybook stories
globs:
alwaysApply: false
---
- Rules to generate storybook stories for components:
- Group components by category: forms, navigation, modals, etc.
- Do not create special stories for Dark Mode, the theme is already set in the preview and applied to all components.
- Do not create stories for every possible state, focus on the most common states.
- Check the usage of the component in the rest of the app to see how it is used in different contexts.
- Generate stories in MDX format, in a file next to the component file: example: button.tsx -> button.stories.mdx
- Add documentation and examples that clarify how to use the component and its purpose. Avoid generic documentation, focus on the component's purpose and how to use it. Assume an expert user who already knows general concepts of React and UI design.
- DO NOT ADD "import React from 'react'; on MDX files, is already available and causes an error.
- Examples should be interactive, and show the component in action
- Examples should let people view the code

Typical structure of a story

# Component name

Component description, general explanation of its purpose

## Usage

Example of code

## When to use

- list of appropriate use cases

## When not to use

- (if applicable) list of cases where is better to avoid this component, and alternatives

## Examples

...

## Props
67 changes: 67 additions & 0 deletions configs/storybook/.storybook/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* Remove list styles (bullets/numbers) */
ol,
ul {
list-style: none;
}

/* Preferred box-sizing value */
*,
*::after,
*::before {
box-sizing: border-box;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
font-smoothing: antialiased;
}

html {
font-size: 13px;
}

input,
button,
select,
textarea {
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
input,
optgroup,
select,
textarea {
color: inherit;
font: inherit;
margin: 0;
}

html,
body,
fieldset,
ul,
ol,
dd,
dt {
margin: 0;
padding: 0;
border: 0;
}

blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: '';
content: none;
}

/* Remove spacing between cells in tables */
table {
border-collapse: collapse;
border-spacing: 0;
}
57 changes: 57 additions & 0 deletions configs/storybook/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const path = require('path');
const webpack = require('webpack');

const monorepoRoot = path.resolve(__dirname, '../../../');

module.exports = {
stories: [
'packages/*/src/**/*.stories.@(js|jsx|ts|tsx)',
'packages/*/src/**/*.stories.mdx',
].map((story) => path.resolve(monorepoRoot, story)),
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'@storybook/addon-a11y',
'@storybook/addon-viewport',
],
framework: {
name: '@storybook/react-webpack5',
options: {},
},
docs: {
autodocs: true,
},
webpackFinal: async (config) => {
config.module.rules.push({
test: /\.(ts|tsx)$/,
use: [
{
loader: require.resolve('ts-loader'),
options: {
transpileOnly: true,
},
},
],
});

config.resolve.fallback = {
...config.resolve.fallback,
buffer: require.resolve('buffer/'),
stream: require.resolve('stream-browserify'),
crypto: require.resolve('crypto-browserify'),
path: require.resolve('path-browserify'),
fs: false,
os: require.resolve('os-browserify/browser'),
};

// Add Buffer polyfill
config.plugins.push(
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
})
);

return config;
},
};
140 changes: 140 additions & 0 deletions configs/storybook/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import {
LeafyGreenProvider,
palette,
css,
cx,
spacing,
fontFamilies,
} from '@mongodb-js/compass-components';

import './global.css';

const fontStyles = css`
@font-face {
font-family: 'Euclid Circular A';
font-weight: 700;
font-style: normal;
src: url('../../../packages/compass/src/app/fonts/EuclidCircularA-Semibold-WebXL.woff2')
format('woff2'),
url('../../../packages/compass/src/app/fonts/EuclidCircularA-Semibold-WebXL.woff')
format('woff');
}

@font-face {
font-family: 'Euclid Circular A';
font-weight: 700;
font-style: italic;
src: url('../../../packages/compass/src/app/fonts/EuclidCircularA-SemiboldItalic-WebXL.woff2')
format('woff2'),
url('../../../packages/compass/src/app/fonts/EuclidCircularA-SemiboldItalic-WebXL.woff')
format('woff');
}

@font-face {
font-family: 'Euclid Circular A';
font-weight: 500;
font-style: normal;
src: url('../../../packages/compass/src/app/fonts/EuclidCircularA-Medium-WebXL.woff2')
format('woff2'),
url('../../../packages/compass/src/app/fonts/EuclidCircularA-Medium-WebXL.woff')
format('woff');
}

@font-face {
font-family: 'Euclid Circular A';
font-weight: 500;
font-style: italic;
src: url('../../../packages/compass/src/app/fonts/EuclidCircularA-MediumItalic-WebXL.woff2')
format('woff2'),
url('../../../packages/compass/src/app/fonts/EuclidCircularA-MediumItalic-WebXL.woff')
format('woff');
}

@font-face {
font-family: 'Euclid Circular A';
font-weight: 400;
font-style: normal;
src: url('../../../packages/compass/src/app/fonts/EuclidCircularA-Regular-WebXL.woff2')
format('woff2'),
url('../../../packages/compass/src/app/fonts/EuclidCircularA-Regular-WebXL.woff')
format('woff');
}

@font-face {
font-family: 'Euclid Circular A';
font-weight: 400;
font-style: italic;
src: url('../../../packages/compass/src/app/fonts/EuclidCircularA-RegularItalic-WebXL.woff2')
format('woff2'),
url('../../../packages/compass/src/app/fonts/EuclidCircularA-RegularItalic-WebXL.woff')
format('woff');
}
`;

const homeContainerStyles = css({
padding: spacing[3],
fontFamily:
"'Euclid Circular A', 'Helvetica Neue', Helvetica, Arial, sans-serif",
fontSize: 13,
fontFamilies: fontFamilies.default,
});

const globalLightThemeStyles = css({
backgroundColor: palette.white,
color: palette.gray.dark2,
});

const globalDarkThemeStyles = css({
backgroundColor: palette.black,
color: palette.white,
});

export const globalTypes = {
theme: {
description: 'Global theme for components',
toolbar: {
// The label to show for this toolbar item
title: 'Theme',
icon: 'circlehollow',
// Array of plain string values or MenuItem shape (see below)
items: ['light', 'dark'],
// Change title based on selected value
dynamicTitle: true,
},
},
};

export const initialGlobals = {
theme: 'light',
};

export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
layout: 'fullscreen',
};

export const decorators = [
(Story, context) => {
const isDarkMode = context.globals.theme === 'dark';
return (
<LeafyGreenProvider darkMode={isDarkMode}>
<div className={fontStyles}>
<div
className={cx(
homeContainerStyles,
isDarkMode ? globalDarkThemeStyles : globalLightThemeStyles
)}
>
<Story />
</div>
</div>
</LeafyGreenProvider>
);
},
];
32 changes: 32 additions & 0 deletions configs/storybook/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "@mongodb-js/storybook-config",
"version": "1.0.0",
"description": "Storybook configuration for MongoDB Compass",
"main": "index.js",
"scripts": {
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
"dependencies": {
"@mongodb-js/compass-components": "^1.36.0",
"@storybook/addon-a11y": "^7.6.17",
"@storybook/addon-essentials": "^7.6.17",
"@storybook/addon-interactions": "^7.6.17",
"@storybook/addon-links": "^7.6.17",
"@storybook/addon-viewport": "^7.6.17",
"@storybook/blocks": "^7.6.17",
"@storybook/react-webpack5": "^7.6.17",
"@storybook/testing-library": "^0.2.2",
"buffer": "^6.0.3",
"crypto-browserify": "^3.12.0",
"os-browserify": "^0.3.0",
"path-browserify": "^1.0.1",
"storybook": "^7.6.17",
"stream-browserify": "^3.0.0",
"ts-loader": "^9.5.1"
},
"peerDependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
}
Loading
Loading