# GbDialogBoxComponent — Deep Analysis

**File:** `features/gbdialogbox/gbdialogbox.component.ts`
**Template:** `features/gbdialogbox/gbdialogbox.component.html`
**Styles:** `features/gbdialogbox/gbdialogbox.component.scss`
**Date:** 2026-02-25
**Analyzer:** Claude Code (claude-sonnet-4-6)

---

## Correction Status (2026-02-25)

All P0s and most P1/P2s were applied in-place. See detail below.

| ID | Issue | Status |
|----|-------|--------|
| P0-1 | document-level Enter key trap | ✅ Fixed — `@HostListener` removed; `<button cdkFocusInitial>` + native Enter used instead |
| P0-2 | Missing `ChangeDetectionStrategy.OnPush` | ✅ Fixed |
| P0-3 | `DialogData: any` | ✅ Fixed — `GbDialogBoxData` interface exported; `inject<GbDialogBoxData>()` used |
| P0-4 | `typeof null === 'object'` crash | ✅ Fixed — `Array.isArray()` + `messageItems` pre-cast property |
| P1-1 | Constructor injection | ✅ Fixed — `inject()` for both `dialogRef` and `dialogData` |
| P1-2 | Color ternary repeated 6× | ✅ Fixed — `HEADING_COLORS` map, `headingColor`/`buttonColor` readonly properties |
| P1-3 | Two `*ngIf` blocks for icon toggle | ✅ Fixed — single block with `{{ displayMore ? 'expand_less' : 'expand_more' }}` |
| P1-4 | `*ngFor` missing `trackBy` | ✅ Fixed — `trackByIndex` added |
| P1-5 | Duplicate `::ng-deep` rule | ✅ Fixed — merged into one rule |
| P1-6 | `::ng-deep` second selector missing prefix | ✅ Fixed — both comma selectors now have `::ng-deep` |
| P1-7 | Non-standard naming conventions | ✅ Fixed — all properties/methods now camelCase |
| P1-8 | Fixed `width: 120px` on buttons | ✅ Fixed — changed to `min-width: 120px` with `padding: 0 12px` |
| P1-9 | Magic number `errorType !== 5` | ✅ Fixed — `DIALOG_ERROR_TYPE_SUPPRESS_DETAILS = 5` exported constant |
| P1-10 | Zero unit tests | ⏳ Pending — spec file still empty; test cases listed below |
| P2-1 | `<div>`/`<span>` as buttons | ✅ Fixed — all three are now `<button type="button">` |
| P2-2 | No `aria-*` attributes | ✅ Partial — `aria-label="Close"` on cancel icon, `aria-expanded` on toggle, `role="button"` + keyboard events on toggle div |
| P2-3 | Hardcoded `#FFFFFF` background | ✅ Fixed — `var(--mat-sys-surface, #ffffff)` |
| P2-4 | Hardcoded `"Helvetica"` font | ✅ Fixed — removed; inherits Material typography |
| P2-5 | No RTL CSS | ✅ Fixed — `[dir="rtl"]` selectors added for float, text-align, and layout |
| P2-6 | `'Cancel'` close value undocumented | ✅ Documented — noted in `GbDialogBoxData` JSDoc and appendix |
| P2-7 | Button color invisible for unknown headings | ✅ Fixed — `buttonColor` falls back to `""` which is now visible because `<button>` inherits `color: #ffffff` from `.alert-button` SCSS |
| P2-8 | No guard against double-click | ⏳ Pending — `closeModal()` still fires on every click; needs a `closed` flag or `MatDialogRef.disableClose` pattern |
| P2-9 | No `maxWidth` safeguard | ⏳ Pending — requires `GbDialogService` wrapper (caller-side fix) |
| P2-10 | Inline styles in template | ✅ Fixed — all moved to SCSS classes (`.dialog-close-btn`, `.dialog-heading`, `.dialog-message`, etc.) |
| CW-1 | Hardcoded English at ~896 call sites | ⏳ Pending — requires `GbDialogService` + Transloco migration across all callers |
| CW-2 | Fixed `width: '600px'` at ~896 call sites | ⏳ Pending — requires `GbDialogService` wrapper |
| CW-3 | `GbHttpService` opens dialog directly | ⏳ Pending — requires `GbNotificationService` extraction |
| CW-4 | No wrapper service | ⏳ Pending — `GbDialogService` to be created |
| CW-5 | `errortype` semantics undocumented | ✅ Fixed — constant exported, JSDoc added to interface |

