Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CL-135] CL migration docs #6535

Merged
merged 7 commits into from
Nov 20, 2023
Merged
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
214 changes: 214 additions & 0 deletions libs/components/src/stories/migration.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
import { Meta } from "@storybook/addon-docs";

<Meta title="Documentation/Migration" />

# Migrating to the Component Library

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).

## Background

The design of Bitwarden is in flux. At the time of writing, the frontend codebase uses a mix of
multiple UI frameworks: Bootstrap, custom "box" styles, and this component library, which is built
on top of Tailwind. In short, the "CL migration" is a move to only use the CL and remove everything
else.

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 Will
Martin.

### 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-500/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-500/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-500/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-500/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-500/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-500/10 tw-p-4">
```html
<!-- FooDialogComponent -->
<div class="modal fade" role="dialog" aria-modal="true">...</div>
```
</div>

<div class="tw-bg-success-500/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-500/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-500/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-500/10 tw-p-4">`this.modalService.open(FooDialogComponent);`</div>

<div class="tw-bg-success-500/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 Will Martin. Thank you!
Loading