diff --git a/.prettierrc.json b/.prettierrc.json index de753c537d..29ca392ce1 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,3 +1,11 @@ { - "printWidth": 100 + "printWidth": 100, + "overrides": [ + { + "files": "*.mdx", + "options": { + "proseWrap": "always" + } + } + ] } diff --git a/libs/components/src/async-actions/in-forms.stories.mdx b/libs/components/src/async-actions/in-forms.stories.mdx index 07db5f4e2a..e0715fed41 100644 --- a/libs/components/src/async-actions/in-forms.stories.mdx +++ b/libs/components/src/async-actions/in-forms.stories.mdx @@ -4,10 +4,12 @@ import { Meta } from "@storybook/addon-docs"; # Async Actions In Forms -These directives should be used when building forms with buttons that trigger long running tasks in the background, -eg. Submit or Delete buttons. For buttons that are not associated with a form see [Standalone Async Actions](?path=/story/component-library-async-actions-standalone-documentation--page). +These directives should be used when building forms with buttons that trigger long running tasks in +the background, eg. Submit or Delete buttons. For buttons that are not associated with a form see +[Standalone Async Actions](?path=/story/component-library-async-actions-standalone-documentation--page). -There are two separately supported use-cases: Submit buttons and standalone form buttons (eg. Delete buttons). +There are two separately supported use-cases: Submit buttons and standalone form buttons (eg. Delete +buttons). ## Usage: Submit buttons @@ -15,17 +17,19 @@ Adding async actions to submit buttons requires the following 3 steps ### 1. Add a handler to your `Component` -A handler is a function that returns a promise or an observable. Functions that return `void` are also supported which is -useful because `return;` can be used to abort an action. +A handler is a function that returns a promise or an observable. Functions that return `void` are +also supported which is useful because `return;` can be used to abort an action. -**NOTE:** Defining the handlers as arrow-functions assigned to variables is mandatory if the handler needs access to the parent -component using the variable `this`. +**NOTE:** Defining the handlers as arrow-functions assigned to variables is mandatory if the handler +needs access to the parent component using the variable `this`. -**NOTE:** `formGroup.invalid` will always return `true` after the first `await` operation, event if the form is not actually -invalid. This is due to the form getting disabled by the `bitSubmit` directive while waiting for the async action to complete. +**NOTE:** `formGroup.invalid` will always return `true` after the first `await` operation, event if +the form is not actually invalid. This is due to the form getting disabled by the `bitSubmit` +directive while waiting for the async action to complete. -**NOTE:** Handlers do not need to check if any previous requests have finished because the directives have built in protection against -users attempting to trigger new actions before the previous ones have finished. +**NOTE:** Handlers do not need to check if any previous requests have finished because the +directives have built in protection against users attempting to trigger new actions before the +previous ones have finished. ```ts @Component({...}) @@ -51,8 +55,8 @@ class Component { Add the `bitSubmit` directive and supply the handler defined in step 1. -**NOTE:** The `directive` is defined using the input syntax: `[input]="handler"`. -This is different from how submit handlers are usually defined with the output syntax `(ngSubmit)="handler()"`. +**NOTE:** The `directive` is defined using the input syntax: `[input]="handler"`. This is different +from how submit handlers are usually defined with the output syntax `(ngSubmit)="handler()"`. **NOTE:** `[bitSubmit]` is used instead of `(ngSubmit)`. Using both is not supported. @@ -76,14 +80,15 @@ Adding async actions to standalone form buttons requires the following 3 steps. ### 1. Add a handler to your `Component` -A handler is a function that returns a promise or an observable. Functions that return `void` are also supported which is -useful for aborting an action. +A handler is a function that returns a promise or an observable. Functions that return `void` are +also supported which is useful for aborting an action. -**NOTE:** Defining the handlers as arrow-functions assigned to variables is mandatory if the handler needs access to the parent -component using the variable `this`. +**NOTE:** Defining the handlers as arrow-functions assigned to variables is mandatory if the handler +needs access to the parent component using the variable `this`. -**NOTE:** Handlers do not need to check if any previous requests have finished because the directives have built in protection against -users attempting to trigger new actions before the previous ones have finished. +**NOTE:** Handlers do not need to check if any previous requests have finished because the +directives have built in protection against users attempting to trigger new actions before the +previous ones have finished. ```ts @Component({...}) @@ -113,7 +118,8 @@ The `bitSubmit` directive is required because of its coordinating role inside of ### 3. Add directives to the `button` element -Add `bitButton`, `bitFormButton`, `bitAction` directives to the button. Make sure to supply a handler. +Add `bitButton`, `bitFormButton`, `bitAction` directives to the button. Make sure to supply a +handler. **NOTE:** A summary of what each directive does can be found inside the source code. @@ -124,7 +130,8 @@ Add `bitButton`, `bitFormButton`, `bitAction` directives to the button. Make sur ## `[bitSubmit]` Disabled Form Submit -If you need your form to be able to submit even when the form is disabled, then add `[allowDisabledFormSubmit]="true"` to your `
` +If you need your form to be able to submit even when the form is disabled, then add +`[allowDisabledFormSubmit]="true"` to your `` ```html ...
diff --git a/libs/components/src/async-actions/overview.stories.mdx b/libs/components/src/async-actions/overview.stories.mdx index 9ec792aefd..7cffd379b8 100644 --- a/libs/components/src/async-actions/overview.stories.mdx +++ b/libs/components/src/async-actions/overview.stories.mdx @@ -4,14 +4,14 @@ import { Meta } from "@storybook/addon-docs"; # Async Actions -The directives in this module makes it easier for developers to reflect the progress of async actions in the UI when using -buttons, while also providing robust and standardized error handling. +The directives in this module makes it easier for developers to reflect the progress of async +actions in the UI when using buttons, while also providing robust and standardized error handling. -These buttons can either be standalone (such as Refresh buttons), submit buttons for forms or as standalone buttons -that are part of a form (such as Delete buttons). +These buttons can either be standalone (such as Refresh buttons), submit buttons for forms or as +standalone buttons that are part of a form (such as Delete buttons). -These directives are meant to replace the older `appApiAction` directive, providing the option to use `observables` and reduce -clutter inside our view `components`. +These directives are meant to replace the older `appApiAction` directive, providing the option to +use `observables` and reduce clutter inside our view `components`. ## When to use? diff --git a/libs/components/src/async-actions/standalone.stories.mdx b/libs/components/src/async-actions/standalone.stories.mdx index 9ff5753388..efde494f2d 100644 --- a/libs/components/src/async-actions/standalone.stories.mdx +++ b/libs/components/src/async-actions/standalone.stories.mdx @@ -4,8 +4,9 @@ import { Meta } from "@storybook/addon-docs"; # Standalone Async Actions -These directives should be used when building a standalone button that triggers a long running task in the background, -eg. Refresh buttons. For non-submit buttons that are associated with forms see [Async Actions In Forms](?path=/story/component-library-async-actions-in-forms-documentation--page). +These directives should be used when building a standalone button that triggers a long running task +in the background, eg. Refresh buttons. For non-submit buttons that are associated with forms see +[Async Actions In Forms](?path=/story/component-library-async-actions-in-forms-documentation--page). ## Usage @@ -13,14 +14,15 @@ Adding async actions to standalone buttons requires the following 2 steps ### 1. Add a handler to your `Component` -A handler is a function that returns a promise or an observable. Functions that return `void` are also supported which is -useful because `return;` can be used to abort an action. +A handler is a function that returns a promise or an observable. Functions that return `void` are +also supported which is useful because `return;` can be used to abort an action. -**NOTE:** Defining the handlers as arrow-functions assigned to variables is mandatory if the handler needs access to the parent -component using the variable `this`. +**NOTE:** Defining the handlers as arrow-functions assigned to variables is mandatory if the handler +needs access to the parent component using the variable `this`. -**NOTE:** Handlers do not need to check if any previous requests have finished because the directives have built in protection against -users attempting to trigger new actions before the previous ones have finished. +**NOTE:** Handlers do not need to check if any previous requests have finished because the +directives have built in protection against users attempting to trigger new actions before the +previous ones have finished. #### Example using promises @@ -48,8 +50,8 @@ class Component { Add the `bitAction` directive and supply the handler defined in step 1. -**NOTE:** The `directive` is defined using the input syntax: `[input]="handler"`. -This is different from how click handlers are usually defined with the output syntax `(click)="handler()"`. +**NOTE:** The `directive` is defined using the input syntax: `[input]="handler"`. This is different +from how click handlers are usually defined with the output syntax `(click)="handler()"`. **NOTE:** `[bitAction]` is used instead of `(click)`. Using both is not supported. diff --git a/libs/components/src/form-field/form-field.stories.ts b/libs/components/src/form-field/form-field.stories.ts index 64080acc66..1b46e6e6c5 100644 --- a/libs/components/src/form-field/form-field.stories.ts +++ b/libs/components/src/form-field/form-field.stories.ts @@ -95,18 +95,12 @@ const Template: Story = (args: BitFormFieldComponent) => ...args, }, template: ` -
+ - Name + Label + Optional Hint - - - Email - - - -
`, }); diff --git a/libs/components/src/radio-button/radio-button.stories.ts b/libs/components/src/radio-button/radio-button.stories.ts index abc7ddb92a..340e76c421 100644 --- a/libs/components/src/radio-button/radio-button.stories.ts +++ b/libs/components/src/radio-button/radio-button.stories.ts @@ -1,5 +1,4 @@ -import { Component, Input } from "@angular/core"; -import { FormsModule, ReactiveFormsModule, FormBuilder } from "@angular/forms"; +import { FormsModule, ReactiveFormsModule, FormControl, FormGroup } from "@angular/forms"; import { Meta, moduleMetadata, Story } from "@storybook/angular"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; @@ -7,70 +6,13 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { I18nMockService } from "../utils/i18n-mock.service"; import { RadioButtonModule } from "./radio-button.module"; - -const template = ` -
- - Group of radio buttons - - {{ option.key }} - This is a hint for the {{option.key}} option - - -
`; - -const TestValue = { - First: 0, - Second: 1, - Third: 2, -}; - -const reverseObject = (obj: Record) => - Object.fromEntries(Object.entries(obj).map(([key, value]) => [value, key])); - -@Component({ - selector: "app-example", - template: template, -}) -class ExampleComponent { - protected TestValue = TestValue; - - protected formObj = this.formBuilder.group({ - radio: TestValue.First, - }); - - @Input() layout: "block" | "inline" = "inline"; - - @Input() label: boolean; - - @Input() set selected(value: number) { - this.formObj.patchValue({ radio: value }); - } - - @Input() set groupDisabled(disable: boolean) { - if (disable) { - this.formObj.disable(); - } else { - this.formObj.enable(); - } - } - - @Input() optionDisabled: number[] = []; - - get blockLayout() { - return this.layout === "block"; - } - - constructor(private formBuilder: FormBuilder) {} -} +import { RadioGroupComponent } from "./radio-group.component"; export default { title: "Component Library/Form/Radio Button", - component: ExampleComponent, + component: RadioGroupComponent, decorators: [ moduleMetadata({ - declarations: [ExampleComponent], imports: [FormsModule, ReactiveFormsModule, RadioButtonModule], providers: [ { @@ -92,56 +34,65 @@ export default { url: "https://www.figma.com/file/Zt3YSeb6E6lebAffrNLa0h/Tailwind-Component-Library?node-id=3930%3A16850&t=xXPx6GJYsJfuMQPE-4", }, }, - args: { - selected: TestValue.First, - groupDisabled: false, - optionDisabled: null, - label: true, - layout: "inline", - }, - argTypes: { - selected: { - options: Object.values(TestValue), - control: { - type: "inline-radio", - labels: reverseObject(TestValue), - }, - }, - optionDisabled: { - options: Object.values(TestValue), - control: { - type: "check", - labels: reverseObject(TestValue), - }, - }, - layout: { - options: ["inline", "block"], - control: { - type: "inline-radio", - labels: ["inline", "block"], - }, - }, - }, } as Meta; -const storyTemplate = ``; +const InlineTemplate: Story = (args: RadioGroupComponent) => ({ + props: { + formObj: new FormGroup({ + radio: new FormControl(0), + }), + }, + template: ` +
+ + Group of radio buttons -const InlineTemplate: Story = (args: ExampleComponent) => ({ - props: args, - template: storyTemplate, + + First + + + + Second + + + + Third + + +
+ `, }); export const Inline = InlineTemplate.bind({}); -Inline.args = { - layout: "inline", -}; -const BlockTemplate: Story = (args: ExampleComponent) => ({ - props: args, - template: storyTemplate, +const BlockTemplate: Story = (args: RadioGroupComponent) => ({ + props: { + formObj: new FormGroup({ + radio: new FormControl(0), + }), + }, + template: ` +
+ + Group of radio buttons + + + First + This is a hint for the first option + + + + Second + This is a hint for the second option + + + + Third + This is a hint for the third option + + +
+ `, }); export const Block = BlockTemplate.bind({}); -Block.args = { - layout: "block", -}; diff --git a/libs/components/src/stories/Introduction.stories.mdx b/libs/components/src/stories/Introduction.stories.mdx index f9cc381398..4fa3af0808 100644 --- a/libs/components/src/stories/Introduction.stories.mdx +++ b/libs/components/src/stories/Introduction.stories.mdx @@ -81,13 +81,13 @@ import { Meta } from "@storybook/addon-docs"; # Bitwarden Component Library -The Bitwarden Component Library is a collection of reusable low level components which empowers designers and -developers to work more efficiently. The primary goal is to ensure a consistent design and behavior across the -different clients and platforms. Currently the primary focus is the web based clients, namely _web_, _browser_ and -_desktop_. +The Bitwarden Component Library is a collection of reusable low level components which empowers +designers and developers to work more efficiently. The primary goal is to ensure a consistent design +and behavior across the different clients and platforms. Currently the primary focus is the web +based clients, namely _web_, _browser_ and _desktop_. -**Roll out status:** we are currently in the process of transitioning the Web Vault to utilize the component library -and the other clients will follow once this work is completed. +**Roll out status:** we are currently in the process of transitioning the Web Vault to utilize the +component library and the other clients will follow once this work is completed.
Configure
diff --git a/libs/components/src/stories/banner-docs.stories.mdx b/libs/components/src/stories/banner-docs.stories.mdx index bee0da8bd6..61b216523b 100644 --- a/libs/components/src/stories/banner-docs.stories.mdx +++ b/libs/components/src/stories/banner-docs.stories.mdx @@ -4,20 +4,21 @@ import { Meta, Story } from "@storybook/addon-docs"; # Banner -Banners are used for important communication with the user that needs to be seen right away, but has little effect on -the experience. Banners appear at the top of the user's screen on page load and persist across all pages a user -navigates to. +Banners are used for important communication with the user that needs to be seen right away, but has +little effect on the experience. Banners appear at the top of the user's screen on page load and +persist across all pages a user navigates to. -- They should always be dismissable and never use a timeout. If a user dismisses a banner, it should not reappear - during that same active session. -- Use banners sparingly, as they can feel intrusive to the user if they appear unexpectedly. Their effectiveness may - decrease if too many are used. +- They should always be dismissable and never use a timeout. If a user dismisses a banner, it should + not reappear during that same active session. +- Use banners sparingly, as they can feel intrusive to the user if they appear unexpectedly. Their + effectiveness may decrease if too many are used. - Avoid stacking multiple banners. -- Banners supports buttons and anchors using [bitLink](?path=/story/component-library-link--anchors). +- Banners support a button link (text button). ## Types -Icons should remain consistent across these types. Do not change the icon without consulting designers. +Icons should remain consistent across these types. Do not change the icon without consulting +designers. Use the following guidelines to help choose the correct type of banner. @@ -47,5 +48,6 @@ Rarely used, but may be used to alert users over critical messages or very outda ## Accessibility -Dialogs sets the `role="status"` and `aria-live="polite"` attributes to ensure screen readers announce the content -prior to the test of the page. This behaviour can be disabled by setting `[useAlertRole]="false"`. +Banners sets the `role="status"` and `aria-live="polite"` attributes to ensure screen readers +announce the content prior to the test of the page. This behaviour can be disabled by setting +`[useAlertRole]="false"`. diff --git a/libs/components/src/stories/button-docs.stories.mdx b/libs/components/src/stories/button-docs.stories.mdx index c598f2d222..3551be8cf6 100644 --- a/libs/components/src/stories/button-docs.stories.mdx +++ b/libs/components/src/stories/button-docs.stories.mdx @@ -4,30 +4,54 @@ import { Meta, Story } from "@storybook/addon-docs"; # Button -Use buttons for actions in forms, dialogs, and more with support for style, block, icon, and state. +Buttons are interactive elements that can be triggered using a mouse, keyboard, or touch. They are +used to indicate actions that can be performed by a user such as submitting a form. -For pairings in the bottom left corner of a page or component, the `primary` call to action will go on the left side of a button group with the `secondary` call to action option on the left. +## Guidelines -Pairings in the top right corner of a page, should have the `primary` call to action on the right. +### Choosing the `` or `