Skip to content

Commit 24b8fbf

Browse files
Copilotjonrohan
andauthored
Revert Dialog body scroll-lock styling from broad :has(...) to explicit body classes (#4069)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Jon Rohan <rohan@github.com>
1 parent a6702f3 commit 24b8fbf

5 files changed

Lines changed: 44 additions & 3 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/view-components": patch
3+
---
4+
5+
Revert Dialog body scroll-lock styling from broad `:has(...)` to explicit body classes

app/components/primer/alpha/dialog.pcss

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
syntax: "<length>";
2222
}
2323

24-
body:has(dialog:modal.Overlay--disableScroll) {
24+
body.has-modal {
2525
padding-right: var(--dialog-scrollgutter) !important;
26+
}
27+
28+
body.has-modal-disable-scroll {
2629
overflow: hidden !important;
2730
}
2831

app/components/primer/dialog_helper.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ function setScrollGutter(doc: Document) {
33
doc.body.style.setProperty('--dialog-scrollgutter', `${window.innerWidth - doc.body.clientWidth}px`)
44
}
55

6+
function updateBodyModalClasses(doc: Document) {
7+
doc.body.classList.toggle('has-modal', Boolean(doc.querySelector('dialog[open]')))
8+
doc.body.classList.toggle(
9+
'has-modal-disable-scroll',
10+
Boolean(doc.querySelector('dialog[open].Overlay--disableScroll')),
11+
)
12+
}
13+
614
function dialogInvokerButtonHandler(event: Event) {
715
const target = event.target as HTMLElement
816
const button = target?.closest('button')
@@ -69,6 +77,8 @@ function dialogInvokerButtonHandler(event: Event) {
6977
{once: true},
7078
)
7179
}
80+
81+
updateBodyModalClasses(dialog.ownerDocument)
7282
}
7383
}
7484

@@ -77,6 +87,7 @@ function dialogInvokerButtonHandler(event: Event) {
7787
const dialog = document.getElementById(dialogId)
7888
if (dialog instanceof HTMLDialogElement && dialog.open) {
7989
dialog.close()
90+
updateBodyModalClasses(dialog.ownerDocument)
8091
}
8192
}
8293
}
@@ -91,6 +102,7 @@ export class DialogHelperElement extends HTMLElement {
91102
const {signal} = (this.#abortController = new AbortController())
92103
document.addEventListener('click', dialogInvokerButtonHandler, true)
93104
document.addEventListener('click', this, {signal})
105+
this.dialog?.addEventListener('close', () => updateBodyModalClasses(this.dialog!.ownerDocument), {signal})
94106
new MutationObserver(records => {
95107
for (const record of records) {
96108
if (record.target === this.dialog) {
@@ -107,14 +119,17 @@ export class DialogHelperElement extends HTMLElement {
107119

108120
#handleDialogOpenAttribute() {
109121
if (!this.dialog) return
122+
const {ownerDocument} = this.dialog
110123
// We don't want to show the Dialog component as non-modal
111124
if (this.dialog.matches('[open]:not(:modal)')) {
112125
// eslint-disable-next-line no-restricted-syntax
113126
this.dialog.addEventListener('close', e => e.stopImmediatePropagation(), {once: true})
114127
this.dialog.close()
115-
setScrollGutter(this.dialog.ownerDocument)
128+
setScrollGutter(ownerDocument)
116129
this.dialog.showModal()
117130
}
131+
132+
updateBodyModalClasses(ownerDocument)
118133
}
119134

120135
handleEvent(event: MouseEvent) {

test/components/primer/alpha/dialog_test.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,22 @@ def test_renders_show_button
2727
assert_selector("[data-show-dialog-id]")
2828
end
2929

30+
def test_applies_disable_scroll_class_by_default
31+
render_inline(Primer::Alpha::Dialog.new(title: "Title")) do |component|
32+
component.with_body { "Hello" }
33+
end
34+
35+
assert_selector("dialog.Overlay--disableScroll")
36+
end
37+
38+
def test_does_not_apply_disable_scroll_class_when_disabled
39+
render_inline(Primer::Alpha::Dialog.new(title: "Title", disable_scroll: false)) do |component|
40+
component.with_body { "Hello" }
41+
end
42+
43+
refute_selector("dialog.Overlay--disableScroll")
44+
end
45+
3046
def test_renders_icon_show_button
3147
render_preview :playground, params: { icon: :ellipsis }
3248

test/css/component_specific_selectors_test.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ class ComponentSpecificSelectorsTest < Minitest::Test
3838
".Banner .Banner-close"
3939
],
4040
Primer::Alpha::Dialog => [
41-
".Overlay"
41+
".Overlay",
42+
".has-modal",
43+
".has-modal-disable-scroll"
4244
],
4345
Primer::Alpha::Layout => [
4446
".Layout-divider",

0 commit comments

Comments
 (0)