### What Changed in Each File

**`gbdialogbox.component.ts`**
- Exported `GbDialogBoxData` interface and `DIALOG_ERROR_TYPE_SUPPRESS_DETAILS = 5`
- Added `changeDetection: ChangeDetectionStrategy.OnPush`
- Replaced constructor with `inject()` for both injected tokens
- Removed `@HostListener` entirely — Enter key now works via `cdkFocusInitial` + native `<button>` behavior
- Replaced `typeof` check with `Array.isArray()` + `messageItems` pre-cast array
- Extracted `HEADING_COLORS` map; `headingColor` and `buttonColor` computed once as `readonly` properties
- All PascalCase fields/methods renamed to camelCase
- Added `trackByIndex`

**`gbdialogbox.component.html`**
- All action buttons are now `<button type="button">` with `(click)` handlers
- `cdkFocusInitial` on `button1` — gives it keyboard focus when dialog opens; native Enter closes it
- Expand/collapse reduced from two `*ngIf` blocks to one, icon name toggled inline
- `trackBy: trackByIndex` on `*ngFor`
- `aria-label="Close"` on cancel button; `aria-expanded` + `role="button"` + `keydown.enter/space` on toggle
- All inline `style="..."` removed — replaced with CSS class names

**`gbdialogbox.component.scss`**
- Merged duplicate `::ng-deep .mat-mdc-dialog-component-host` rules into one
- Fixed `::ng-deep` on both comma-separated dialog-surface selectors
- `background-color: var(--mat-sys-surface, #ffffff)` — dark-mode aware
- `min-width: 120px` + `padding: 0 12px` on `.alert-button` (was `width: 120px`)
- `&:focus-visible` outline added to `.alert-button`
- `[dir="rtl"]` selectors on `.dialog-close-btn` (float), `.dialog-message` (text-align), `.dialog-scrollable`, `.error-toggle`
- `.dialog-actions` uses `display: flex; gap: 8px` — replaces `margin-right: 20px` on each button
- Removed all `font-family: "Helvetica"` declarations

### Remaining Work (Pending Items)

1. **Unit tests** (`P1-10`) — write 8 test cases in `gbdialogbox.component.spec.ts`:
   - String message renders
   - Array message renders with all items
   - Button 1/2/3 each close with their label as value
   - Cancel icon closes with `'Cancel'`
   - Expand/collapse toggles `displayMore`
   - Detail panel hidden when `errortype === DIALOG_ERROR_TYPE_SUPPRESS_DETAILS`
   - `message: null` does not throw (regression for P0-4)

2. **Double-click guard** (`P2-8`) — add a `private closed = false` flag to `closeModal()`.

3. **`GbDialogService` wrapper** (`CW-2`, `CW-4`) — new service with `error()`, `warn()`, `confirm()`, `success()` typed methods; enforces `width: 'min(600px, 95vw)'` and `maxWidth: '95vw'`.

4. **Transloco integration** (`CW-1`) — `GbDialogService` methods accept Transloco keys + params; component renders via `translocoService.translate()`.

5. **`GbNotificationService`** (`CW-3`) — decouple `GbHttpService` from `MatDialog`; HTTP layer calls a notification abstraction instead.

---

## Overview

`GbDialogBoxComponent` is the universal alert/confirmation dialog for the entire application. It is used in **~896 files** across all 39 micro-frontends — making it the most-used shared component in the project. Any bug, regression, or behavior change here affects nearly every module. Despite its critical role, the component is only ~40 lines of TypeScript with no interface contract, no tests, and several correctness bugs.

---

## Issue Summary

| Severity | Count |
|----------|-------|
| P0 — Critical (correctness / bugs) | 4 |
| P1 — High (maintainability / standards) | 10 |
| P2 — Medium (UX / accessibility / design) | 10 |
| Consumer-wide issues (cross-cutting) | 5 |

---

## P0 — Critical Issues

### P0-1: `@HostListener('document:keydown.enter')` — dangerous document-level key trap
**File:** `gbdialogbox.component.ts:13`

