Skip to content

Commit 41b4421

Browse files
committed
only renders a footer border on dialogs with a scrolling body
1 parent 79e9ac1 commit 41b4421

File tree

2 files changed

+76
-5
lines changed

2 files changed

+76
-5
lines changed

packages/react/src/Dialog/Dialog.module.css

+30-2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@
3838
}
3939
}
4040

41+
/* Used to determine whether there should be a border between the body and footer */
42+
@keyframes detect-scroll {
43+
from,
44+
to {
45+
--can-scroll: 1;
46+
}
47+
}
48+
4149
.Backdrop {
4250
position: fixed;
4351
top: 0;
@@ -212,6 +220,28 @@
212220
flex-grow: 1;
213221
}
214222

223+
/*
224+
Add a border between the body and footer if:
225+
- the dialog has a footer
226+
- the dialog has a body that can scroll
227+
- the browser supports the `animation-timeline` property and its `scroll()` function
228+
*/
229+
.Dialog:has(.Footer) {
230+
--can-scroll: 0;
231+
232+
.DialogOverflowWrapper {
233+
animation: detect-scroll;
234+
animation-timeline: scroll(self);
235+
236+
/* If the browser does not support the `animation-timeline` property, always show a border */
237+
border-bottom: var(--borderWidth-default) solid var(--borderColor-default);
238+
239+
@supports (animation-timeline: scroll(self)) {
240+
border-bottom: calc(1px * var(--can-scroll)) solid var(--borderColor-default);
241+
}
242+
}
243+
}
244+
215245
.Header {
216246
z-index: 1;
217247
padding: var(--base-size-8);
@@ -246,8 +276,6 @@
246276
flex-flow: wrap;
247277
justify-content: flex-end;
248278
padding: var(--base-size-16);
249-
/* stylelint-disable-next-line primer/box-shadow */
250-
box-shadow: 0 -1px 0 var(--borderColor-default);
251279
gap: var(--base-size-8);
252280
flex-shrink: 0;
253281

packages/react/src/Dialog/Dialog.tsx

+46-3
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,35 @@ const StyledDialog = toggleStyledComponent(
370370
}
371371
}
372372
373+
/* Used to determine whether there should be a border between the body and footer */
374+
@keyframes detect-scroll {
375+
from,
376+
to {
377+
--can-scroll: 1;
378+
}
379+
}
380+
381+
/*
382+
Add a border between the body and footer if:
383+
- the dialog has a footer
384+
- the dialog has a body that can scroll
385+
- the browser supports the animation-timeline property and its scroll() function
386+
*/
387+
&:has([data-component='Dialog.Footer']) {
388+
--can-scroll: 0;
389+
[data-component='Dialog.Body'] {
390+
animation: detect-scroll;
391+
animation-timeline: scroll(self);
392+
393+
/* If the browser does not support the animation-timeline property, always show a border */
394+
border-bottom: var(--borderWidth-default) solid var(--borderColor-default);
395+
396+
@supports (animation-timeline: scroll(self)) {
397+
border-bottom: calc(1px * var(--can-scroll)) solid var(--borderColor-default);
398+
}
399+
}
400+
}
401+
373402
${sx};
374403
`,
375404
)
@@ -527,7 +556,13 @@ const _Dialog = React.forwardRef<HTMLDivElement, React.PropsWithChildren<DialogP
527556
className={clsx(className, enabled && classes.Dialog)}
528557
>
529558
{header}
530-
<ScrollableRegion aria-labelledby={dialogLabelId} className={classes.DialogOverflowWrapper}>
559+
<ScrollableRegion
560+
// `data-component` is used for a `:has` selector for `styled-components`.
561+
// This can be removed when we remove `styled-components`.
562+
data-component="Dialog.Body"
563+
aria-labelledby={dialogLabelId}
564+
className={classes.DialogOverflowWrapper}
565+
>
531566
{body}
532567
</ScrollableRegion>
533568
{footer}
@@ -623,7 +658,6 @@ const StyledFooter = toggleStyledComponent(
623658
CSS_MODULES_FEATURE_FLAG,
624659
'div',
625660
styled.div<SxProp>`
626-
box-shadow: 0 -1px 0 ${get('colors.border.default')};
627661
padding: ${get('space.3')};
628662
display: flex;
629663
flex-flow: wrap;
@@ -644,7 +678,16 @@ type StyledFooterProps = React.ComponentProps<'div'> & SxProp
644678

645679
const Footer = React.forwardRef<HTMLElement, StyledFooterProps>(function Footer({className, ...rest}, forwardRef) {
646680
const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG)
647-
return <StyledFooter ref={forwardRef} className={clsx(className, enabled && classes.Footer)} {...rest} />
681+
return (
682+
<StyledFooter
683+
ref={forwardRef}
684+
className={clsx(className, enabled && classes.Footer)}
685+
// `data-component` is used for a `:has` selector for `styled-components`.
686+
// This can be removed when we remove `styled-components`.
687+
data-component="Dialog.Footer"
688+
{...rest}
689+
/>
690+
)
648691
})
649692
Footer.displayName = 'Dialog.Footer'
650693

0 commit comments

Comments
 (0)