@ -4,10 +4,12 @@ import { Meta } from "@storybook/addon-docs";
@@ -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
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
@@ -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 {
@@ -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.
@@ -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
@@ -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
@@ -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 `<form>`
If you need your form to be able to submit even when the form is disabled, then add
`[allowDisabledFormSubmit]="true"` to your `<form>`
@ -4,8 +4,9 @@ import { Meta } from "@storybook/addon-docs";
@@ -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
@@ -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 {
@@ -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.
@ -4,20 +4,21 @@ import { Meta, Story } from "@storybook/addon-docs";
@@ -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.
- 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.
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.
- 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
@@ -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
@ -4,29 +4,53 @@ import { Meta, Story } from "@storybook/addon-docs";
@@ -4,29 +4,53 @@ 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 `<a>` or `<button>`
Groups of buttons should have 1rem of spacing between them.
## Choosing the `<a>` or `<button>`
Buttons can use either the `<a>` or `<button>` tags. Choose which based on the action the button takes:
Buttons can use either the `<a>` or `<button>` tags. Choose which based on the action the button
takes:
- If navigating to a new page, use `<a>`
- If taking an action on the current page use `<button>`
- If the button launches a dialog, use `<button>`
## Submit and async actions
### Groups
Both submit and async action buttons use a loading button state while an action is taken.
Groups of buttons should be seperated by a `0.5` rem gap. Usually acomplished by using the
`tw-gap-2` class in the button group container.
<Story id="component-library-button--loading" />
Groups within page content, dialog footers or forms should have the `primary` call to action placed
to left. Groups in headers and navigational areas should have the `primary` call to action on the
right.
## Accessibility
Please follow these guidelines to ensure that buttons are accessible to all users.
### Color contrast
All button styles are WCAG compliant when displayed on `background` and `background-alt` colors. To
use a button on a different background, double check that the color contrast is sufficient in both
the light and dark themes.
### Loading Buttons
Include an `aria-label` attribute that defaults to “loading” but can be configurable per
implementation. On click, the screen reader should announce the `aria-label`. Once the action is
compelted, use another messaging pattern to alert the user that the action is complete (example:
success toast).
If your button is preforming a long running task in the background like a server API call, be sure to review the [Async Actions Directive](https://components.bitwarden.com/?path=/story/component-library-async-actions-overview--page).
### Submit and async actions
Both submit and async action buttons use a loading button state while an action is taken. If your
button is preforming a long running task in the background like a server API call, be sure to review
the [Async Actions Directive](?path=/story/component-library-async-actions-overview--page).
<Story id="component-library-button--loading" />
## Styles
@ -36,13 +60,16 @@ There are 3 main styles for the button: Primary, Secondary, and Danger.
@@ -36,13 +60,16 @@ There are 3 main styles for the button: Primary, Secondary, and Danger.
<Story id="component-library-button--primary" />
Use the primary button styling for all Primary call to actions. An action is "primary" if it relates to the main purpose of a page. There should never be 2 primary styled buttons next to each other.
Use the primary button styling for all Primary call to actions. An action is "primary" if it relates
to the main purpose of a page. There should never be 2 primary styled buttons next to each other.
The secondary styling should be used for secondary calls to action. An action is "secondary" if it relates indirectly to the purpose of a page. There may be multiple secondary buttons next to each other; however, generally there should only be 1 or 2 calls to action per page.
The secondary styling should be used for secondary calls to action. An action is "secondary" if it
relates indirectly to the purpose of a page. There may be multiple secondary buttons next to each
other; however, generally there should only be 1 or 2 calls to action per page.
### Danger
@ -52,22 +79,14 @@ Use the danger styling only in settings when the user may preform a permanent ac
@@ -52,22 +79,14 @@ Use the danger styling only in settings when the user may preform a permanent ac
## Disabled UI
Both the disabled and loading states use the default state’s color with a 60% opacity or `tw-opacity-60`.
Both the disabled and loading states use the default state’s color with a 60% opacity or
`tw-opacity-60`.
<Story id="component-library-button--disabled" />
## Block
Typically button widths expand with their text. In some causes though buttons may need to be block where the width is fixed and the text wraps to 2 lines if exceeding the button’s width.
Typically button widths expand with their text. In some causes though buttons may need to be block
where the width is fixed and the text wraps to 2 lines if exceeding the button’s width.
<Story id="component-library-button--block" />
## Accessibility
### Color contrast
All button styles are WCAG compliant when displayed on `background` and `background-alt` colors. To use a button on a different background, double check that the color contrast is sufficient in both the light and dark themes.
### Loading Buttons
Include an `aria-label` attribute that defaults to “loading” but can be configurable per implementation. On click, the screen reader should announce the `aria-label`. Once the action is compelted, use another messaging pattern to alert the user that the action is complete (example: success toast).
@ -6,7 +6,11 @@ import { Meta } from "@storybook/addon-docs/";
@@ -6,7 +6,11 @@ import { Meta } from "@storybook/addon-docs/";
# Iconography
Avoid using icons to convey information unless paired with meaningful, clear text. If an icon must be used and text cannot be displayed visually along with the icon, use an `aria-label` to provide the text to screen readers, and a `title` attribute to provide the text visually through a tool tip. Note: this pattern should only be followed for very common iconography such as, a settings cog icon or an options menu icon.
Avoid using icons to convey information unless paired with meaningful, clear text. If an icon must
be used and text cannot be displayed visually along with the icon, use an `aria-label` to provide
the text to screen readers, and a `title` attribute to provide the text visually through a tool tip.
Note: this pattern should only be followed for very common iconography such as, a settings cog icon
@ -4,9 +4,9 @@ import { Meta } from "@storybook/addon-docs";
@@ -4,9 +4,9 @@ import { Meta } from "@storybook/addon-docs";
# `bitInput`
`bitInput` is an Angular directive to be used on `<input>`, `<select>`, and `<textarea>`
tags in order to provide standardized TailwindCss styling, error handling, and more.
It is meant to be used within a `<bit-form-field>` custom component.
`bitInput` is an Angular directive to be used on `<input>`, `<select>`, and `<textarea>` tags in
order to provide standardized TailwindCss styling, error handling, and more. It is meant to be used
within a `<bit-form-field>` custom component.
## Basic Usage Example
@ -20,8 +20,8 @@ It is meant to be used within a `<bit-form-field>` custom component.
@@ -20,8 +20,8 @@ It is meant to be used within a `<bit-form-field>` custom component.
## Disabled `bitInput` and Error Handling
If you would like to be able to still show errors when an input is disabled for
specific validation scenarios, then set `[showErrorsWhenDisabled]="true"`
If you would like to be able to still show errors when an input is disabled for specific validation
scenarios, then set `[showErrorsWhenDisabled]="true"`
```html
<bit-form-field>
@ -31,7 +31,8 @@ specific validation scenarios, then set `[showErrorsWhenDisabled]="true"`
@@ -31,7 +31,8 @@ specific validation scenarios, then set `[showErrorsWhenDisabled]="true"`
</bit-form-field>
```
**NOTE:** Disabling a FormControl removes validation errors so you must manually set the errors after disabling:
**NOTE:** Disabling a FormControl removes validation errors so you must manually set the errors
We provide a simple component for displaying sortable column headers. The `bitSortable` component
wires up to the `TableDataSource` and will automatically sort the data when clicked and display
an indicator for which column is currently sorted. The dafault sorting can be specified by setting
the `default`.
wires up to the `TableDataSource` and will automatically sort the data when clicked and display an
indicator for which column is currently sorted. The dafault sorting can be specified by setting the
`default`.
```html
<th bitCell bitSortable="id" default>Id</th>
@ -71,6 +111,16 @@ It's also possible to define a custom sorting function by setting the `fn` input
@@ -71,6 +111,16 @@ It's also possible to define a custom sorting function by setting the `fn` input
The `TableDataSource` supports a rudimentary filtering capability most commonly used to implement a
search function. It works by converting each entry into a string of it's properties. The string is
then compared against the filter value using a simple `indexOf`check.
```ts
dataSource.filter = "search value";
```
### Virtual Scrolling
It's heavily adviced to use virtual scrolling if you expect the table to have any significant amount
@ -97,8 +147,3 @@ specify a `itemSize`, set `scrollWindow` to `true` and replace `*ngFor` with `*c
@@ -97,8 +147,3 @@ specify a `itemSize`, set `scrollWindow` to `true` and replace `*ngFor` with `*c
</bit-table>
</cdk-virtual-scroll-viewport>
```
## Accessibility
- Always incude a row or column header with your table; this allows screen readers to better contextualize the data