The Enter key listener is bound to `document`, not to the dialog element. This means:
- **Any** Enter keypress anywhere in the browser fires `handleEnterKey()` while the dialog is open.
- If focus is in a text input inside the dialog, pressing Enter closes the dialog instead of submitting the input.
- A confirmation dialog with a destructive `button1` (e.g. "Delete") will auto-confirm on Enter — even unintentionally.
- If dialog is opened from a form where Enter submits the form, the event fires for both simultaneously.

**Fix:** Bind the listener to the dialog host element via `(keydown.enter)` in the template instead of hooking `document`.

```typescript
// Current — dangerous
@HostListener('document:keydown.enter', ['$event'])
handleEnterKey() { ... }

// Fix — scope to dialog container in template
// <div class="dialog-container" (keydown.enter)="handleEnterKey()" tabindex="0">
```

---

### P0-2: Missing `ChangeDetectionStrategy.OnPush`
**File:** `gbdialogbox.component.ts:6`

Default change detection runs on every event in the application event loop. The component's data comes from `MAT_DIALOG_DATA` which is set once at open time and never changes — OnPush is safe and correct here. With ~896 callers triggering this dialog constantly, this is a repeated performance anti-pattern.

**Fix:** Add `changeDetection: ChangeDetectionStrategy.OnPush`.

---

### P0-3: `DialogData: any` — no typed contract across ~896 callers
**File:** `gbdialogbox.component.ts:27`

The entire dialog data object is typed as `any`. The actual shape used across the codebase is:
```typescript
{
  heading: 'Success' | 'Warning' | 'Error' | string;
  message: string | string[];
  button1?: string;
  button2?: string;
  button3?: string;
  errorinfo?: string;
  errortype?: number;
}
```
With `any`, there is zero compile-time safety. Callers can omit required fields, add typos, or use wrong types and TypeScript will not catch it across ~896 call sites.

**Fix:** Define and export a `GbDialogBoxData` interface and use it at `inject<GbDialogBoxData>(MAT_DIALOG_DATA)`.

---

### P0-4: `typeof null === 'object'` — silent null message bug
**File:** `gbdialogbox.component.html:12` and `gbdialogbox.component.ts:29`

`typeofmessage` is set to `typeof DialogData.message`. In JavaScript, `typeof null === 'object'`. If any caller passes `message: null`, the `*ngIf="typeofmessage === 'object'"` block renders and `*ngFor` iterates over `null` — throwing a runtime error. The string block also does not render, leaving a blank dialog with no indication of the problem.

**Fix:** Use `Array.isArray()` instead of `typeof`:
```typescript
this.typeofmessage = Array.isArray(DialogData.message) ? 'object' : 'string';
```

---

## P1 — High Priority Issues

### P1-1: Constructor injection instead of `inject()`
**File:** `gbdialogbox.component.ts:25`

Violates project standards. Both `MatDialogRef` and `MAT_DIALOG_DATA` must use `inject()`.

```typescript
// Current
constructor(
  private dialogRef: MatDialogRef<GbDialogBoxComponent>,
  @Inject(MAT_DIALOG_DATA) public DialogData: any
) { ... }

// Required
private dialogRef = inject(MatDialogRef<GbDialogBoxComponent>);
protected dialogData = inject<GbDialogBoxData>(MAT_DIALOG_DATA);
```

---

### P1-2: Heading color ternary repeated 6 times in template
**File:** `gbdialogbox.component.html:4, 50, 61, 72`

The same color-resolution expression appears 6 times across the heading and all three buttons:
```html
[style.color]="DialogData.heading === 'Success' ? '#32AE73' :
               DialogData.heading === 'Warning' ? '#F58D00' :
               DialogData.heading === 'Error' ? '#ED2531' :
               'var(--action-primary-default)'"
```
This is maintenance-heavy (one color change = 6 edits), unreadable, and evaluated on every CD cycle.

**Fix:** Compute once as a `computed()` signal or protected getter.

---

### P1-3: Two separate `*ngIf` blocks for expand/collapse icon toggle
**File:** `gbdialogbox.component.html:28–38`

Two near-identical blocks render the expand/collapse chevron — one for `!DisplayMore`, one for `DisplayMore`. Only the icon name differs. This doubles DOM nodes for no reason.

**Fix:** Single block with conditional icon name:
```html
<div *ngIf="Errormsg && errorType !== 5" (click)="moretoggle()">
  <mat-icon>{{ DisplayMore ? 'expand_less' : 'expand_more' }}</mat-icon>
</div>
```

