Skip to content

Commit 7d2172f

Browse files
committed
Revert "Fix misc issues with Dialog v2 (#3444)"
This reverts commit d3146ce.
1 parent 44688c6 commit 7d2172f

28 files changed

+888
-1000
lines changed

.changeset/strange-geese-drive.md

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

docs/content/Dialog.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ status: Alpha
44
source: https://github.com/primer/react/blob/main/src/Dialog
55
---
66

7-
import data from '../../src/Dialog/Dialog.docs.json'
7+
import data from '../../src/Dialog.docs.json'
88

99
The dialog component is used for all modals. It renders on top of the rest of the app with an overlay.
1010

docs/content/drafts/Dialog.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ componentId: dialog
44
status: Draft
55
---
66

7-
import data from '../../../src/drafts/Dialog2/Dialog.docs.json'
7+
import data from '../../../src/Dialog/Dialog.docs.json'
88

99
```js
1010
import {Dialog} from '@primer/react/drafts'

docs/src/@primer/gatsby-theme-doctocat/nav.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@
7070
url: /CounterLabel
7171
- title: Details
7272
url: /Details
73+
- title: Dialog
74+
url: /Dialog
7375
- title: Flash
7476
url: /Flash
7577
- title: FormControl

src/DataTable/ErrorDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import {ConfirmationDialog} from '../drafts/Dialog2/ConfirmationDialog'
2+
import {ConfirmationDialog} from '../Dialog/ConfirmationDialog'
33

44
export type TableErrorDialogProps = React.PropsWithChildren<{
55
/**

src/Dialog.docs.json

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"id": "dialog",
3+
"name": "Dialog",
4+
"status": "alpha",
5+
"a11yReviewed": false,
6+
"stories": [],
7+
"props": [
8+
{
9+
"name": "isOpen",
10+
"type": "boolean",
11+
"description": "Whether or not the dialog is open"
12+
},
13+
{
14+
"name": "onDismiss",
15+
"type": "() => void",
16+
"description": "Function that will be called when the dialog is closed"
17+
},
18+
{
19+
"name": "returnFocusRef",
20+
"type": " React.RefObject<HTMLElement>",
21+
"description": "The element to restore focus back to after the `Dialog` is closed"
22+
},
23+
{
24+
"name": "initialFocusRef",
25+
"type": " React.RefObject<HTMLElement>",
26+
"description": "Element inside of the `Dialog` you'd like to be focused when the Dialog is opened. If nothing is passed to `initialFocusRef` the close button is focused."
27+
},
28+
{
29+
"name": "aria-labelledby",
30+
"type": "string",
31+
"description": "Pass an id to use for the aria-label. Use either a `aria-label` or an `aria-labelledby` but not both."
32+
},
33+
{
34+
"name": "aria-label",
35+
"type": "string",
36+
"description": "Pass a label to be used to describe the Dialog. Use either a `aria-label` or an `aria-labelledby` but not both."
37+
},
38+
{
39+
"name": "sx",
40+
"type": "SystemStyleObject"
41+
}
42+
],
43+
"subcomponents": [
44+
{
45+
"name": "Dialog.Header",
46+
"props": [
47+
{
48+
"name": "sx",
49+
"type": "SystemStyleObject"
50+
}
51+
]
52+
}
53+
]
54+
}

src/Dialog.tsx

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import React, {forwardRef, useRef} from 'react'
2+
import styled from 'styled-components'
3+
import {IconButton} from './Button'
4+
import {get} from './constants'
5+
import Box from './Box'
6+
import useDialog from './hooks/useDialog'
7+
import sx, {SxProp} from './sx'
8+
import Text from './Text'
9+
import {ComponentProps} from './utils/types'
10+
import {useRefObjectAsForwardedRef} from './hooks/useRefObjectAsForwardedRef'
11+
import {XIcon} from '@primer/octicons-react'
12+
13+
const noop = () => null
14+
15+
type StyledDialogBaseProps = {
16+
narrow?: boolean
17+
wide?: boolean
18+
} & SxProp
19+
20+
const DialogBase = styled.div<StyledDialogBaseProps>`
21+
box-shadow: ${get('shadows.shadow.large')};
22+
border-radius: ${get('radii.2')};
23+
position: fixed;
24+
top: 0;
25+
left: 50%;
26+
transform: translateX(-50%);
27+
max-height: 80vh;
28+
z-index: 999;
29+
margin: 10vh auto;
30+
background-color: ${get('colors.canvas.default')};
31+
width: ${props => (props.narrow ? '320px' : props.wide ? '640px' : '440px')};
32+
outline: none;
33+
34+
@media screen and (max-width: 750px) {
35+
width: 100vw;
36+
margin: 0;
37+
border-radius: 0;
38+
height: 100vh;
39+
}
40+
41+
${sx};
42+
`
43+
44+
const DialogHeaderBase = styled(Box)<SxProp>`
45+
border-radius: ${get('radii.2')} ${get('radii.2')} 0px 0px;
46+
border-bottom: 1px solid ${get('colors.border.default')};
47+
display: flex;
48+
49+
@media screen and (max-width: 750px) {
50+
border-radius: 0px;
51+
}
52+
53+
${sx};
54+
`
55+
export type DialogHeaderProps = ComponentProps<typeof DialogHeaderBase>
56+
57+
function DialogHeader({theme, children, backgroundColor = 'canvas.subtle', ...rest}: DialogHeaderProps) {
58+
if (React.Children.toArray(children).every(ch => typeof ch === 'string')) {
59+
children = (
60+
<Text theme={theme} color="fg.default" fontSize={1} fontWeight="bold" fontFamily="sans-serif">
61+
{children}
62+
</Text>
63+
)
64+
}
65+
66+
return (
67+
<DialogHeaderBase theme={theme} p={3} backgroundColor={backgroundColor} {...rest}>
68+
{children}
69+
</DialogHeaderBase>
70+
)
71+
}
72+
73+
const Overlay = styled.span`
74+
&:before {
75+
position: fixed;
76+
top: 0;
77+
right: 0;
78+
bottom: 0;
79+
left: 0;
80+
display: block;
81+
cursor: default;
82+
content: ' ';
83+
background: transparent;
84+
z-index: 99;
85+
background: ${get('colors.primer.canvas.backdrop')};
86+
}
87+
`
88+
89+
type InternalDialogProps = {
90+
isOpen?: boolean
91+
onDismiss?: () => void
92+
initialFocusRef?: React.RefObject<HTMLElement>
93+
returnFocusRef?: React.RefObject<HTMLElement>
94+
} & ComponentProps<typeof DialogBase>
95+
96+
const Dialog = forwardRef<HTMLDivElement, InternalDialogProps>(
97+
({children, onDismiss = noop, isOpen, initialFocusRef, returnFocusRef, ...props}, forwardedRef) => {
98+
const overlayRef = useRef(null)
99+
const modalRef = useRef<HTMLDivElement>(null)
100+
useRefObjectAsForwardedRef(forwardedRef, modalRef)
101+
const closeButtonRef = useRef(null)
102+
103+
const onCloseClick = () => {
104+
onDismiss()
105+
if (returnFocusRef && returnFocusRef.current) {
106+
returnFocusRef.current.focus()
107+
}
108+
}
109+
110+
const {getDialogProps} = useDialog({
111+
modalRef,
112+
onDismiss: onCloseClick,
113+
isOpen,
114+
initialFocusRef,
115+
closeButtonRef,
116+
returnFocusRef,
117+
overlayRef,
118+
})
119+
return isOpen ? (
120+
<>
121+
<Overlay ref={overlayRef} />
122+
<DialogBase tabIndex={-1} ref={modalRef} role="dialog" aria-modal="true" {...props} {...getDialogProps()}>
123+
<IconButton
124+
icon={XIcon}
125+
ref={closeButtonRef}
126+
onClick={onCloseClick}
127+
sx={{position: 'absolute', top: '8px', right: '16px'}}
128+
aria-label="Close"
129+
variant="invisible"
130+
/>
131+
{children}
132+
</DialogBase>
133+
</>
134+
) : null
135+
},
136+
)
137+
138+
DialogHeader.propTypes = {
139+
...Box.propTypes,
140+
}
141+
142+
DialogHeader.displayName = 'Dialog.Header'
143+
Dialog.displayName = 'Dialog'
144+
145+
export type DialogProps = ComponentProps<typeof Dialog>
146+
export default Object.assign(Dialog, {Header: DialogHeader})

src/drafts/Dialog2/ConfirmationDialog.tsx renamed to src/Dialog/ConfirmationDialog.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React, {useCallback} from 'react'
22
import {createRoot} from 'react-dom/client'
33
import styled from 'styled-components'
4-
import Box from '../../Box'
5-
import {ThemeProvider, useTheme, ThemeProviderProps} from '../../ThemeProvider'
4+
import Box from '../Box'
5+
import {ThemeProvider, useTheme, ThemeProviderProps} from '../ThemeProvider'
66
import {FocusKeys} from '@primer/behaviors'
7-
import {get} from '../../constants'
8-
import {Dialog, DialogProps, DialogHeaderProps, DialogButtonProps} from './Dialog'
9-
import {useFocusZone} from '../../hooks/useFocusZone'
7+
import {get} from '../constants'
8+
import {Dialog, DialogProps, DialogHeaderProps, DialogButtonProps} from '../Dialog/Dialog'
9+
import {useFocusZone} from '../hooks/useFocusZone'
1010

1111
/**
1212
* Props to customize the ConfirmationDialog.

src/Dialog/Dialog.docs.json

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,58 @@
11
{
2-
"id": "dialog",
2+
"id": "drafts_dialog",
33
"name": "Dialog",
4-
"status": "alpha",
4+
"status": "draft",
55
"a11yReviewed": false,
66
"stories": [],
77
"props": [
88
{
9-
"name": "isOpen",
10-
"type": "boolean",
11-
"description": "Whether or not the dialog is open"
9+
"name": "title",
10+
"type": "React.ReactNode",
11+
"description": "Title of the Dialog. Also serves as the aria-label for this Dialog."
1212
},
1313
{
14-
"name": "onDismiss",
15-
"type": "() => void",
16-
"description": "Function that will be called when the dialog is closed"
14+
"name": "subtitle",
15+
"type": "React.ReactNode",
16+
"description": "The Dialog's subtitle. Optional. Rendered below the title in smaller type with less contrast. Also serves as the aria-describedby for this Dialog."
1717
},
1818
{
19-
"name": "returnFocusRef",
20-
"type": " React.RefObject<HTMLElement>",
21-
"description": "The element to restore focus back to after the `Dialog` is closed"
19+
"name": "renderHeader",
20+
"type": "React.FunctionComponent<React.PropsWithChildren<DialogHeaderProps>>",
21+
"description": "Provide a custom renderer for the dialog header. This content is rendered directly into the dialog body area, full bleed from edge to edge, top to the start of the body element. Warning: using a custom renderer may violate Primer UX principles."
2222
},
2323
{
24-
"name": "initialFocusRef",
25-
"type": " React.RefObject<HTMLElement>",
26-
"description": "Element inside of the `Dialog` you'd like to be focused when the Dialog is opened. If nothing is passed to `initialFocusRef` the close button is focused."
24+
"name": "renderBody",
25+
"type": "React.FunctionComponent<React.PropsWithChildren<DialogProps>>",
26+
"description": "Provide a custom render function for the dialog body. This content is rendered directly into the dialog body area, full bleed from edge to edge, header to footer. Warning: using a custom renderer may violate Primer UX principles."
2727
},
2828
{
29-
"name": "aria-labelledby",
30-
"type": "string",
31-
"description": "Pass an id to use for the aria-label. Use either a `aria-label` or an `aria-labelledby` but not both."
29+
"name": "renderFooter",
30+
"type": "React.FunctionComponent<React.PropsWithChildren<DialogProps>>",
31+
"description": "Provide a custom render function for the dialog footer. This content is rendered directly into the dialog footer area, full bleed from edge to edge, end of the body element to bottom. Warning: using a custom renderer may violate Primer UX principles."
3232
},
3333
{
34-
"name": "aria-label",
35-
"type": "string",
36-
"description": "Pass a label to be used to describe the Dialog. Use either a `aria-label` or an `aria-labelledby` but not both."
34+
"name": "footerButtons",
35+
"type": "DialogButtonProps[]",
36+
"description": "Specifies the buttons to be rendered in the Dialog footer."
3737
},
3838
{
39-
"name": "sx",
40-
"type": "SystemStyleObject"
39+
"name": "onClose",
40+
"type": "(gesture: 'close-button' | 'escape') => void",
41+
"description": "This method is invoked when a gesture to close the dialog is used (either an Escape key press or clicking the 'X' in the top-right corner). The gesture argument indicates the gesture that was used to close the dialog (either 'close-button' or 'escape')."
42+
},
43+
{
44+
"name": "role",
45+
"type": "'dialog' | 'alertdialog'",
46+
"description": "The ARIA role to assign to this dialog."
47+
},
48+
{
49+
"name": "width",
50+
"type": "'small' | 'medium' | 'large' | 'xlarge'"
51+
},
52+
{
53+
"name": "height",
54+
"type": "'small' | 'large' | 'auto'"
4155
}
4256
],
43-
"subcomponents": [
44-
{
45-
"name": "Dialog.Header",
46-
"props": [
47-
{
48-
"name": "sx",
49-
"type": "SystemStyleObject"
50-
}
51-
]
52-
}
53-
]
57+
"subcomponents": []
5458
}

0 commit comments

Comments
 (0)