-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
181b673
commit 1dbff31
Showing
1 changed file
with
214 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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! |