mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
[CL-500] Add disclosure component and directive (#11865)
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
import { Directive, HostBinding, HostListener, Input } from "@angular/core";
|
||||
|
||||
import { DisclosureComponent } from "./disclosure.component";
|
||||
|
||||
@Directive({
|
||||
selector: "[bitDisclosureTriggerFor]",
|
||||
exportAs: "disclosureTriggerFor",
|
||||
standalone: true,
|
||||
})
|
||||
export class DisclosureTriggerForDirective {
|
||||
/**
|
||||
* Accepts template reference for a bit-disclosure component instance
|
||||
*/
|
||||
@Input("bitDisclosureTriggerFor") disclosure: DisclosureComponent;
|
||||
|
||||
@HostBinding("attr.aria-expanded") get ariaExpanded() {
|
||||
return this.disclosure.open;
|
||||
}
|
||||
|
||||
@HostBinding("attr.aria-controls") get ariaControls() {
|
||||
return this.disclosure.id;
|
||||
}
|
||||
|
||||
@HostListener("click") click() {
|
||||
this.disclosure.open = !this.disclosure.open;
|
||||
}
|
||||
}
|
||||
21
libs/components/src/disclosure/disclosure.component.ts
Normal file
21
libs/components/src/disclosure/disclosure.component.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Component, HostBinding, Input, booleanAttribute } from "@angular/core";
|
||||
|
||||
let nextId = 0;
|
||||
|
||||
@Component({
|
||||
selector: "bit-disclosure",
|
||||
standalone: true,
|
||||
template: `<ng-content></ng-content>`,
|
||||
})
|
||||
export class DisclosureComponent {
|
||||
/**
|
||||
* Optionally init the disclosure in its opened state
|
||||
*/
|
||||
@Input({ transform: booleanAttribute }) open?: boolean = false;
|
||||
|
||||
@HostBinding("class") get classList() {
|
||||
return this.open ? "" : "tw-hidden";
|
||||
}
|
||||
|
||||
@HostBinding("id") id = `bit-disclosure-${nextId++}`;
|
||||
}
|
||||
55
libs/components/src/disclosure/disclosure.mdx
Normal file
55
libs/components/src/disclosure/disclosure.mdx
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Meta, Story, Primary, Controls } from "@storybook/addon-docs";
|
||||
|
||||
import * as stories from "./disclosure.stories";
|
||||
|
||||
<Meta of={stories} />
|
||||
|
||||
```ts
|
||||
import { DisclosureComponent, DisclosureTriggerForDirective } from "@bitwarden/components";
|
||||
```
|
||||
|
||||
# Disclosure
|
||||
|
||||
The `bit-disclosure` component is used in tandem with the `bitDisclosureTriggerFor` directive to
|
||||
create an accessible content area whose visibility is controlled by a trigger button.
|
||||
|
||||
To compose a disclosure and trigger:
|
||||
|
||||
1. Create a trigger component (see "Supported Trigger Components" section below)
|
||||
2. Create a `bit-disclosure`
|
||||
3. Set a template reference on the `bit-disclosure`
|
||||
4. Use the `bitDisclosureTriggerFor` directive on the trigger component, and pass it the
|
||||
`bit-disclosure` template reference
|
||||
5. Set the `open` property on the `bit-disclosure` to init the disclosure as either currently
|
||||
expanded or currently collapsed. The disclosure will default to `false`, meaning it defaults to
|
||||
being hidden.
|
||||
|
||||
```
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-sliders"
|
||||
[buttonType]="'muted'"
|
||||
[bitDisclosureTriggerFor]="disclosureRef"
|
||||
></button>
|
||||
<bit-disclosure #disclosureRef open>click button to hide this content</bit-disclosure>
|
||||
```
|
||||
|
||||
<Story of={stories.DisclosureWithIconButton} />
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
## Supported Trigger Components
|
||||
|
||||
This is the list of currently supported trigger components:
|
||||
|
||||
- Icon button `muted` variant
|
||||
|
||||
## Accessibility
|
||||
|
||||
The disclosure and trigger directive functionality follow the
|
||||
[Disclosure (Show/Hide)](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/) pattern for
|
||||
accessibility, automatically handling the `aria-controls` and `aria-expanded` properties. A `button`
|
||||
element must be used as the trigger for the disclosure. The `button` element must also have an
|
||||
accessible label/title -- please follow the accessibility guidelines for whatever trigger component
|
||||
you choose.
|
||||
29
libs/components/src/disclosure/disclosure.stories.ts
Normal file
29
libs/components/src/disclosure/disclosure.stories.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Meta, moduleMetadata, StoryObj } from "@storybook/angular";
|
||||
|
||||
import { IconButtonModule } from "../icon-button";
|
||||
|
||||
import { DisclosureTriggerForDirective } from "./disclosure-trigger-for.directive";
|
||||
import { DisclosureComponent } from "./disclosure.component";
|
||||
|
||||
export default {
|
||||
title: "Component Library/Disclosure",
|
||||
component: DisclosureComponent,
|
||||
decorators: [
|
||||
moduleMetadata({
|
||||
imports: [DisclosureTriggerForDirective, DisclosureComponent, IconButtonModule],
|
||||
}),
|
||||
],
|
||||
} as Meta<DisclosureComponent>;
|
||||
|
||||
type Story = StoryObj<DisclosureComponent>;
|
||||
|
||||
export const DisclosureWithIconButton: Story = {
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: /*html*/ `
|
||||
<button type="button" bitIconButton="bwi-sliders" [buttonType]="'muted'" [bitDisclosureTriggerFor]="disclosureRef">
|
||||
</button>
|
||||
<bit-disclosure #disclosureRef class="tw-text-main tw-block" open>click button to hide this content</bit-disclosure>
|
||||
`,
|
||||
}),
|
||||
};
|
||||
2
libs/components/src/disclosure/index.ts
Normal file
2
libs/components/src/disclosure/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./disclosure-trigger-for.directive";
|
||||
export * from "./disclosure.component";
|
||||
Reference in New Issue
Block a user