Skip to content

Commit 7f01208

Browse files
committed
feat(dialog): add dialog
1 parent 51614ab commit 7f01208

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { mount } from 'cypress-ct-qwik';
2+
import * as Dialog from './dialog';
3+
4+
describe('Dialog', () => {
5+
it('renders an opened Dialog', () => {
6+
mount(
7+
<Dialog.Root open={true}>
8+
<h2>Hello World!</h2>
9+
</Dialog.Root>
10+
);
11+
12+
cy.get('dialog').should('contain', 'Hello World');
13+
});
14+
15+
it('does not show if Dialog is closed', () => {
16+
mount(
17+
<Dialog.Root open={false}>
18+
<h2>Hello World!</h2>
19+
</Dialog.Root>
20+
);
21+
22+
cy.get('dialog').should('not.be.visible');
23+
});
24+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import {
2+
$,
3+
QRL,
4+
QwikMouseEvent,
5+
Slot,
6+
component$,
7+
createContextId,
8+
useComputed$,
9+
useContextProvider,
10+
useSignal,
11+
useStore,
12+
useVisibleTask$,
13+
} from '@builder.io/qwik';
14+
15+
export type DialogState = {
16+
opened: boolean;
17+
};
18+
19+
export type DialogContext = {
20+
state: DialogState;
21+
open: QRL<() => void>;
22+
close: QRL<() => void>;
23+
};
24+
25+
export type RootProps = {
26+
open: boolean;
27+
type?: 'modal' | 'bottom-sheet' | 'side-nav';
28+
};
29+
30+
export const dialogContext = createContextId<DialogContext>('dialog');
31+
32+
export const Root = component$((props: RootProps) => {
33+
const dialogRef = useSignal<HTMLDialogElement>();
34+
const classes = useComputed$(() => [props.type ?? 'modal']);
35+
36+
const state = useStore({
37+
opened: false,
38+
});
39+
40+
const openDialog$ = $(() => {
41+
const dialog = dialogRef.value;
42+
43+
if (!dialog) {
44+
throw new Error(
45+
'[Qwik UI Dialog]: Cannot open the Dialog. <dialog>-Element not found.'
46+
);
47+
}
48+
49+
dialog.showModal();
50+
state.opened = true;
51+
});
52+
53+
const closeDialog$ = $(() => {
54+
const dialog = dialogRef.value;
55+
56+
if (!dialog) {
57+
throw new Error(
58+
'[Qwik UI Dialog]: Cannot close the Dialog. <dialog>-Element not found.'
59+
);
60+
}
61+
62+
dialog.close();
63+
state.opened = false;
64+
});
65+
66+
const handleClick$ = $(
67+
(
68+
event: QwikMouseEvent<HTMLDialogElement, MouseEvent>,
69+
element: HTMLDialogElement
70+
) => {
71+
if (event.target !== element) return;
72+
73+
return closeDialog$();
74+
}
75+
);
76+
77+
const context: DialogContext = {
78+
state,
79+
open: openDialog$,
80+
close: closeDialog$,
81+
};
82+
83+
useContextProvider(dialogContext, context);
84+
85+
useVisibleTask$(async ({ track }) => {
86+
const shallBeOpened = track(() => props.open);
87+
88+
shallBeOpened ? await openDialog$() : await closeDialog$();
89+
});
90+
91+
return (
92+
<dialog class={classes} ref={dialogRef} onClick$={handleClick$}>
93+
<Slot></Slot>
94+
</dialog>
95+
);
96+
});

0 commit comments

Comments
 (0)