---

### P1-4: `*ngFor` missing `trackBy`
**File:** `gbdialogbox.component.html:13`

```html
<div *ngFor="let data of DialogData.message" ...>
```
Angular re-creates all DOM nodes on every CD cycle with no `trackBy`. Add `trackBy: trackByIndex`.

---

### P1-5: Duplicate `::ng-deep .mat-mdc-dialog-component-host` rule
**File:** `gbdialogbox.component.scss:6` and `:54`

The same selector appears twice with different (non-conflicting but split) declarations. These should be merged into one rule.

---

### P1-6: Three `::ng-deep` selectors — all leak globally
**File:** `gbdialogbox.component.scss:1, 6, 54`

All three `::ng-deep` rules affect the global Material dialog CDK overlay. Every `mat-dialog-container` in the application receives `border-radius: 12px` and `background-color: #FFFFFF !important` from this component — including dialogs that are completely unrelated to `GbDialogBoxComponent`.

**Fix:** Move dialog surface overrides to the global Material theme configuration (`@use '@angular/material'`) or use `ViewEncapsulation.None` with a unique host class scoped to this component.

---

### P1-7: Non-standard naming conventions
**File:** `gbdialogbox.component.ts`

Angular convention is camelCase for properties and methods. Current violations:
- `DialogData` → should be `dialogData`
- `Errormsg` → should be `errorMsg`
- `DisplayMore` → should be `displayMore`
- `moretoggle()` → should be `toggleMore()`
- `closeModal(CloseValue)` → parameter should be `closeValue`

---

### P1-8: Fixed `width: 120px` on buttons truncates localized text
**File:** `gbdialogbox.component.scss:43`

`width: 120px` clips Arabic, German, or long English button labels. Use `min-width: 120px` and remove `width` to let buttons grow naturally.

---

### P1-9: Magic number `errorType !== 5` undocumented
**File:** `gbdialogbox.component.html:28, 34, 41`

The constant `5` has no explanation anywhere in the codebase. What is error type 5? Why should it suppress the expand/collapse panel? This must be a named constant or enum exported alongside `GbDialogBoxData`.

---

### P1-10: Zero test coverage
**File:** `gbdialogbox.component.spec.ts` — empty file (0 bytes)

The most-used component in the project has no unit tests. Minimum test cases needed:
- Renders string message correctly
- Renders array message correctly via `*ngFor`
- Button 1/2/3 closes dialog with correct return value
- Cancel icon closes with `'Cancel'`
- Expand/collapse toggles `DisplayMore`
- Error detail panel hidden when `errorType === 5`
- Enter key triggers button1 close
- `typeof null` does not crash (regression test for P0-4)

---

## P2 — Medium Issues

### P2-1: `<div>` and `<span>` used as buttons — accessibility failure
**File:** `gbdialogbox.component.html:47, 58, 69`

Button 1 is a `<div>`, buttons 2 and 3 are `<span>`. None are semantic button elements:
- Not focusable by keyboard by default (no `tabindex`)
- Not announced as "button" by screen readers
- No `Space` key activation (HostListener only covers Enter, and only for button1)
- No `disabled` state support

**Fix:** Use `<button type="button">` for all three.

---

### P2-2: No `aria-*` attributes — dialog not screen-reader friendly
**File:** `gbdialogbox.component.html`

- No `aria-labelledby` pointing to the heading element
- No `aria-describedby` pointing to the message
- Cancel icon has no `aria-label` or `title`
- Expand/collapse chevron has no `aria-expanded` attribute
- Error detail panel has no `role="alert"` or `aria-live`

Material Dialog sets `role="dialog"` automatically, but all internal landmarks are missing.

---

### P2-3: Hardcoded `#FFFFFF` background — not dark-mode aware
**File:** `gbdialogbox.component.scss:3`

```scss
background-color: #FFFFFF !important;
```
Forces white with `!important`, overriding any dark theme. Use `var(--mat-sys-surface)` instead.

---

### P2-4: Hardcoded `"Helvetica"` font — ignores Material typography system
**File:** `gbdialogbox.component.scss:12, 19, 32, 45`

`font-family: "Helvetica"` on every text element. The app has a Material theme with `--mat-sys-*` typography tokens. Use `font: var(--mat-body-medium-font)` or the Material typography mixin instead.

