## autodocs usage

**autodocs** is an umbrella term used to describe all tools related to automating documentation.

**story** is a term used to describe single page which contains documentation about one or more components.
Many things are automated and many things are customizable. This
document describes how to use it all.

Here's an [example of `<RadioGroup/>` story configuration](https://wix-wix-style-react.surge.sh/?selectedKind=4.%20Selection&selectedStory=4.3%20Radio%20Button%20Group&full=0&addons=0&stories=1&panelRight=0) in wix-style-react ([and source of it](https://github.com/wix/wix-style-react/blob/master/stories/RadioGroup.story.js)).

What you see in that example is generated from component source: props list, preview area and code examples.

## Creating a story

Stories are files with `.story.js` extension. These files go through tools that extract component metadata and render
it. Those tools need to know what/how to document component and for that reason you must provide a small configuration.

## Short example

```js
import RadioGroup from 'wix-style-react/RadioGroup'; // 1

export default { // 2
  category: '4. Selection', // 3
  storyName: '4.3 Radio Button Group', // 4
  component: RadioGroup, // 5
  componentPath: '../src/RadioGroup', // 6

  componentProps: setState => ({ // 7
    value: 1,
    hasError: false,
    size: 'medium',
    children: exampleChildren[0].value,
    onChange: value => setState({value}),
    dataHook: 'storybook-radiogroup'
  }),

  hiddenProps: ['dataHook'], // 8

  exampleProps: { // 9
    children: exampleChildren,
    onChange: value => value
  },

  componentWrapper: component => <div>{component}</div>, // 10

  exampleImport: "import Component from 'custom-location-if-autodocs-cant-parse-it'", // 11

  codeExample: true, // set to false if you want to hide interactive code example. It is enabled by default

  sections: [] // 12
};
```

1. `import` component you wish to document
1. `export` default a single object which will be treated as story configuration
1. `category` is a name of Storybook sidebar section
1. `storyName` is a name of specific story
1. `component` a reference to component which is to be documented
1. `componentPath` a path to component. This is for parser to know where to start parsing your component
1. `componentProps` an object (or function returning object) which outlines props to be given to `5.` - a component
1. `hiddenProps` **optional** array of props that should not appear in storybook
1. `exampleProps` **optional** object of the same shape as component props used to configure possible prop values (explained below)
1. `componentWrapper` **optional** function which receives component to be documented and must return a react component. Use this if you need more control in preview (some styling, for example).
1. `exampleImport` **optional** string which will be displayed as example of how documented component should be imported. Use this if AutoDocs fails to corretly interpret how component should be imported.
1. `sections` **optional** but very recommended. This is a list of predefined functions (so called, sections) that help construct a consistent documentation page.

## Long example

### Readme files

Your component may have documentation written in markdown. Markdown
files should stay alongside component source, for example:

```md
  Component
  ├── index.js // entry file
  ├── Component.js // source of component
  ├── README.md // will be shown at the top of story page. make sure it includes a nice title
  ├── README.ACCESSIBILITY.md // will appear as separate `Accessibility` tab
  └── README.TESTKIT.md // will appear as separate `Testkit` tab
```

### Props categories

Interactive props list is split into sections:
1. **Primary Props** - props set in `componentProps` or `exampleProps` get here;
1. **Callback Props** - props that start with `on`, like `onClick`;
1. **HTML Props** - props like `tabIndex` or `href` and alike
1. **Accessibility** - props that start with `aria` like `ariaRequired`
1. **Misc. props** - props that don't fit any other category

if some prop should be under **Primary Props** but it's not, simply define it in
`componentProps` or `exampleProps`.

### Component

AutoExample supports both JS and TS components. Component should be written in a regular manner, ideally one component per file which has one default export, or exports one component. Write simple components for best results, if it's hard for developer to read code, it will be hard for AutoExample to parse and automate documentation too.

Both class and funtional components are supported.

A simple example:

```js
import React from 'react';

/** here can be a description written in `markdown` */
class MyComponent extends React.Component {
  /** this function will be displayed in API tab as a public method */
  publicMethod() {
    return 'hello';
  }

  /** this function will be hidden from API tab */
  _privateMethod() {
    return 'Do not interact with my privates';
  }

  render() {
    return (
      <div>Hello, World</div>
    );
  }
}
```

### Full API

Scaffold:

```js
// MyStory.story.js

export default {
  category: '',
  component: '',
  componentPath: ''
}
```

<details>
  <summary>`category` - `string` required</summary>

  Name of Storybook "section" under which this story will be placed (e.g. `Core`, `6. Navigation`, `3. Inputs`)
</details>

---

<details>
  <summary>`storyName` - `string`</summary>

  Name of the story in sidebar. If omitted, it will use `displayName` of
  the component.
</details>

---

<details>
  <summary>`component` - `ReactNode` required</summary>

  Reference to react component which will be used in interactive example.
  Most often it will be imported component:

  ```js
  import MyComponent from 'wix-style-react/Component';

  export default {
    // ... other config
    component: MyComponent
  }
  ```
</details>

---

<details>
  <summary>`componentPath` - `string` required</summary>

  A string of relative path to component source. This is required in order
  for automatic documentation to know where to start parsing.

  Even though just folder is enough, it is better to provide exact path to file.

  ```js
  import MyComponent from './src/components/MyComponent';

  export default {
    // ... other config
    component: MyComponent,
    componentPath: './src/components/MyComponent/index.js'
  }
  ```

  NOTE: when proxying component from another library (e.g. wix-ui-backoffice -> wix-style-react), give path using `node_modules` to original source file.
