Reference
an-modal
Content presented over everything — and it really is presented, which is what makes the screen reader and the back button behave.
A UIViewController presented on iOS and a Dialog on Android — not a view
laid over the others. It looks similar, and the difference matters: the system
knows there is something modal in front, so VoiceOver and TalkBack stop reading
what is behind it, Android’s back button closes it, and it does not compete for
draw order with the system’s own dialogs.
(dismiss) fires when the user closes it — the sheet dragged down, the back
button — as opposed to [visible] going false because your code said so.
Availability
Section titled “Availability”| iOS · iPadOS | Android | macOS | tvOS | visionOS | watchOS | Wear OS |
|---|---|---|---|---|---|---|
| ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
What it becomes
Section titled “What it becomes”| iOS · iPadOS | Android | macOS | watchOS |
|---|---|---|---|
a presented UIViewController |
Dialog |
a presented sheet | .sheet |
Inputs
Section titled “Inputs”| Prop | Type | Default | |
|---|---|---|---|
visible |
boolean | null |
false |
|
presentation |
'fullScreen' | 'sheet' | null |
null |
fullScreen covers the screen; sheet comes up from the bottom with the system’s grabber, resting where [ios].detents says. |
Outputs
Section titled “Outputs”| Output | Payload | |
|---|---|---|
(dismiss) |
— | It closed. |
[ios] — what UIKit has and the others do not
Section titled “[ios] — what UIKit has and the others do not”| Key | Type | |
|---|---|---|
detents |
readonly ('medium' | 'large' | number)[] |
Where the sheet is allowed to rest, in the order UIKit is given them. UISheetPresentationController.detents. 'medium' and 'large' are UIKit’s own; a number is .custom(resolver:), a height in points measured from the bottom. Without it, the two the system suggests. Only read when presentation is sheet. Android has no equivalent to ask for: its Dialog is as tall as its content, and BottomSheetBehavior is Material’s, not the platform’s. |
Example
Section titled “Example”<an-modal [visible]="editing()" [presentation]="'sheet'" [ios]="{ detents: ['medium', 'large'] }" (dismiss)="editing.set(false)"> <an-safe-area [edges]="['top', 'bottom']" [padding]="20" [style.gap]="'12'"> <an-text [fontSize]="20">Edit note</an-text> <an-textarea [value]="draft()" (change)="draft.set($event.value)" /> </an-safe-area></an-modal>Every primitive also carries the base props — background, border, opacity, the transforms, animate, the accessibility contract — and every gesture. See Components for the full base, Events for the payloads.