npm package: @ng-shangjc/dialog
Description: Dialog component source package for ng-shangjc angular components
Author: jc-develop
Latest version: 1.0.4-beta

<p align="center">
<a href="https://juliancallejas.github.io/ng-shangjc-docs">
  <img src="https://res.cloudinary.com/dphleqb5t/image/upload/v1772819746/shangjc/shangjc-64-bg-dark_kwzs81.svg" width="307" alt="Shangjc"  /> 
</a>
</p>

# Dialog Component

A versatile modal dialog component with smooth animations, comprehensive accessibility features, and flexible composition patterns. Built with modern Angular signals and offering both controlled and uncontrolled usage patterns.

## Official Documentation

<a href="https://juliancallejas.github.io/ng-shangjc-docs/?path=/docs/components-dialog">
    ng-Shangjc docs
</a>

## Features

- 🚀 **Flexible Composition**: Modular subcomponents for complete dialog customization
- 🎨 **Multiple Sizes**: Support for sm, md, lg, and xl dialog sizes
- ♿ **Full Accessibility**: ARIA compliance, focus management, and screen reader support
- ⌨️ **Keyboard Navigation**: Escape key handling and proper focus trapping
- 🎯 **Type-Safe**: Full TypeScript support with comprehensive type definitions
- 🎨 **Customizable**: Extensive styling options with class-variance-authority
- ⚡ **Performance**: Optimized with OnPush change detection and signals
- 🔗 **Controlled/Uncontrolled**: Support for both usage patterns
- 🎭 **Smooth Animations**: Backdrop blur and fade-in effects

## Installation

### Step 1: Install the CLI

First, install the ng-shangjc CLI globally or use npx:

```bash
# Install globally
npm install -g @ng-shangjc/cli

# or with yarn
yarn global add @ng-shangjc/cli

# or with pnpm
pnpm install -g @ng-shangjc/cli

# Or use npx without installation
npx @ng-shangjc/cli <command>
```

### Step 2: Initialize your project

If you haven't already, initialize your Angular project for ng-shangjc components:

```bash
ng-shangjc init
```

This will create a `shangjc.config.json` file and set up your project for component installations.

### Step 3: Install the component

Install the dialog component into your project:

```bash
ng-shangjc install dialog
```

The component will be installed in the configured path (default: `src/ui/shangjc`). Adjust the import path in your components based on your project structure and the configured installation path.

## Import

After installation, import the components from your configured installation path. The examples below use the default path `src/ui/shangjc` - adjust the path according to your project structure and configuration.

### Standalone Components (Recommended)

Import and use the individual components directly in your standalone components:

```typescript
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { 
  DialogComponent,
  DialogTriggerComponent,
  DialogHeaderComponent,
  DialogTitleComponent,
  DialogDescriptionComponent,
  DialogContentComponent,
  DialogFooterComponent,
  DialogCloseComponent
} from './ui/shangjc/dialog';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [
    CommonModule,
    DialogComponent,
    DialogTriggerComponent,
    DialogHeaderComponent,
    DialogTitleComponent,
    DialogDescriptionComponent,
    DialogContentComponent,
    DialogFooterComponent,
    DialogCloseComponent
  ],
  template: `
    <ng-shangjc-dialog>
      <!-- Component content -->
    </ng-shangjc-dialog>
  `
})
export class ExampleComponent { }
```

### Using NgModule (Legacy)

If you're using NgModules, import the `DialogModule`:

```typescript
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DialogModule } from './ui/shangjc/dialog';

@NgModule({
  declarations: [YourComponent],
  imports: [
    CommonModule,
    DialogModule
  ]
})
export class YourModule { }
```

Then use the components in your templates:

```html
<ng-shangjc-dialog>
  <!-- Component content -->
</ng-shangjc-dialog>
```

## Basic Usage

### Default Example