</details>

---

<details>
  <summary>`displayName` - `string`</summary>

  use this string as components displayName. There may be a case when
  parsed displayName is incorrect (for example some HOC changed it).
</details>

---

<details>
  <summary>`componentProps` - `object` or `function`</summary>

  Props that will be passed to `component`. Either given as-is with
  `object` or computed in `function`. Imagine it as `<Component
  {...componentProps}/>`. This is the place to set required props.

  * when `object`, it will be passed to `component` as props.
  * when `function`, its signature is `(setState, getState) => props` where:
    * `setState` - `function`: accepts one argument - object. When called this object will be set as `componentProps`
    * `getState` - `function`: does not accept anything. When called it will return an object containing currently used props
    * `props` - return value `object`: whatever is returned will be used as new `componentProps`

  For example:

  ```js
  // `componentProps` as object
  export default {
    component: ToggleSwitch,
    // ...other config
    componentProps: {
      onChange: () => console.log('wooo onChange called!')
    }
  }

  // This is equivalent to the following
  <ToggleSwitch onChange={() => console.log('wooo onChange called!')}/>
  ```

  Function is used to allow dynamic changes from within `component`.
  The return value of that function will be used as new `component` props.

  When component calls `onChange` it will
  first take `checked` (which initially is set to `false`) and invert it.

  This is how you can imitate surrounding state without managing it yourself:
  ```js
  // `componentProps` as function
  export default {
    component: ToggleSwitch,
    // ...other config
    componentProps: (setState, getState) => ({
      checked: false,
      onChange: () => setProps({checked: !getProps().checked})
    }),
  }
  ```
</details>

---

<details>
  <summary>`examples` - `ReactNode`</summary>

  Automatically generated story page might not include all possible
  examples. In that case use `examples` and pass a `ReactNode`. It will be
  rendered without modification at the bottom of story page.

  For example:

  ```js
  export default {
    // ... other config
    examples: (
      <div>
        Hello, I am custom example
      </div>
    )
  }
  ```
</details>

---

<details>
  <summary>`exampleImport` - `string`</summary>

  at the top of the page there is code showing how to import component,
  something like `import Component from 'module/Component';`

  However, due to various reasons story may not show correct import example. In that case use `exampleImport` and pass
  hardcoded string of import example
</details>

---

<details>
  <summary>`exampleProps` - `object`</summary>

  `exampleProps` is an optional object of same shape as `componentProps`.
  It's purpose is to configure how interactive props in storybook are displayed.

  automated process tries to derive how a prop is controlled from it's
  type (e.g. a boolean prop is controlled with `<ToggleSwitch/>`, a string with `<Input/>` etc.)

  however, it's not always possible to derive controller from prop type
  and in those cases you are able to configure it manually:

  ```js
  exampleProps: {
    children: ['a', 'list', 'of', 'possible', 'children']
  }
  ```

  the above would show `children` prop with a dropdown.

  Below are possible ways to set `exampleProps`

##### Using list

  this will create a dropdown for `placement` prop with `bottom`,`top`,`right` & `left` options

  ```js
  export default {
    // ... other config
    exampleProps: {
      placement: ['bottom','top','right','left']
    }
  }
  ```

##### Using list of objects

  objects are of `{label, value}` shape. They are useful when example
  value can't be represented as string (for example if value is a component or a function)

  ```js
  export default {
    // ... other config
    exampleProps: {
      children: [
        { label: 'just a string', value: 'hello' },
        { label: 'simple component', value: <div>hello</div> },
        { label: 'another component', value: <MaybeImportedComponent/> },
        {
          label: 'nested components',
          value: (
            <div>
              <SomeComponent/>
              <SomeOtherComponent/>
            </div>
          )
        },
      ]
    }
  }
  ```

  the above would show `children` prop with a dropdown having 4 options.

##### Using functions

  when exampleProp is a function, it's return value will be displayed in
  storybook when that function was called. It will also glow blue. Very
  useful to indicate when callbacks happen.

  ```js
  export default {
    // ... other config
    exampleProps: {
      onClick: () => 'i was called!'
    }
  }
  ```
</details>

---


<details>
  <summary>`hiddenProps` - `array`</summary>

  there can be many reasons why some props should not appear in
  documentation. In such cases, list those props in `hiddenProps` array:

  ```js
  export default {
    // ... other config
    hiddenProps: ['dataHook', 'className']
  }
  ```
</details>

---

<details>

  <summary>`componentWrapper` - `func`</summary>

  A render function for the component (in the Preview). Typicaly this function can wrap the component in something usefull like a theme className if needed.
  Signature: ({component}) => JSXElement

  ```js
  export default {
    componentWrapper: ({component})=> <div className="theme">{component}</div>
  }
  ```

</details>

---

<details>
  <summary>`sections` - `array`</summary>

  A very recommended approach to document components: provide a list of sections and construct doc page the way you
  wish, but according to conventions.

  For full list of sections, usage and API read [here](./sections.md)

  Short example:

  ```js
  export default {
    // ... other config
    sections: [
      header({
        component: <Button>A show-off example of button!</Button>
      }),
      tabs([
        tab({
          title: 'Description',
          sections: [
            description('This component is awesome, look at the code!'),
            code('<Button>Interactive code</Button')
          ]
        })
      ])
    ]
  }
  ```
</details>