---

### P2-5: No RTL CSS support
**File:** `gbdialogbox.component.scss`

No `[dir="rtl"]` selectors. The app supports Arabic which requires:
- Text alignment flip
- Button order reverse
- Cancel icon position flip (`float: left` in RTL)
- Icon margin flip (`margin-right` → `margin-left`)

---

### P2-6: Cancel icon always sends `'Cancel'` — undocumented magic close value
**File:** `gbdialogbox.component.html:1`

```html
(click)="closeModal('Cancel')"
```
Consumers that only check for `'Yes'` / `'No'` / `'OK'` silently ignore the case where the user clicked X. There is no documentation or type enforcement to tell callers what the close icon emits. Should be configurable via `DialogData.cancelValue` or clearly documented.

---

### P2-7: Heading color not applied consistently to buttons vs heading
**File:** `gbdialogbox.component.html:50–76`

The heading falls back to `var(--action-primary-default)` for unknown heading types (e.g. `'Info'`). The buttons fall back to `''` (empty string — no override). For an `'Info'` heading, the title shows primary color but buttons show white-on-primary-background (`.alertbutton` has `color: #FFFFFF` in SCSS), making buttons effectively invisible when the fallback case is hit.

---

### P2-8: No guard against multiple rapid clicks
**File:** `gbdialogbox.component.ts:38`

`closeModal()` does not guard against double-clicks. If the consumer performs an async action (e.g., HTTP delete) after receiving the close value, rapid button clicks can emit multiple close events before the dialog closes. The component should close only once.

---

### P2-9: No max-width safeguard in component — mobile broken at all 896 call sites
**File:** All consumer call sites (e.g., `gbhttp.service.ts:1145`, `gbtime.component.ts:132`)

All observed callers pass `width: '600px'` with no `maxWidth`. On viewports narrower than 600px, the dialog clips off-screen. The component should enforce `maxWidth: '95vw'` as a default through a `GbDialogService` wrapper, removing the burden from all 896 callers.

---

### P2-10: Inline styles throughout template — not theme/RTL/dark-mode aware
**File:** `gbdialogbox.component.html`

Multiple elements carry inline `style="..."` attributes:
- Close icon: `style="color: red; float: right; cursor: pointer;"`
- Message divs: `style="max-width: 500px; margin-bottom: 10px; text-align: left;"`
- Toggle divs: `style="cursor: pointer; text-align: right;"`
- Buttons: `style="margin-top: 14px;"`

Inline styles cannot be overridden by theme, cannot respond to RTL, and cannot be tested. All should be moved to SCSS classes.

---

## Consumer-Wide Issues (Cross-Cutting)

These issues exist in the ~896 consumer files and stem from the lack of a typed interface and a wrapper service.

### CW-1: Hardcoded English strings at all ~896 call sites
All consumers pass hardcoded English strings directly:
```typescript
heading: 'Error'
message: 'Please enter Valid Time Format'
button1: 'OK'
```
Since `GbDialogBoxComponent` renders these directly via `{{ DialogData.heading }}`, the dialog is never localized. The component must translate via `translocoService.translate()` or accept Transloco keys and render via `| transloco`.

---

### CW-2: Fixed `width: '600px'` at all call sites — mobile broken
All observed callers pass fixed `width: '600px'` with no `maxWidth`. Confirmed in `gbhttp.service.ts:1145`, `gbtime.component.ts:132`, and others. On mobile viewports < 600px this clips the dialog off-screen. Needs a migration to `width: 'min(600px, 95vw)', maxWidth: '95vw'` at all call sites, or enforcement via a `GbDialogService` wrapper.

---

### CW-3: `gbhttp.service.ts` opens dialog directly — HTTP layer coupled to UI
**File:** `libs/common/src/lib/gbservice/gbhttpservice/gbhttp.service.ts:1138, 1200`

The core HTTP service (singleton, used by all 39 MFEs) directly calls `MatDialog.open(GbDialogBoxComponent)`. This:
- Couples the HTTP infrastructure layer to a UI component
- Makes unit testing `GbHttpService` impossible without a dialog fixture
- Bypasses any future `GbDialogService` abstraction

**Fix:** Extract into a `GbNotificationService` or `GbAlertService` that the HTTP service calls instead.

---

