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:
@@ -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);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user