```typescript
import { Component } from '@angular/core';
import { 
  DialogComponent,
  DialogTriggerComponent,
  DialogHeaderComponent,
  DialogTitleComponent,
  DialogDescriptionComponent,
  DialogContentComponent,
  DialogFooterComponent,
  DialogCloseComponent
} from './ui/shangjc/dialog';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [
    DialogComponent,
    DialogTriggerComponent,
    DialogHeaderComponent,
    DialogTitleComponent,
    DialogDescriptionComponent,
    DialogContentComponent,
    DialogFooterComponent,
    DialogCloseComponent
  ],
  template: `
    <ng-shangjc-dialog>
      <ng-shangjc-dialog-trigger>
        <button>Open Dialog</button>
      </ng-shangjc-dialog-trigger>
      
      <ng-shangjc-dialog-content>
        <ng-shangjc-dialog-header>
          <ng-shangjc-dialog-title>Confirm Action</ng-shangjc-dialog-title>
          <ng-shangjc-dialog-description>
            Are you sure you want to continue? This action cannot be undone.
          </ng-shangjc-dialog-description>
        </ng-shangjc-dialog-header>
        
        <p>This is the main content area of the dialog.</p>
        
        <ng-shangjc-dialog-footer>
          <ng-shangjc-dialog-close>Cancel</ng-shangjc-dialog-close>
          <button (click)="confirmAction()">Confirm</button>
        </ng-shangjc-dialog-footer>
      </ng-shangjc-dialog-content>
    </ng-shangjc-dialog>
  `,
})
export class ExampleComponent {
  confirmAction() {
    console.log('Action confirmed');
  }
}
```

### Different Sizes

```html
<!-- Small Dialog -->
<ng-shangjc-dialog size="sm">
  <ng-shangjc-dialog-trigger>
    <button>Small Dialog</button>
  </ng-shangjc-dialog-trigger>
  <ng-shangjc-dialog-content>
    <ng-shangjc-dialog-header>
      <ng-shangjc-dialog-title>Small Dialog</ng-shangjc-dialog-title>
    </ng-shangjc-dialog-header>
    <p>Compact dialog content.</p>
  </ng-shangjc-dialog-content>
</ng-shangjc-dialog>

<!-- Large Dialog -->
<ng-shangjc-dialog size="lg">
  <ng-shangjc-dialog-trigger>
    <button>Large Dialog</button>
  </ng-shangjc-dialog-trigger>
  <ng-shangjc-dialog-content>
    <ng-shangjc-dialog-header>
      <ng-shangjc-dialog-title>Large Dialog</ng-shangjc-dialog-title>
    </ng-shangjc-dialog-header>
    <p>Spacious dialog content with more room for complex layouts.</p>
  </ng-shangjc-dialog-content>
</ng-shangjc-dialog>
```

## Advanced Usage

### Controlled Component

```typescript
import { Component, signal } from '@angular/core';
import { 
  DialogComponent,
  DialogTriggerComponent,
  DialogHeaderComponent,
  DialogTitleComponent,
  DialogContentComponent,
  DialogFooterComponent,
  DialogCloseComponent
} from './ui/shangjc/dialog';

@Component({
  selector: 'app-controlled-example',
  standalone: true,
  imports: [
    DialogComponent,
    DialogTriggerComponent,
    DialogHeaderComponent,
    DialogTitleComponent,
    DialogContentComponent,
    DialogFooterComponent,
    DialogCloseComponent
  ],
  template: `
    <div class="space-y-4">
      <button (click)="openDialog()">Open Controlled Dialog</button>
      
      <ng-shangjc-dialog 
        [isOpen]="isOpen()" 
        (opened)="onOpened()" 
        (closed)="onClosed()"
      >
        <ng-shangjc-dialog-trigger>
          <button>Uncontrolled Trigger</button>
        </ng-shangjc-dialog-trigger>
        
        <ng-shangjc-dialog-content>
          <ng-shangjc-dialog-header>
            <ng-shangjc-dialog-title>Controlled Dialog</ng-shangjc-dialog-title>
          </ng-shangjc-dialog-header>
          
          <p>This dialog is controlled by the parent component.</p>
          <p>Current state: {{ isOpen() ? 'Open' : 'Closed' }}</p>
          
          <ng-shangjc-dialog-footer>
            <button (click)="closeDialog()">Controlled Close</button>
            <ng-shangjc-dialog-close>Uncontrolled Close</ng-shangjc-dialog-close>
          </ng-shangjc-dialog-footer>
        </ng-shangjc-dialog-content>
      </ng-shangjc-dialog>
    </div>
  `
})
export class ControlledExampleComponent {
  isOpen = signal(false);

  openDialog() {
    this.isOpen.set(true);
  }

  closeDialog() {
    this.isOpen.set(false);
  }

  onOpened() {
    console.log('Dialog opened');
  }

  onClosed() {
    console.log('Dialog closed');
  }
}
```

