-
-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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
add typescript docs #3361
add typescript docs #3361
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,19 +19,19 @@ Let's say you want to add [SASS](http://sass-lang.com/) support to Storybook. Th | |
Simply add the following content to a file called `webpack.config.js` in your Storybook config directory (`.storybook` by default ). | ||
|
||
```js | ||
const path = require('path'); | ||
const path = require("path"); | ||
|
||
module.exports = { | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.scss$/, | ||
loaders: ["style-loader", "css-loader", "sass-loader"], | ||
include: path.resolve(__dirname, '../') | ||
include: path.resolve(__dirname, "../") | ||
} | ||
] | ||
} | ||
} | ||
}; | ||
``` | ||
|
||
Since this config file stays in the Storybook directory, you need to set the include path as above. If the config directory stays in a different directory, you need to set the include path relative to that. | ||
|
@@ -45,9 +45,9 @@ You also need to install the loaders (style, css, sass, as well as node-sass) us | |
You can add any kind of Webpack configuration options with the above config, whether they are plugins, loaders, or aliases. | ||
But you won't be able to change the following config options: | ||
|
||
- entry | ||
- output | ||
- js loader with babel | ||
* entry | ||
* output | ||
* js loader with babel | ||
|
||
For the advanced usage we strongly recommend [full control mode](#full-control-mode). | ||
|
||
|
@@ -60,7 +60,7 @@ That's where you can use our full control mode. | |
To enable that, you need to export a **function** from the above `webpack.config.js` file, just like this: | ||
|
||
```js | ||
const path = require('path'); | ||
const path = require("path"); | ||
|
||
// Export a function. Accept the base config as the only param. | ||
module.exports = (storybookBaseConfig, configType) => { | ||
|
@@ -72,7 +72,7 @@ module.exports = (storybookBaseConfig, configType) => { | |
storybookBaseConfig.module.rules.push({ | ||
test: /\.scss$/, | ||
loaders: ["style-loader", "css-loader", "sass-loader"], | ||
include: path.resolve(__dirname, '../') | ||
include: path.resolve(__dirname, "../") | ||
}); | ||
|
||
// Return the altered config | ||
|
@@ -82,10 +82,10 @@ module.exports = (storybookBaseConfig, configType) => { | |
|
||
Storybook uses the config returned from the above function. So, try to edit the `storybookBaseConfig` with care. Make sure to preserve the following config options: | ||
|
||
- entry | ||
- output | ||
- first loader in the module.loaders (Babel loader for JS) | ||
- all existing plugins | ||
* entry | ||
* output | ||
* first loader in the module.loaders (Babel loader for JS) | ||
* all existing plugins | ||
|
||
> If your custom webpack config uses a loader that does not explicitly include specific file extensions via the `test` property, it is necessary to `exclude` the `.ejs` file extension from that loader. | ||
|
||
|
@@ -96,28 +96,30 @@ If so, this is how you do it using the Full Control Mode. | |
Add following content to the `webpack.config.js` in your Storybook config directory. | ||
|
||
```js | ||
const path = require('path'); | ||
const path = require("path"); | ||
|
||
module.exports = (baseConfig, env, defaultConfig) => { | ||
// Extend defaultConfig as you need. | ||
|
||
// For example, add typescript loader: | ||
defaultConfig.module.rules.push({ | ||
test: /\.(ts|tsx)$/, | ||
include: path.resolve(__dirname, '../src'), | ||
loader: require.resolve('ts-loader') | ||
include: path.resolve(__dirname, "../src"), | ||
loader: require.resolve("ts-loader") | ||
}); | ||
defaultConfig.resolve.extensions.push('.ts', '.tsx'); | ||
defaultConfig.resolve.extensions.push(".ts", ".tsx"); | ||
|
||
return defaultConfig; | ||
}; | ||
``` | ||
|
||
For full instructions on Typescript setup, check [our dedicated Typescript page](/configurations/typescript-config/). | ||
|
||
## Using Your Existing Config | ||
|
||
You may have an existing Webpack config for your project. So, you may need to copy and paste some config items into Storybook's custom Webpack config file. | ||
|
||
But you don't need to. There are a few options: | ||
|
||
- Simply import your main Webpack config into Storybook's `webpack.config.js` and use the loaders and plugins used in that. | ||
- Create a new file with common Webpack options and use it in both inside the main Webpack config and inside Storybook's `webpack.config.js`. | ||
* Simply import your main Webpack config into Storybook's `webpack.config.js` and use the loaders and plugins used in that. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you remove this It should just say There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hahaha i didnt write that |
||
* Create a new file with common Webpack options and use it in both inside the main Webpack config and inside Storybook's `webpack.config.js`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
--- | ||
id: 'typescript-config' | ||
title: 'Typescript Config' | ||
--- | ||
|
||
This is a central reference for using Storybook with Typescript. | ||
|
||
## Dependencies you may need | ||
|
||
```bash | ||
yarn add -D typescript | ||
yarn add -D awesome-typescript-loader # alternative to ts-loader | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are these two loaders interchangeable in this guide? we should leave a note about it here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes |
||
yarn add -D @storybook/addon-info react-docgen-typescript-webpack-plugin # optional but recommended | ||
yarn add -D jest "@types/jest" ts-jest #testing | ||
``` | ||
|
||
## Setting up Typescript to work with Storybook | ||
|
||
We first have to use the [custom Webpack config in full control mode, extending default configs](https://storybook.js.org/configurations/custom-webpack-config/#full-control-mode--default): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think relative URLs work here, so There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok |
||
|
||
```js | ||
// load the default config generator. | ||
const genDefaultConfig = require("@storybook/react/dist/server/config/defaults/webpack.config.js"); | ||
const path = require("path"); | ||
const TSDocgenPlugin = require("react-docgen-typescript-webpack-plugin"); // optional | ||
|
||
module.exports = (baseConfig, env) => { | ||
const config = genDefaultConfig(baseConfig, env); | ||
config.module.rules.push({ | ||
test: /\.(ts|tsx)$/, | ||
include: [ | ||
path.resolve(__dirname, "../src"), | ||
path.resolve(__dirname, "../stories") // e.g. if you have a separate /stories folder | ||
], | ||
loader: require.resolve("awesome-typescript-loader") // or ts-loader | ||
// alternatively | ||
// loader: 'babel-loader!ts-loader', | ||
}); | ||
config.plugins.push(new TSDocgenPlugin()); // optional | ||
config.resolve.extensions.push(".ts", ".tsx"); | ||
return config; | ||
}; | ||
``` | ||
|
||
The above example shows a working config with the TSDocgen plugin also integrated; remove the optional sections if you don't plan on using them. | ||
|
||
## `tsconfig.json` | ||
|
||
```json | ||
{ | ||
"compilerOptions": { | ||
"outDir": "build/lib", | ||
"module": "commonjs", | ||
"target": "es5", | ||
"lib": ["es5", "es6", "es7", "es2017", "dom"], | ||
"sourceMap": true, | ||
"allowJs": false, | ||
"jsx": "react", | ||
"moduleResolution": "node", | ||
"rootDir": "src", | ||
"baseUrl": "src", | ||
"forceConsistentCasingInFileNames": true, | ||
"noImplicitReturns": true, | ||
"noImplicitThis": true, | ||
"noImplicitAny": true, | ||
"strictNullChecks": true, | ||
"suppressImplicitAnyIndexErrors": true, | ||
"noUnusedLocals": true, | ||
"declaration": true, | ||
"allowSyntheticDefaultImports": true, | ||
"experimentalDecorators": true | ||
}, | ||
"include": ["src/**/*"], | ||
"exclude": ["node_modules", "build", "scripts"] | ||
} | ||
``` | ||
|
||
If you have your stories in a separate `/stories` folder you may wish to replace `rootDir` above with `"rootDirs": ["src", "stories"]`. | ||
|
||
## Using Typescript with the TSDocgen addon | ||
|
||
The very handy [Storybook Info addon](https://github.com/storybooks/storybook/tree/master/addons/info) autogenerates prop tables documentation for each component, however it doesn't work with Typescript types. The current solution is to use [react-docgen-typescript-loader](https://github.com/strothj/react-docgen-typescript-loader) to preprocess the Typescript files to give the Info addon what it needs. The webpack config above does this, and so for the rest of your stories you use it as per normal: | ||
|
||
```js | ||
import React from "react"; | ||
import { storiesOf } from "@storybook/react"; | ||
import { withInfo } from "@storybook/addon-info"; | ||
import { action } from "@storybook/addon-actions"; | ||
import TicTacToeCell from "./TicTacToeCell"; | ||
|
||
const stories = storiesOf("Components", module); | ||
|
||
stories.add( | ||
"TicTacToeCell", | ||
withInfo({ inline: true })(() => <TicTacToeCell value="X" position={{ x: 0, y: 0 }} onClick={action("onClick")} />) | ||
); | ||
``` | ||
|
||
## Customizing Type annotations/descriptions | ||
|
||
Please refer to the [react-docgen-typescript-loader](https://github.com/strothj/react-docgen-typescript-loader) docs for writing prop descriptions and other annotations to your Typescript interfaces. | ||
|
||
Additional annotation can be achieved by creating a `wInfo` higher order component: | ||
|
||
```js | ||
import { withInfo } from "@storybook/addon-info"; | ||
const wInfoStyle = { | ||
header: { | ||
h1: { | ||
marginRight: "20px", | ||
fontSize: "25px", | ||
display: "inline" | ||
}, | ||
body: { | ||
paddingTop: 0, | ||
paddingBottom: 0 | ||
}, | ||
h2: { | ||
display: "inline", | ||
color: "#999" | ||
} | ||
}, | ||
infoBody: { | ||
backgroundColor: "#eee", | ||
padding: "0px 5px", | ||
lineHeight: "2" | ||
} | ||
}; | ||
export const wInfo = text => withInfo({ inline: true, source: false, styles: wInfoStyle, text: text }); | ||
``` | ||
|
||
This can be used like so: | ||
|
||
```js | ||
import React from "react"; | ||
|
||
import { storiesOf } from "@storybook/react"; | ||
import { PrimaryButton } from "./Button"; | ||
import { wInfo } from "../../utils"; | ||
import { text, select, boolean } from "@storybook/addon-knobs/react"; | ||
|
||
storiesOf("Components/Button", module).addWithJSX( | ||
"basic PrimaryButton", | ||
wInfo(` | ||
|
||
### Notes | ||
|
||
light button seen on <https://zpl.io/aM49ZBd> | ||
|
||
### Usage | ||
~~~js | ||
<PrimaryButton | ||
label={text('label', 'Enroll')} | ||
disabled={boolean('disabled',false)} | ||
onClick={() => alert('hello there')} | ||
/> | ||
~~~ | ||
|
||
`)(() => ( | ||
<PrimaryButton | ||
label={text("label", "Enroll")} | ||
disabled={boolean("disabled", false)} | ||
onClick={() => alert("hello there")} | ||
/> | ||
)) | ||
); | ||
``` | ||
|
||
And this is how it looks: | ||
|
||
![image](https://user-images.githubusercontent.com/35976578/38376038-ac02b432-38c5-11e8-9aed-f4fa2e258f60.png) | ||
|
||
Note: Component docgen information can not be generated for components that are only exported as default. You can work around the issue by exporting the component using a named export. | ||
|
||
## Setting up Jest tests | ||
|
||
The ts-jest [README](https://github.com/kulshekhar/ts-jest) explains pretty clearly how to get Jest to recognize TypeScript code. | ||
|
||
This is an example package.json config for jest: | ||
|
||
```json | ||
"jest": { | ||
"transform": { | ||
".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js" | ||
}, | ||
"mapCoverage": true, | ||
"testPathIgnorePatterns": [ | ||
"/node_modules/", | ||
"/lib/" | ||
], | ||
"testRegex": "(/test/.*|\\.(test|spec))\\.(ts|tsx|js)$", | ||
"moduleFileExtensions": [ | ||
"ts", | ||
"tsx", | ||
"js", | ||
"json" | ||
] | ||
} | ||
``` | ||
|
||
## Building your Typescript Storybook | ||
|
||
You will need to set up some scripts - these may help: | ||
|
||
```json | ||
"scripts": { | ||
"start": "react-scripts-ts start", | ||
"build": "npm run lint && npm run build-lib && build-storybook", | ||
"build-lib-watch": "tsc -w", | ||
"build-lib": "tsc && npm run copy-css-to-lib && npm run copy-svg-to-lib && npm run copy-png-to-lib && npm run copy-woff2-to-lib", | ||
"test": "react-scripts-ts test --env=jsdom", | ||
"test:coverage": "npm test -- --coverage", | ||
"eject": "react-scripts-ts eject", | ||
"storybook": "start-storybook -p 6006", | ||
"build-storybook": "build-storybook", | ||
"copy-css-to-lib": "cpx \"./src/**/*.css\" ./build/lib", | ||
"copy-woff2-to-lib": "cpx \"./src/**/*.woff2\" ./build/lib", | ||
"copy-svg-to-lib": "cpx \"./src/**/*.svg\" ./build/lib", | ||
"copy-png-to-lib": "cpx \"./src/**/*.png\" ./build/lib", | ||
"lint": "tslint -c tslint.json 'src/**/*.{ts,tsx}'" | ||
}, | ||
``` | ||
|
||
## Related Issues and Helpful Resources | ||
|
||
* [Issue: Add proper typescript webpack setup in readme #1778](https://github.com/storybooks/storybook/issues/1778) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's leave these GitHub issues out of the docs. It's a lot of stuff to read through to get very little information. If you think there are useful information there, please copy and paste them to the doc instead. |
||
* [Issue: Addons info and Typescript props docgen? #1519](https://github.com/storybooks/storybook/issues/1519) | ||
* [Storybook, React, TypeScript and Jest](https://medium.com/@mtiller/storybook-react-typescript-and-jest-c9059ea06fa7) | ||
* [React, Storybook & TypeScript](http://www.joshschreuder.me/react-storybooks-with-typescript/) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same with this
Simply
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hahaha i didnt write that