md-dialog spec card
Identity · when to use / when NOT · decision cues · behavioural contract · do/don't · anti-patterns · full API. Paste into your agent when you're implementing with this component.
A modal that interrupts to get a decision. Basic or full-screen, with an optional icon and headline, a scrim, focus trapping, and an actions row you populate yourself.
Your changes will be lost.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-button variant="filled">Open dialog</md-button>
<md-dialog id="demo-dialog-basic" headline="Discard draft?">
<p style="margin: 0;">Your changes will be lost.</p>
<md-button slot="actions" variant="text">Cancel</md-button>
<md-button slot="actions" variant="filled">Discard</md-button>
</md-dialog>
<script type="module">
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-basic').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-basic').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-basic').close());
</script>import { useRef } from 'react';
import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
const demoDialogBasicRef = useRef(null);
const demoDialogBasicRef = useRef(null);
const demoDialogBasicRef = useRef(null);
return (
<>
<MdButton variant="filled" onClick={() => demoDialogBasicRef.current?.show()}>Open dialog</MdButton>
<MdDialog id="demo-dialog-basic" ref={demoDialogBasicRef} ref={demoDialogBasicRef} ref={demoDialogBasicRef} headline="Discard draft?">
<p style={{ margin: '0' }}>Your changes will be lost.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogBasicRef.current?.close()}>Cancel</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDialogBasicRef.current?.close()}>Discard</MdButton>
</MdDialog>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-button variant="filled" (click)="demoDialogBasic.show()">Open dialog</md-button>
<md-dialog id="demo-dialog-basic" #demoDialogBasic #demoDialogBasic #demoDialogBasic headline="Discard draft?">
<p style="margin: 0;">Your changes will be lost.</p>
<md-button slot="actions" variant="text" (click)="demoDialogBasic.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" (click)="demoDialogBasic.close()">Discard</md-button>
</md-dialog><script setup>
import { ref } from 'vue';
import '@awc-ui/core/define';
const demoDialogBasic = ref(null);
const demoDialogBasic = ref(null);
const demoDialogBasic = ref(null);
</script>
<template>
<md-button variant="filled" @click="demoDialogBasic?.show()">Open dialog</md-button>
<md-dialog id="demo-dialog-basic" ref="demoDialogBasic" ref="demoDialogBasic" ref="demoDialogBasic" headline="Discard draft?">
<p style="margin: 0;">Your changes will be lost.</p>
<md-button slot="actions" variant="text" @click="demoDialogBasic?.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" @click="demoDialogBasic?.close()">Discard</md-button>
</md-dialog>
</template><script>
import '@awc-ui/core/define';
let demoDialogBasic;
let demoDialogBasic;
let demoDialogBasic;
</script>
<md-button variant="filled" on:click={() => demoDialogBasic?.show()}>Open dialog</md-button>
<md-dialog id="demo-dialog-basic" bind:this={demoDialogBasic} bind:this={demoDialogBasic} bind:this={demoDialogBasic} headline="Discard draft?">
<p style="margin: 0;">Your changes will be lost.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogBasic?.close()}>Cancel</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDialogBasic?.close()}>Discard</md-button>
</md-dialog>
Already installed? See the
Installation guide for one-time package setup
(core + tokens, fonts). Each tab below shows two patterns for using
md-dialog in your project: Option A registers every AWC UI
component at once (simplest), Option B imports only this component for
tree-shake-friendly bundles.
<!-- ─── Option A: global registration (all components) ─── -->
<script type="module">
import '@awc-ui/core/define';
</script>
<!-- ─── Option B: single import (tree-shake only md-dialog) ─── -->
<script type="module">
import '@awc-ui/core/components/md-dialog';
</script>
<md-dialog></md-dialog>// ─── Option A: typed React wrapper (registers all components) ───
// Importing from '@awc-ui/react' calls defineCustomElements() as a
// side effect, so every md-* element becomes available in the browser.
import { MdDialog } from '@awc-ui/react';
export function Example() {
return <MdDialog></MdDialog>;
}
// ─── Option B: single import (tree-shake to only md-dialog) ───
// Skip the wrapper and use the raw custom element. Smallest bundle,
// but you lose typed props/events on JSX.
import '@awc-ui/core/components/md-dialog';
export function ExampleTreeShaken() {
return <md-dialog></md-dialog>;
}// ─── Option A: schema module (any md-* element accepted) ───
// Pair with `defineCustomElements(window)` in main.ts.
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@Component({
standalone: true,
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `<md-dialog></md-dialog>`,
})
export class ExampleComponent {}
// ─── Option B: typed directive (tree-shake friendly) ───
// Pair with `import '@awc-ui/core/components/md-dialog'` in main.ts.
import { Component } from '@angular/core';
import { MdDialog } from '@awc-ui/angular';
@Component({
standalone: true,
imports: [MdDialog],
template: `<md-dialog></md-dialog>`,
})
export class ExampleTreeShakenComponent {}<!-- ─── Option A: typed Vue wrapper (registers all components) ─── -->
<script setup lang="ts">
import { MdDialog } from '@awc-ui/vue';
</script>
<template>
<MdDialog></MdDialog>
</template>
<!-- ─── Option B: single import (tree-shake to only md-dialog) ─── -->
<script setup lang="ts">
import '@awc-ui/core/components/md-dialog';
</script>
<template>
<md-dialog></md-dialog>
</template><!-- ─── Option A: global registration (done once in main entry) ─── -->
<!-- main.ts: -->
<!-- import { defineCustomElements } from '@awc-ui/svelte'; -->
<!-- defineCustomElements(window); -->
<md-dialog></md-dialog>
<!-- ─── Option B: single import (tree-shake to only md-dialog) ─── -->
<script lang="ts">
import '@awc-ui/core/components/md-dialog';
</script>
<md-dialog></md-dialog>fullscreen).| Situation | Use instead |
|---|---|
| Low- or medium-priority information | md-snackbar |
| A brief confirmation of something that already happened | md-snackbar |
| Explaining a control | md-tooltip |
| Supplementary content, mobile | md-bottom-sheet |
| Supplementary content, desktop | md-side-sheet |
| A list of actions from a trigger | md-menu |
| Content that could just live on the page | A page or md-card |
| Field-level validation errors | Inline error text on the field |
You supply the buttons through slot="actions". cancel-label and ok-label
name the built-in fallback buttons that appear when you slot nothing;
slotted buttons win, so don’t set both and expect them to merge.
M3 also wants confirming actions disabled until a choice is made, while dismissive actions are never disabled. That is your logic, not the component’s.
Both buttons are mine. Dismissive first in DOM order, confirming second — the component renders them exactly as written.
Nothing is slotted into actions, so the built-in pair renders instead — named by cancel-label and ok-label. Both close the dialog; the cancel one also fires mdCancel.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<!-- You supply the pair: dismissive first, confirming second -->
<md-dialog headline="Discard draft?">
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text">Cancel</md-button>
<md-button slot="actions" variant="filled">Discard</md-button>
</md-dialog>
<!-- Nothing slotted: the built-in pair renders, named by cancel-label / ok-label -->
<md-dialog headline="Leave without saving?" cancel-label="Stay" ok-label="Leave">
<p>Your changes will be lost.</p>
</md-dialog>import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
return (
<>
<!-- You supply the pair: dismissive first, confirming second -->
<MdDialog headline="Discard draft?">
<p>Your changes will be lost.</p>
<MdButton slot="actions" variant="text">Cancel</MdButton>
<MdButton slot="actions" variant="filled">Discard</MdButton>
</MdDialog>
<!-- Nothing slotted: the built-in pair renders, named by cancel-label / ok-label -->
<MdDialog headline="Leave without saving?" cancelLabel="Stay" okLabel="Leave">
<p>Your changes will be lost.</p>
</MdDialog>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<!-- You supply the pair: dismissive first, confirming second -->
<md-dialog headline="Discard draft?">
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text">Cancel</md-button>
<md-button slot="actions" variant="filled">Discard</md-button>
</md-dialog>
<!-- Nothing slotted: the built-in pair renders, named by cancel-label / ok-label -->
<md-dialog headline="Leave without saving?" cancel-label="Stay" ok-label="Leave">
<p>Your changes will be lost.</p>
</md-dialog><script setup>
import '@awc-ui/core/define';
</script>
<template>
<!-- You supply the pair: dismissive first, confirming second -->
<md-dialog headline="Discard draft?">
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text">Cancel</md-button>
<md-button slot="actions" variant="filled">Discard</md-button>
</md-dialog>
<!-- Nothing slotted: the built-in pair renders, named by cancel-label / ok-label -->
<md-dialog headline="Leave without saving?" cancel-label="Stay" ok-label="Leave">
<p>Your changes will be lost.</p>
</md-dialog>
</template><script>
import '@awc-ui/core/define';
</script>
<!-- You supply the pair: dismissive first, confirming second -->
<md-dialog headline="Discard draft?">
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text">Cancel</md-button>
<md-button slot="actions" variant="filled">Discard</md-button>
</md-dialog>
<!-- Nothing slotted: the built-in pair renders, named by cancel-label / ok-label -->
<md-dialog headline="Leave without saving?" cancel-label="Stay" ok-label="Leave">
<p>Your changes will be lost.</p>
</md-dialog>An icon sits above the headline and centre-aligns the header. Without one the
header is start-aligned.
The basic-dialog story is the same shape without the icon.
This cannot be undone.
Version 2.4 is now active.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-button variant="tonal">Delete permanently</md-button>
<md-dialog id="demo-dialog-icon" headline="Delete 3 files?" icon="delete">
<p style="margin: 0;">This cannot be undone.</p>
<md-button slot="actions" variant="text">Cancel</md-button>
<md-button slot="actions" variant="filled">Delete</md-button>
</md-dialog>
<md-button variant="tonal">Show update notice</md-button>
<md-dialog id="demo-dialog-ack" headline="Update installed" icon="check_circle">
<p style="margin: 0;">Version 2.4 is now active.</p>
<md-button slot="actions" variant="text">Got it</md-button>
</md-dialog>
<script type="module">
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-icon').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-icon').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-icon').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-ack').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-ack').close());
</script>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { useRef } from 'react';
import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
const demoDialogIconRef = useRef(null);
const demoDialogIconRef = useRef(null);
const demoDialogIconRef = useRef(null);
const demoDialogAckRef = useRef(null);
const demoDialogAckRef = useRef(null);
return (
<>
<MdButton variant="tonal" onClick={() => demoDialogIconRef.current?.show()}>Delete permanently</MdButton>
<MdDialog id="demo-dialog-icon" ref={demoDialogIconRef} ref={demoDialogIconRef} ref={demoDialogIconRef} headline="Delete 3 files?" icon="delete">
<p style={{ margin: '0' }}>This cannot be undone.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogIconRef.current?.close()}>Cancel</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDialogIconRef.current?.close()}>Delete</MdButton>
</MdDialog>
<MdButton variant="tonal" onClick={() => demoDialogAckRef.current?.show()}>Show update notice</MdButton>
<MdDialog id="demo-dialog-ack" ref={demoDialogAckRef} ref={demoDialogAckRef} headline="Update installed" icon="check_circle">
<p style={{ margin: '0' }}>Version 2.4 is now active.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogAckRef.current?.close()}>Got it</MdButton>
</MdDialog>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-button variant="tonal" (click)="demoDialogIcon.show()">Delete permanently</md-button>
<md-dialog id="demo-dialog-icon" #demoDialogIcon #demoDialogIcon #demoDialogIcon headline="Delete 3 files?" icon="delete">
<p style="margin: 0;">This cannot be undone.</p>
<md-button slot="actions" variant="text" (click)="demoDialogIcon.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" (click)="demoDialogIcon.close()">Delete</md-button>
</md-dialog>
<md-button variant="tonal" (click)="demoDialogAck.show()">Show update notice</md-button>
<md-dialog id="demo-dialog-ack" #demoDialogAck #demoDialogAck headline="Update installed" icon="check_circle">
<p style="margin: 0;">Version 2.4 is now active.</p>
<md-button slot="actions" variant="text" (click)="demoDialogAck.close()">Got it</md-button>
</md-dialog><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { ref } from 'vue';
import '@awc-ui/core/define';
const demoDialogIcon = ref(null);
const demoDialogIcon = ref(null);
const demoDialogIcon = ref(null);
const demoDialogAck = ref(null);
const demoDialogAck = ref(null);
</script>
<template>
<md-button variant="tonal" @click="demoDialogIcon?.show()">Delete permanently</md-button>
<md-dialog id="demo-dialog-icon" ref="demoDialogIcon" ref="demoDialogIcon" ref="demoDialogIcon" headline="Delete 3 files?" icon="delete">
<p style="margin: 0;">This cannot be undone.</p>
<md-button slot="actions" variant="text" @click="demoDialogIcon?.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" @click="demoDialogIcon?.close()">Delete</md-button>
</md-dialog>
<md-button variant="tonal" @click="demoDialogAck?.show()">Show update notice</md-button>
<md-dialog id="demo-dialog-ack" ref="demoDialogAck" ref="demoDialogAck" headline="Update installed" icon="check_circle">
<p style="margin: 0;">Version 2.4 is now active.</p>
<md-button slot="actions" variant="text" @click="demoDialogAck?.close()">Got it</md-button>
</md-dialog>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
let demoDialogIcon;
let demoDialogIcon;
let demoDialogIcon;
let demoDialogAck;
let demoDialogAck;
</script>
<md-button variant="tonal" on:click={() => demoDialogIcon?.show()}>Delete permanently</md-button>
<md-dialog id="demo-dialog-icon" bind:this={demoDialogIcon} bind:this={demoDialogIcon} bind:this={demoDialogIcon} headline="Delete 3 files?" icon="delete">
<p style="margin: 0;">This cannot be undone.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogIcon?.close()}>Cancel</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDialogIcon?.close()}>Delete</md-button>
</md-dialog>
<md-button variant="tonal" on:click={() => demoDialogAck?.show()}>Show update notice</md-button>
<md-dialog id="demo-dialog-ack" bind:this={demoDialogAck} bind:this={demoDialogAck} headline="Update installed" icon="check_circle">
<p style="margin: 0;">Version 2.4 is now active.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogAck?.close()}>Got it</md-button>
</md-dialog>A single action is only right when it is an acknowledgement. “Cancel” makes no sense when nothing was proposed.
icon takes a Material Symbols name; the icon slot replaces it when you need
a custom glyph or an SVG.
Every panel returns to its default position. Saved layouts are untouched.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-button variant="tonal">Slotted icon</md-button>
<md-dialog id="demo-dialog-svgicon" headline="Reset your workspace?">
<svg slot="icon" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" aria-hidden="true"><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>
<p style="margin: 0;">Every panel returns to its default position. Saved layouts are untouched.</p>
<md-button slot="actions" variant="text">Cancel</md-button>
<md-button slot="actions" variant="filled">Reset</md-button>
</md-dialog>
<script type="module">
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-svgicon').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-svgicon').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-svgicon').close());
</script>import { useRef } from 'react';
import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
const demoDialogSvgiconRef = useRef(null);
const demoDialogSvgiconRef = useRef(null);
const demoDialogSvgiconRef = useRef(null);
return (
<>
<MdButton variant="tonal" onClick={() => demoDialogSvgiconRef.current?.show()}>Slotted icon</MdButton>
<MdDialog id="demo-dialog-svgicon" ref={demoDialogSvgiconRef} ref={demoDialogSvgiconRef} ref={demoDialogSvgiconRef} headline="Reset your workspace?">
<svg slot="icon" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" aria-hidden="true"><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>
<p style={{ margin: '0' }}>Every panel returns to its default position. Saved layouts are untouched.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogSvgiconRef.current?.close()}>Cancel</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDialogSvgiconRef.current?.close()}>Reset</MdButton>
</MdDialog>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-button variant="tonal" (click)="demoDialogSvgicon.show()">Slotted icon</md-button>
<md-dialog id="demo-dialog-svgicon" #demoDialogSvgicon #demoDialogSvgicon #demoDialogSvgicon headline="Reset your workspace?">
<svg slot="icon" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" aria-hidden="true"><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>
<p style="margin: 0;">Every panel returns to its default position. Saved layouts are untouched.</p>
<md-button slot="actions" variant="text" (click)="demoDialogSvgicon.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" (click)="demoDialogSvgicon.close()">Reset</md-button>
</md-dialog><script setup>
import { ref } from 'vue';
import '@awc-ui/core/define';
const demoDialogSvgicon = ref(null);
const demoDialogSvgicon = ref(null);
const demoDialogSvgicon = ref(null);
</script>
<template>
<md-button variant="tonal" @click="demoDialogSvgicon?.show()">Slotted icon</md-button>
<md-dialog id="demo-dialog-svgicon" ref="demoDialogSvgicon" ref="demoDialogSvgicon" ref="demoDialogSvgicon" headline="Reset your workspace?">
<svg slot="icon" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" aria-hidden="true"><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>
<p style="margin: 0;">Every panel returns to its default position. Saved layouts are untouched.</p>
<md-button slot="actions" variant="text" @click="demoDialogSvgicon?.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" @click="demoDialogSvgicon?.close()">Reset</md-button>
</md-dialog>
</template><script>
import '@awc-ui/core/define';
let demoDialogSvgicon;
let demoDialogSvgicon;
let demoDialogSvgicon;
</script>
<md-button variant="tonal" on:click={() => demoDialogSvgicon?.show()}>Slotted icon</md-button>
<md-dialog id="demo-dialog-svgicon" bind:this={demoDialogSvgicon} bind:this={demoDialogSvgicon} bind:this={demoDialogSvgicon} headline="Reset your workspace?">
<svg slot="icon" viewBox="0 0 24 24" width="24" height="24" fill="currentColor" aria-hidden="true"><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></svg>
<p style="margin: 0;">Every panel returns to its default position. Saved layouts are untouched.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogSvgicon?.close()}>Cancel</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDialogSvgicon?.close()}>Reset</md-button>
</md-dialog>scrim-dismissible defaults to true — clicking the scrim closes the
dialog. Turn it off for destructive confirmations, where an accidental
click-away shouldn’t decide anything.
Every setting returns to its default. Clicking outside will not dismiss this dialog.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-button variant="filled">Reset account</md-button>
<md-dialog id="demo-dialog-strict" headline="Reset this account?" icon="warning" scrim-dismissible="false">
<p style="margin: 0;">Every setting returns to its default. Clicking outside will not dismiss this dialog.</p>
<md-button slot="actions" variant="text">Cancel</md-button>
<md-button slot="actions" variant="filled">Reset</md-button>
</md-dialog>
<script type="module">
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-strict').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-strict').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-strict').close());
</script>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { useRef } from 'react';
import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
const demoDialogStrictRef = useRef(null);
const demoDialogStrictRef = useRef(null);
const demoDialogStrictRef = useRef(null);
return (
<>
<MdButton variant="filled" onClick={() => demoDialogStrictRef.current?.show()}>Reset account</MdButton>
<MdDialog id="demo-dialog-strict" ref={demoDialogStrictRef} ref={demoDialogStrictRef} ref={demoDialogStrictRef} headline="Reset this account?" icon="warning" scrimDismissible="false">
<p style={{ margin: '0' }}>Every setting returns to its default. Clicking outside will not dismiss this dialog.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogStrictRef.current?.close()}>Cancel</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDialogStrictRef.current?.close()}>Reset</MdButton>
</MdDialog>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-button variant="filled" (click)="demoDialogStrict.show()">Reset account</md-button>
<md-dialog id="demo-dialog-strict" #demoDialogStrict #demoDialogStrict #demoDialogStrict headline="Reset this account?" icon="warning" scrim-dismissible="false">
<p style="margin: 0;">Every setting returns to its default. Clicking outside will not dismiss this dialog.</p>
<md-button slot="actions" variant="text" (click)="demoDialogStrict.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" (click)="demoDialogStrict.close()">Reset</md-button>
</md-dialog><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { ref } from 'vue';
import '@awc-ui/core/define';
const demoDialogStrict = ref(null);
const demoDialogStrict = ref(null);
const demoDialogStrict = ref(null);
</script>
<template>
<md-button variant="filled" @click="demoDialogStrict?.show()">Reset account</md-button>
<md-dialog id="demo-dialog-strict" ref="demoDialogStrict" ref="demoDialogStrict" ref="demoDialogStrict" headline="Reset this account?" icon="warning" scrim-dismissible="false">
<p style="margin: 0;">Every setting returns to its default. Clicking outside will not dismiss this dialog.</p>
<md-button slot="actions" variant="text" @click="demoDialogStrict?.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" @click="demoDialogStrict?.close()">Reset</md-button>
</md-dialog>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
let demoDialogStrict;
let demoDialogStrict;
let demoDialogStrict;
</script>
<md-button variant="filled" on:click={() => demoDialogStrict?.show()}>Reset account</md-button>
<md-dialog id="demo-dialog-strict" bind:this={demoDialogStrict} bind:this={demoDialogStrict} bind:this={demoDialogStrict} headline="Reset this account?" icon="warning" scrim-dismissible="false">
<p style="margin: 0;">Every setting returns to its default. Clicking outside will not dismiss this dialog.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogStrict?.close()}>Cancel</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDialogStrict?.close()}>Reset</md-button>
</md-dialog>divider draws a rule between the content area and the actions row, on either
variant. header-divider draws the matching rule under the header — and it is
full-screen only: the component gates it on fullscreen, so on a basic
dialog the attribute is inert. Both earn their place when the body scrolls;
without them a scrolled body runs visually into the headline and the actions
row.
A basic dialog takes divider only — the rule sits above the actions row.
Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.
Section 4. Duis aute irure dolor in reprehenderit in voluptate velit.
Full-screen is where header-divider renders — a rule under the app bar, plus the content rule from divider.
Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-button variant="outlined">Open terms (basic)</md-button>
<md-button variant="outlined">Open terms (full-screen)</md-button>
<md-dialog id="demo-dialog-divider" headline="Terms of service" divider>
<p style="margin: 0 0 12px;">A basic dialog takes <code>divider</code> only — the rule sits above the actions row.</p>
<p style="margin: 0 0 12px;">Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p style="margin: 0 0 12px;">Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p style="margin: 0 0 12px;">Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
<p style="margin: 0;">Section 4. Duis aute irure dolor in reprehenderit in voluptate velit.</p>
<md-button slot="actions" variant="text">Decline</md-button>
<md-button slot="actions" variant="filled">Accept</md-button>
</md-dialog>
<md-dialog id="demo-dialog-divider-full" fullscreen headline="Terms of service" close-label="Close" header-divider divider>
<p style="margin: 0 0 12px;">Full-screen is where <code>header-divider</code> renders — a rule under the app bar, plus the content rule from <code>divider</code>.</p>
<p style="margin: 0 0 12px;">Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p style="margin: 0 0 12px;">Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p style="margin: 0;">Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
<md-button slot="actions" variant="text">Decline</md-button>
<md-button slot="actions" variant="filled">Accept</md-button>
</md-dialog>
<script type="module">
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-divider').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-divider-full').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-divider').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-divider').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-divider-full').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-divider-full').close());
</script>import { useRef } from 'react';
import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
const demoDialogDividerRef = useRef(null);
const demoDialogDividerFullRef = useRef(null);
const demoDialogDividerRef = useRef(null);
const demoDialogDividerRef = useRef(null);
const demoDialogDividerFullRef = useRef(null);
const demoDialogDividerFullRef = useRef(null);
return (
<>
<MdButton variant="outlined" onClick={() => demoDialogDividerRef.current?.show()}>Open terms (basic)</MdButton>
<MdButton variant="outlined" onClick={() => demoDialogDividerFullRef.current?.show()}>Open terms (full-screen)</MdButton>
<MdDialog id="demo-dialog-divider" ref={demoDialogDividerRef} ref={demoDialogDividerRef} ref={demoDialogDividerRef} headline="Terms of service" divider>
<p style={{ margin: '0 0 12px' }}>A basic dialog takes <code>divider</code> only — the rule sits above the actions row.</p>
<p style={{ margin: '0 0 12px' }}>Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p style={{ margin: '0 0 12px' }}>Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p style={{ margin: '0 0 12px' }}>Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
<p style={{ margin: '0' }}>Section 4. Duis aute irure dolor in reprehenderit in voluptate velit.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogDividerRef.current?.close()}>Decline</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDialogDividerRef.current?.close()}>Accept</MdButton>
</MdDialog>
<MdDialog id="demo-dialog-divider-full" ref={demoDialogDividerFullRef} ref={demoDialogDividerFullRef} ref={demoDialogDividerFullRef} fullscreen headline="Terms of service" closeLabel="Close" headerDivider divider>
<p style={{ margin: '0 0 12px' }}>Full-screen is where <code>header-divider</code> renders — a rule under the app bar, plus the content rule from <code>divider</code>.</p>
<p style={{ margin: '0 0 12px' }}>Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p style={{ margin: '0 0 12px' }}>Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p style={{ margin: '0' }}>Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogDividerFullRef.current?.close()}>Decline</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDialogDividerFullRef.current?.close()}>Accept</MdButton>
</MdDialog>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-button variant="outlined" (click)="demoDialogDivider.show()">Open terms (basic)</md-button>
<md-button variant="outlined" (click)="demoDialogDividerFull.show()">Open terms (full-screen)</md-button>
<md-dialog id="demo-dialog-divider" #demoDialogDivider #demoDialogDivider #demoDialogDivider headline="Terms of service" divider>
<p style="margin: 0 0 12px;">A basic dialog takes <code>divider</code> only — the rule sits above the actions row.</p>
<p style="margin: 0 0 12px;">Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p style="margin: 0 0 12px;">Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p style="margin: 0 0 12px;">Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
<p style="margin: 0;">Section 4. Duis aute irure dolor in reprehenderit in voluptate velit.</p>
<md-button slot="actions" variant="text" (click)="demoDialogDivider.close()">Decline</md-button>
<md-button slot="actions" variant="filled" (click)="demoDialogDivider.close()">Accept</md-button>
</md-dialog>
<md-dialog id="demo-dialog-divider-full" #demoDialogDividerFull #demoDialogDividerFull #demoDialogDividerFull fullscreen headline="Terms of service" close-label="Close" header-divider divider>
<p style="margin: 0 0 12px;">Full-screen is where <code>header-divider</code> renders — a rule under the app bar, plus the content rule from <code>divider</code>.</p>
<p style="margin: 0 0 12px;">Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p style="margin: 0 0 12px;">Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p style="margin: 0;">Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
<md-button slot="actions" variant="text" (click)="demoDialogDividerFull.close()">Decline</md-button>
<md-button slot="actions" variant="filled" (click)="demoDialogDividerFull.close()">Accept</md-button>
</md-dialog><script setup>
import { ref } from 'vue';
import '@awc-ui/core/define';
const demoDialogDivider = ref(null);
const demoDialogDividerFull = ref(null);
const demoDialogDivider = ref(null);
const demoDialogDivider = ref(null);
const demoDialogDividerFull = ref(null);
const demoDialogDividerFull = ref(null);
</script>
<template>
<md-button variant="outlined" @click="demoDialogDivider?.show()">Open terms (basic)</md-button>
<md-button variant="outlined" @click="demoDialogDividerFull?.show()">Open terms (full-screen)</md-button>
<md-dialog id="demo-dialog-divider" ref="demoDialogDivider" ref="demoDialogDivider" ref="demoDialogDivider" headline="Terms of service" divider>
<p style="margin: 0 0 12px;">A basic dialog takes <code>divider</code> only — the rule sits above the actions row.</p>
<p style="margin: 0 0 12px;">Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p style="margin: 0 0 12px;">Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p style="margin: 0 0 12px;">Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
<p style="margin: 0;">Section 4. Duis aute irure dolor in reprehenderit in voluptate velit.</p>
<md-button slot="actions" variant="text" @click="demoDialogDivider?.close()">Decline</md-button>
<md-button slot="actions" variant="filled" @click="demoDialogDivider?.close()">Accept</md-button>
</md-dialog>
<md-dialog id="demo-dialog-divider-full" ref="demoDialogDividerFull" ref="demoDialogDividerFull" ref="demoDialogDividerFull" fullscreen headline="Terms of service" close-label="Close" header-divider divider>
<p style="margin: 0 0 12px;">Full-screen is where <code>header-divider</code> renders — a rule under the app bar, plus the content rule from <code>divider</code>.</p>
<p style="margin: 0 0 12px;">Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p style="margin: 0 0 12px;">Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p style="margin: 0;">Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
<md-button slot="actions" variant="text" @click="demoDialogDividerFull?.close()">Decline</md-button>
<md-button slot="actions" variant="filled" @click="demoDialogDividerFull?.close()">Accept</md-button>
</md-dialog>
</template><script>
import '@awc-ui/core/define';
let demoDialogDivider;
let demoDialogDividerFull;
let demoDialogDivider;
let demoDialogDivider;
let demoDialogDividerFull;
let demoDialogDividerFull;
</script>
<md-button variant="outlined" on:click={() => demoDialogDivider?.show()}>Open terms (basic)</md-button>
<md-button variant="outlined" on:click={() => demoDialogDividerFull?.show()}>Open terms (full-screen)</md-button>
<md-dialog id="demo-dialog-divider" bind:this={demoDialogDivider} bind:this={demoDialogDivider} bind:this={demoDialogDivider} headline="Terms of service" divider>
<p style="margin: 0 0 12px;">A basic dialog takes <code>divider</code> only — the rule sits above the actions row.</p>
<p style="margin: 0 0 12px;">Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p style="margin: 0 0 12px;">Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p style="margin: 0 0 12px;">Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
<p style="margin: 0;">Section 4. Duis aute irure dolor in reprehenderit in voluptate velit.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogDivider?.close()}>Decline</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDialogDivider?.close()}>Accept</md-button>
</md-dialog>
<md-dialog id="demo-dialog-divider-full" bind:this={demoDialogDividerFull} bind:this={demoDialogDividerFull} bind:this={demoDialogDividerFull} fullscreen headline="Terms of service" close-label="Close" header-divider divider>
<p style="margin: 0 0 12px;">Full-screen is where <code>header-divider</code> renders — a rule under the app bar, plus the content rule from <code>divider</code>.</p>
<p style="margin: 0 0 12px;">Section 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p style="margin: 0 0 12px;">Section 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
<p style="margin: 0;">Section 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogDividerFull?.close()}>Decline</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDialogDividerFull?.close()}>Accept</md-button>
</md-dialog>fullscreen is the mobile sub-task form: an app bar with the headline, a close
button, and the body filling the viewport.
Long headlines belong here in the body, not in the app bar.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-button variant="filled" id="new-event">New event</md-button>
<md-dialog id="event" fullscreen headline="New event" close-label="Close">
<h2>Create a calendar event</h2>
<md-text-field label="Title"></md-text-field>
<md-button slot="actions" variant="text" data-close>Cancel</md-button>
<md-button slot="actions" variant="filled" disabled>Create</md-button>
</md-dialog>
<script type="module">
const dialog = document.getElementById('event');
document.getElementById('new-event').addEventListener('mdClick', () => dialog.show());
dialog.querySelectorAll('[data-close]').forEach((b) =>
b.addEventListener('mdClick', () => dialog.close()),
);
</script>import { useEffect, useRef } from 'react';
import { MdButton, MdDialog, MdTextField } from '@awc-ui/react';
export function Demo() {
const dialogRef = useRef(null);
useEffect(() => {
const dialog = dialogRef.current;
document.getElementById('new-event').addEventListener('mdClick', () => dialog.show());
dialog.querySelectorAll('[data-close]').forEach((b) =>
b.addEventListener('mdClick', () => dialog.close()),
);
}, []);
return (
<>
<MdButton variant="filled" id="new-event">New event</MdButton>
<MdDialog id="event" ref={dialogRef} fullscreen headline="New event" closeLabel="Close">
<h2>Create a calendar event</h2>
<MdTextField label="Title"></MdTextField>
<MdButton slot="actions" variant="text" data-close>Cancel</MdButton>
<MdButton slot="actions" variant="filled" disabled>Create</MdButton>
</MdDialog>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
// app.component.ts
import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';
@Component({
selector: 'app-demo',
templateUrl: './app.component.html',
})
export class DemoComponent implements AfterViewInit {
@ViewChild('dialog') dialogRef!: ElementRef;
ngAfterViewInit() {
const dialog = this.dialogRef.nativeElement;
document.getElementById('new-event').addEventListener('mdClick', () => dialog.show());
dialog.querySelectorAll('[data-close]').forEach((b) =>
b.addEventListener('mdClick', () => dialog.close()),
);
}
}
<!-- app.component.html -->
<md-button variant="filled" id="new-event">New event</md-button>
<md-dialog id="event" #dialog fullscreen headline="New event" close-label="Close">
<h2>Create a calendar event</h2>
<md-text-field label="Title"></md-text-field>
<md-button slot="actions" variant="text" data-close>Cancel</md-button>
<md-button slot="actions" variant="filled" disabled>Create</md-button>
</md-dialog><script setup>
import { onMounted, ref } from 'vue';
import '@awc-ui/core/define';
const dialogRef = ref(null);
onMounted(() => {
const dialog = dialogRef.value;
document.getElementById('new-event').addEventListener('mdClick', () => dialog.show());
dialog.querySelectorAll('[data-close]').forEach((b) =>
b.addEventListener('mdClick', () => dialog.close()),
);
});
</script>
<template>
<md-button variant="filled" id="new-event">New event</md-button>
<md-dialog id="event" ref="dialogRef" fullscreen headline="New event" close-label="Close">
<h2>Create a calendar event</h2>
<md-text-field label="Title"></md-text-field>
<md-button slot="actions" variant="text" data-close>Cancel</md-button>
<md-button slot="actions" variant="filled" disabled>Create</md-button>
</md-dialog>
</template><script>
import { onMount } from 'svelte';
import '@awc-ui/core/define';
let dialogRef;
onMount(() => {
const dialog = dialogRef;
document.getElementById('new-event').addEventListener('mdClick', () => dialog.show());
dialog.querySelectorAll('[data-close]').forEach((b) =>
b.addEventListener('mdClick', () => dialog.close()),
);
});
</script>
<md-button variant="filled" id="new-event">New event</md-button>
<md-dialog id="event" bind:this={dialogRef} fullscreen headline="New event" close-label="Close">
<h2>Create a calendar event</h2>
<md-text-field label="Title"></md-text-field>
<md-button slot="actions" variant="text" data-close>Cancel</md-button>
<md-button slot="actions" variant="filled" disabled>Create</md-button>
</md-dialog>open is two-way: assign it to drive the dialog from your own state, and read
it back after a user dismissal. show() / close() do the same thing
imperatively — pick one and stay with it, because mixing them is how state ends
up disagreeing with what is on screen. To mirror the state elsewhere in your UI,
listen for mdOpen / mdClose (see Events) rather than polling the
property; a scrim dismissal or Escape changes it without going through your
button.
This dialog was opened by assigning open, not by calling show() — and the action below closes it the same way.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-button variant="filled" onclick="document.getElementById('demo-dialog-ctl').open = true">Open by setting open = true</md-button>
<md-dialog id="demo-dialog-ctl" headline="Driven by the prop">
<p style="margin: 0;">This dialog was opened by assigning <code>open</code>, not by calling <code>show()</code> — and the action below closes it the same way.</p>
<md-button slot="actions" variant="text" onclick="document.getElementById('demo-dialog-ctl').open = false">Set open = false</md-button>
</md-dialog>import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
return (
<>
<MdButton variant="filled" onclick="document.getElementById('demo-dialog-ctl').open = true">Open by setting open = true</MdButton>
<MdDialog id="demo-dialog-ctl" headline="Driven by the prop">
<p style={{ margin: '0' }}>This dialog was opened by assigning <code>open</code>, not by calling <code>show()</code> — and the action below closes it the same way.</p>
<MdButton slot="actions" variant="text" onclick="document.getElementById('demo-dialog-ctl').open = false">Set open = false</MdButton>
</MdDialog>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-button variant="filled" onclick="document.getElementById('demo-dialog-ctl').open = true">Open by setting open = true</md-button>
<md-dialog id="demo-dialog-ctl" headline="Driven by the prop">
<p style="margin: 0;">This dialog was opened by assigning <code>open</code>, not by calling <code>show()</code> — and the action below closes it the same way.</p>
<md-button slot="actions" variant="text" onclick="document.getElementById('demo-dialog-ctl').open = false">Set open = false</md-button>
</md-dialog><script setup>
import '@awc-ui/core/define';
</script>
<template>
<md-button variant="filled" onclick="document.getElementById('demo-dialog-ctl').open = true">Open by setting open = true</md-button>
<md-dialog id="demo-dialog-ctl" headline="Driven by the prop">
<p style="margin: 0;">This dialog was opened by assigning <code>open</code>, not by calling <code>show()</code> — and the action below closes it the same way.</p>
<md-button slot="actions" variant="text" onclick="document.getElementById('demo-dialog-ctl').open = false">Set open = false</md-button>
</md-dialog>
</template><script>
import '@awc-ui/core/define';
</script>
<md-button variant="filled" onclick="document.getElementById('demo-dialog-ctl').open = true">Open by setting open = true</md-button>
<md-dialog id="demo-dialog-ctl" headline="Driven by the prop">
<p style="margin: 0;">This dialog was opened by assigning <code>open</code>, not by calling <code>show()</code> — and the action below closes it the same way.</p>
<md-button slot="actions" variant="text" onclick="document.getElementById('demo-dialog-ctl').open = false">Set open = false</md-button>
</md-dialog>| Event | Cancelable | Detail | Fires |
|---|---|---|---|
mdOpen | no | void | The dialog opened |
mdClose | no | void | The dialog closed, for any reason |
mdCancel | no | void | The user dismissed it — Escape, scrim click, or the close button |
They overlap on purpose. Every dismissal fires both, in this order:
mdCancel, then mdClose. mdClose is the superset — it also covers your own
close() call and an open = false assignment. mdCancel is the narrow one
that means the user backed out, and it is the only way to tell a dismissal
apart from a confirmation, because the component itself doesn’t know which of
your slotted buttons meant what.
Neither event is cancelable, so neither can veto a close. They report; they don’t gate.
| You want to… | Listen to |
|---|---|
| Tear down or resync whenever the dialog goes away | mdClose |
Mirror open back into your own state | mdClose |
| Treat “backed out” differently from “confirmed” | mdCancel |
Log an explicit dismissal — Escape, scrim, close button | mdCancel |
| Run something once per dismissal | mdCancel alone — not both |
| Block a close | Neither. Set scrim-dismissible="false"; Escape always closes |
Methods — show() and close() drive the dialog imperatively; open is
the declarative equivalent.
All three events bubble and are composed, so a single listener on the dialog — or on an ancestor of it — catches every one. Open the dialog below and close it four different ways; the log records what fired.
Close me with Discard, with Cancel, with Escape, or by clicking the scrim — then read the log underneath.
<md-button id="open" variant="filled">Open the dialog</md-button>
<md-dialog id="confirm" headline="Discard draft?" icon="delete">
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text" data-close>Cancel</md-button>
<md-button slot="actions" variant="filled" data-close>Discard</md-button>
</md-dialog>
<script type="module">
const dialog = document.getElementById('confirm');
document.getElementById('open').addEventListener('mdClick', () => dialog.show());
dialog.querySelectorAll('[data-close]').forEach((b) =>
b.addEventListener('mdClick', () => dialog.close()),
);
dialog.addEventListener('mdOpen', () => console.log('opened'));
dialog.addEventListener('mdCancel', () => console.log('dismissed'));
dialog.addEventListener('mdClose', () => console.log('closed'));
</script>import { MdButton, MdDialog } from '@awc-ui/react';
import { useState } from 'react';
export function DiscardDialog() {
const [open, setOpen] = useState(false);
return (
<>
<MdButton variant="filled" onMdClick={() => setOpen(true)}>Open the dialog</MdButton>
<MdDialog
open={open}
headline="Discard draft?"
icon="delete"
onMdOpen={() => console.log('opened')}
onMdCancel={() => console.log('dismissed')}
onMdClose={() => setOpen(false)}
>
<p>Your changes will be lost.</p>
<MdButton slot="actions" variant="text" onMdClick={() => setOpen(false)}>Cancel</MdButton>
<MdButton slot="actions" variant="filled" onMdClick={() => setOpen(false)}>Discard</MdButton>
</MdDialog>
</>
);
}import { Component } from '@angular/core';
@Component({
selector: 'app-discard-dialog',
template: `
<md-button variant="filled" (mdClick)="open = true">Open the dialog</md-button>
<md-dialog
[open]="open"
headline="Discard draft?"
icon="delete"
(mdOpen)="log('opened')"
(mdCancel)="log('dismissed')"
(mdClose)="open = false"
>
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text" (mdClick)="open = false">Cancel</md-button>
<md-button slot="actions" variant="filled" (mdClick)="open = false">Discard</md-button>
</md-dialog>
`,
})
export class DiscardDialogComponent {
open = false;
log(what: string) { console.log(what); }
}<script setup lang="ts">
import { ref } from 'vue';
const open = ref(false);
const log = (what: string) => console.log(what);
</script>
<template>
<md-button variant="filled" @mdClick="open = true">Open the dialog</md-button>
<md-dialog
:open="open"
headline="Discard draft?"
icon="delete"
@mdOpen="log('opened')"
@mdCancel="log('dismissed')"
@mdClose="open = false"
>
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text" @mdClick="open = false">Cancel</md-button>
<md-button slot="actions" variant="filled" @mdClick="open = false">Discard</md-button>
</md-dialog>
</template><script lang="ts">
let open = false;
const log = (what: string) => console.log(what);
</script>
<md-button variant="filled" on:mdClick={() => (open = true)}>Open the dialog</md-button>
<md-dialog
{open}
headline="Discard draft?"
icon="delete"
on:mdOpen={() => log('opened')}
on:mdCancel={() => log('dismissed')}
on:mdClose={() => (open = false)}
>
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text" on:mdClick={() => (open = false)}>Cancel</md-button>
<md-button slot="actions" variant="filled" on:mdClick={() => (open = false)}>Discard</md-button>
</md-dialog>That same wiring inside a real destructive confirmation — click-away turned off,
open owned by your state, and the discard branch doing actual work:
<md-button id="trigger" variant="filled">Discard draft</md-button>
<md-dialog id="confirm" headline="Discard draft?" icon="delete" scrim-dismissible="false">
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text" id="cancel">Cancel</md-button>
<md-button slot="actions" variant="filled" id="discard">Discard</md-button>
</md-dialog>
<script type="module">
const dlg = document.getElementById('confirm');
document.getElementById('trigger').addEventListener('click', () => dlg.show());
document.getElementById('cancel').addEventListener('mdClick', () => dlg.close());
document.getElementById('discard').addEventListener('mdClick', () => {
discardDraft();
dlg.close();
});
dlg.addEventListener('mdCancel', () => console.log('dismissed'));
dlg.addEventListener('mdClose', () => restoreFocusToTrigger());
</script>import { MdButton, MdDialog } from '@awc-ui/react';
import { useState } from 'react';
export function DiscardConfirm({ onDiscard }: { onDiscard: () => void }) {
const [open, setOpen] = useState(false);
return (
<>
<MdButton variant="filled" onClick={() => setOpen(true)}>Discard draft</MdButton>
<MdDialog
open={open}
headline="Discard draft?"
icon="delete"
scrimDismissible={false}
onMdCancel={() => console.log('dismissed')}
onMdClose={() => setOpen(false)}
>
<p>Your changes will be lost.</p>
<MdButton slot="actions" variant="text" onClick={() => setOpen(false)}>Cancel</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => { onDiscard(); setOpen(false); }}>
Discard
</MdButton>
</MdDialog>
</>
);
}import { Component } from '@angular/core';
@Component({
selector: 'app-discard-confirm',
template: `
<md-button variant="filled" (click)="open = true">Discard draft</md-button>
<md-dialog
[open]="open"
headline="Discard draft?"
icon="delete"
[scrimDismissible]="false"
(mdCancel)="onCancel()"
(mdClose)="open = false"
>
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text" (mdClick)="open = false">Cancel</md-button>
<md-button slot="actions" variant="filled" (mdClick)="discard()">Discard</md-button>
</md-dialog>
`,
})
export class DiscardConfirmComponent {
open = false;
onCancel() { console.log('dismissed'); }
discard() { /* your logic */ this.open = false; }
}<script setup lang="ts">
import { ref } from 'vue';
const open = ref(false);
</script>
<template>
<md-button variant="filled" @click="open = true">Discard draft</md-button>
<md-dialog
:open="open"
headline="Discard draft?"
icon="delete"
:scrim-dismissible="false"
@mdCancel="console.log('dismissed')"
@mdClose="open = false"
>
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text" @mdClick="open = false">Cancel</md-button>
<md-button slot="actions" variant="filled" @mdClick="open = false">Discard</md-button>
</md-dialog>
</template><script lang="ts">
let open = false;
</script>
<md-button variant="filled" on:click={() => (open = true)}>Discard draft</md-button>
<md-dialog
{open}
headline="Discard draft?"
icon="delete"
scrim-dismissible="false"
on:mdCancel={() => console.log('dismissed')}
on:mdClose={() => (open = false)}
>
<p>Your changes will be lost.</p>
<md-button slot="actions" variant="text" on:mdClick={() => (open = false)}>Cancel</md-button>
<md-button slot="actions" variant="filled" on:mdClick={() => (open = false)}>Discard</md-button>
</md-dialog>| Property | Attribute | Type | Default | Reflects |
|---|---|---|---|---|
open | open | boolean | false | Yes |
headline | headline | string | '' | — |
icon | icon | string | '' | — |
fullscreen | fullscreen | boolean | false | Yes |
scrimDismissible | scrim-dismissible | boolean | true | — |
locale | locale | string | 'en-US' | — |
closeLabel | close-label | string | '' | — |
cancelLabel | cancel-label | string | '' | — |
okLabel | ok-label | string | '' | — |
divider | divider | boolean | false | Yes |
headerDivider | header-divider | boolean | false | Yes |
density | density | 0 | -1 | -2 | -3 | -4 | 0 | Yes |
| Method | Parameters |
|---|---|
show() | none |
close() | none |
| Slot | Description |
|---|---|
(default) | — |
actions | Action buttons |
header-action | Full-screen header action (e.g. Save button) |
icon | Custom icon (replaces icon prop) |
headline | Custom headline content |
Override on the host element for per-instance theming:
| Property | Description |
|---|---|
--md-dialog-container-color | Container background |
--md-dialog-container-shape | Container corner radius |
--md-dialog-headline-color | Headline text color |
--md-dialog-content-color | Supporting text color |
--md-dialog-icon-color | Icon color |
--md-dialog-icon-size | Icon dimensions |
--md-dialog-scrim-color | Scrim overlay color |
--md-dialog-divider-color | Divider color |
--md-dialog-z-index | Surface z-index (default near int32 max) |
--md-dialog-scrim-z-index | Scrim z-index (one below the surface) |
Style internal elements through shadow DOM with ::part():
| Part | Description |
|---|---|
actions | Action buttons row |
cancel-button | Default cancel button (slot fallback) |
ok-button | Default confirm button (slot fallback) |
scrim | Scrim overlay (basic only) |
container | Dialog surface |
header | Header area (both variants) |
close-button | Close button (full-screen) |
headline | Headline text |
divider | Horizontal divider |
icon | Icon element (basic) |
content | Supporting text / body |
Escape dismisses (firing mdCancel). Don’t try to
keep background controls reachable.preventScroll so the page
never jumps. You don’t need an mdClose handler for it — use mdClose for
whatever else the surrounding UI has to resync.headline supplies the accessible name. If you slot a custom headline, make
sure the dialog still ends up with one.fullscreen dialog, give the app-bar close button a localized name via
close-label. A basic dialog has no close button, so the prop does nothing
there.Open this one and hold Tab down: focus cycles through the field and the two
actions and never reaches the page behind the scrim. Press Escape and focus
lands back on the button you pressed — the component does that itself.
The field and both buttons are the whole tab cycle. Nothing behind the scrim is reachable.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-button variant="filled" id="rename">Rename project</md-button>
<md-dialog id="rename-dialog" headline="Rename project" icon="edit">
<md-text-field label="Project name" value="Untitled"></md-text-field>
<md-button slot="actions" variant="text" data-close>Cancel</md-button>
<md-button slot="actions" variant="filled" data-close>Rename</md-button>
</md-dialog>
<script type="module">
const trigger = document.getElementById('rename');
const dialog = document.getElementById('rename-dialog');
trigger.addEventListener('mdClick', () => dialog.show());
dialog.querySelectorAll('[data-close]').forEach((b) =>
b.addEventListener('mdClick', () => dialog.close()),
);
// Focus is restored to the opener for you. Use mdClose for anything else
// the surrounding UI needs to resync after any close.
dialog.addEventListener('mdClose', () => refreshProjectList());
</script>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { useEffect, useRef } from 'react';
import { MdButton, MdDialog, MdTextField } from '@awc-ui/react';
export function Demo() {
const triggerRef = useRef(null);
const dialogRef = useRef(null);
useEffect(() => {
const trigger = triggerRef.current;
const dialog = dialogRef.current;
trigger.addEventListener('mdClick', () => dialog.show());
dialog.querySelectorAll('[data-close]').forEach((b) =>
b.addEventListener('mdClick', () => dialog.close()),
);
// Focus is restored to the opener for you. Use mdClose for anything else
// the surrounding UI needs to resync after any close.
dialog.addEventListener('mdClose', () => refreshProjectList());
}, []);
return (
<>
<MdButton variant="filled" id="rename" ref={triggerRef}>Rename project</MdButton>
<MdDialog id="rename-dialog" ref={dialogRef} headline="Rename project" icon="edit">
<MdTextField label="Project name" value="Untitled"></MdTextField>
<MdButton slot="actions" variant="text" data-close>Cancel</MdButton>
<MdButton slot="actions" variant="filled" data-close>Rename</MdButton>
</MdDialog>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
// app.component.ts
import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';
@Component({
selector: 'app-demo',
templateUrl: './app.component.html',
})
export class DemoComponent implements AfterViewInit {
@ViewChild('trigger') triggerRef!: ElementRef;
@ViewChild('dialog') dialogRef!: ElementRef;
ngAfterViewInit() {
const trigger = this.triggerRef.nativeElement;
const dialog = this.dialogRef.nativeElement;
trigger.addEventListener('mdClick', () => dialog.show());
dialog.querySelectorAll('[data-close]').forEach((b) =>
b.addEventListener('mdClick', () => dialog.close()),
);
// Focus is restored to the opener for you. Use mdClose for anything else
// the surrounding UI needs to resync after any close.
dialog.addEventListener('mdClose', () => refreshProjectList());
}
}
<!-- app.component.html -->
<md-button variant="filled" id="rename" #trigger>Rename project</md-button>
<md-dialog id="rename-dialog" #dialog headline="Rename project" icon="edit">
<md-text-field label="Project name" value="Untitled"></md-text-field>
<md-button slot="actions" variant="text" data-close>Cancel</md-button>
<md-button slot="actions" variant="filled" data-close>Rename</md-button>
</md-dialog><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { onMounted, ref } from 'vue';
import '@awc-ui/core/define';
const triggerRef = ref(null);
const dialogRef = ref(null);
onMounted(() => {
const trigger = triggerRef.value;
const dialog = dialogRef.value;
trigger.addEventListener('mdClick', () => dialog.show());
dialog.querySelectorAll('[data-close]').forEach((b) =>
b.addEventListener('mdClick', () => dialog.close()),
);
// Focus is restored to the opener for you. Use mdClose for anything else
// the surrounding UI needs to resync after any close.
dialog.addEventListener('mdClose', () => refreshProjectList());
});
</script>
<template>
<md-button variant="filled" id="rename" ref="triggerRef">Rename project</md-button>
<md-dialog id="rename-dialog" ref="dialogRef" headline="Rename project" icon="edit">
<md-text-field label="Project name" value="Untitled"></md-text-field>
<md-button slot="actions" variant="text" data-close>Cancel</md-button>
<md-button slot="actions" variant="filled" data-close>Rename</md-button>
</md-dialog>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { onMount } from 'svelte';
import '@awc-ui/core/define';
let triggerRef;
let dialogRef;
onMount(() => {
const trigger = triggerRef;
const dialog = dialogRef;
trigger.addEventListener('mdClick', () => dialog.show());
dialog.querySelectorAll('[data-close]').forEach((b) =>
b.addEventListener('mdClick', () => dialog.close()),
);
// Focus is restored to the opener for you. Use mdClose for anything else
// the surrounding UI needs to resync after any close.
dialog.addEventListener('mdClose', () => refreshProjectList());
});
</script>
<md-button variant="filled" id="rename" bind:this={triggerRef}>Rename project</md-button>
<md-dialog id="rename-dialog" bind:this={dialogRef} headline="Rename project" icon="edit">
<md-text-field label="Project name" value="Untitled"></md-text-field>
<md-button slot="actions" variant="text" data-close>Cancel</md-button>
<md-button slot="actions" variant="filled" data-close>Rename</md-button>
</md-dialog>The trap reaches into slotted custom elements: the <input> inside
md-text-field is a real tab stop even though it lives behind a shadow
boundary. role follows the variant — a basic dialog is an alertdialog, a
fullscreen one is a plain dialog.
The accessibility story walks the focus trap, the restored focus target and the announced role, and responsiveness covers narrow viewports.
RTL — the container and the actions row mirror under dir="rtl".
“Dismissive on the left” means leading, so it lands on the right in RTL
automatically. Don’t hardcode a side. See RTL.
<md-dialog dir="rtl" headline="حذف الملف؟" icon="delete"> <md-button slot="actions" variant="text">إلغاء</md-button> <md-button slot="actions" variant="filled">حذف</md-button></md-dialog>This cannot be undone.
لا يمكن التراجع عن هذا الإجراء.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">ltr</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled">Delete file</md-button>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">rtl</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled">حذف الملف</md-button>
</div>
</div>
<md-dialog id="demo-dialog-ltr" headline="Delete file?" icon="delete">
<p style="margin: 0;">This cannot be undone.</p>
<md-button slot="actions" variant="text">Cancel</md-button>
<md-button slot="actions" variant="filled">Delete</md-button>
</md-dialog>
<md-dialog id="demo-dialog-rtl" dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">لا يمكن التراجع عن هذا الإجراء.</p>
<md-button slot="actions" variant="text">إلغاء</md-button>
<md-button slot="actions" variant="filled">حذف</md-button>
</md-dialog>
<script type="module">
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-ltr').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-rtl').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-ltr').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-ltr').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-rtl').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-rtl').close());
</script>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { useRef } from 'react';
import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
const demoDialogLtrRef = useRef(null);
const demoDialogRtlRef = useRef(null);
const demoDialogLtrRef = useRef(null);
const demoDialogLtrRef = useRef(null);
const demoDialogRtlRef = useRef(null);
const demoDialogRtlRef = useRef(null);
return (
<>
<div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '14px 16px', alignItems: 'center' }}>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>ltr</span>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px' }}>
<MdButton variant="filled" onClick={() => demoDialogLtrRef.current?.show()}>Delete file</MdButton>
</div>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>rtl</span>
<div dir="rtl" style={{ display: 'flex', flexWrap: 'wrap', gap: '12px' }}>
<MdButton variant="filled" onClick={() => demoDialogRtlRef.current?.show()}>حذف الملف</MdButton>
</div>
</div>
<MdDialog id="demo-dialog-ltr" ref={demoDialogLtrRef} ref={demoDialogLtrRef} ref={demoDialogLtrRef} headline="Delete file?" icon="delete">
<p style={{ margin: '0' }}>This cannot be undone.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogLtrRef.current?.close()}>Cancel</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDialogLtrRef.current?.close()}>Delete</MdButton>
</MdDialog>
<MdDialog id="demo-dialog-rtl" ref={demoDialogRtlRef} ref={demoDialogRtlRef} ref={demoDialogRtlRef} dir="rtl" headline="حذف الملف؟" icon="delete">
<p style={{ margin: '0' }}>لا يمكن التراجع عن هذا الإجراء.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogRtlRef.current?.close()}>إلغاء</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDialogRtlRef.current?.close()}>حذف</MdButton>
</MdDialog>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">ltr</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" (click)="demoDialogLtr.show()">Delete file</md-button>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">rtl</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" (click)="demoDialogRtl.show()">حذف الملف</md-button>
</div>
</div>
<md-dialog id="demo-dialog-ltr" #demoDialogLtr #demoDialogLtr #demoDialogLtr headline="Delete file?" icon="delete">
<p style="margin: 0;">This cannot be undone.</p>
<md-button slot="actions" variant="text" (click)="demoDialogLtr.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" (click)="demoDialogLtr.close()">Delete</md-button>
</md-dialog>
<md-dialog id="demo-dialog-rtl" #demoDialogRtl #demoDialogRtl #demoDialogRtl dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">لا يمكن التراجع عن هذا الإجراء.</p>
<md-button slot="actions" variant="text" (click)="demoDialogRtl.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" (click)="demoDialogRtl.close()">حذف</md-button>
</md-dialog><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { ref } from 'vue';
import '@awc-ui/core/define';
const demoDialogLtr = ref(null);
const demoDialogRtl = ref(null);
const demoDialogLtr = ref(null);
const demoDialogLtr = ref(null);
const demoDialogRtl = ref(null);
const demoDialogRtl = ref(null);
</script>
<template>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">ltr</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" @click="demoDialogLtr?.show()">Delete file</md-button>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">rtl</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" @click="demoDialogRtl?.show()">حذف الملف</md-button>
</div>
</div>
<md-dialog id="demo-dialog-ltr" ref="demoDialogLtr" ref="demoDialogLtr" ref="demoDialogLtr" headline="Delete file?" icon="delete">
<p style="margin: 0;">This cannot be undone.</p>
<md-button slot="actions" variant="text" @click="demoDialogLtr?.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" @click="demoDialogLtr?.close()">Delete</md-button>
</md-dialog>
<md-dialog id="demo-dialog-rtl" ref="demoDialogRtl" ref="demoDialogRtl" ref="demoDialogRtl" dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">لا يمكن التراجع عن هذا الإجراء.</p>
<md-button slot="actions" variant="text" @click="demoDialogRtl?.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" @click="demoDialogRtl?.close()">حذف</md-button>
</md-dialog>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
let demoDialogLtr;
let demoDialogRtl;
let demoDialogLtr;
let demoDialogLtr;
let demoDialogRtl;
let demoDialogRtl;
</script>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">ltr</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" on:click={() => demoDialogLtr?.show()}>Delete file</md-button>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">rtl</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" on:click={() => demoDialogRtl?.show()}>حذف الملف</md-button>
</div>
</div>
<md-dialog id="demo-dialog-ltr" bind:this={demoDialogLtr} bind:this={demoDialogLtr} bind:this={demoDialogLtr} headline="Delete file?" icon="delete">
<p style="margin: 0;">This cannot be undone.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogLtr?.close()}>Cancel</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDialogLtr?.close()}>Delete</md-button>
</md-dialog>
<md-dialog id="demo-dialog-rtl" bind:this={demoDialogRtl} bind:this={demoDialogRtl} bind:this={demoDialogRtl} dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">لا يمكن التراجع عن هذا الإجراء.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogRtl?.close()}>إلغاء</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDialogRtl?.close()}>حذف</md-button>
</md-dialog>The pair mirrors because the actions row is a logical-direction flex row and
your slotted buttons keep their DOM order. Force a physical side — with
::part(actions) and row-reverse, say — and RTL breaks: the confirming action
ends up where the dismissive one belongs.
الإجراء الرافض في الجهة الأمامية — تلقائياً.
نفس ترتيب العناصر، لكن الصف مقلوب يدوياً — والنتيجة خاطئة.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<style>
#demo-dialog-rtl-wrong::part(actions) { flex-direction: row-reverse; }
</style>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">correct</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled">DOM order only</md-button>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">wrong</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="outlined">Hardcoded row-reverse</md-button>
</div>
</div>
<md-dialog id="demo-dialog-rtl-right" dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">الإجراء الرافض في الجهة الأمامية — تلقائياً.</p>
<md-button slot="actions" variant="text">إلغاء</md-button>
<md-button slot="actions" variant="filled">حذف</md-button>
</md-dialog>
<md-dialog id="demo-dialog-rtl-wrong" dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">نفس ترتيب العناصر، لكن الصف مقلوب يدوياً — والنتيجة خاطئة.</p>
<md-button slot="actions" variant="text">إلغاء</md-button>
<md-button slot="actions" variant="filled">حذف</md-button>
</md-dialog>
<script type="module">
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-rtl-right').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-rtl-wrong').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-rtl-right').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-rtl-right').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-rtl-wrong').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-rtl-wrong').close());
</script>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { useRef } from 'react';
import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
const demoDialogRtlRightRef = useRef(null);
const demoDialogRtlWrongRef = useRef(null);
const demoDialogRtlRightRef = useRef(null);
const demoDialogRtlRightRef = useRef(null);
const demoDialogRtlWrongRef = useRef(null);
const demoDialogRtlWrongRef = useRef(null);
return (
<>
<style>
#demo-dialog-rtl-wrong::part(actions) { flex-direction: row-reverse; }
</style>
<div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '14px 16px', alignItems: 'center' }}>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>correct</span>
<div dir="rtl" style={{ display: 'flex', flexWrap: 'wrap', gap: '12px' }}>
<MdButton variant="filled" onClick={() => demoDialogRtlRightRef.current?.show()}>DOM order only</MdButton>
</div>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>wrong</span>
<div dir="rtl" style={{ display: 'flex', flexWrap: 'wrap', gap: '12px' }}>
<MdButton variant="outlined" onClick={() => demoDialogRtlWrongRef.current?.show()}>Hardcoded row-reverse</MdButton>
</div>
</div>
<MdDialog id="demo-dialog-rtl-right" ref={demoDialogRtlRightRef} ref={demoDialogRtlRightRef} ref={demoDialogRtlRightRef} dir="rtl" headline="حذف الملف؟" icon="delete">
<p style={{ margin: '0' }}>الإجراء الرافض في الجهة الأمامية — تلقائياً.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogRtlRightRef.current?.close()}>إلغاء</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDialogRtlRightRef.current?.close()}>حذف</MdButton>
</MdDialog>
<MdDialog id="demo-dialog-rtl-wrong" ref={demoDialogRtlWrongRef} ref={demoDialogRtlWrongRef} ref={demoDialogRtlWrongRef} dir="rtl" headline="حذف الملف؟" icon="delete">
<p style={{ margin: '0' }}>نفس ترتيب العناصر، لكن الصف مقلوب يدوياً — والنتيجة خاطئة.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogRtlWrongRef.current?.close()}>إلغاء</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDialogRtlWrongRef.current?.close()}>حذف</MdButton>
</MdDialog>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<style>
#demo-dialog-rtl-wrong::part(actions) { flex-direction: row-reverse; }
</style>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">correct</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" (click)="demoDialogRtlRight.show()">DOM order only</md-button>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">wrong</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="outlined" (click)="demoDialogRtlWrong.show()">Hardcoded row-reverse</md-button>
</div>
</div>
<md-dialog id="demo-dialog-rtl-right" #demoDialogRtlRight #demoDialogRtlRight #demoDialogRtlRight dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">الإجراء الرافض في الجهة الأمامية — تلقائياً.</p>
<md-button slot="actions" variant="text" (click)="demoDialogRtlRight.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" (click)="demoDialogRtlRight.close()">حذف</md-button>
</md-dialog>
<md-dialog id="demo-dialog-rtl-wrong" #demoDialogRtlWrong #demoDialogRtlWrong #demoDialogRtlWrong dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">نفس ترتيب العناصر، لكن الصف مقلوب يدوياً — والنتيجة خاطئة.</p>
<md-button slot="actions" variant="text" (click)="demoDialogRtlWrong.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" (click)="demoDialogRtlWrong.close()">حذف</md-button>
</md-dialog><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { ref } from 'vue';
import '@awc-ui/core/define';
const demoDialogRtlRight = ref(null);
const demoDialogRtlWrong = ref(null);
const demoDialogRtlRight = ref(null);
const demoDialogRtlRight = ref(null);
const demoDialogRtlWrong = ref(null);
const demoDialogRtlWrong = ref(null);
</script>
<template>
<style>
#demo-dialog-rtl-wrong::part(actions) { flex-direction: row-reverse; }
</style>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">correct</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" @click="demoDialogRtlRight?.show()">DOM order only</md-button>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">wrong</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="outlined" @click="demoDialogRtlWrong?.show()">Hardcoded row-reverse</md-button>
</div>
</div>
<md-dialog id="demo-dialog-rtl-right" ref="demoDialogRtlRight" ref="demoDialogRtlRight" ref="demoDialogRtlRight" dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">الإجراء الرافض في الجهة الأمامية — تلقائياً.</p>
<md-button slot="actions" variant="text" @click="demoDialogRtlRight?.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" @click="demoDialogRtlRight?.close()">حذف</md-button>
</md-dialog>
<md-dialog id="demo-dialog-rtl-wrong" ref="demoDialogRtlWrong" ref="demoDialogRtlWrong" ref="demoDialogRtlWrong" dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">نفس ترتيب العناصر، لكن الصف مقلوب يدوياً — والنتيجة خاطئة.</p>
<md-button slot="actions" variant="text" @click="demoDialogRtlWrong?.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" @click="demoDialogRtlWrong?.close()">حذف</md-button>
</md-dialog>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
let demoDialogRtlRight;
let demoDialogRtlWrong;
let demoDialogRtlRight;
let demoDialogRtlRight;
let demoDialogRtlWrong;
let demoDialogRtlWrong;
</script>
<style>
#demo-dialog-rtl-wrong::part(actions) { flex-direction: row-reverse; }
</style>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">correct</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" on:click={() => demoDialogRtlRight?.show()}>DOM order only</md-button>
</div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">wrong</span>
<div dir="rtl" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="outlined" on:click={() => demoDialogRtlWrong?.show()}>Hardcoded row-reverse</md-button>
</div>
</div>
<md-dialog id="demo-dialog-rtl-right" bind:this={demoDialogRtlRight} bind:this={demoDialogRtlRight} bind:this={demoDialogRtlRight} dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">الإجراء الرافض في الجهة الأمامية — تلقائياً.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogRtlRight?.close()}>إلغاء</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDialogRtlRight?.close()}>حذف</md-button>
</md-dialog>
<md-dialog id="demo-dialog-rtl-wrong" bind:this={demoDialogRtlWrong} bind:this={demoDialogRtlWrong} bind:this={demoDialogRtlWrong} dir="rtl" headline="حذف الملف؟" icon="delete">
<p style="margin: 0;">نفس ترتيب العناصر، لكن الصف مقلوب يدوياً — والنتيجة خاطئة.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogRtlWrong?.close()}>إلغاء</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDialogRtlWrong?.close()}>حذف</md-button>
</md-dialog>density="-1…-4" is a local override of the inherited data-density. The
resting state is simply no density attribute — there is no [density="0"]
rule to opt back in with (see the caution below). All five steps, same dialog,
so the taper — inset, headline size, corner radius and the actions row — is
visible in one place:
Inset, headline size, corner radius and the actions row all taper together.
Inset, headline size, corner radius and the actions row all taper together.
Inset, headline size, corner radius and the actions row all taper together.
Inset, headline size, corner radius and the actions row all taper together.
Inset, headline size, corner radius and the actions row all taper together.
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">default</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="filled">Open default</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-1</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined">Open rung -1</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-2</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined">Open rung -2</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-3</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined">Open rung -3</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-4</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined">Open rung -4</md-button></div>
</div>
<md-dialog id="demo-dlg-d0" headline="Default density"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d1" density="-1" headline="Density -1"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d2" density="-2" headline="Density -2"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d3" density="-3" headline="Density -3"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d4" density="-4" headline="Density -4"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text">Close</md-button></md-dialog>
<script type="module">
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-d0').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-d1').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-d2').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-d3').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-d4').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-d0').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-d1').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-d2').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-d3').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-d4').close());
</script>import { useRef } from 'react';
import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
const demoDlgD0Ref = useRef(null);
const demoDlgD1Ref = useRef(null);
const demoDlgD2Ref = useRef(null);
const demoDlgD3Ref = useRef(null);
const demoDlgD4Ref = useRef(null);
const demoDlgD0Ref = useRef(null);
const demoDlgD1Ref = useRef(null);
const demoDlgD2Ref = useRef(null);
const demoDlgD3Ref = useRef(null);
const demoDlgD4Ref = useRef(null);
return (
<>
<div style={{ display: 'grid', gridTemplateColumns: 'auto 1fr', gap: '14px 16px', alignItems: 'center' }}>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>default</span>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px' }}><MdButton variant="filled" onClick={() => demoDlgD0Ref.current?.show()}>Open default</MdButton></div>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>-1</span>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px' }}><MdButton variant="outlined" onClick={() => demoDlgD1Ref.current?.show()}>Open rung -1</MdButton></div>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>-2</span>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px' }}><MdButton variant="outlined" onClick={() => demoDlgD2Ref.current?.show()}>Open rung -2</MdButton></div>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>-3</span>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px' }}><MdButton variant="outlined" onClick={() => demoDlgD3Ref.current?.show()}>Open rung -3</MdButton></div>
<span style={{ inlineSize: '3.5rem', opacity: '.65', fontSize: '.75rem', fontFamily: 'ui-monospace,monospace' }}>-4</span>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '12px' }}><MdButton variant="outlined" onClick={() => demoDlgD4Ref.current?.show()}>Open rung -4</MdButton></div>
</div>
<MdDialog id="demo-dlg-d0" ref={demoDlgD0Ref} ref={demoDlgD0Ref} headline="Default density"><p style={{ margin: '0' }}>Inset, headline size, corner radius and the actions row all taper together.</p><MdButton slot="actions" variant="text" onClick={() => demoDlgD0Ref.current?.close()}>Close</MdButton></MdDialog>
<MdDialog id="demo-dlg-d1" ref={demoDlgD1Ref} ref={demoDlgD1Ref} density="-1" headline="Density -1"><p style={{ margin: '0' }}>Inset, headline size, corner radius and the actions row all taper together.</p><MdButton slot="actions" variant="text" onClick={() => demoDlgD1Ref.current?.close()}>Close</MdButton></MdDialog>
<MdDialog id="demo-dlg-d2" ref={demoDlgD2Ref} ref={demoDlgD2Ref} density="-2" headline="Density -2"><p style={{ margin: '0' }}>Inset, headline size, corner radius and the actions row all taper together.</p><MdButton slot="actions" variant="text" onClick={() => demoDlgD2Ref.current?.close()}>Close</MdButton></MdDialog>
<MdDialog id="demo-dlg-d3" ref={demoDlgD3Ref} ref={demoDlgD3Ref} density="-3" headline="Density -3"><p style={{ margin: '0' }}>Inset, headline size, corner radius and the actions row all taper together.</p><MdButton slot="actions" variant="text" onClick={() => demoDlgD3Ref.current?.close()}>Close</MdButton></MdDialog>
<MdDialog id="demo-dlg-d4" ref={demoDlgD4Ref} ref={demoDlgD4Ref} density="-4" headline="Density -4"><p style={{ margin: '0' }}>Inset, headline size, corner radius and the actions row all taper together.</p><MdButton slot="actions" variant="text" onClick={() => demoDlgD4Ref.current?.close()}>Close</MdButton></MdDialog>
</>
);
}// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">default</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="filled" (click)="demoDlgD0.show()">Open default</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-1</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" (click)="demoDlgD1.show()">Open rung -1</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-2</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" (click)="demoDlgD2.show()">Open rung -2</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-3</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" (click)="demoDlgD3.show()">Open rung -3</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-4</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" (click)="demoDlgD4.show()">Open rung -4</md-button></div>
</div>
<md-dialog id="demo-dlg-d0" #demoDlgD0 #demoDlgD0 headline="Default density"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" (click)="demoDlgD0.close()">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d1" #demoDlgD1 #demoDlgD1 density="-1" headline="Density -1"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" (click)="demoDlgD1.close()">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d2" #demoDlgD2 #demoDlgD2 density="-2" headline="Density -2"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" (click)="demoDlgD2.close()">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d3" #demoDlgD3 #demoDlgD3 density="-3" headline="Density -3"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" (click)="demoDlgD3.close()">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d4" #demoDlgD4 #demoDlgD4 density="-4" headline="Density -4"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" (click)="demoDlgD4.close()">Close</md-button></md-dialog><script setup>
import { ref } from 'vue';
import '@awc-ui/core/define';
const demoDlgD0 = ref(null);
const demoDlgD1 = ref(null);
const demoDlgD2 = ref(null);
const demoDlgD3 = ref(null);
const demoDlgD4 = ref(null);
const demoDlgD0 = ref(null);
const demoDlgD1 = ref(null);
const demoDlgD2 = ref(null);
const demoDlgD3 = ref(null);
const demoDlgD4 = ref(null);
</script>
<template>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">default</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="filled" @click="demoDlgD0?.show()">Open default</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-1</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" @click="demoDlgD1?.show()">Open rung -1</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-2</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" @click="demoDlgD2?.show()">Open rung -2</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-3</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" @click="demoDlgD3?.show()">Open rung -3</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-4</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" @click="demoDlgD4?.show()">Open rung -4</md-button></div>
</div>
<md-dialog id="demo-dlg-d0" ref="demoDlgD0" ref="demoDlgD0" headline="Default density"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" @click="demoDlgD0?.close()">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d1" ref="demoDlgD1" ref="demoDlgD1" density="-1" headline="Density -1"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" @click="demoDlgD1?.close()">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d2" ref="demoDlgD2" ref="demoDlgD2" density="-2" headline="Density -2"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" @click="demoDlgD2?.close()">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d3" ref="demoDlgD3" ref="demoDlgD3" density="-3" headline="Density -3"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" @click="demoDlgD3?.close()">Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d4" ref="demoDlgD4" ref="demoDlgD4" density="-4" headline="Density -4"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" @click="demoDlgD4?.close()">Close</md-button></md-dialog>
</template><script>
import '@awc-ui/core/define';
let demoDlgD0;
let demoDlgD1;
let demoDlgD2;
let demoDlgD3;
let demoDlgD4;
let demoDlgD0;
let demoDlgD1;
let demoDlgD2;
let demoDlgD3;
let demoDlgD4;
</script>
<div style="display:grid;grid-template-columns:auto 1fr;gap:14px 16px;align-items:center;">
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">default</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="filled" on:click={() => demoDlgD0?.show()}>Open default</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-1</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" on:click={() => demoDlgD1?.show()}>Open rung -1</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-2</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" on:click={() => demoDlgD2?.show()}>Open rung -2</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-3</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" on:click={() => demoDlgD3?.show()}>Open rung -3</md-button></div>
<span style="inline-size:3.5rem;opacity:.65;font-size:.75rem;font-family:ui-monospace,monospace;">-4</span>
<div style="display:flex;flex-wrap:wrap;gap:12px;"><md-button variant="outlined" on:click={() => demoDlgD4?.show()}>Open rung -4</md-button></div>
</div>
<md-dialog id="demo-dlg-d0" bind:this={demoDlgD0} bind:this={demoDlgD0} headline="Default density"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" on:click={() => demoDlgD0?.close()}>Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d1" bind:this={demoDlgD1} bind:this={demoDlgD1} density="-1" headline="Density -1"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" on:click={() => demoDlgD1?.close()}>Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d2" bind:this={demoDlgD2} bind:this={demoDlgD2} density="-2" headline="Density -2"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" on:click={() => demoDlgD2?.close()}>Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d3" bind:this={demoDlgD3} bind:this={demoDlgD3} density="-3" headline="Density -3"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" on:click={() => demoDlgD3?.close()}>Close</md-button></md-dialog>
<md-dialog id="demo-dlg-d4" bind:this={demoDlgD4} bind:this={demoDlgD4} density="-4" headline="Density -4"><p style="margin:0;">Inset, headline size, corner radius and the actions row all taper together.</p><md-button slot="actions" variant="text" on:click={() => demoDlgD4?.close()}>Close</md-button></md-dialog>They are independent signals: dir mirrors the layout and data-density
compacts it, and a local density prop retunes one dialog without touching
direction. All three dialogs below sit in the same dir="rtl" data-density="-1"
wrapper: the first inherits -1, the second declares density="-4" and that
lower local rung wins, and the third resets to default spacing the only way that
works — style="--md-sys-density-scale: 0", not density="0".
يرث الرُتبة -1 من العنصر الأب.
نفس العنصر الأب، لكن الرُتبة المحلية -4 تتغلب عليه.
نفس العنصر الأب، لكن المتغير المخصص يعيد التباعد الافتراضي.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<div dir="rtl" data-density="-1" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled">مضغوط (-1 موروث)</md-button>
<md-button variant="outlined">أكثر ضغطاً (-4 محلي)</md-button>
<md-button variant="text">إعادة الضبط (متغير مخصص)</md-button>
<md-dialog id="demo-dlg-rtl-dense" headline="حذف الملف؟" icon="delete">
<p style="margin:0;">يرث الرُتبة -1 من العنصر الأب.</p>
<md-button slot="actions" variant="text">إلغاء</md-button>
<md-button slot="actions" variant="filled">حذف</md-button>
</md-dialog>
<md-dialog id="demo-dlg-rtl-denser" density="-4" headline="حذف الملف؟" icon="delete">
<p style="margin:0;">نفس العنصر الأب، لكن الرُتبة المحلية -4 تتغلب عليه.</p>
<md-button slot="actions" variant="text">إلغاء</md-button>
<md-button slot="actions" variant="filled">حذف</md-button>
</md-dialog>
<md-dialog id="demo-dlg-rtl-reset" style="--md-sys-density-scale: 0;" headline="حذف الملف؟" icon="delete">
<p style="margin:0;">نفس العنصر الأب، لكن المتغير المخصص يعيد التباعد الافتراضي.</p>
<md-button slot="actions" variant="text">إلغاء</md-button>
<md-button slot="actions" variant="filled">حذف</md-button>
</md-dialog>
</div>
<script type="module">
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-rtl-dense').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-rtl-denser').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-rtl-reset').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-rtl-dense').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-rtl-dense').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-rtl-denser').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-rtl-denser').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-rtl-reset').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dlg-rtl-reset').close());
</script>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { useRef } from 'react';
import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
const demoDlgRtlDenseRef = useRef(null);
const demoDlgRtlDenserRef = useRef(null);
const demoDlgRtlResetRef = useRef(null);
const demoDlgRtlDenseRef = useRef(null);
const demoDlgRtlDenseRef = useRef(null);
const demoDlgRtlDenserRef = useRef(null);
const demoDlgRtlDenserRef = useRef(null);
const demoDlgRtlResetRef = useRef(null);
const demoDlgRtlResetRef = useRef(null);
return (
<>
<div dir="rtl" data-density="-1" style={{ display: 'flex', flexWrap: 'wrap', gap: '12px' }}>
<MdButton variant="filled" onClick={() => demoDlgRtlDenseRef.current?.show()}>مضغوط (-1 موروث)</MdButton>
<MdButton variant="outlined" onClick={() => demoDlgRtlDenserRef.current?.show()}>أكثر ضغطاً (-4 محلي)</MdButton>
<MdButton variant="text" onClick={() => demoDlgRtlResetRef.current?.show()}>إعادة الضبط (متغير مخصص)</MdButton>
<MdDialog id="demo-dlg-rtl-dense" ref={demoDlgRtlDenseRef} ref={demoDlgRtlDenseRef} ref={demoDlgRtlDenseRef} headline="حذف الملف؟" icon="delete">
<p style={{ margin: '0' }}>يرث الرُتبة -1 من العنصر الأب.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDlgRtlDenseRef.current?.close()}>إلغاء</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDlgRtlDenseRef.current?.close()}>حذف</MdButton>
</MdDialog>
<MdDialog id="demo-dlg-rtl-denser" ref={demoDlgRtlDenserRef} ref={demoDlgRtlDenserRef} ref={demoDlgRtlDenserRef} density="-4" headline="حذف الملف؟" icon="delete">
<p style={{ margin: '0' }}>نفس العنصر الأب، لكن الرُتبة المحلية -4 تتغلب عليه.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDlgRtlDenserRef.current?.close()}>إلغاء</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDlgRtlDenserRef.current?.close()}>حذف</MdButton>
</MdDialog>
<MdDialog id="demo-dlg-rtl-reset" ref={demoDlgRtlResetRef} ref={demoDlgRtlResetRef} ref={demoDlgRtlResetRef} style={{ '--md-sys-density-scale': '0' }} headline="حذف الملف؟" icon="delete">
<p style={{ margin: '0' }}>نفس العنصر الأب، لكن المتغير المخصص يعيد التباعد الافتراضي.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDlgRtlResetRef.current?.close()}>إلغاء</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDlgRtlResetRef.current?.close()}>حذف</MdButton>
</MdDialog>
</div>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<div dir="rtl" data-density="-1" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" (click)="demoDlgRtlDense.show()">مضغوط (-1 موروث)</md-button>
<md-button variant="outlined" (click)="demoDlgRtlDenser.show()">أكثر ضغطاً (-4 محلي)</md-button>
<md-button variant="text" (click)="demoDlgRtlReset.show()">إعادة الضبط (متغير مخصص)</md-button>
<md-dialog id="demo-dlg-rtl-dense" #demoDlgRtlDense #demoDlgRtlDense #demoDlgRtlDense headline="حذف الملف؟" icon="delete">
<p style="margin:0;">يرث الرُتبة -1 من العنصر الأب.</p>
<md-button slot="actions" variant="text" (click)="demoDlgRtlDense.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" (click)="demoDlgRtlDense.close()">حذف</md-button>
</md-dialog>
<md-dialog id="demo-dlg-rtl-denser" #demoDlgRtlDenser #demoDlgRtlDenser #demoDlgRtlDenser density="-4" headline="حذف الملف؟" icon="delete">
<p style="margin:0;">نفس العنصر الأب، لكن الرُتبة المحلية -4 تتغلب عليه.</p>
<md-button slot="actions" variant="text" (click)="demoDlgRtlDenser.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" (click)="demoDlgRtlDenser.close()">حذف</md-button>
</md-dialog>
<md-dialog id="demo-dlg-rtl-reset" #demoDlgRtlReset #demoDlgRtlReset #demoDlgRtlReset style="--md-sys-density-scale: 0;" headline="حذف الملف؟" icon="delete">
<p style="margin:0;">نفس العنصر الأب، لكن المتغير المخصص يعيد التباعد الافتراضي.</p>
<md-button slot="actions" variant="text" (click)="demoDlgRtlReset.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" (click)="demoDlgRtlReset.close()">حذف</md-button>
</md-dialog>
</div><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { ref } from 'vue';
import '@awc-ui/core/define';
const demoDlgRtlDense = ref(null);
const demoDlgRtlDenser = ref(null);
const demoDlgRtlReset = ref(null);
const demoDlgRtlDense = ref(null);
const demoDlgRtlDense = ref(null);
const demoDlgRtlDenser = ref(null);
const demoDlgRtlDenser = ref(null);
const demoDlgRtlReset = ref(null);
const demoDlgRtlReset = ref(null);
</script>
<template>
<div dir="rtl" data-density="-1" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" @click="demoDlgRtlDense?.show()">مضغوط (-1 موروث)</md-button>
<md-button variant="outlined" @click="demoDlgRtlDenser?.show()">أكثر ضغطاً (-4 محلي)</md-button>
<md-button variant="text" @click="demoDlgRtlReset?.show()">إعادة الضبط (متغير مخصص)</md-button>
<md-dialog id="demo-dlg-rtl-dense" ref="demoDlgRtlDense" ref="demoDlgRtlDense" ref="demoDlgRtlDense" headline="حذف الملف؟" icon="delete">
<p style="margin:0;">يرث الرُتبة -1 من العنصر الأب.</p>
<md-button slot="actions" variant="text" @click="demoDlgRtlDense?.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" @click="demoDlgRtlDense?.close()">حذف</md-button>
</md-dialog>
<md-dialog id="demo-dlg-rtl-denser" ref="demoDlgRtlDenser" ref="demoDlgRtlDenser" ref="demoDlgRtlDenser" density="-4" headline="حذف الملف؟" icon="delete">
<p style="margin:0;">نفس العنصر الأب، لكن الرُتبة المحلية -4 تتغلب عليه.</p>
<md-button slot="actions" variant="text" @click="demoDlgRtlDenser?.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" @click="demoDlgRtlDenser?.close()">حذف</md-button>
</md-dialog>
<md-dialog id="demo-dlg-rtl-reset" ref="demoDlgRtlReset" ref="demoDlgRtlReset" ref="demoDlgRtlReset" style="--md-sys-density-scale: 0;" headline="حذف الملف؟" icon="delete">
<p style="margin:0;">نفس العنصر الأب، لكن المتغير المخصص يعيد التباعد الافتراضي.</p>
<md-button slot="actions" variant="text" @click="demoDlgRtlReset?.close()">إلغاء</md-button>
<md-button slot="actions" variant="filled" @click="demoDlgRtlReset?.close()">حذف</md-button>
</md-dialog>
</div>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
let demoDlgRtlDense;
let demoDlgRtlDenser;
let demoDlgRtlReset;
let demoDlgRtlDense;
let demoDlgRtlDense;
let demoDlgRtlDenser;
let demoDlgRtlDenser;
let demoDlgRtlReset;
let demoDlgRtlReset;
</script>
<div dir="rtl" data-density="-1" style="display:flex;flex-wrap:wrap;gap:12px;">
<md-button variant="filled" on:click={() => demoDlgRtlDense?.show()}>مضغوط (-1 موروث)</md-button>
<md-button variant="outlined" on:click={() => demoDlgRtlDenser?.show()}>أكثر ضغطاً (-4 محلي)</md-button>
<md-button variant="text" on:click={() => demoDlgRtlReset?.show()}>إعادة الضبط (متغير مخصص)</md-button>
<md-dialog id="demo-dlg-rtl-dense" bind:this={demoDlgRtlDense} bind:this={demoDlgRtlDense} bind:this={demoDlgRtlDense} headline="حذف الملف؟" icon="delete">
<p style="margin:0;">يرث الرُتبة -1 من العنصر الأب.</p>
<md-button slot="actions" variant="text" on:click={() => demoDlgRtlDense?.close()}>إلغاء</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDlgRtlDense?.close()}>حذف</md-button>
</md-dialog>
<md-dialog id="demo-dlg-rtl-denser" bind:this={demoDlgRtlDenser} bind:this={demoDlgRtlDenser} bind:this={demoDlgRtlDenser} density="-4" headline="حذف الملف؟" icon="delete">
<p style="margin:0;">نفس العنصر الأب، لكن الرُتبة المحلية -4 تتغلب عليه.</p>
<md-button slot="actions" variant="text" on:click={() => demoDlgRtlDenser?.close()}>إلغاء</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDlgRtlDenser?.close()}>حذف</md-button>
</md-dialog>
<md-dialog id="demo-dlg-rtl-reset" bind:this={demoDlgRtlReset} bind:this={demoDlgRtlReset} bind:this={demoDlgRtlReset} style="--md-sys-density-scale: 0;" headline="حذف الملف؟" icon="delete">
<p style="margin:0;">نفس العنصر الأب، لكن المتغير المخصص يعيد التباعد الافتراضي.</p>
<md-button slot="actions" variant="text" on:click={() => demoDlgRtlReset?.close()}>إلغاء</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDlgRtlReset?.close()}>حذف</md-button>
</md-dialog>
</div>Density — density="-1…-4" compacts the padding, the headline and the
actions row. A global data-density ancestor drives the same signal, and a
lower rung declared on the dialog itself overrides it. See
Density.
i18n — translate headline, the body content, close-label,
cancel-label and ok-label (the
localization story
switches the whole set). locale drives any Intl-formatted values the
dialog renders. Translated action labels run longer, so check whether the pair
still fits side by side or needs stacking (confirming above dismissive).
| Custom property | Purpose | Default |
|---|---|---|
--md-dialog-container-color | Surface fill | surface-container-high |
--md-dialog-container-shape | Corner radius | 28px (0 when fullscreen) |
--md-dialog-headline-color / --md-dialog-content-color | Text | on-surface / on-surface-variant |
--md-dialog-icon-color / --md-dialog-icon-size | Header glyph | secondary / 24px |
--md-dialog-scrim-color | Backdrop | rgba(0, 0, 0, 0.32) |
--md-dialog-divider-color | Header and content rules | outline-variant |
--md-dialog-z-index / --md-dialog-scrim-z-index | Stacking | 2147483647 / 2147483646 |
8px corners, an error-tinted icon and a heavier scrim.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<md-button variant="outlined">Open themed dialog</md-button>
<md-dialog id="demo-dialog-themed" headline="Themed" icon="palette" style="--md-dialog-container-shape: 8px; --md-dialog-icon-color: var(--md-sys-color-error); --md-dialog-scrim-color: rgba(0, 0, 0, 0.6);">
<p style="margin: 0;">8px corners, an error-tinted icon and a heavier scrim.</p>
<md-button slot="actions" variant="text">Close</md-button>
</md-dialog>
<script type="module">
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-themed').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-themed').close());
</script>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { useRef } from 'react';
import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
const demoDialogThemedRef = useRef(null);
const demoDialogThemedRef = useRef(null);
return (
<>
<MdButton variant="outlined" onClick={() => demoDialogThemedRef.current?.show()}>Open themed dialog</MdButton>
<MdDialog id="demo-dialog-themed" ref={demoDialogThemedRef} ref={demoDialogThemedRef} headline="Themed" icon="palette" style={{ '--md-dialog-container-shape': '8px', '--md-dialog-icon-color': 'var(--md-sys-color-error)', '--md-dialog-scrim-color': 'rgba(0, 0, 0, 0.6)' }}>
<p style={{ margin: '0' }}>8px corners, an error-tinted icon and a heavier scrim.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogThemedRef.current?.close()}>Close</MdButton>
</MdDialog>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<md-button variant="outlined" (click)="demoDialogThemed.show()">Open themed dialog</md-button>
<md-dialog id="demo-dialog-themed" #demoDialogThemed #demoDialogThemed headline="Themed" icon="palette" style="--md-dialog-container-shape: 8px; --md-dialog-icon-color: var(--md-sys-color-error); --md-dialog-scrim-color: rgba(0, 0, 0, 0.6);">
<p style="margin: 0;">8px corners, an error-tinted icon and a heavier scrim.</p>
<md-button slot="actions" variant="text" (click)="demoDialogThemed.close()">Close</md-button>
</md-dialog><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { ref } from 'vue';
import '@awc-ui/core/define';
const demoDialogThemed = ref(null);
const demoDialogThemed = ref(null);
</script>
<template>
<md-button variant="outlined" @click="demoDialogThemed?.show()">Open themed dialog</md-button>
<md-dialog id="demo-dialog-themed" ref="demoDialogThemed" ref="demoDialogThemed" headline="Themed" icon="palette" style="--md-dialog-container-shape: 8px; --md-dialog-icon-color: var(--md-sys-color-error); --md-dialog-scrim-color: rgba(0, 0, 0, 0.6);">
<p style="margin: 0;">8px corners, an error-tinted icon and a heavier scrim.</p>
<md-button slot="actions" variant="text" @click="demoDialogThemed?.close()">Close</md-button>
</md-dialog>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
let demoDialogThemed;
let demoDialogThemed;
</script>
<md-button variant="outlined" on:click={() => demoDialogThemed?.show()}>Open themed dialog</md-button>
<md-dialog id="demo-dialog-themed" bind:this={demoDialogThemed} bind:this={demoDialogThemed} headline="Themed" icon="palette" style="--md-dialog-container-shape: 8px; --md-dialog-icon-color: var(--md-sys-color-error); --md-dialog-scrim-color: rgba(0, 0, 0, 0.6);">
<p style="margin: 0;">8px corners, an error-tinted icon and a heavier scrim.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogThemed?.close()}>Close</md-button>
</md-dialog>Check any override in both themes — the scrim sits at a different opacity in each, so a container colour that separates cleanly on light can disappear into the backdrop on dark. See the dark-theme story.
CSS parts — container, header, headline, content, divider and
actions render on both variants. The rest are conditional: scrim and icon
are basic-only (a full-screen dialog has neither), close-button is
full-screen only, and cancel-button / ok-button exist only while nothing
is slotted into actions. Styling a part the current variant doesn’t render is
a silent no-op.
Outlined container, italic headline, tinted scrim and a wider action gap.
<!-- index.html <head> — the icon font the components draw from -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap">
<!-- index.html — register the AWC UI elements once -->
<script type="module">
import '@awc-ui/core/define';
</script>
<style>
#demo-dialog-parts::part(container) { border: 2px solid var(--md-sys-color-primary); max-inline-size: 420px; }
#demo-dialog-parts::part(headline) { font-style: italic; letter-spacing: .04em; }
#demo-dialog-parts::part(scrim) { background: color-mix(in srgb, var(--md-sys-color-primary) 28%, transparent); }
#demo-dialog-parts::part(actions) { gap: 16px; }
</style>
<md-button variant="filled">Styled parts</md-button>
<md-dialog id="demo-dialog-parts" headline="Styled with ::part()" icon="palette">
<p style="margin: 0;">Outlined container, italic headline, tinted scrim and a wider action gap.</p>
<md-button slot="actions" variant="text">Cancel</md-button>
<md-button slot="actions" variant="filled">Apply</md-button>
</md-dialog>
<script type="module">
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-parts').show());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-parts').close());
// Give the trigger an id, then:
// trigger.addEventListener('click', () => document.getElementById('demo-dialog-parts').close());
</script>// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { useRef } from 'react';
import { MdButton, MdDialog } from '@awc-ui/react';
export function Demo() {
const demoDialogPartsRef = useRef(null);
const demoDialogPartsRef = useRef(null);
const demoDialogPartsRef = useRef(null);
return (
<>
<style>
#demo-dialog-parts::part(container) { border: 2px solid var(--md-sys-color-primary); max-inline-size: 420px; }
#demo-dialog-parts::part(headline) { font-style: italic; letter-spacing: .04em; }
#demo-dialog-parts::part(scrim) { background: color-mix(in srgb, var(--md-sys-color-primary) 28%, transparent); }
#demo-dialog-parts::part(actions) { gap: 16px; }
</style>
<MdButton variant="filled" onClick={() => demoDialogPartsRef.current?.show()}>Styled parts</MdButton>
<MdDialog id="demo-dialog-parts" ref={demoDialogPartsRef} ref={demoDialogPartsRef} ref={demoDialogPartsRef} headline="Styled with ::part()" icon="palette">
<p style={{ margin: '0' }}>Outlined container, italic headline, tinted scrim and a wider action gap.</p>
<MdButton slot="actions" variant="text" onClick={() => demoDialogPartsRef.current?.close()}>Cancel</MdButton>
<MdButton slot="actions" variant="filled" onClick={() => demoDialogPartsRef.current?.close()}>Apply</MdButton>
</MdDialog>
</>
);
}// Icons need the Material Symbols stylesheet in index.html — see Installation.
// app.module.ts — register the AWC UI elements once
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { AwcUiModule } from '@awc-ui/angular';
@NgModule({
imports: [AwcUiModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<style>
#demo-dialog-parts::part(container) { border: 2px solid var(--md-sys-color-primary); max-inline-size: 420px; }
#demo-dialog-parts::part(headline) { font-style: italic; letter-spacing: .04em; }
#demo-dialog-parts::part(scrim) { background: color-mix(in srgb, var(--md-sys-color-primary) 28%, transparent); }
#demo-dialog-parts::part(actions) { gap: 16px; }
</style>
<md-button variant="filled" (click)="demoDialogParts.show()">Styled parts</md-button>
<md-dialog id="demo-dialog-parts" #demoDialogParts #demoDialogParts #demoDialogParts headline="Styled with ::part()" icon="palette">
<p style="margin: 0;">Outlined container, italic headline, tinted scrim and a wider action gap.</p>
<md-button slot="actions" variant="text" (click)="demoDialogParts.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" (click)="demoDialogParts.close()">Apply</md-button>
</md-dialog><script setup>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import { ref } from 'vue';
import '@awc-ui/core/define';
const demoDialogParts = ref(null);
const demoDialogParts = ref(null);
const demoDialogParts = ref(null);
</script>
<template>
<style>
#demo-dialog-parts::part(container) { border: 2px solid var(--md-sys-color-primary); max-inline-size: 420px; }
#demo-dialog-parts::part(headline) { font-style: italic; letter-spacing: .04em; }
#demo-dialog-parts::part(scrim) { background: color-mix(in srgb, var(--md-sys-color-primary) 28%, transparent); }
#demo-dialog-parts::part(actions) { gap: 16px; }
</style>
<md-button variant="filled" @click="demoDialogParts?.show()">Styled parts</md-button>
<md-dialog id="demo-dialog-parts" ref="demoDialogParts" ref="demoDialogParts" ref="demoDialogParts" headline="Styled with ::part()" icon="palette">
<p style="margin: 0;">Outlined container, italic headline, tinted scrim and a wider action gap.</p>
<md-button slot="actions" variant="text" @click="demoDialogParts?.close()">Cancel</md-button>
<md-button slot="actions" variant="filled" @click="demoDialogParts?.close()">Apply</md-button>
</md-dialog>
</template><script>
// Icons need the Material Symbols stylesheet in index.html — see Installation.
import '@awc-ui/core/define';
let demoDialogParts;
let demoDialogParts;
let demoDialogParts;
</script>
<style>
#demo-dialog-parts::part(container) { border: 2px solid var(--md-sys-color-primary); max-inline-size: 420px; }
#demo-dialog-parts::part(headline) { font-style: italic; letter-spacing: .04em; }
#demo-dialog-parts::part(scrim) { background: color-mix(in srgb, var(--md-sys-color-primary) 28%, transparent); }
#demo-dialog-parts::part(actions) { gap: 16px; }
</style>
<md-button variant="filled" on:click={() => demoDialogParts?.show()}>Styled parts</md-button>
<md-dialog id="demo-dialog-parts" bind:this={demoDialogParts} bind:this={demoDialogParts} bind:this={demoDialogParts} headline="Styled with ::part()" icon="palette">
<p style="margin: 0;">Outlined container, italic headline, tinted scrim and a wider action gap.</p>
<md-button slot="actions" variant="text" on:click={() => demoDialogParts?.close()}>Cancel</md-button>
<md-button slot="actions" variant="filled" on:click={() => demoDialogParts?.close()}>Apply</md-button>
</md-dialog>md-dialog::part(container) { max-inline-size: 420px;}md-snackbar ·
md-bottom-sheet ·
md-side-sheet ·
md-menu ·
md-card ·
md-button ·
md-tooltip
md-dialogTwo artefacts to give your AI agent so it generates correct UI with this component. The per-component spec answers "how do I use this exact tag?". The main-llm spec answers "which tag should I pick in the first place?".
md-dialog spec card
Identity · when to use / when NOT · decision cues · behavioural contract · do/don't · anti-patterns · full API. Paste into your agent when you're implementing with this component.
System-prompt preamble · decision matrix · token reference · page recipes · anti-patterns. Paste into the system prompt at the start of a piece of work.