Skip to content
This repository has been archived by the owner on Nov 5, 2020. It is now read-only.

Docs in panel mode #70

Merged
merged 3 commits into from
Feb 2, 2019
Merged
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ This addon accepts [@storybook/addon-info](https://github.com/storybooks/storybo
| `wrapperComponent` | `Component` | [default wrapper](src/components/Wrapper/index.vue) | Override docs component. |
| `summary` | `string` | `''` | Summary for the story. Accepts Markdown. |
| `components` | `{ [name: string]: Component }\|null` | `null` | Display info for these components. Same type as component's `components` property. If `null` or `false`, this addon tries to use `components` property in story component then outermost tag in `template`. |
| `docsInPanel` | `boolean` | `true` | Whether to show docs in addon panel. |
| `useDocgen` | `boolean` | `true` | Whether to use result of vue-docgen-api. |

In addition to addon options, we have a component option.
Expand Down
1 change: 1 addition & 0 deletions example/.storybook/addons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import 'storybook-addon-vue-info/lib/register'
48 changes: 46 additions & 2 deletions example/stories/examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,45 @@ storiesOf('Examples/Advance usage', module)
}
}))
)
.add(
'Show docs in preview area',
withInfo({
summary: `
To show docs in preview area, turn off \`docsInPanel\` option.

\`\`\`js
withInfo({
docsInPanel: false
})
\`\`\`

This will override descriptions generated by docgen.

If you never use docsInPanel feature,
you can omit \`import 'storybook-addon-vue-info/register\` in \`.storybook/addons.js\`.

### ATTENTION!

Docs in preview wraps story component, which might cause unexpected behaviors/bugs,
especially with other addons and Vue.js plugins.

I recommend to use this only for documentation and
separate from interactive story such as one using addon-knobs
(otherwise you should set this option true).
`,
docsInPanel: false
})(() => ({
components: { BaseButton },
template: '<base-button label="I\'m a button!"/>',
}))
)
.add(
'Customize docs',
withInfo({
summary: `
To customize docs view, set your docs component to \`wrapperComponent\` option.
## Customize docs in preview

To customize docs in preview area, set your docs component to \`wrapperComponent\` option.

This addon passes two props:

Expand All @@ -185,8 +219,18 @@ storiesOf('Examples/Advance usage', module)

For more detail, please look at source code of this example
(\`example/components/customDocs/wrapper\`).

<br/>

## Customize docs in addon panel

Not supported.

It's challenging to change components in addon panel.
To avoid plugin being complex and messy, customizing addon panel is not supported.
`,
wrapperComponent: CustomWrapper
wrapperComponent: CustomWrapper,
docsInPanel: false
})(() => ({
components: { BaseButton },
template: '<base-button label="I\'m a button!"/>'
Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@types/highlight.js": "^9.12.2",
"@types/jest": "^22.2.3",
"@types/marked": "^0.3.0",
"@types/react": "^16.7.22",
"@types/storybook__vue": "^3.3.0",
"autoprefixer": "^9.4.7",
"babel-loader": "^8.0.5",
Expand All @@ -65,12 +66,13 @@
"ts-jest": "^22.4.5",
"tslint": "^5.10.0",
"tslint-config-prettier": "^1.13.0",
"typescript": "^2.9.2",
"typescript": "3",
"vue": "^2.5.16",
"vue-loader": "^15.6.2"
},
"peerDependencies": {
"@storybook/vue": "*",
"react": "*",
"vue": "^2.0.0"
},
"prettier": {
Expand Down Expand Up @@ -99,11 +101,13 @@
]
},
"dependencies": {
"@storybook/addons": "^4.1.11",
"dedent": "^0.7.0",
"highlight.js": "^9.12.0",
"marked": "^0.3.19",
"querystring": "^0.2.0",
"vue-docgen-api": "^3.3.4",
"vue-template-compiler": "^2.5.16"
"vue-template-compiler": "^2.5.16",
"vuera": "^0.2.3"
}
}
28 changes: 21 additions & 7 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@ import resolve from 'rollup-plugin-node-resolve'
import typescript from 'rollup-plugin-typescript2'
import vue from 'rollup-plugin-vue'

export default {
input: './src/index.ts',
output: {
file: './lib/index.js',
format: 'es'
},
const commonConfig = {
plugins: [
resolve({
only: ['parse5']
Expand Down Expand Up @@ -42,5 +37,24 @@ export default {
plugins: ['external-helpers']
})
],
external: ['vue', 'dedent', 'marked', 'highlight.js', 'vue-template-compiler']
external: ['vue', 'dedent', 'marked', 'highlight.js', 'vue-template-compiler', 'react', 'vuera', '@storybook/addons']
}

export default [
{
input: './src/index.ts',
output: {
file: './lib/index.js',
format: 'es'
},
...commonConfig
},
{
input: './src/register.tsx',
output: {
file: './lib/register.js',
format: 'es'
},
...commonConfig
}
]
7 changes: 7 additions & 0 deletions src/addon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const AddonName = 'STORYBOOK_ADDON_VUE_INFO'

export const PanelName = AddonName + '/panel'

export const Events = {
ShowDocs: AddonName + '/show_docs'
}
2 changes: 1 addition & 1 deletion src/components/Wrapper/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default {
:title="info.title"
:subtitle="info.subtitle"
/>
<x-preview> <slot /> </x-preview>
<x-preview v-if="!options.docsInPanel"> <slot /> </x-preview>
<x-summary :markdown="info.summary" />
<x-story-source
v-if="options.source"
Expand Down
8 changes: 7 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { StoryDecorator, StoryFunction } from '@storybook/vue'

import { extract } from './extract'
import { defaultOptions, InfoAddonOptions } from './options'
import { wrap } from './view'
import { transfer, wrap } from './view'

export * from './components'

Expand Down Expand Up @@ -47,6 +47,12 @@ export function withInfo(
// Extract information to display
const info = extract(storyComponent, ctx.kind, ctx.story, opts)

if (opts.docsInPanel) {
transfer(info, opts)

return storyComponent
}

// Return story component wrapped with docs
return wrap(storyComponent, info, opts)
}
Expand Down
49 changes: 49 additions & 0 deletions src/lib.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* tslint:disable:ban-types */

declare module 'vue-template-compiler' {
export interface ASTElement {
attrs?: any[]
Expand All @@ -17,3 +19,50 @@ declare module 'vue-template-compiler' {
}
export function compile(template: string): CompileResult
}

declare module 'vuera' {
import * as React from 'react'
import { AsyncComponent, Component } from 'vue'

interface Props {
component:
| Component<any, any, any, any>
| AsyncComponent<any, any, any, any>
[prop: string]: any
}

export const VueWrapper: React.SFC<Props>
}

declare module '@storybook/addons' {
import { SFC } from 'react'

export interface Api {
onStory(callback: Function): () => void
}

export interface Channel {
on(name: string, handler: Function): void
emit(name: string, payload: any): void

removeListener(name: string, handler: Function): void
}

interface Mod {
register(name: string, callback: (api: Api) => any): void

addPanel(
name: string,
options: {
title: string
render: SFC<{ active: boolean }>
}
): void

getChannel(): Channel
}

const addons: Mod

export default addons
}
6 changes: 6 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const defaultOptions: InfoAddonOptions = {
summary: '',
components: null,
wrapperComponent: DefaultWrapper,
docsInPanel: true,
useDocgen: true
}

Expand Down Expand Up @@ -40,6 +41,11 @@ export interface InfoAddonOptions {
*/
wrapperComponent: AnyComponent

/**
* Whether to show docs in panel instead of wrapping story
*/
docsInPanel: boolean

/**
* Whether to use component infomation generated by vue-docgen-api
*/
Expand Down
86 changes: 86 additions & 0 deletions src/register.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import * as React from 'react'
import Vue, { ComponentOptions } from 'vue'
import { VueWrapper } from 'vuera'

import addons, { Api, Channel } from '@storybook/addons'

import { AddonName, PanelName, Events } from './addon'
import { InfoAddonOptions } from './options'
import { StoryInfo } from './types/info'

import Wrapper from './components/Wrapper/index.vue'

interface Props {
channel: Channel
api: Api
active: boolean
}

interface State {
/** Information of current story */
info?: StoryInfo
/** Addon options */
options?: InfoAddonOptions
}

class Info extends React.Component<Props, State> {
public state: State = {}

/** Callback to remove event handler */
private stopListen?: () => void

/**
* Callback for ShowDocs event
*/
private onShowDocs = ({ info, options }: State) => {
this.setState({ info, options })
}

public componentDidMount() {
const { channel, api } = this.props

channel.on(Events.ShowDocs, this.onShowDocs)

this.stopListen = api.onStory(() => {
// Clear panel when story changes
this.setState({
info: undefined,
options: undefined
})
})
}

public render() {
const { info, options } = this.state
const { active } = this.props

if (!active || !info || !options) {
return null
}

return (
<div>
<VueWrapper component={Wrapper} info={info} options={options} />
</div>
)
}

public componentWillUnmount() {
if (this.stopListen) {
this.stopListen()
}

const { channel } = this.props

channel.removeListener(Events.ShowDocs, this.onShowDocs)
}
}

addons.register(AddonName, api => {
addons.addPanel(PanelName, {
title: 'Info(Vue)',
render: ({ active }) => (
<Info channel={addons.getChannel()} api={api} active={active} />
)
})
})
9 changes: 9 additions & 0 deletions src/view/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import Vue, { ComponentOptions } from 'vue'

import addons from '@storybook/addons'

import { Events } from '../addon'
import { InfoAddonOptions } from '../options'
import { StoryInfo } from '../types/info'

Expand All @@ -20,3 +23,9 @@ export function wrap(
}
}
}

export function transfer(info: StoryInfo, options: InfoAddonOptions): void {
const channel = addons.getChannel()

channel.emit(Events.ShowDocs, { info, options })
}
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"es2015",
"es2015.promise"
],
"jsx": "react",
"target": "es5",
"strict": true,
"module": "es2015",
Expand Down
Loading