# Contributing

As this design system will be used among multiple products and multiple teams, we prefer consistency above all. So the best way to know how to do something new is to look around.

## Adding a new Component

Before writing a Component you must know what problem it is supposed to solve and in what context to use it.
Before adding a new Component, please see if the Component does not already exist, or the problem is not already solved by another Component.
As a general advice, you should ask the assigned designer what to do and make sure you have everything you need to start implementing your new Component.

- Create a branch (`git checkout -b branch_name`)
- Use the included Component generator
- Start Storybook in dev mode

```bash
$ akeneo-design-system/bin/dsm generate ComponentName
$ yarn --cwd=akeneo-design-system storybook:start
# Or with Docker
$ docker-compose run --rm -p 6006:6006 node yarn --cwd=akeneo-design-system storybook:start
```

- Then implement your Component logic in the newly created file `src/components/ComponentName/ComponentName.tsx`
  - First of all define all properties that your Component requires, using TypeScript to type them the most strongly possible
    - For closed choice property, prefer type union ('primary' | 'secondary' | 'danger') instead of Enum
    - If you have a doubt, don't hesitate to ask on #pim-frontend
  - Add JSDoc on all your properties (these comments will be used as descriptor in Storybook)
  - Style your Component with [styled-components](https://styled-components.com/docs)
  - If necessary, add icons in the folder `src/icons/` (color & size should be configurable)
  - Make sure `forwardRef` management works properly on your Component ([https://reactjs.org/docs/forwarding-refs.html](https://reactjs.org/docs/forwarding-refs.html)) (should be automatically done by the generator)
  - Make sure you forward ...props to your Component (should be automatically done by the generator)
  - Make your Component accessible ([https://developer.mozilla.org/en-US/docs/Web/Accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility))
    - Your component should react to keyboard events if relevant
    - Your component should be describable (`aria-label`, `alt`, etc) and readable by screen readers
    - Your component should be focusable if relevant.
- Write the related Story of your Component `src/components/ComponentName/ComponentName.stories.tsx` (should be automatically generated by the generator)
  - Copy and paste `Usage introduction` and `General guidance` paragraph from the [notion design system page](https://www.notion.so/akeneo/Components-2654ae12360d48c7954142e472c043d4)
  - Define all `argTypes`
    - Use `control` when your property expects a value (string, number, boolean, enum ...), you can retrieve full list of control types [here](https://storybook.js.org/docs/react/essentials/controls#annotation).
    - Use `action` when your property expects a callback relative to an action on the Component ([https://storybook.js.org/docs/react/essentials/actions](https://storybook.js.org/docs/react/essentials/actions))
  - Define `arg` when you want a specific default value
  - Write all variations of your Component
    - Be careful, on the notion page, the variation are not always relevant and some should not be implemented this way.
    - Variations should only vary on one prop at a time
- Complete the unit test file generated earlier `src/components/ComponentName/ComponentName.unit.tsx`
  - Add unit tests to validate all Component behaviours
- Commit and push your change
- Open a pull request (Github Action will be automatically launched)
  - Github Action will assign you a pull request to alert you that new stories found, review it and merge it when it looks good for you
  - Github Action will deploy a new version of the storybook give the url to designer for review

## Update style of Component

If you update the style of one Component, the visual test will fail. Github Action will assign you a pull request to alert you that Component changed, review it and merge it when it looks good for you.

Github Action will deploy a new version of the storybook give the url to designer for review.

## Components checklist

- Component should be strongly typed with TypeScript
- All properties should be documented
- Simple components should be stateless
- Coding style should follow rules defined in .eslintrc (`yarn lint:check`)
- Component should manage forwardRef and ...props
- Component should provide aria attributes if necessary
- Components should be keyboard accessible
- Component should not have hardcoded color, it should use color in theme
- Component should use CSS-in-JS with [styled-components](https://styled-components.com/docs)
- Components should follow the [compound components pattern](https://www.youtube.com/watch?v=hEGg-3pIHlE).

## Stories checklist

- All stories should be in [MDX format](https://mdxjs.com/)
- Story should describe when the Component should be used
- All properties should be editable by the user
- Story should display all possible variations
- Variations should describe itself through value label when it's possible

## Story template

```mdx
import {Meta, Story, ArgsTable, Canvas} from '@storybook/addon-docs/blocks';
import {ComponentName} from './ComponentName';

<Meta
  title="Components/ComponentName"
  component={ComponentName}
  argTypes={{
    arg1: {control: {type: 'select', options: ['default', 'small']}},
    arg2: {control: {type: 'boolean'}},
    onArg3: {action: 'Click on the button'},
  }}
  args={{
    arg1: 'default',
  }}
/>

# Name of the Component

## Usage

_Describe what problem the Component is supposed to solve_

### General guidance

_Describe when the Component should be used_
_Describe each element on the component_

## Playground

<Canvas>
  <Story name="Standard">
    {args => {
      return <ComponentName {...args} />;
    }}
  </Story>
</Canvas>

## Variation through arg1

_Show all possible variations that allow user to have a better overview of the Component capabilities_

<Canvas>
  <Story name="Variation through arg1">
    {args => {
      return (
        <>
          <ComponentName {...args} arg1="default">
            Default
          </ComponentName>
          <ComponentName {...args} arg1="small">
            Small
          </ComponentName>
        </>
      );
    }}
  </Story>
</Canvas>

## Variation through arg2

<Canvas>
  <Story name="Variation through arg2">
    {args => {
      return (
        <>
          <ComponentName {...args} arg2={false}>
            Default
          </ComponentName>
          <ComponentName {...args} arg2={true}>
            Arg2 activated
          </ComponentName>
        </>
      );
    }}
  </Story>
</Canvas>
```

## Tests guidelines

- Test should use [Jest](https://jestjs.io/docs/en/getting-started)
- Test should use [React Testing Library](https://testing-library.com/docs/react-testing-library/intro)