### CW-4: No wrapper service — same boilerplate at every call site
Every consumer must independently `inject(MatDialog)`, import `GbDialogBoxComponent`, and construct the full config object. A `GbDialogService` with typed convenience methods would reduce 5–8 lines to 1:
```typescript
// Instead of current ~8 lines per call site:
this.gbDialog.error('Save Failed', errorMessages);
this.gbDialog.confirm('Delete this record?').afterClosed().subscribe(...);
```

---

### CW-5: `errortype` field semantics completely undocumented
The `errortype` field only affects behavior when it equals `5` (suppresses detail panel). No enum, no documentation, no validation anywhere in the codebase. Most callers don't pass it; a few do (e.g., `gbhttp.service.ts:1143`). The behavior difference is invisible at call sites.

---

## Recommendations (Priority Order)

### Immediate (fix P0s — correctness bugs)

1. ~~**Fix Enter key scope** (`P0-1`)~~ ✅ Done — `@HostListener` removed; `<button cdkFocusInitial>` + native keyboard used.

2. ~~**Guard `typeof null`** (`P0-4`)~~ ✅ Done — `Array.isArray()` replaces `typeof` check.

3. ~~**Add `ChangeDetectionStrategy.OnPush`** (`P0-2`)~~ ✅ Done.

4. ~~**Define `GbDialogBoxData` interface** (`P0-3`)~~ ✅ Done — exported; TypeScript will now flag mismatches at all ~896 call sites on next compile.

### Short-term (P1)

5. ~~Migrate to `inject()`~~ ✅ Done.
6. ~~Extract heading color to a single map~~ ✅ Done — `HEADING_COLORS` + `readonly` properties.
7. ~~Merge duplicate `::ng-deep` rules~~ ✅ Done.
8. ~~Replace `<div>` / `<span>` buttons with `<button type="button">`~~ ✅ Done.
9. ~~Change button `width: 120px` to `min-width: 120px`~~ ✅ Done.
10. **Write unit tests** (`P1-10`) ⏳ — minimum 8 cases listed in Remaining Work above.
11. ~~Export named constant for `errorType === 5`~~ ✅ Done — `DIALOG_ERROR_TYPE_SUPPRESS_DETAILS`.

### Medium-term (Architecture)

12. **Create `GbDialogService` wrapper** ⏳ — typed `confirm()`, `error()`, `warn()`, `success()` methods. Enforces `maxWidth: '95vw'`, default widths, and Transloco integration. Eliminates boilerplate at all ~896 call sites.

13. **Localize all dialog content** ⏳ — `GbDialogService` accepts Transloco keys + interpolation params.

14. **Decouple `GbHttpService` from dialog** ⏳ — introduce `GbNotificationService`.

15. ~~**Add RTL CSS**~~ ✅ Done — `[dir="rtl"]` selectors added for float, text-align, and layout.

16. ~~**Dark mode + typography**~~ ✅ Done — `var(--mat-sys-surface, #ffffff)` replaces `#FFFFFF`; `"Helvetica"` removed.

---

## Appendix: `GbDialogBoxData` Interface (now exported from component)

```typescript
export interface GbDialogBoxData {
  /**
   * Dialog header text. Controls accent color:
   * 'Success' → #32AE73 | 'Warning' → #F58D00 | 'Error' → #ED2531 | else → var(--action-primary-default)
   */
  heading: 'Success' | 'Warning' | 'Error' | 'Info' | string;

  /** Main message body. string = single paragraph; string[] = scrollable item list */
  message: string | string[];

  /** Primary action button label. Also triggered by Enter key. Returned as dialog close value. */
  button1?: string;

  /** Secondary action button label. Returned as dialog close value on click. */
  button2?: string;

  /** Tertiary action button label. Returned as dialog close value on click. */
  button3?: string;

  /** Expandable technical error detail text. Shown behind expand/collapse toggle. */
  errorinfo?: string;

  /**
   * Controls detail panel visibility.
   * Known magic value: 5 = suppress the expand/collapse panel entirely.
   * All other values (or undefined): show expand/collapse toggle when errorinfo is present.
   */
  errortype?: number;
}
```

**Close values emitted by the dialog:**
- Close icon (X): always `'Cancel'`
- `button1` click or Enter key: value of `DialogData.button1`
- `button2` click: value of `DialogData.button2`
- `button3` click: value of `DialogData.button3`
