import { Meta } from "@storybook/addon-docs";

<Meta title="Documentation/Migration" />

# Migrating to the Component Library

## Background

Bitwarden is in the process of migrating client code to fully use the Component Library.

Previously, the clients used a mix of multiple UI frameworks: Bootstrap, custom "box" styles, and
this component library, which is built on top of Tailwind.

Bootstrap is now removed from the clients repo in favor of using Tailwind Preflight for global reset
styles.

Tailwind is used in client code where layout-level html is written in conjunction with Component
Library components.

Some custom css still lingers in all the clients and is planned to be removed. Do not write more
custom css.

## Performing a migration

You have been tasked with migrating a component to use the CL. What does that entail?

### Getting Started

Before progressing here, please ensure that...

- You have fully setup your dev environment as described in the
  [contributing docs](https://contributing.bitwarden.com/).
- You are familiar with [Angular reactive forms](https://angular.io/guide/reactive-forms).
- You are familiar with [Tailwind](https://tailwindcss.com/docs/utility-first).

This is very important work. Centralizing around a shared design system will:

- improve user experience by utilizing consistent patterns
- improve developer experience by reducing custom complex UI code
- improve dev & design velocity by having a central location to make UI/UX changes that impact the
  entire project

### Success Criteria

Follow these steps to fully migrate a component.

#### Use Storybook

Don't recreate the wheel.

After reviewing a design, consult this Storybook to determine if there is a component built for your
usecase. Don't waste effort styling a button or building a popover menu from scratch--we already
have those. If a component isn't flexible enough or doesn't exist for your usecase, contact the
Component Library team.

#### Use Tailwind

Only use Tailwind for styling. No Bootstrap or other custom CSS is allowed.

This is easy to verify. Bitwarden prefixes all Tailwind classes with `tw-`. If you see a class
without this prefix, it probably shouldn't be there.

<div class="tw-bg-danger-600/10 tw-p-4">
  <span class="tw-font-bold tw-text-danger">Bad (Bootstrap)</span>
  ```html
  <div class="mb-2"></div>
  ```
</div>

<div class="tw-bg-success-600/10 tw-p-4">
  <span class="tw-font-bold tw-text-success">Good (Tailwind)</span>
  ```html
  <div class="tw-mb-2"></div>
  ```
</div>

**Exception:** Icon font classes, prefixed with `bwi`, are allowed.

<div class="tw-bg-success-600/10 tw-p-4">
  <span class="tw-font-bold tw-text-success">Good (Icons)</span>
  ```html
  <i class="bwi bwi-spinner bwi-lg bwi-spin" aria-hidden="true"></i>
  ```
</div>

#### Use Reactive Forms

The CL has form components that integrate with Angular's reactive forms: `bit-form-field`,
`bitSubmit`, `bit-form-control`, etc. All forms should be migrated from template-drive forms to
reactive forms to make use of these components. Review the
[form component docs](?path=/docs/component-library-form--docs).

<div class="tw-bg-danger-600/10 tw-p-4">
    <span class="tw-text-danger tw-font-bold">Bad</span>
    ```html
    <form #form (ngSubmit)="submit()">
        ...
    </form>
    ```
</div>

<div class="tw-bg-success-600/10 tw-p-4">
    <span class="tw-text-success tw-font-bold">Good</span>
    ```html
    <form [formGroup]="formGroup" [bitSubmit]="submit">
        ...
    </form>
    ```
</div>

#### Dialogs

Legacy Bootstrap modals use the `ModalService`. These should be converted to use the `DialogService`
and it's [related CL components](?path=/docs/component-library-dialogs--docs). Components that are
fully migrated should have no reference to the `ModalService`.

1. Update the template to use CL components:

<div class="tw-bg-danger-600/10 tw-p-4">
    ```html
    <!-- FooDialogComponent -->
    <div class="modal fade" role="dialog" aria-modal="true">...</div>
    ```
</div>

<div class="tw-bg-success-600/10 tw-p-4">
    ```html
    <!-- FooDialogComponent -->
    <bit-dialog>...</bit-dialog>
    ```
</div>

2. Create a static `open` method on the component, that calls `DialogService.open`:

<div class="tw-bg-success-600/10 tw-p-4">
    ```ts
      export class FooDialogComponent {
        //...

        static open(dialogService: DialogService) {
          return dialogService.open(DeleteAccountComponent);
        }
      }
    ```

</div>

3. If you need to pass data into the dialog, pass it to `open` as a parameter and inject
   `DIALOG_DATA` into the component's constructor.

<div class="tw-bg-success-600/10 tw-p-4">
    ```ts
    export type FooDialogParams = {
      bar: string;
    }

    export class FooDialogComponent {
      constructor(@Inject(DIALOG_DATA) protected params: FooDialogParams) {}

      static open(dialogService: DialogService, data: FooDialogParams) {
        return dialogService.open(DeleteAccountComponent, { data });
      }
    }
    ```

</div>

4. Replace calls to `ModalService.open` or `ModalService.openViewRef` with the newly created static
   `open` method:

<div class="tw-bg-danger-600/10 tw-p-4">`this.modalService.open(FooDialogComponent);`</div>

<div class="tw-bg-success-600/10 tw-p-4">`FooDialogComponent.open(this.dialogService);`</div>

### Examples

The following examples come from accross the Bitwarden codebase.

#### 1.) AboutComponent

Codeowner: Platform

https://github.com/bitwarden/clients/pull/6301/files

This migration updates a `ModalService` component to the `DialogService`.

**Note:** Most of the internal markup of this component was unchanged, aside from the removal of
defunct Bootstrap classes.

#### 2.) Auth

Codeowner: Auth

https://github.com/bitwarden/clients/pull/5377

This PR also does some general refactoring, the main relevant change can be seen here:

[Old template](https://github.com/bitwarden/clients/pull/5377/files#diff-4fcab9ffa4ed26904c53da3bd130e346986576f2372e90b0f66188c809f9284d)
-->
[New template](https://github.com/bitwarden/clients/pull/5377/files#diff-cb93c74c828b9b49dc7869cc0324f5f7d6609da6f72e38ac6baba6d5b6384327)

Updates a dialog, similar to example 1, but also adds CL form components and Angular Reactive Forms.

#### 3.) AC

Codeowner: Admin Console

https://github.com/bitwarden/clients/pull/5417

Migrates dialog, form, buttons, and a table.

#### 4.) Vault

Codeowner: Vault

https://github.com/bitwarden/clients/pull/5648

Some of our components are shared between multiple clients (web, desktop, and the browser extension)
through the use of inheritance. This PR updates the _web_ template of a cross-client component to
use Tailwind and the CL, and updates the base component implementation to use reactive forms,
without updating the desktop or browser templates.

### Questions

Please direct any development questions to the Component Library team. Thank you!
