Skip to content

Commit 983e3a5

Browse files
keithamusjonrohan
andauthored
Refactor Dialog to use <dialog> internally (#2496)
Co-authored-by: Jon Rohan <[email protected]>
1 parent dfd306c commit 983e3a5

File tree

13 files changed

+182
-177
lines changed

13 files changed

+182
-177
lines changed

.changeset/wise-coats-buy.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@primer/view-components': minor
3+
---
4+
5+
Primer::Alpha::Dialog uses <dialog> internally

app/components/primer/alpha/action_menu/action_menu_element.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,15 @@ export class ActionMenuElement extends HTMLElement {
279279
if (this.#isOpen()) {
280280
this.#hide()
281281
}
282+
const activeElement = this.ownerDocument.activeElement
283+
const lostFocus = this.ownerDocument.activeElement === this.ownerDocument.body
284+
const focusInClosedMenu = this.contains(activeElement)
285+
if (lostFocus || focusInClosedMenu) {
286+
setTimeout(() => this.invokerElement?.focus(), 0)
287+
}
282288
}
289+
// a modal <dialog> element will close all popovers
290+
setTimeout(() => this.#show(), 0)
283291
dialog.addEventListener('close', handleDialogClose, {signal})
284292
dialog.addEventListener('cancel', handleDialogClose, {signal})
285293
}

app/components/primer/alpha/dialog.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<%= show_button %>
2-
<div class="Overlay--hidden <%= @backdrop_classes %>" data-modal-dialog-overlay>
2+
<dialog-helper>
33
<%= render Primer::BaseComponent.new(**@system_arguments) do %>
44
<%= header %>
55
<% if content.present? %>
@@ -11,4 +11,4 @@
1111
<%= footer %>
1212
<% end %>
1313
<% end %>
14-
</div>
14+
</dialog-helper>

app/components/primer/alpha/dialog.pcss

Lines changed: 56 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
/* Overlay */
22

3+
dialog.Overlay:not([open]) {
4+
display: none;
5+
}
6+
37
.Overlay--hidden {
48
display: none !important;
59
}
@@ -13,12 +17,18 @@
1317

1418
.Overlay {
1519
display: flex;
20+
inset: 0;
21+
position: static;
22+
margin: auto;
23+
padding: 0;
1624
width: min(var(--overlay-width), 100vw - 2rem);
1725
min-width: 192px;
1826
max-height: min(calc(100vh - 2rem), var(--overlay-height));
1927
white-space: normal;
2028
flex-direction: column;
2129
background-color: var(--overlay-bgColor);
30+
color: var(--fgColor-default);
31+
border: 0;
2232
border-radius: var(--borderRadius-large);
2333
box-shadow: var(--shadow-floating-small);
2434
opacity: 1;
@@ -74,6 +84,23 @@
7484
height: auto;
7585
}
7686

87+
&.Overlay--placement-left, &.Overlay--placement-right {
88+
height: 100%;
89+
max-height: unset;
90+
}
91+
92+
&.Overlay--placement-left {
93+
inset: 0 auto 0 0;
94+
border-top-left-radius: 0;
95+
border-bottom-left-radius: 0;
96+
}
97+
98+
&.Overlay--placement-right {
99+
inset: 0 0 0 auto;
100+
border-top-right-radius: 0;
101+
border-bottom-right-radius: 0;
102+
}
103+
77104
/* start deprecate in favor of Alpha::Dialog */
78105
&.Overlay--height-xsmall {
79106
height: min(192px, 100vh - 2rem);
@@ -295,121 +322,50 @@
295322
}
296323
}
297324

298-
@define-mixin Overlay-backdrop {
299-
position: fixed;
300-
top: 0;
301-
right: 0;
302-
bottom: 0;
303-
left: 0;
304-
z-index: 999;
305-
display: flex;
306-
background-color: var(--overlay-backdrop-bgColor, var(--color-neutral-muted));
307-
}
308-
309-
@define-mixin Overlay-backdrop--transparent {
310-
position: absolute;
311-
z-index: 999;
312-
background-color: transparent;
313-
}
314-
315325
/* variants must be mixins so we can extend within a media query (@extend is not supported inside media queries) */
316326

317327
/* border-radius repeats within placement options to ensure the original radius is reset when two classes co-exist */
318328

