Skip to content

Commit 06ec172

Browse files
authored
Migrate the dialog component to plain HTML. (dart-lang#9450)
1 parent 157f34e commit 06ec172

4 files changed

Lines changed: 154 additions & 64 deletions

File tree

pkg/pub_integration/lib/src/pub_puppeteer_helpers.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ extension PubPageExt on Page {
245245
Future<void> _waitForModelHidden() async {
246246
try {
247247
await waitForSelector(
248-
'.mdc-dialog',
248+
'.pub-dialog',
249249
hidden: true,
250250
timeout: Duration(seconds: 5),
251251
);
@@ -255,7 +255,7 @@ extension PubPageExt on Page {
255255
}
256256

257257
// return if the dialog is no longer present
258-
final dialogs = await $$('.mdc-dialog');
258+
final dialogs = await $$('.pub-dialog');
259259
if (dialogs.isEmpty) {
260260
return;
261261
}
@@ -267,7 +267,7 @@ extension PubPageExt on Page {
267267

268268
// second attempt to wait for the dialog to disappear
269269
await waitForSelector(
270-
'.mdc-dialog',
270+
'.pub-dialog',
271271
hidden: true,
272272
timeout: Duration(seconds: 5),
273273
);

pkg/web_app/lib/src/_dom_helper.dart

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import 'package:web/web.dart';
88

99
import '_focusability.dart';
1010
import 'deferred/markdown.dart' deferred as md;
11-
import 'mdc/mdc_dialog.dart';
1211
import 'web_util.dart';
1312

1413
/// Displays a message via the modal window.
@@ -51,6 +50,13 @@ Future<bool> modalWindow({
5150
allowedComponents: [content],
5251
);
5352
final c = Completer<bool>();
53+
54+
void cancel() {
55+
if (!c.isCompleted) {
56+
c.complete(false);
57+
}
58+
}
59+
5460
final root = _buildDialog(
5561
titleText: titleText,
5662
content: content,
@@ -61,21 +67,31 @@ Future<bool> modalWindow({
6167
c.complete(pushedOk);
6268
}
6369
},
70+
onDismiss: cancel,
6471
cancelButtonText: cancelButtonText,
6572
okButtonText: okButtonText,
6673
);
74+
75+
// Close the dialog when the escape key was hit.
76+
final keySubscription = window.onKeyDown.listen((event) {
77+
if (event.key == 'Escape') {
78+
event.preventDefault();
79+
cancel();
80+
}
81+
});
82+
6783
document.body!.append(root);
68-
final dialog = MdcDialog.attachTo(root);
84+
document.body!.classList.add('pub-dialog-scroll-lock');
85+
// Note: this forces a layout event, so that the open transition animates from the hidden state.
86+
root.getBoundingClientRect();
87+
root.classList.add('pub-dialog--open');
6988
try {
70-
dialog.open();
71-
dialog.listenOnClose(() => c.complete(false));
7289
await c.future;
7390
} finally {
91+
await keySubscription.cancel();
7492
restoreFocusabilityFn();
75-
dialog.destroy();
7693
root.remove();
77-
// Note: This seems to be a bug in the JS library
78-
document.body!.classList.remove('mdc-dialog-scroll-lock');
94+
document.body!.classList.remove('pub-dialog-scroll-lock');
7995
}
8096
return await c.future;
8197
}
@@ -90,27 +106,26 @@ Element _buildDialog({
90106
/// The callback will be called with `true` when "OK" was clicked, and `false`
91107
/// when "Cancel" was clicked.
92108
required void Function(bool) closing,
109+
110+
/// Called when the dialog is dismissed without pressing a button (e.g. click outside).
111+
required void Function() onDismiss,
93112
}) {
94113
final title = document.createElement('h2') as HTMLElement
95-
..classList.add('mdc-dialog__title')
114+
..classList.add('pub-dialog-title')
96115
..id = 'pub-dialog-title'
97116
..innerText = titleText;
98117

99118
final contentDiv = HTMLDivElement()
100-
..classList.add('mdc-dialog__content')
119+
..classList.add('pub-dialog-content')
101120
..id = 'pub-dialog-content'
102121
..append(content);
103122

104-
final footer = document.createElement('footer');
105-
footer.classList.add('mdc-dialog__actions');
123+
final footer = document.createElement('footer')
124+
..classList.add('pub-dialog-actions');
106125

107126
if (isQuestion) {
108127
final cancelBtn = HTMLButtonElement()
109-
..classList.addAll([
110-
'pub-button',
111-
'mdc-dialog__button',
112-
'-pub-dom-dialog-cancel-button',
113-
])
128+
..classList.addAll(['pub-button', '-pub-dom-dialog-cancel-button'])
114129
..tabIndex = 2
115130
..innerText = cancelButtonText ?? 'Cancel';
116131
cancelBtn.onClick.listen((e) {
@@ -121,11 +136,7 @@ Element _buildDialog({
121136
}
122137

123138
final okBtn = HTMLButtonElement()
124-
..classList.addAll([
125-
'pub-button',
126-
'mdc-dialog__button',
127-
'-pub-dom-dialog-ok-button',
128-
])
139+
..classList.addAll(['pub-button', '-pub-dom-dialog-ok-button'])
129140
..tabIndex = 1
130141
..innerText = okButtonText ?? 'Ok';
131142
okBtn.onClick.listen((e) {
@@ -135,23 +146,29 @@ Element _buildDialog({
135146
footer.append(okBtn);
136147

137148
final surface = HTMLDivElement()
138-
..classList.add('mdc-dialog__surface')
149+
..classList.add('pub-dialog-surface')
139150
..append(title)
140151
..append(contentDiv)
141152
..append(footer);
142153

143154
final container = HTMLDivElement()
144-
..classList.add('mdc-dialog__container')
155+
..classList.add('pub-dialog-container')
145156
..append(surface);
146157

158+
final scrim = HTMLDivElement()..classList.add('pub-dialog-scrim');
159+
scrim.onClick.listen((e) {
160+
e.preventDefault();
161+
onDismiss();
162+
});
163+
147164
final root = HTMLDivElement()
148-
..classList.add('mdc-dialog')
165+
..classList.add('pub-dialog')
149166
..setAttribute('role', 'alertdialog')
150-
..setAttribute('aria-model', 'true')
167+
..setAttribute('aria-modal', 'true')
151168
..setAttribute('aria-labelledby', 'pub-dialog-title')
152169
..setAttribute('aria-describedby', 'pub-dialog-content')
153-
..append(container)
154-
..append(HTMLDivElement()..classList.add('mdc-dialog__scrim'));
170+
..append(scrim)
171+
..append(container);
155172

156173
return root;
157174
}

pkg/web_app/lib/src/mdc/mdc_dialog.dart

Lines changed: 0 additions & 29 deletions
This file was deleted.

pkg/web_css/lib/src/_form.scss

Lines changed: 107 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,113 @@
107107
}
108108
}
109109

110-
.dark-theme {
111-
.mdc-dialog__surface {
112-
.mdc-dialog__title,
113-
.mdc-dialog__content {
114-
color: var(--pub-neutral-textColor);
110+
.pub-dialog-scroll-lock {
111+
overflow: hidden;
112+
}
113+
114+
.pub-dialog {
115+
position: fixed;
116+
top: 0;
117+
left: 0;
118+
display: flex;
119+
align-items: center;
120+
justify-content: center;
121+
box-sizing: border-box;
122+
width: 100%;
123+
height: 100%;
124+
// Must sit above the navigation mask ($z-index-nav-mask: 1000).
125+
z-index: 1100;
126+
visibility: hidden;
127+
128+
.pub-dialog-scrim {
129+
position: fixed;
130+
top: 0;
131+
left: 0;
132+
width: 100%;
133+
height: 100%;
134+
background-color: var(--pub-full_page_mask-background-color);
135+
opacity: 0;
136+
z-index: -1;
137+
transition: opacity 150ms linear;
138+
}
139+
140+
.pub-dialog-container {
141+
display: flex;
142+
align-items: center;
143+
justify-content: center;
144+
box-sizing: border-box;
145+
height: 100%;
146+
opacity: 0;
147+
transform: scale(0.8);
148+
pointer-events: none;
149+
transition: opacity 75ms linear,
150+
transform 150ms 0ms cubic-bezier(0, 0, 0.2, 1);
151+
}
152+
153+
.pub-dialog-surface {
154+
position: relative;
155+
display: flex;
156+
flex-direction: column;
157+
flex-grow: 0;
158+
flex-shrink: 0;
159+
box-sizing: border-box;
160+
min-width: 280px;
161+
max-width: min(560px, calc(100vw - 32px));
162+
max-height: calc(100% - 32px);
163+
overflow-y: auto;
164+
pointer-events: auto;
165+
color: var(--pub-neutral-textColor);
166+
background-color: var(--pub-neutral-bgColor);
167+
border-radius: 4px;
168+
box-shadow: 0 11px 15px -7px rgba(0, 0, 0, 0.2),
169+
0 24px 38px 3px rgba(0, 0, 0, 0.14),
170+
0 9px 46px 8px rgba(0, 0, 0, 0.12);
171+
}
172+
173+
.pub-dialog-title {
174+
flex-shrink: 0;
175+
box-sizing: border-box;
176+
margin: 0;
177+
padding: 16px 24px 9px;
178+
font-size: 1.25rem;
179+
line-height: 2rem;
180+
font-weight: 500;
181+
letter-spacing: 0.0125em;
182+
}
183+
184+
.pub-dialog-content {
185+
flex-grow: 1;
186+
box-sizing: border-box;
187+
margin: 0;
188+
padding: 0 24px 20px;
189+
overflow-y: auto;
190+
font-size: 1rem;
191+
line-height: 1.5rem;
192+
}
193+
194+
.pub-dialog-actions {
195+
display: flex;
196+
position: relative;
197+
flex-shrink: 0;
198+
flex-wrap: wrap;
199+
align-items: center;
200+
justify-content: flex-end;
201+
box-sizing: border-box;
202+
min-height: 52px;
203+
margin: 0;
204+
padding: 8px;
205+
}
206+
207+
&.pub-dialog--open {
208+
visibility: visible;
209+
210+
.pub-dialog-scrim {
211+
opacity: 1;
212+
}
213+
214+
.pub-dialog-container {
215+
opacity: 1;
216+
transform: none;
115217
}
116218
}
117219
}

0 commit comments

Comments
 (0)