Skip to content

Commit 10a0b7c

Browse files
Merge pull request #277 from commitd/stuarthendren/issue274
feat(dialog): improves behaviour of dialogs and provides more option
2 parents aae9515 + b61afb1 commit 10a0b7c

File tree

7 files changed

+420
-97
lines changed

7 files changed

+420
-97
lines changed

.storybook/preview-head.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<style>
2+
#docs-root {
3+
isolation: isolate;
4+
}
5+
</style>

src/components/Backdrop/Backdrop.tsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { Content, Overlay, Root } from '@radix-ui/react-dialog'
2-
import React, { FC } from 'react'
1+
import { Content, Overlay, Portal, Root } from '@radix-ui/react-dialog'
2+
import React, { ComponentProps, FC } from 'react'
33
import { CSS, styled } from '../../stitches.config'
4+
import { ConditionalWrapper } from '../../utils'
45
import { overlayAnimationStyles, overlayStyles } from '../Overlay'
56

67
const StyledOverlay = styled(Overlay, overlayStyles, overlayAnimationStyles, {
@@ -33,6 +34,10 @@ type BackdropProps = React.ComponentProps<typeof Root> & {
3334
overlayCss?: CSS
3435
/** Modify the default styling of the content wrapper */
3536
contentCss?: CSS
37+
/** By default, portals your overlay and content parts into the body, set false to add at dom location. */
38+
portalled?: boolean
39+
/** Specify a container element to portal the content into. */
40+
container?: ComponentProps<typeof Portal>['container']
3641
}
3742

3843
/**
@@ -45,13 +50,22 @@ type BackdropProps = React.ComponentProps<typeof Root> & {
4550
export const Backdrop: FC<BackdropProps> = ({
4651
overlayCss,
4752
contentCss,
53+
container,
54+
portalled = true,
4855
children,
4956
...props
5057
}) => {
5158
return (
5259
<Root {...props}>
53-
<StyledOverlay css={overlayCss} />
54-
<StyledContent css={contentCss}>{children}</StyledContent>
60+
<ConditionalWrapper
61+
condition={portalled}
62+
wrapper={(child) => <Portal container={container}>{child}</Portal>}
63+
>
64+
<>
65+
<StyledOverlay css={overlayCss} />
66+
<StyledContent css={contentCss}>{children}</StyledContent>
67+
</>
68+
</ConditionalWrapper>
5569
</Root>
5670
)
5771
}

src/components/ComponentsProvider/ComponentsProvider.tsx

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, { FC, PropsWithChildren } from 'react'
2+
import { CSSProps, styled } from '../../stitches.config'
23
import { ConditionalWrapper } from '../../utils'
34
import { ThemeProvider, ThemeProviderProps } from '../ThemeProvider'
45
import { ToastProvider, ToastViewport } from '../Toast'
@@ -40,7 +41,15 @@ export type ComponentsProviderProps = {
4041
* Toast viewport configuration options
4142
*/
4243
viewport?: false | ToastViewportPropsWithoutChildren
43-
}
44+
/**
45+
* By default the childre are put into their own stacking context to better separate the content from the portalled dialog elements. Set false to turn this off and controll it yourself.
46+
*/
47+
isolated?: boolean
48+
} & CSSProps
49+
50+
const Isolate = styled('div', {
51+
variants: { isolated: { false: {}, true: { isolation: 'isolate' } } },
52+
})
4453