### Custom Styling

```html
<ng-shangjc-dialog 
  size="xl" 
  class="custom-dialog"
  [showCloseButton]="false"
  [backdropClick]="false"
>
  <ng-shangjc-dialog-trigger>
    <button>Custom Dialog</button>
  </ng-shangjc-dialog-trigger>
  
  <ng-shangjc-dialog-content>
    <ng-shangjc-dialog-header>
      <ng-shangjc-dialog-title>Custom Styled Dialog</ng-shangjc-dialog-title>
    </ng-shangjc-dialog-header>
    
    <p>This dialog has custom styling and behavior.</p>
    
    <ng-shangjc-dialog-footer>
      <ng-shangjc-dialog-close>Close</ng-shangjc-dialog-close>
    </ng-shangjc-dialog-footer>
  </ng-shangjc-dialog-content>
</ng-shangjc-dialog>
```

## API Reference

### DialogComponent

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `id` | `string` | `dlg-<random>` | Unique id for the dialog. Useful for accessibility purposes |
| `showCloseButton` | `boolean` | `true` | Determines whether the close button should be shown |
| `backdropClick` | `boolean` | `true` | Determines whether the dialog should close when the backdrop is clicked |
| `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | The size of the dialog |
| `isOpen` | `boolean` | `false` | Determines whether the dialog is open or closed |
| `class` | `string` | `''` | Additional classes to be applied to the dialog |
| `opened` | `EventEmitter<void>` | - | Emits when the dialog is opened |
| `closed` | `EventEmitter<void>` | - | Emits when the dialog is closed |

### DialogTriggerComponent

Used to trigger the dialog opening. Place any clickable content inside this component.

### DialogHeaderComponent

Container for the dialog header section. Typically contains DialogTitle and DialogDescription.

### DialogTitleComponent

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `id` | `string` | - | Optional ID for the title element |

### DialogDescriptionComponent

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `id` | `string` | - | Optional ID for the description element |

### DialogContentComponent

The main dialog container that handles the backdrop and positioning.

### DialogFooterComponent

Container for dialog footer content, typically action buttons.

### DialogCloseComponent

A button that closes the dialog when clicked. Can contain any content.

## Accessibility

- **Keyboard Navigation**: Full support for Escape key to close dialog
- **ARIA Attributes**: Proper ARIA labels, roles, and states including `role="dialog"` and `aria-modal`
- **Focus Management**: Automatic focus trapping and restoration when dialog opens/closes
- **Screen Reader**: Compatible with screen readers with proper title and description association
- **Semantic Structure**: Uses proper HTML semantic elements and heading hierarchy

### ARIA Features

- `role="dialog"` on the dialog content
- `aria-modal="true"` when dialog is open
- `aria-labelledby` references the dialog title
- `aria-describedby` references the dialog description
- Automatic focus management and focus trapping
- Body scroll lock when dialog is open

## Browser Support

- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+

## Contributing

See the main project [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines.

---

**Part of ng-shangjc component library** • [Documentation](https://juliancallejas.github.io/ng-shangjc-docs/)

<p align="center">
<a href="https://github.com/JulianCallejas">
  <img src="https://res.cloudinary.com/dphleqb5t/image/upload/v1740784502/github-jc-develop/JC-LOGO-Horizontal-170-50-thin-github_uu3b5n.svg" width="170" alt="{ jc - develop }"  /> 
</a>
</p>