1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 21:33:27 +00:00

[CL-748] Support nondismissable dialogs and simple dialogs (#15464)

This commit is contained in:
Vicki League
2025-07-03 15:23:21 -04:00
committed by GitHub
parent 40cbd5942b
commit 3e4b82d725
4 changed files with 177 additions and 20 deletions

View File

@@ -25,10 +25,13 @@ interface Animal {
template: ` template: `
<bit-layout> <bit-layout>
<button class="tw-mr-2" bitButton type="button" (click)="openDialog()">Open Dialog</button> <button class="tw-mr-2" bitButton type="button" (click)="openDialog()">Open Dialog</button>
<button class="tw-mr-2" bitButton type="button" (click)="openDialogNonDismissable()">
Open Non-Dismissable Dialog
</button>
<button bitButton type="button" (click)="openDrawer()">Open Drawer</button> <button bitButton type="button" (click)="openDrawer()">Open Drawer</button>
</bit-layout> </bit-layout>
`, `,
imports: [ButtonModule], imports: [ButtonModule, LayoutComponent],
}) })
class StoryDialogComponent { class StoryDialogComponent {
constructor(public dialogService: DialogService) {} constructor(public dialogService: DialogService) {}
@@ -41,6 +44,15 @@ class StoryDialogComponent {
}); });
} }
openDialogNonDismissable() {
this.dialogService.open(NonDismissableContent, {
data: {
animal: "panda",
},
disableClose: true,
});
}
openDrawer() { openDrawer() {
this.dialogService.openDrawer(StoryDialogContentComponent, { this.dialogService.openDrawer(StoryDialogContentComponent, {
data: { data: {
@@ -79,13 +91,40 @@ class StoryDialogContentComponent {
} }
} }
@Component({
template: `
<bit-dialog title="Dialog Title" dialogSize="large">
<span bitDialogContent>
Dialog body text goes here.
<br />
Animal: {{ animal }}
</span>
<ng-container bitDialogFooter>
<button type="button" bitButton buttonType="primary" (click)="dialogRef.close()">
Save
</button>
</ng-container>
</bit-dialog>
`,
imports: [DialogModule, ButtonModule],
})
class NonDismissableContent {
constructor(
public dialogRef: DialogRef,
@Inject(DIALOG_DATA) private data: Animal,
) {}
get animal() {
return this.data?.animal;
}
}
export default { export default {
title: "Component Library/Dialogs/Service", title: "Component Library/Dialogs/Service",
component: StoryDialogComponent, component: StoryDialogComponent,
decorators: [ decorators: [
positionFixedWrapperDecorator(), positionFixedWrapperDecorator(),
moduleMetadata({ moduleMetadata({
declarations: [StoryDialogContentComponent],
imports: [ imports: [
SharedModule, SharedModule,
ButtonModule, ButtonModule,
@@ -138,8 +177,7 @@ export const Default: Story = {
}, },
}; };
/** Drawers must be a descendant of `bit-layout`. */ export const NonDismissable: Story = {
export const Drawer: Story = {
play: async (context) => { play: async (context) => {
const canvas = context.canvasElement; const canvas = context.canvasElement;
@@ -147,3 +185,13 @@ export const Drawer: Story = {
await userEvent.click(button); await userEvent.click(button);
}, },
}; };
/** Drawers must be a descendant of `bit-layout`. */
export const Drawer: Story = {
play: async (context) => {
const canvas = context.canvasElement;
const button = getAllByRole(canvas, "button")[2];
await userEvent.click(button);
},
};

View File

@@ -30,15 +30,17 @@
} }
<ng-content select="[bitDialogTitle]"></ng-content> <ng-content select="[bitDialogTitle]"></ng-content>
</h2> </h2>
<button @if (!this.dialogRef?.disableClose) {
type="button" <button
bitIconButton="bwi-close" type="button"
buttonType="main" bitIconButton="bwi-close"
size="default" buttonType="main"
bitDialogClose size="default"
[attr.title]="'close' | i18n" bitDialogClose
[attr.aria-label]="'close' | i18n" [attr.title]="'close' | i18n"
></button> [attr.aria-label]="'close' | i18n"
></button>
}
</header> </header>
<div <div

View File

@@ -87,8 +87,10 @@ export class DialogComponent {
} }
handleEsc(event: Event) { handleEsc(event: Event) {
this.dialogRef?.close(); if (!this.dialogRef?.disableClose) {
event.stopPropagation(); this.dialogRef?.close();
event.stopPropagation();
}
} }
get width() { get width() {

View File

@@ -2,6 +2,7 @@ import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
import { Component, Inject } from "@angular/core"; import { Component, Inject } from "@angular/core";
import { provideAnimations } from "@angular/platform-browser/animations"; import { provideAnimations } from "@angular/platform-browser/animations";
import { Meta, StoryObj, moduleMetadata } from "@storybook/angular"; import { Meta, StoryObj, moduleMetadata } from "@storybook/angular";
import { getAllByRole, userEvent } from "@storybook/test";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -15,19 +16,45 @@ interface Animal {
} }
@Component({ @Component({
template: `<button type="button" bitButton (click)="openDialog()">Open Simple Dialog</button>`, template: `
<button type="button" bitButton (click)="openSimpleDialog()">Open Simple Dialog</button>
<button type="button" bitButton (click)="openNonDismissableWithPrimaryButtonDialog()">
Open Non-Dismissable Simple Dialog with Primary Button
</button>
<button type="button" bitButton (click)="openNonDismissableWithNoButtonsDialog()">
Open Non-Dismissable Simple Dialog with No Buttons
</button>
`,
imports: [ButtonModule], imports: [ButtonModule],
}) })
class StoryDialogComponent { class StoryDialogComponent {
constructor(public dialogService: DialogService) {} constructor(public dialogService: DialogService) {}
openDialog() { openSimpleDialog() {
this.dialogService.open(StoryDialogContentComponent, { this.dialogService.open(SimpleDialogContent, {
data: { data: {
animal: "panda", animal: "panda",
}, },
}); });
} }
openNonDismissableWithPrimaryButtonDialog() {
this.dialogService.open(NonDismissableWithPrimaryButtonContent, {
data: {
animal: "panda",
},
disableClose: true,
});
}
openNonDismissableWithNoButtonsDialog() {
this.dialogService.open(NonDismissableWithNoButtonsContent, {
data: {
animal: "panda",
},
disableClose: true,
});
}
} }
@Component({ @Component({
@@ -49,7 +76,60 @@ class StoryDialogComponent {
`, `,
imports: [ButtonModule, DialogModule], imports: [ButtonModule, DialogModule],
}) })
class StoryDialogContentComponent { class SimpleDialogContent {
constructor(
public dialogRef: DialogRef,
@Inject(DIALOG_DATA) private data: Animal,
) {}
get animal() {
return this.data?.animal;
}
}
@Component({
template: `
<bit-simple-dialog>
<span bitDialogTitle>Dialog Title</span>
<span bitDialogContent>
Dialog body text goes here.
<br />
Animal: {{ animal }}
</span>
<ng-container bitDialogFooter>
<button type="button" bitButton buttonType="primary" (click)="dialogRef.close()">
Save
</button>
</ng-container>
</bit-simple-dialog>
`,
imports: [ButtonModule, DialogModule],
})
class NonDismissableWithPrimaryButtonContent {
constructor(
public dialogRef: DialogRef,
@Inject(DIALOG_DATA) private data: Animal,
) {}
get animal() {
return this.data?.animal;
}
}
@Component({
template: `
<bit-simple-dialog>
<span bitDialogTitle>Dialog Title</span>
<span bitDialogContent>
Dialog body text goes here.
<br />
Animal: {{ animal }}
</span>
</bit-simple-dialog>
`,
imports: [ButtonModule, DialogModule],
})
class NonDismissableWithNoButtonsContent {
constructor( constructor(
public dialogRef: DialogRef, public dialogRef: DialogRef,
@Inject(DIALOG_DATA) private data: Animal, @Inject(DIALOG_DATA) private data: Animal,
@@ -89,4 +169,29 @@ export default {
type Story = StoryObj<StoryDialogComponent>; type Story = StoryObj<StoryDialogComponent>;
export const Default: Story = {}; export const Default: Story = {
play: async (context) => {
const canvas = context.canvasElement;
const button = getAllByRole(canvas, "button")[0];
await userEvent.click(button);
},
};
export const NonDismissableWithPrimaryButton: Story = {
play: async (context) => {
const canvas = context.canvasElement;
const button = getAllByRole(canvas, "button")[1];
await userEvent.click(button);
},
};
export const NonDismissableWithNoButtons: Story = {
play: async (context) => {
const canvas = context.canvasElement;
const button = getAllByRole(canvas, "button")[2];
await userEvent.click(button);
},
};