# ConvertKit Design

Welcome to ConvertKit's component library!

Here, you'll find the source and documentation for our [`@convertkit/design`](https://www.npmjs.com/package/@convertkit/design) package on npm. This readme provides more information on our development, review, and release processes.

## 🧪 Development process

Make sure you are on Node v14.19.2 or higher. You can use NVM to manage Node versions. To develop in this repo, navigate into its root directory and run:

```
yarn start
```

This will start a local server at [localhost:6060](http://localhost:6060/). You'll also receive a URL that you can visit from other devices on your network, which can be helpful for testing your component on phones and tablets.

### Using with the main ConvertKit app

You can link a local version of this repo against the main app so you can see changes without having to publish this package.

The most complicated part about this is making sure that this package and the main app are using the same version of react.

1. In the main app, create a link to react

    ```sh
    cd node_modules/react
    yarn link
    ```
2. In this repo, run `yarn link`
3. In this repo, run `yarn link react`
4. In the main app, run `yarn link "@convertkit/design"`
5. In this repo, run `yarn build`
    * You will have to do this every time you make a change. There is no automatic rebuilding as of now.

Now when using `bin/webpack-dev-server` in the main app, it should compile a local version of this package instead of the published one.

If you need to use either a component or a hook inside of Node server-side renderering, make sure to add an entry point in
the `exports` property in `package.json` if it is not already covered by the substring matching pattern (such as `modal/confirm`).

### Working on components

Components are located under [`src/components`](https://github.com/ConvertKit/convertkit-design/tree/main/src/components). Each component has a directory structure that (generally) looks like this:

```
components/
  example-component/            # directory names are all lowercase and use dashes for spaces
    __tests__/
      example-component.test.js # tests are included in a __tests__ directory
    index.js                    # contains a default export for the component
    readme.md                   # used for documentation
```

If needed, you can also add other files to this directory — for instance, some components might need an `assets` directory or utility files.

To preview a component during development, we recommend accessing it via its documentation. To learn more about this part, see "[Tips for writing documentation](#tips-for-writing-documentation)" below.

### Working on hooks

ConvertKit Design also provides hooks which are located in the [`src/hooks`](https://github.com/ConvertKit/convertkit-design/tree/main/src/hooks) directory. You can import these into the main app and use them to interact with components from the library.

<details>

<summary>Usage example</summary>

For a concrete example, [`src/hooks/use-toast/index.js`](https://github.com/ConvertKit/convertkit-design/blob/main/src/hooks/use-toast/index.js) provides a `useToast()` hook as its default export. In the main app, we can import it with:

```js
import useToast from "@convertkit/design/use-toast"
```

</details>

### Tips for writing documentation

We use [Styleguidist](https://react-styleguidist.js.org/) to generate ConvertKit Design's documentation from the readme files located in each component directory.

- You don't need to import `React`; it's available at the global scope. However, named imports like `useState` aren't. For these, it's easier to call things like `React.useState`.
- The default export from the directory's `index.js` file can be accessed in this file without any need to import it.
- The code snippets in your readme must end in semi-colons for the lines below them to be evaluated.
- Markdown code snippets accept additional options:
  - Beginning your code snippet with ` ```jsx noeditor ` will show _only_ the demo (no code).
  - Beginning your code snippet with ` ```jsx static ` will show _only_ the code (no demo).
- If you add a new Readme.md file for component markdown code snippets, restart the server to view it.

You can read up on more ways to document with Styleguidist [here](https://react-styleguidist.js.org/docs/documenting#usage-examples-and-readme-files).

### Adding non-component documentation

If you want to add documentation for something other than a component, you can use a "route" configuration inside [`styleguide.config.js`](https://github.com/ConvertKit/convertkit-design/blob/main/styleguide.config.js). After that, you can add a markdown file to the [`docs`](https://github.com/ConvertKit/convertkit-design/tree/main/docs) directory.

## ✅ Review process

### PR authors

The component library is used by engineers from every squad and across every part of the app. Because of this, we have a group of volunteer engineers, called "Component Librarians", to help facilitate code reviews.

To request a review on your PR, you can tag `ConvertKit/component-librarians` from the "Reviewers" dropdown in GitHub. Several engineers will be randomly assigned to review your changes. You can use your best judgment on how many reviews you need before merging: if you're making a small update, you might only need one review; if you're making a bigger change (like updating an API, layout, or component functionality), a broader consensus should be reached before merging. This reduces the risk of a breaking change for another squad.

If your PR adjusts a component's design, we also recommend tagging `ConvertKit/design` as a reviewer, and having at least one designer sign off on the changes.

### Reviewers

If you're reviewing a PR, you can find a live preview of its changes under the "Checks" section at the bottom of the page. Look for the item that says:

> **netlify/convertkit-design/deploy-preview** — Deploy Preview ready!

You can click the "Details" link next to it to view a live preview.

## 🚀 Release process

### Releasing to prod

1. Make sure your PR [bumps the version number](https://github.com/ConvertKit/convertkit-design/blob/main/package.json#L3).
2. Merge your PR. As long as the version number was changed, this will automatically deploy a new version of `@convertkit/design` to npm. This usually takes a few minutes; you can check its progress in the merge commit's status on GitHub, or refresh [the package on npm](https://www.npmjs.com/package/@convertkit/design) to watch the "Last publish" date.
3. In the main app's [app/javascript/package.json](https://github.com/ConvertKit/convertkit/blob/main/app/javascript/package.json), find the line that says `"@convertkit/design": "...",` and change its version number to the version you've just published. Save the file.
4. In your terminal, run the command `yarn` to install the package from npm.
5. Make a PR for the changes to the main app. This ensures that we're always running an up-to-date version of `@convertkit/design` on main, which helps us catch regressions early, and gives other engineers access to the most recent designs and APIs.

### Releasing to beta

If you want to test one of your PRs in the main app (or even put up an [ephemeral environment](https://app.getguru.com/card/TKELRErc/Ephemeral-QA-Environment-Usage) for QA or Design), you can follow these instructions to release a beta version of the component library. In order to do this, you'll need to [have an npm account](https://www.npmjs.com/signup) and ask [#frontend](https://convertkit.slack.com/archives/CHWCNV8TX) to invite you to the `@convertkit` organization. Make sure to verify your email address, or publishing will silently fail!

In order to build and release, you will need [rollup](https://rollupjs.org/) installed globally. If you don't have it, you can install it with `yarn global add rollup` or `npm install -g rollup`.

1. Run `yarn release`.
2. A prompt will show you the _current_ version number and ask for the _new_ one. Bump the version and append "-beta". For example:

    ```bash
    info     Current version: 1.0.1
    question New version: # you could enter 1.0.2-beta
    ```

    If you're releasing multiple betas for your PR, you can also append a version number such as `1.0.2-beta.2`.

    If successful, you'll see a success message in the terminal.

3. In the main app, update [`app/javascript/package.json`](https://github.com/ConvertKit/convertkit/blob/main/app/javascript/package.json) to use your new beta version for `@convertkit/design`. For example:

    ```js
    "@convertkit/design": "1.0.2-beta",
    ```

4. In a terminal pointed at the main app, run `yarn`. This will install the beta you just released to your local dev environment. Once you're ready to release to prod, you can follow the instructions in "Releasing to prod" above.

## 📚 Join Component Librarians

Component Librarians is a volunteer review group which helps facilitate reviews for this repo. Its goal is to make sure that each squad has a voice in changes to our component library, especially around its APIs and documentation. We also want to make sure that our designers are aware of, and in agreement on, the updates we're making. We'd love to have broad representation across all of our squads. If you're interested in joining, please let us know in [`#frontend` on Slack](https://convertkit.slack.com/archives/CHWCNV8TX)!

## Using convertkit-design in other projects

You can use this module in Node server-side rendering and browser environments.

For Webpack/Babel browser environments, note that each component is exported as a submodule, with the prefix /dist/, so to import a button:

```
import Button from "@convertkit/design/dist/button"
```

You can add a Babel rule to remove the necessity of specifying dist:

```
plugins: [
  [
    "module-resolver",
    {
      alias: {
        "@convertkit/design": "@convertkit/design/dist"
      }
    }
  ]
]
```

You will also need to import `"@convertkit/design/dist/styles"` either in SCSS or in your main JS component.

SCSS:
```
@import "node_modules/@convertkit/design/dist/styles";
```

JS:
```
import "@convertkit/design/styles"
```
