1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-15 07:54:55 +00:00

[CL-1046] Update dialog components to support attribute selector usage for form integration (#18929)

- Add [bit-dialog] and [bit-simple-dialog] attribute selectors
- Update documentation with recommended form usage pattern
- Add Storybook examples demonstrating <form bit-dialog> pattern
- Migrate simple-configurable-dialog template to new pattern

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Will Martin
2026-02-12 12:26:25 -05:00
committed by GitHub
parent 7342bf672f
commit fe15b44ccc
8 changed files with 70 additions and 29 deletions

View File

@@ -45,7 +45,7 @@ const drawerSizeToWidth = {
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({
selector: "bit-dialog",
selector: "bit-dialog, [bit-dialog]",
templateUrl: "./dialog.component.html",
host: {
"[class]": "classes()",

View File

@@ -82,3 +82,12 @@ The `background` input can be set to `alt` to change the background color. This
dialogs that contain multiple card sections.
<Canvas of={stories.WithCards} />
## Using Forms with Dialogs
When using forms with dialogs, apply the `bit-dialog` attribute directly to the `<form>` element
instead of wrapping the dialog in a form. This ensures proper styling.
```html
<form bit-dialog>...</form>
```

View File

@@ -225,8 +225,7 @@ export const WithCards: Story = {
...args,
},
template: /*html*/ `
<form [formGroup]="formObj">
<bit-dialog [dialogSize]="dialogSize" [background]="background" [title]="title" [subtitle]="subtitle" [loading]="loading" [disablePadding]="disablePadding" [disableAnimations]="disableAnimations">
<form [formGroup]="formObj" bit-dialog [dialogSize]="dialogSize" [background]="background" [title]="title" [subtitle]="subtitle" [loading]="loading" [disablePadding]="disablePadding" [disableAnimations]="disableAnimations">
<ng-container bitDialogContent>
<bit-section>
<bit-section-header>
@@ -270,7 +269,7 @@ export const WithCards: Story = {
</bit-section>
</ng-container>
<ng-container bitDialogFooter>
<button type="button" bitButton buttonType="primary" [disabled]="loading">Save</button>
<button type="submit" bitButton buttonType="primary" [disabled]="loading">Save</button>
<button type="button" bitButton buttonType="secondary" [disabled]="loading">Cancel</button>
<button
type="button"
@@ -281,8 +280,7 @@ export const WithCards: Story = {
size="default"
label="Delete"></button>
</ng-container>
</bit-dialog>
</form>
</form>
`,
}),
args: {

View File

@@ -92,3 +92,12 @@ Once closed, focus should remain on the element which triggered the Dialog.
**Note:** If a Simple Dialog is triggered from a main Dialog, be sure to make sure focus is moved to
the Simple Dialog.
## Using Forms with Dialogs
When using forms with dialogs, apply the `bit-dialog` attribute directly to the `<form>` element
instead of wrapping the dialog in a form. This ensures proper styling.
```html
<form bit-dialog>...</form>
```

View File

@@ -1,27 +1,25 @@
<form [formGroup]="formGroup" [bitSubmit]="accept">
<bit-simple-dialog>
<i bitDialogIcon class="bwi tw-text-3xl" [class]="iconClasses" aria-hidden="true"></i>
<form [formGroup]="formGroup" [bitSubmit]="accept" bit-simple-dialog>
<i bitDialogIcon class="bwi tw-text-3xl" [class]="iconClasses" aria-hidden="true"></i>
<span bitDialogTitle>{{ title }}</span>
<span bitDialogTitle>{{ title }}</span>
<div bitDialogContent>{{ content }}</div>
<div bitDialogContent>{{ content }}</div>
<ng-container bitDialogFooter>
<button type="submit" bitButton bitFormButton buttonType="primary">
{{ acceptButtonText }}
<ng-container bitDialogFooter>
<button type="submit" bitButton bitFormButton buttonType="primary">
{{ acceptButtonText }}
</button>
@if (showCancelButton) {
<button
type="button"
bitButton
bitFormButton
buttonType="secondary"
(click)="dialogRef.close(false)"
>
{{ cancelButtonText }}
</button>
@if (showCancelButton) {
<button
type="button"
bitButton
bitFormButton
buttonType="secondary"
(click)="dialogRef.close(false)"
>
{{ cancelButtonText }}
</button>
}
</ng-container>
</bit-simple-dialog>
}
</ng-container>
</form>

View File

@@ -12,7 +12,7 @@ export class IconDirective {}
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
@Component({
selector: "bit-simple-dialog",
selector: "bit-simple-dialog, [bit-simple-dialog]",
templateUrl: "./simple-dialog.component.html",
animations: [fadeIn],
imports: [DialogTitleContainerDirective, TypographyDirective],

View File

@@ -49,3 +49,12 @@ Simple dialogs can support scrolling content if necessary, but typically with la
content a [Dialog component](?path=/docs/component-library-dialogs-dialog--docs).
<Canvas of={stories.ScrollingContent} />
## Using Forms with Dialogs
When using forms with dialogs, apply the `bit-simple-dialog` attribute directly to the `<form>`
element instead of wrapping the dialog in a form. This ensures proper styling.
```html
<form bit-simple-dialog>...</form>
```

View File

@@ -126,3 +126,21 @@ export const TextOverflow: Story = {
`,
}),
};
export const WithForm: Story = {
render: (args) => ({
props: args,
template: /*html*/ `
<form bit-simple-dialog>
<span bitDialogTitle>Confirm Action</span>
<span bitDialogContent>
Are you sure you want to proceed with this action? This cannot be undone.
</span>
<ng-container bitDialogFooter>
<button type="submit" bitButton buttonType="primary">Confirm</button>
<button type="button" bitButton buttonType="secondary">Cancel</button>
</ng-container>
</form>
`,
}),
};