Skip to content

Commit 8f106d1

Browse files
authored
feat: add support of non visible backdrop to the experimental Dialog component (#535)
1 parent 05222f3 commit 8f106d1

File tree

4 files changed

+68
-4
lines changed

4 files changed

+68
-4
lines changed

src/components/experimental/Backdrop/Backdrop.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,33 @@ import { ModalOverlayProps, ModalOverlay } from 'react-aria-components';
33
import { getSemanticHslValue } from '../../../essentials/experimental';
44
import { Elevation } from '../../../essentials';
55

6-
type BackdropProps = ModalOverlayProps;
6+
interface BackdropProps extends ModalOverlayProps {
7+
isBackdropVisible?: boolean;
8+
}
79

8-
const Backdrop = styled(ModalOverlay)`
10+
const Backdrop = styled(ModalOverlay)<{ isBackdropVisible?: boolean }>`
911
position: fixed;
1012
top: 0;
1113
left: 0;
1214
width: 100vw;
1315
height: var(--visual-viewport-height);
14-
background: hsla(${getSemanticHslValue('on-surface')}, 60%);
16+
background: ${props =>
17+
props.isBackdropVisible !== false ? `hsla(${getSemanticHslValue('on-surface')}, 60%)` : 'transparent'};
1518
display: flex;
1619
align-items: center;
1720
justify-content: center;
1821
z-index: ${Elevation.DIMMING};
1922
23+
${props =>
24+
props.isBackdropVisible === false &&
25+
`
26+
pointer-events: none;
27+
28+
& > * {
29+
pointer-events: auto;
30+
}
31+
`}
32+
2033
&[data-entering] {
2134
animation: backdrop-fade 200ms;
2235
}

src/components/experimental/Dialog/Dialog.spec.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,12 @@ describe('Dialog', () => {
9292
fireEvent.click(screen.getByLabelText('Accept Terms'));
9393
expect(handleCheckbox).toHaveBeenCalled();
9494
});
95+
96+
it('correctly renders the component when isBackdropVisible is false', () => {
97+
render(<Dialog {...defaultProps} isBackdropVisible={false} />);
98+
99+
expect(screen.getByText('Test Headline')).toBeInTheDocument();
100+
expect(screen.getByText('Test Subtitle')).toBeInTheDocument();
101+
expect(screen.getByRole('dialog')).toBeInTheDocument();
102+
});
95103
});

src/components/experimental/Dialog/Dialog.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ interface DialogProps extends Omit<BackdropProps, 'isDismissable' | 'isKeyboardD
4747
dismissButton?: ReactNode;
4848
actionButton: ReactNode;
4949
body?: ReactNode;
50+
isBackdropVisible?: boolean;
5051
}
5152

5253
const Dialog = ({
@@ -56,9 +57,10 @@ const Dialog = ({
5657
dismissButton,
5758
actionButton,
5859
body,
60+
isBackdropVisible = true,
5961
...props
6062
}: DialogProps): ReactElement => (
61-
<Backdrop {...props} isDismissable={false} isKeyboardDismissDisabled>
63+
<Backdrop {...props} isDismissable={false} isKeyboardDismissDisabled isBackdropVisible={isBackdropVisible}>
6264
<StyledModal role={role}>
6365
<Card>
6466
<HeadlineText slot="title">{headline}</HeadlineText>

src/components/experimental/Dialog/docs/Dialog.stories.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ const meta: Meta = {
1919
component: Dialog,
2020
parameters: {
2121
layout: 'centered'
22+
},
23+
argTypes: {
24+
isBackdropVisible: {
25+
control: 'boolean',
26+
description: 'Whether to show the backdrop behind the dialog',
27+
defaultValue: true
28+
}
2229
}
2330
};
2431

@@ -93,6 +100,40 @@ export const Alert: Story = {
93100
}
94101
};
95102

103+
export const WithInvisibleBackdrop: Story = {
104+
render: () => {
105+
const [isOpen, setIsOpen] = useState(false);
106+
107+
return (
108+
<>
109+
<Button onPress={() => setIsOpen(true)}>Open dialog without backdrop</Button>
110+
<Dialog
111+
isOpen={isOpen}
112+
onOpenChange={setIsOpen}
113+
isBackdropVisible={false}
114+
headline="No Backdrop Dialog"
115+
subtitle="This dialog has no visible backdrop"
116+
dismissButton={
117+
<Button emphasis="secondary" onPress={() => setIsOpen(false)}>
118+
Cancel
119+
</Button>
120+
}
121+
actionButton={
122+
<Button
123+
onPress={() => {
124+
action('Action')();
125+
setIsOpen(false);
126+
}}
127+
>
128+
Confirm
129+
</Button>
130+
}
131+
/>
132+
</>
133+
);
134+
}
135+
};
136+
96137
export const WithCheckboxesAsBody: Story = {
97138
render: () => {
98139
const [isOpen, setIsOpen] = useState(false);

0 commit comments

Comments
 (0)