Files
knock-gui/desktop-angular/MODAL_DIALOG_IMPLEMENTATION.md

285 lines
8.5 KiB
Markdown

# Modal Dialog Implementation Documentation
## Overview
This document describes the implementation of two configurable modal dialog systems for the desktop-angular project:
1) Angular in-app modal component (already integrated into the UI)
2) Electron-native modal window (opens a frameless BrowserWindow as a dialog)
Both allow variable questions, 1-3 buttons with custom labels, and return metadata for the clicked button. The Electron-native dialog additionally supports color customization for background, text, button colors per dialog.
## Files Added/Modified
### 1. New Files Created
#### `src/frontend/src/app/modal.service.ts`
**Purpose**: Core service for managing modal dialogs
**What it does**:
- Defines interfaces for modal configuration (`ModalConfig`, `ModalButton`, `ModalResult`)
- Provides `ModalService` with methods to show/hide modals
- Returns promises that resolve with button click results
- Includes convenience methods for common dialog types
**Key Features**:
- `show(config: ModalConfig): Promise<ModalResult>` - Main method to show custom modals
- `showConfirm(title, message): Promise<boolean>` - Yes/No confirmation dialog
- `showYesNoCancel(title, message): Promise<'yes'|'no'|'cancel'>` - Three-option dialog
- `showInfo(title, message): Promise<void>` - Information dialog with OK button
#### `src/frontend/src/app/modal.component.ts`
**Purpose**: Angular component that renders the modal dialog
**What it does**:
- Displays modal overlay and dialog box
- Renders configurable buttons with different styles
- Handles button clicks and communicates with service
- Manages modal visibility through service subscription
**Key Features**:
- Standalone Angular component
- Reactive to service state changes
- Supports button styling (primary, secondary, danger)
- Overlay click handling (currently disabled)
#### `src/frontend/src/app/modal.component.scss`
**Purpose**: Styling for the modal dialog
**What it does**:
- Creates modal overlay with semi-transparent background
- Styles dialog box with footer-matching colors (#aa1c3a)
- Implements button styles matching the app's footer buttons
- Provides responsive design for mobile devices
**Key Features**:
- Modal overlay with backdrop
- Dialog box with header, body, and footer sections
- Button styles matching app footer (white background, red text)
- Three button style variants: primary, secondary, danger
- Mobile-responsive design
### 2. Modified Files
#### `src/frontend/src/app/root.component.ts`
**Changes Made**:
- Added imports for `ModalService` and `ModalComponent`
- Added `ModalComponent` to component imports
- Injected `ModalService` in constructor
- Added example methods demonstrating modal usage:
- `showCustomModal()` - Shows 3-button custom dialog
- `showConfirmDialog()` - Shows Yes/No confirmation
- `showYesNoCancelDialog()` - Shows Yes/No/Cancel dialog
- `showInfoDialog()` - Shows information dialog
#### `src/frontend/src/app/root.component.html`
**Changes Made**:
- Added `<app-modal></app-modal>` component to template
- Added test buttons in form section to demonstrate modal functionality
- Test buttons include: Custom Modal, Confirm Dialog, Yes/No/Cancel, Info Dialog
### 3. Electron-Native Modal (Alternative)
To support invoking modals from the Electron main process with fully customizable styling, we added an alternative modal implementation which opens a dedicated `BrowserWindow` as a modal dialog.
#### New Files
- `src/main/modal.html`
- HTML/CSS/JS for a self-contained modal page
- Receives configuration over IPC (`custom-modal:config`)
- Renders title, message and up to 3 buttons
- Colors can be customized via CSS variables populated from config:
- background, text, buttonBg, buttonText, secondaryBg, secondaryText
- Each button can define its own inline style overrides via `buttonStyles` map
#### Changes in `src/main/main.js`
- Added `openCustomModalWindow(config)` helper to create a modal `BrowserWindow`
- Loads `modal.html` and sends the configuration after load
- Listens for `custom-modal:result` IPC to resolve the clicked button
- Exposed IPC handler `dialog:custom` to open the modal from renderer/preload
#### Changes in `src/preload/preload.js`
- Exposed `showNativeModal(config)` in `window.api` via `ipcRenderer.invoke('dialog:custom')`
#### Changes in `src/frontend/src/app/ipc.service.ts`
- Added wrapper method `showNativeModal(config)` to call the Electron-native modal from Angular code
#### Usage Example (from Angular renderer)
```ts
const result = await this.ipc.showNativeModal({
title: 'System Dialog',
message: 'Proceed with operation?',
buttons: [
{ id: 'yes', label: 'Yes', style: 'primary' },
{ id: 'no', label: 'No', style: 'secondary' },
{ id: 'cancel', label: 'Cancel', style: 'danger' }
],
colors: {
background: '#aa1c3a',
text: '#ffffff',
buttonBg: '#ffffff',
buttonText: '#aa1c3a',
secondaryBg: 'rgba(255,255,255,0.1)',
secondaryText: '#ffffff'
},
buttonStyles: {
yes: { bg: '#ffffff', text: '#aa1c3a' },
no: { bg: 'rgba(255,255,255,0.1)', text: '#ffffff' },
cancel: { bg: '#e53935', text: '#fff' }
}
});
// result => { buttonId: 'yes' | 'no' | 'cancel', buttonIndex: number, buttonLabel?: string }
```
## Usage Examples
### Basic Custom Modal
```typescript
const result = await this.modal.show({
title: 'Custom Dialog',
message: 'Choose an option:',
buttons: [
{ id: 'option1', label: 'Option 1', style: 'primary' },
{ id: 'option2', label: 'Option 2', style: 'secondary' },
{ id: 'cancel', label: 'Cancel', style: 'danger' }
]
});
console.log(`Clicked: ${result.buttonLabel} (ID: ${result.buttonId})`);
```
### Confirmation Dialog
```typescript
const confirmed = await this.modal.showConfirm(
'Delete Item',
'Are you sure you want to delete this item?'
);
if (confirmed) {
// Proceed with deletion
}
```
### Yes/No/Cancel Dialog
```typescript
const result = await this.modal.showYesNoCancel(
'Save Changes',
'Do you want to save your changes?'
);
switch (result) {
case 'yes': /* Save and continue */ break;
case 'no': /* Continue without saving */ break;
case 'cancel': /* Cancel operation */ break;
}
```
### Information Dialog
```typescript
await this.modal.showInfo(
'Success',
'Your changes have been saved successfully.'
);
```
## Button Styles
The modal supports three button styles:
1. **Primary** (`style: 'primary'`): White background, red text - matches footer buttons
2. **Secondary** (`style: 'secondary'`): Transparent background, white text
3. **Danger** (`style: 'danger'`): Red background, white text
## Styling Details
### Color Scheme
- **Background**: #aa1c3a (matches footer)
- **Text**: White (#ffffff)
- **Primary Buttons**: White background, red text
- **Secondary Buttons**: Transparent with white text
- **Danger Buttons**: Red background (#e53935)
### Layout
- Modal overlay covers entire screen
- Dialog is centered and responsive
- Maximum width: 500px
- Mobile-friendly with stacked buttons on small screens
## Integration Points
### Service Integration
The `ModalService` is provided at root level, making it available throughout the application:
```typescript
constructor(private modal: ModalService) {}
```
### Component Integration
The `ModalComponent` is imported in the main component and added to the template:
```html
<app-modal></app-modal>
```
## Testing
The implementation includes test buttons in the form section that demonstrate all modal types:
- Custom Modal: Shows 3-button dialog with different styles
- Confirm Dialog: Shows Yes/No confirmation
- Yes/No/Cancel: Shows 3-option dialog
- Info Dialog: Shows information with OK button
## Future Enhancements
Potential improvements could include:
1. Modal animations (fade in/out)
2. Keyboard navigation support
3. Escape key to close
4. Custom modal sizes
5. Modal stacking support
6. Form inputs within modals
7. Optional keyboard shortcuts (Enter/Esc)
8. Focus management and initial focus button
## Dependencies
The modal system requires:
- Angular CommonModule
- RxJS for reactive programming
- No external dependencies
## File Structure
``` еуче
src/frontend/src/app/
├── modal.service.ts # Service for modal management
├── modal.component.ts # Modal component
├── modal.component.scss # Modal styles
├── root.component.ts # Updated with modal integration
└── root.component.html # Updated with modal component
```
This implementation provides a complete, reusable modal dialog system that matches the application's design language and provides flexible configuration options for various dialog types.