A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
import { UbButtonDirective } from '@/components/ui/button' import { UbDialogContentDirective, UbDialogDescriptionDirective, UbDialogFooterDirective, UbDialogHeaderDirective, UbDialogTitleDirective, UbDialogTriggerDirective, } from '@/components/ui/dialog' import { UbInputDirective } from '@/components/ui/input' import { UbLabelDirective } from '@/components/ui/label' import { Component } from '@angular/core' @Component({ standalone: true, selector: 'dialog-demo-new-york', imports: [ UbDialogTriggerDirective, UbDialogContentDirective, UbDialogHeaderDirective, UbDialogTitleDirective, UbDialogDescriptionDirective, UbDialogFooterDirective, UbButtonDirective, UbLabelDirective, UbInputDirective, ], template: ` <button ubButton variant="outline" [ubDialogTrigger]="dialog">Edit Profile</button> <ng-template #dialog> <div ubDialogContent class="sm:max-w-[425px]"> <div ubDialogHeader> <h2 ubDialogTitle>Edit profile</h2> <p ubDialogDescription>Make changes to your profile here. Click save when you're done.</p> </div> <div class="grid gap-4 py-4"> <div class="grid grid-cols-4 items-center gap-4"> <label ubLabel htmlFor="name" class="text-right"> Name </label> <input ubInput type="text" id="name" value="Pedro Duarte" class="col-span-3" /> </div> <div class="grid grid-cols-4 items-center gap-4"> <label ubLabel htmlFor="username" class="text-right"> Username </label> <input ubInput type="text" id="username" value="@peduarte" class="col-span-3" /> </div> </div> <div ubDialogFooter> <button ubButton>Save changes</button> </div> </div> </ng-template> `, }) export class DialogDemoNewYork { }
import { UbButtonDirective } from '@/components/ui/button' import { UbDialogContentDirective, UbDialogDescriptionDirective, UbDialogFooterDirective, UbDialogHeaderDirective, UbDialogTitleDirective, UbDialogTriggerDirective, } from '@/components/ui/dialog' import { UbInputDirective } from '@/components/ui/input' import { UbLabelDirective } from '@/components/ui/label' import { Component } from '@angular/core' @Component({ standalone: true, selector: 'dialog-demo-default', imports: [ UbDialogTriggerDirective, UbDialogContentDirective, UbDialogHeaderDirective, UbDialogTitleDirective, UbDialogDescriptionDirective, UbDialogFooterDirective, UbButtonDirective, UbLabelDirective, UbInputDirective, ], template: ` <button ubButton variant="outline" [ubDialogTrigger]="dialog">Edit Profile</button> <ng-template #dialog> <div ubDialogContent class="sm:max-w-[425px]"> <div ubDialogHeader> <h2 ubDialogTitle>Edit profile</h2> <p ubDialogDescription>Make changes to your profile here. Click save when you're done.</p> </div> <div class="grid gap-4 py-4"> <div class="grid grid-cols-4 items-center gap-4"> <label ubLabel htmlFor="name" class="text-right"> Name </label> <input ubInput type="text" id="name" value="Pedro Duarte" class="col-span-3" /> </div> <div class="grid grid-cols-4 items-center gap-4"> <label ubLabel htmlFor="username" class="text-right"> Username </label> <input ubInput type="text" id="username" value="@peduarte" class="col-span-3" /> </div> </div> <div ubDialogFooter> <button ubButton>Save changes</button> </div> </div> </ng-template> `, }) export class DialogDemoDefault { }
npx shadcn-ng@latest add dialog
npm install @radix-ng/primitives @ng-icons/core @ng-icons/lucide
import { cn } from '@/lib/utils' import { Component, computed, Directive, effect, inject, input, type TemplateRef } from '@angular/core' import { NgIconComponent, provideIcons } from '@ng-icons/core' import { lucideX } from '@ng-icons/lucide' import { RdxDialogCloseDirective, type RdxDialogConfig, RdxDialogContentDirective, RdxDialogDescriptionDirective, RdxDialogTitleDirective, RdxDialogTriggerDirective, } from '@radix-ng/primitives/dialog' @Directive({ standalone: true, selector: 'button[ubDialogClose]', hostDirectives: [RdxDialogCloseDirective], }) export class UbDialogCloseDirective {} @Directive({ standalone: true, selector: 'ubDialogTrigger', hostDirectives: [ { directive: RdxDialogTriggerDirective, inputs: ['rdxDialogTrigger: ubDialogTrigger'], }, ], }) export class UbDialogTriggerDirective { rdxDialogTrigger = inject(RdxDialogTriggerDirective, { host: true }) ubDialogTrigger = input.required<TemplateRef<void>>() ubDialogConfig = input<RdxDialogConfig<unknown>>() passingConfig = effect(() => { this.rdxDialogTrigger.dialogConfig = { ...this.ubDialogConfig(), content: this.ubDialogTrigger(), backdropClass: ['fixed', 'inset-0', 'z-50', 'bg-black/80', 'data-[state=open]:animate-in', 'data-[state=closed]:animate-out', 'data-[state=closed]:fade-out-0', 'data-[state=open]:fade-in-0'], } }) } @Component({ standalone: true, selector: '[ubDialogContent]', imports: [RdxDialogCloseDirective, NgIconComponent], host: { '[class]': 'computedClass()', }, hostDirectives: [ { directive: RdxDialogContentDirective, }, ], viewProviders: [provideIcons({ lucideX })], template: ` <ng-content /> <button class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground" rdxDialogClose> <ng-icon name="lucideX" /> <span class="sr-only">Close</span> </button> `, }) export class UbDialogContentDirective { class = input<string>() computedClass = computed(() => cn('fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg', this.class())) } @Directive({ standalone: true, selector: 'div[ubDialogHeader]', host: { '[class]': 'computedClass()', }, }) export class UbDialogHeaderDirective { class = input<string>() computedClass = computed(() => cn('flex flex-col space-y-1.5 text-center sm:text-left', this.class())) } @Directive({ standalone: true, selector: 'div[ubDialogFooter]', host: { '[class]': 'computedClass()', }, }) export class UbDialogFooterDirective { class = input<string>() computedClass = computed(() => cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', this.class())) } @Directive({ standalone: true, selector: 'h2[ubDialogTitle]', host: { '[class]': 'computedClass()', }, hostDirectives: [RdxDialogTitleDirective], }) export class UbDialogTitleDirective { class = input<string>() computedClass = computed(() => cn('text-lg font-semibold leading-none tracking-tight', this.class())) } @Directive({ standalone: true, selector: 'p[ubDialogDescription]', host: { '[class]': 'computedClass()', }, hostDirectives: [RdxDialogDescriptionDirective], }) export class UbDialogDescriptionDirective { class = input<string>() computedClass = computed(() => cn('text-sm text-muted-foreground', this.class())) }
import { UbDialogContentDirective, UbDialogDescriptionDirective, UbDialogFooterDirective, UbDialogHeaderDirective, UbDialogTitleDirective, UbDialogTriggerDirective, } from '@/components/ui/dialog'
<button ubButton variant="outline" [ubDialogTrigger]="dialog">Open</button> <ng-template #dialog> <div ubDialogContent> <div ubDialogHeader> <h2 ubDialogTitle>Are you absolutely sure?</h2> <p ubDialogDescription> This action cannot be undone. This will permanently delete your account and remove your data from our servers. </p> </div> </div> </ng-template>