From f341b0009248967ad30d401eefbdf963dda5ab01 Mon Sep 17 00:00:00 2001 From: Bryan Cunningham Date: Mon, 5 Jan 2026 08:59:11 -0500 Subject: [PATCH] [CL-947] drawer width variants (#18156) * allow drawer to adapt to size input * add new drawer sizes * move logic back to dialog component * convert width to computed signal * fix template error and remove duplicate class * use normal const object * ensure dialogSize undefined is handled --- .../src/dialog/dialog.service.stories.ts | 101 +++++++++++++++++- .../src/dialog/dialog/dialog.component.html | 2 +- .../src/dialog/dialog/dialog.component.ts | 50 +++++---- 3 files changed, 129 insertions(+), 24 deletions(-) diff --git a/libs/components/src/dialog/dialog.service.stories.ts b/libs/components/src/dialog/dialog.service.stories.ts index 4e5c718e494..26f2b585f2d 100644 --- a/libs/components/src/dialog/dialog.service.stories.ts +++ b/libs/components/src/dialog/dialog.service.stories.ts @@ -31,7 +31,11 @@ interface Animal { - + + + `, imports: [ButtonModule, LayoutComponent], @@ -63,13 +67,29 @@ class StoryDialogComponent { }, }); } + + openSmallDrawer() { + this.dialogService.openDrawer(SmallDrawerContentComponent, { + data: { + animal: "panda", + }, + }); + } + + openLargeDrawer() { + this.dialogService.openDrawer(LargeDrawerContentComponent, { + data: { + animal: "panda", + }, + }); + } } // FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush // eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection @Component({ template: ` - + Dialog body text goes here.
@@ -100,7 +120,6 @@ class StoryDialogContentComponent { template: ` Dialog body text goes here. @@ -125,6 +144,64 @@ class NonDismissableContentComponent { } } +// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush +// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection +@Component({ + template: ` + + + Dialog body text goes here. +
+ Animal: {{ animal }} +
+ + + + +
+ `, + imports: [DialogModule, ButtonModule], +}) +class SmallDrawerContentComponent { + dialogRef = inject(DialogRef); + private data = inject(DIALOG_DATA); + + get animal() { + return this.data?.animal; + } +} + +// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush +// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection +@Component({ + template: ` + + + Dialog body text goes here. +
+ Animal: {{ animal }} +
+ + + + +
+ `, + imports: [DialogModule, ButtonModule], +}) +class LargeDrawerContentComponent { + dialogRef = inject(DialogRef); + private data = inject(DIALOG_DATA); + + get animal() { + return this.data?.animal; + } +} + export default { title: "Component Library/Dialogs/Service", component: StoryDialogComponent, @@ -206,3 +283,21 @@ export const Drawer: Story = { await userEvent.click(button); }, }; + +export const DrawerSmall: Story = { + play: async (context) => { + const canvas = context.canvasElement; + + const button = getAllByRole(canvas, "button")[3]; + await userEvent.click(button); + }, +}; + +export const DrawerLarge: Story = { + play: async (context) => { + const canvas = context.canvasElement; + + const button = getAllByRole(canvas, "button")[4]; + await userEvent.click(button); + }, +}; diff --git a/libs/components/src/dialog/dialog/dialog.component.html b/libs/components/src/dialog/dialog/dialog.component.html index 22aa99c44cb..58364dfd045 100644 --- a/libs/components/src/dialog/dialog/dialog.component.html +++ b/libs/components/src/dialog/dialog/dialog.component.html @@ -2,7 +2,7 @@
("default"); + readonly dialogSize = input("default"); /** * Title to show in the dialog's header @@ -100,21 +114,31 @@ export class DialogComponent { private readonly animationCompleted = signal(false); + protected readonly width = computed(() => { + const size = this.dialogSize() ?? "default"; + const isDrawer = this.dialogRef?.isDrawer; + + if (isDrawer) { + return drawerSizeToWidth[size]; + } + + return dialogSizeToWidth[size]; + }); + protected readonly classes = computed(() => { // `tw-max-h-[90vh]` is needed to prevent dialogs from overlapping the desktop header const baseClasses = ["tw-flex", "tw-flex-col", "tw-w-screen"]; - const sizeClasses = this.dialogRef?.isDrawer - ? ["tw-h-full", "md:tw-w-[23rem]"] - : ["md:tw-p-4", "tw-w-screen", "tw-max-h-[90vh]"]; + const sizeClasses = this.dialogRef?.isDrawer ? ["tw-h-full"] : ["md:tw-p-4", "tw-max-h-[90vh]"]; + const size = this.dialogSize() ?? "default"; const animationClasses = this.disableAnimations() || this.animationCompleted() || this.dialogRef?.isDrawer ? [] - : this.dialogSize() === "small" + : size === "small" ? ["tw-animate-slide-down"] : ["tw-animate-slide-up", "md:tw-animate-slide-down"]; - return [...baseClasses, this.width, ...sizeClasses, ...animationClasses]; + return [...baseClasses, this.width(), ...sizeClasses, ...animationClasses]; }); handleEsc(event: Event) { @@ -124,20 +148,6 @@ export class DialogComponent { } } - get width() { - switch (this.dialogSize()) { - case "small": { - return "md:tw-max-w-sm"; - } - case "large": { - return "md:tw-max-w-3xl"; - } - default: { - return "md:tw-max-w-xl"; - } - } - } - onAnimationEnd() { this.animationCompleted.set(true); }