319-
/* center */
320-
@define-mixin Overlay-backdrop--center {
321-
@mixin Overlay-backdrop;
322-
323-
align-items: center;
324-
justify-content: center;
325-
}
326-
327-
/* anchor */
328-
@define-mixin Overlay-backdrop--anchor {
329-
@mixin Overlay-backdrop--transparent;
329+
/* full width */
330+
.Overlay--full {
331+
width: 100%;
332+
max-width: 100vw;
333+
height: 100%;
334+
max-height: 100vh;
335+
border-radius: unset !important;
336+
flex-grow: 1;
330337
}
331338

332-
/* anchor side(s) */
333-
@define-mixin Overlay-backdrop--side $responsiveVariant {
334-
@mixin Overlay-backdrop;
335-
336-
/* default left */
337-
align-items: center;
338-
justify-content: left;
339-
340-
&.Overlay-backdrop--placement-left$(responsiveVariant) {
341-
align-items: center;
342-
justify-content: left;
343-
344-
& > .Overlay$(responsiveVariant) {
345-
height: 100vh;
346-
max-height: unset;
347-
border-radius: var(--borderRadius-large);
348-
border-top-left-radius: 0;
349-
border-bottom-left-radius: 0;
339+
/* responsive variants */
350340

351-
@media screen and (prefers-reduced-motion: no-preference) {
352-
animation: 250ms cubic-bezier(0.33, 1, 0.68, 1) 0s 1 normal none running Overlay--motion-slideInRight;
353-
}
354-
}
341+
/* --viewportRange-narrowLandscape */
342+
@media (max-width: 767px) {
343+
.Overlay--placement-left-whenNarrow, .Overlay--placement-right-whenNarrow {
344+
height: 100%;
345+
max-height: 100vh;
355346
}
356347

357-
&.Overlay-backdrop--placement-right$(responsiveVariant) {
358-
align-items: center;
359-
justify-content: right;
360-
361-
& > .Overlay$(responsiveVariant) {
362-
height: 100vh;
363-
max-height: unset;
364-
border-radius: var(--borderRadius-large);
365-
border-top-right-radius: 0;
366-
border-bottom-right-radius: 0;
367-
368-
@media screen and (prefers-reduced-motion: no-preference) {
369-
animation: 250ms cubic-bezier(0.33, 1, 0.68, 1) 0s 1 normal none running Overlay--motion-slideInLeft;
370-
}
371-
}
348+
.Overlay--placement-left-whenNarrow {
349+
inset: 0 auto 0 0;
350+
border-top-left-radius: 0;
351+
border-bottom-left-radius: 0;
372352
}
373353

374-
&.Overlay-backdrop--placement-bottom$(responsiveVariant) {
375-
align-items: end;
376-
justify-content: center;
377-
378-
& > .Overlay$(responsiveVariant) {
379-
width: 100vw;
380-
height: auto;
381-
max-height: calc(100vh - 2rem);
382-
border-radius: var(--borderRadius-large);
383-
border-bottom-right-radius: 0;
384-
border-bottom-left-radius: 0;
385-
386-
@media screen and (prefers-reduced-motion: no-preference) {
387-
animation: 250ms cubic-bezier(0.33, 1, 0.68, 1) 0s 1 normal none running Overlay--motion-slideUp;
388-
}
389-
}
354+
.Overlay--placement-right-whenNarrow {
355+
inset: 0 0 0 auto;
356+
border-top-right-radius: 0;
357+
border-bottom-right-radius: 0;
390358
}
391359

392-
&.Overlay-backdrop--placement-top$(responsiveVariant) {
393-
align-items: start;
394-
justify-content: center;
395-
396-
& > .Overlay$(responsiveVariant) {
397-
border-radius: var(--borderRadius-large);
398-
border-top-left-radius: 0;
399-
border-top-right-radius: 0;
400-
401-
@media screen and (prefers-reduced-motion: no-preference) {
402-
animation: 250ms cubic-bezier(0.33, 1, 0.68, 1) 0s 1 normal none running Overlay--motion-slideDown;
403-
}
404-
}
360+
.Overlay--placement-bottom-whenNarrow {
361+
width: 100%;
362+
max-width: 100vw;
363+
inset: auto 0 0;
364+
border-bottom-left-radius: 0;
365+
border-bottom-right-radius: 0;
405366
}
406-
}
407367

408-
/* full width */
409-
@define-mixin Overlay-backdrop--full {
410-
@mixin Overlay-backdrop;
411-
412-
& .Overlay {
368+
.Overlay--full-whenNarrow {
413369
width: 100%;
414370
max-width: 100vw;
415371
height: 100%;
@@ -419,44 +375,6 @@
419375
}
420376
}
421377

422-
/* Overlay variant classnames */
423-
.Overlay-backdrop--center {
424-
@mixin Overlay-backdrop--center;
425-
}
426-
427-
.Overlay-backdrop--anchor {
428-
@mixin Overlay-backdrop--anchor;
429-
}
430-
431-
.Overlay-backdrop--side {
432-
@mixin Overlay-backdrop--side;
433-
}
434-
435-
.Overlay-backdrop--full {
436-
@mixin Overlay-backdrop--full;
437-
}
438-
439-
/* responsive variants */
440-
441-
/* --viewportRange-narrowLandscape */
442-
@media (max-width: 767px) {
443-
.Overlay-backdrop--center-whenNarrow {
444-
@mixin Overlay-backdrop--center;
445-
}
446-
447-
.Overlay-backdrop--anchor-whenNarrow {
448-
@mixin Overlay-backdrop--anchor;
449-
}
450-
451-
.Overlay-backdrop--side-whenNarrow {
452-
@mixin Overlay-backdrop--side -whenNarrow;
453-
}
454-
455-
.Overlay-backdrop--full-whenNarrow {
456-
@mixin Overlay-backdrop--full;
457-
}
458-
}
459-
460378
@keyframes Overlay--motion-slideDown {
461379
from {
462380
transform: translateY(-100%);

app/components/primer/alpha/dialog.rb

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,19 @@ class Dialog < Primer::Component
3434

3535
DEFAULT_POSITION = :center
3636
POSITION_MAPPINGS = {
37-
DEFAULT_POSITION => "Overlay-backdrop--center",
38-
:left => "Overlay-backdrop--side Overlay-backdrop--placement-left",
39-
:right => "Overlay-backdrop--side Overlay-backdrop--placement-right"
37+
DEFAULT_POSITION => "",
38+
:left => "Overlay--placement-left",
39+
:right => "Overlay--placement-right"
4040
}.freeze
4141
POSITION_OPTIONS = POSITION_MAPPINGS.keys
4242

4343
DEFAULT_POSITION_NARROW = :inherit
4444
POSITION_NARROW_MAPPINGS = {
4545
DEFAULT_POSITION_NARROW => "",
46-
:bottom => "Overlay-backdrop--side-whenNarrow Overlay-backdrop--placement-bottom-whenNarrow",
47-
:fullscreen => "Overlay-backdrop--full-whenNarrow",
48-
:left => "Overlay-backdrop--side-whenNarrow Overlay-backdrop--placement-left-whenNarrow",
49-
:right => "Overlay-backdrop--side-whenNarrow Overlay-backdrop--placement-right-whenNarrow"
46+
:bottom => "Overlay--placement-bottom-whenNarrow",
47+
:fullscreen => "Overlay--full-whenNarrow",
48+
:left => "Overlay--placement-left-whenNarrow",
49+
:right => "Overlay--placement-right-whenNarrow"
5050
}.freeze
5151
POSITION_NARROW_OPTIONS = POSITION_NARROW_MAPPINGS.keys
5252

@@ -125,8 +125,7 @@ def initialize(
125125
@position_narrow = position_narrow
126126
@visually_hide_title = visually_hide_title
127127

128-
@system_arguments[:tag] = "modal-dialog"
129-
@system_arguments[:role] = "dialog"
128+
@system_arguments[:tag] = "dialog"
130129
@system_arguments[:id] = @id
131130
@system_arguments[:aria] = { modal: true }
132131
@system_arguments[:aria] = merge_aria(
@@ -143,11 +142,9 @@ def initialize(
143142
"Overlay-whenNarrow",
144143
SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, @size, DEFAULT_SIZE)],
145144
"Overlay--motion-scaleFade",
146-
system_arguments[:classes]
147-
)
148-
@backdrop_classes = class_names(
149145
POSITION_MAPPINGS[fetch_or_fallback(POSITION_OPTIONS, @position, DEFAULT_POSITION)],
150-
POSITION_NARROW_MAPPINGS[fetch_or_fallback(POSITION_NARROW_MAPPINGS, @position_narrow, DEFAULT_POSITION_NARROW)]
146+
POSITION_NARROW_MAPPINGS[fetch_or_fallback(POSITION_NARROW_MAPPINGS, @position_narrow, DEFAULT_POSITION_NARROW)],
147+
system_arguments[:classes]
151148
)
152149
end
153150

app/components/primer/alpha/overlay.pcss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ anchored-position:not(.Overlay) {
1515
display: none
1616
}
1717

18-
anchored-position.not-anchored::backdrop {
18+
anchored-position.not-anchored::backdrop, dialog::backdrop {
1919
background-color: var(--overlay-backdrop-bgColor, var(--color-neutral-muted));
2020
}
2121

0 commit comments

Comments
 (0)