4554
/**
4655
* The `ComponentsProvider` should wrap you application.
@@ -53,7 +62,15 @@ export type ComponentsProviderProps = {
5362
*/
5463
export const ComponentsProvider: FC<
5564
PropsWithChildren<ComponentsProviderProps>
56-
> = ({ theme = {}, tooltip = {}, toast = {}, viewport = {}, children }) => (
65+
> = ({
66+
theme = {},
67+
tooltip = {},
68+
toast = {},
69+
viewport = {},
70+
css,
71+
isolated = true,
72+
children,
73+
}) => (
5774
<ConditionalWrapper
5875
condition={toast}
5976
wrapper={(wrappedChildren) => (
@@ -73,7 +90,9 @@ export const ComponentsProvider: FC<
7390
)}
7491
>
7592
<>
76-
{children}
93+
<Isolate css={css as any} isolated={isolated}>
94+
{children}
95+
</Isolate>
7796
{viewport && <ToastViewport {...viewport} />}
7897
</>
7998
</ConditionalWrapper>

src/components/ConfirmDialog/ConfirmDialog.tsx

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import {
44
Content,
55
Description,
66
Overlay,
7+
Portal,
78
Root,
89
Title,
910
Trigger,
1011
} from '@radix-ui/react-alert-dialog'
1112
import React, { ComponentProps, ElementRef, FC, forwardRef } from 'react'
1213
import type { CSSProps } from '../../stitches.config'
1314
import { CSS, styled } from '../../stitches.config'
15+
import { ConditionalWrapper } from '../../utils'
1416
import { Button } from '../Button'
1517
import { Heading } from '../Heading'
1618
import { overlayAnimationStyles, overlayStyles } from '../Overlay'
@@ -56,11 +58,6 @@ export const StyledContent = styled(
5658
overlayAnimationStyles
5759
)
5860

59-
type ConfirmDialogProps = ComponentProps<typeof Root> & {
60-
/** Modify the default styling of the overlay */
61-
overlayCss?: CSS
62-
}
63-
6461
/**
6562
* The `ConfirmDialog` component can be used get confirmation of an action from the user.
6663
* This is done by isolating the user from the main window by overlaying
@@ -80,39 +77,55 @@ type ConfirmDialogProps = ComponentProps<typeof Root> & {
8077
*
8178
* Based on [Radix Alert Dialog](https://radix-ui.com/primitives/docs/components/alert-dialog).
8279
*/
83-
export const ConfirmDialog: FC<ConfirmDialogProps> = ({
84-
children,
85-
overlayCss,
86-
...props
87-
}) => {
88-
return (
89-
<Root {...props}>
90-
<StyledOverlay css={overlayCss} />
91-
{children}
92-
</Root>
93-
)
94-
}
80+
export const ConfirmDialog = Root
9581

9682
type ConfirmDialogContentProps = ComponentProps<typeof StyledContent> &
9783
CSSProps & {
9884
/** Add a title to the content. */
9985
title?: string
10086
/** Add a description to the content. */
10187
description?: string
88+
/** Modify the default styling of the overlay */
89+
overlayCss?: CSS
90+
/** By default, portals your overlay and content parts into the body, set false to add at dom location. */
91+
portalled?: boolean
92+
/** Specify a container element to portal the content into. */
93+
container?: ComponentProps<typeof Portal>['container']
10294
}
10395

10496
export const ConfirmDialogContent = forwardRef<
10597
ElementRef<typeof StyledContent>,
10698
ConfirmDialogContentProps
107-
>(({ title, description, children, ...props }, forwardedRef) => (
108-
<StyledContent {...props} ref={forwardedRef}>
109-
{title && <ConfirmDialogTitle>{title}</ConfirmDialogTitle>}
110-
{description && (
111-
<ConfirmDialogDescription>{description}</ConfirmDialogDescription>
112-
)}
113-
{children}
114-
</StyledContent>
115-
))
99+
>(
100+
(
101+
{
102+
title,
103+
description,
104+
overlayCss,
105+
container,
106+
portalled = true,
107+
children,
108+
...props
109+
},
110+
forwardedRef
111+
) => (
112+
<ConditionalWrapper
113+
condition={portalled}
114+
wrapper={(child) => <Portal container={container}>{child}</Portal>}
115+
>
116+
<>
117+
<StyledOverlay css={overlayCss} />
118+
<StyledContent {...props} ref={forwardedRef}>
119+
{title && <ConfirmDialogTitle>{title}</ConfirmDialogTitle>}
120+
{description && (
121+
<ConfirmDialogDescription>{description}</ConfirmDialogDescription>
122+
)}
123+
{children}
124+
</StyledContent>
125+
</>
126+
</ConditionalWrapper>
127+
)
128+
)
116129
ConfirmDialogContent.toString = () => `.${StyledContent.className}`
117130

118131
export const ConfirmDialogTrigger = forwardRef<

0 commit comments

Comments
 (0)