https://github.com/HoplaGeiss/ngx-dialog-forge
Declarative, signals-native Angular dialog library built on the native <dialog> element — zero dependencies, CSS-only theming, fully accessible.
https://github.com/HoplaGeiss/ngx-dialog-forge
angular dialog modal native-dialog signals typescript
Last synced: 2 days ago
JSON representation
Declarative, signals-native Angular dialog library built on the native <dialog> element — zero dependencies, CSS-only theming, fully accessible.
- Host: GitHub
- URL: https://github.com/HoplaGeiss/ngx-dialog-forge
- Owner: HoplaGeiss
- License: mit
- Created: 2026-06-26T07:15:35.000Z (11 days ago)
- Default Branch: main
- Last Pushed: 2026-06-26T08:18:03.000Z (11 days ago)
- Last Synced: 2026-06-26T10:04:51.209Z (11 days ago)
- Topics: angular, dialog, modal, native-dialog, signals, typescript
- Language: TypeScript
- Homepage: https://hoplageiss.github.io/ngx-dialog-forge/
- Size: 183 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- fucking-awesome-angular - ngx-dialog-forge - Declarative, signals-native Angular dialog library built on the native dialog element. (Third Party Components / Modals)
- awesome-angular - ngx-dialog-forge - Declarative, signals-native Angular dialog library built on the native dialog element. (Third Party Components / Modals)
README
# ngx-dialog-forge
A declarative, signals-native Angular dialog library built on the native `` element.
[](https://github.com/HoplaGeiss/ngx-dialog-forge/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/ngx-dialog-forge)
[](LICENSE)
**[Live demo →](https://hoplageiss.github.io/ngx-dialog-forge/)**
---
## Features
- **Declarative API** — place `` directly in your template, no service calls
- **Signals-first** — two-way binding via `model()`, `input()`, `output()` throughout; OnPush everywhere
- **Native `` element** — free focus trapping, backdrop, and `inert` management from the browser
- **Zero runtime dependencies** — no CDK, no third-party packages
- **Flexible actions** — declarative slot (`ng-template ngxDialogActions`) or shorthand `[actions]` input
- **CSS-only theming** — three ready-made themes (Material, Bootstrap, PrimeNG) activated via a single `data-ngx-theme` attribute; no Angular input required
- **Per-instance overrides** — `closeButton`, `closeOnBackdrop`, `closeOnEscape`, and `size` can all be overridden per dialog
- **Global config** — set defaults once with `provideDialog()` in `app.config.ts`
- **SSR-compatible** — all DOM calls are guarded with `isPlatformBrowser`
---
## Requirements
- Angular **22+**
---
## Installation
```bash
pnpm add ngx-dialog-forge
# or
npm install ngx-dialog-forge
```
---
## Setup
### 1. Register global defaults (optional)
```ts
// app.config.ts
import { provideDialog } from 'ngx-dialog-forge';
export const appConfig: ApplicationConfig = {
providers: [
provideDialog({
closeButton: true,
closeOnBackdrop: true,
closeOnEscape: true,
}),
],
};
```
### 2. Load a theme
Import one of the provided SCSS partials in your global stylesheet and set `data-ngx-theme` on an ancestor element (typically ``):
```scss
// styles.scss
@use 'ngx-dialog-forge/themes/material';
@use 'ngx-dialog-forge/themes/bootstrap';
@use 'ngx-dialog-forge/themes/primeng';
```
```html
...
```
Switching the attribute value at runtime changes the active theme instantly — no JavaScript style injection required.
---
## Usage
### Basic dialog
```ts
import { NgxDialogComponent } from 'ngx-dialog-forge';
@Component({
imports: [NgxDialogComponent],
template: `
Open
Dialog body content.
`,
})
export class MyComponent {
open = signal(false);
}
```
---
### Declarative actions slot
Use `ng-template ngxDialogActions` with `ngxDialogCancel` / `ngxDialogConfirm` marker directives. The dialog closes and emits through `(action)` automatically when either is clicked.
```ts
import {
NgxDialogComponent,
NgxDialogActionsDirective,
NgxDialogCancelDirective,
NgxDialogConfirmDirective,
} from 'ngx-dialog-forge';
@Component({
imports: [NgxDialogComponent, NgxDialogActionsDirective, NgxDialogCancelDirective, NgxDialogConfirmDirective],
template: `
This action cannot be undone.
Cancel
Delete
`,
})
export class MyComponent {
open = signal(false);
onAction(type: string): void {
console.log(type); // 'confirm' | 'cancel'
}
}
```
---
### Actions via `[actions]` input
Shorthand for simple confirm / cancel flows without a template slot:
```html
Are you sure?
```
---
### Per-instance overrides
Every option from `provideDialog()` can be overridden per dialog:
```html
Only the X button closes this.
```
---
## `NgxDialogComponent` API
### Inputs
| Input | Type | Default | Description |
|---|---|---|---|
| `open` | `model` | `false` | Two-way binding for the open state |
| `title` | `string` | — | Dialog heading text |
| `closeButton` | `boolean` | from config / `true` | Show the × close button in the header |
| `closeOnBackdrop` | `boolean` | from config / `true` | Close when the backdrop is clicked |
| `closeOnEscape` | `boolean` | from config / `true` | Close on the Escape key |
| `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Max-width preset |
| `actions` | `NgxDialogAction[]` | `[]` | Shorthand action buttons (alternative to the slot) |
### Outputs
| Output | Payload | Description |
|---|---|---|
| `action` | `string` | Emits the action `type` when a button is clicked (`'confirm'`, `'cancel'`, or custom) |
| `opened` | `void` | Fires after `showModal()` is called |
| `closed` | `void` | Fires after the dialog closes (any cause) |
---
## Directives
| Selector | Description |
|---|---|
| `ng-template[ngxDialogActions]` | Marks an `ng-template` as the actions slot |
| `[ngxDialogConfirm]` | Marks a button as the confirm action — emits `'confirm'` and closes the dialog on click |
| `[ngxDialogCancel]` | Marks a button as the cancel action — emits `'cancel'` and closes the dialog on click |
---
## `provideDialog()` options
```ts
interface NgxDialogConfig {
closeButton?: boolean; // default: true
closeOnBackdrop?: boolean; // default: true
closeOnEscape?: boolean; // default: true
}
```
---
## CSS custom properties
Override any of these on `dialog.ngx-dialog` (or a parent) to customise the look without writing a full theme.
| Property | Default | Description |
|---|---|---|
| `--ngx-dialog-bg` | `#ffffff` | Dialog background |
| `--ngx-dialog-border` | `none` | Dialog outline border |
| `--ngx-dialog-border-radius` | `8px` | Corner radius |
| `--ngx-dialog-shadow` | medium drop shadow | Box shadow |
| `--ngx-dialog-border-color` | `rgba(0,0,0,.08)` | Header / footer divider colour |
| `--ngx-dialog-backdrop-color` | `rgba(0,0,0,.5)` | `::backdrop` colour |
| `--ngx-dialog-padding` | `1.25rem 1.5rem` | Fallback padding for header and body |
| `--ngx-dialog-header-bg` | `transparent` | Header background |
| `--ngx-dialog-header-padding` | inherits `--ngx-dialog-padding` | Header padding |
| `--ngx-dialog-title-color` | `inherit` | Title text colour |
| `--ngx-dialog-title-size` | `1.125rem` | Title font size |
| `--ngx-dialog-title-weight` | `600` | Title font weight |
| `--ngx-dialog-body-padding` | inherits `--ngx-dialog-padding` | Body padding |
| `--ngx-dialog-body-color` | `inherit` | Body text colour |
| `--ngx-dialog-footer-bg` | `transparent` | Footer background |
| `--ngx-dialog-footer-padding` | `1rem 1.5rem` | Footer padding |
| `--ngx-dialog-confirm-bg` | `#3b82f6` | Confirm button background |
| `--ngx-dialog-confirm-color` | `#ffffff` | Confirm button text |
| `--ngx-dialog-confirm-border` | matches bg | Confirm button border |
| `--ngx-dialog-confirm-shadow` | `none` | Confirm button box-shadow |
| `--ngx-dialog-cancel-bg` | `transparent` | Cancel button background |
| `--ngx-dialog-cancel-color` | `#374151` | Cancel button text |
| `--ngx-dialog-cancel-border` | `#d1d5db` | Cancel button border |
| `--ngx-dialog-btn-radius` | `6px` | Button corner radius |
| `--ngx-dialog-btn-padding` | `0.5rem 1.25rem` | Button padding |
| `--ngx-dialog-btn-font-size` | `0.875rem` | Button font size |
| `--ngx-dialog-btn-font-weight` | `500` | Button font weight |
| `--ngx-dialog-btn-letter-spacing` | `normal` | Button letter spacing |
| `--ngx-dialog-close-btn-color` | `#6b7280` | × button colour |
| `--ngx-dialog-close-btn-radius` | `4px` | × button corner radius |
| `--ngx-dialog-close-btn-hover-bg` | `rgba(0,0,0,.06)` | × button hover background |
| `--ngx-dialog-close-btn-hover-color` | `#111827` | × button hover colour |
| `--ngx-dialog-focus-ring` | `#3b82f6` | Focus outline colour |
| `--ngx-dialog-width-sm` | `360px` | Width for `size="sm"` |
| `--ngx-dialog-width-md` | `540px` | Width for `size="md"` |
| `--ngx-dialog-width-lg` | `720px` | Width for `size="lg"` |
| `--ngx-dialog-width-xl` | `960px` | Width for `size="xl"` |
---
## Contributing
Pull requests are welcome. For significant changes please open an issue first.
```bash
git clone https://github.com/HoplaGeiss/ngx-dialog-forge.git
cd ngx-dialog-forge
pnpm install
pnpm start # starts the demo app at localhost:4200
```
---
## License
[MIT](LICENSE)