Skip to content

Commit aa7cf41

Browse files
GregOnNetGregor Woiwode
authored and
Gregor Woiwode
committed
feat(dialog): introduce Dialog.Trigger & Dialog.Portal
1 parent 2c832f5 commit aa7cf41

File tree

1 file changed

+48
-19
lines changed
  • packages/kit-headless/src/components/dialog

1 file changed

+48
-19
lines changed

Diff for: packages/kit-headless/src/components/dialog/dialog.tsx

+48-19
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,46 @@ import {
22
$,
33
QRL,
44
QwikMouseEvent,
5+
Signal,
56
Slot,
67
component$,
78
createContextId,
89
useComputed$,
10+
useContext,
911
useContextProvider,
12+
useOn,
1013
useSignal,
1114
useStore,
12-
useVisibleTask$,
1315
} from '@builder.io/qwik';
1416

1517
export type DialogState = {
1618
opened: boolean;
19+
dialogRef: Signal<HTMLDialogElement | undefined>;
1720
};
1821

1922
export type DialogContext = {
2023
state: DialogState;
24+
2125
open: QRL<() => void>;
2226
close: QRL<() => void>;
23-
};
24-
25-
export type RootProps = {
26-
open: boolean;
27-
type?: 'modal' | 'bottom-sheet' | 'side-nav';
27+
closeOnDialogClick: QRL<
28+
(
29+
event: QwikMouseEvent<HTMLDialogElement, MouseEvent>,
30+
element: HTMLDialogElement
31+
) => void
32+
>;
2833
};
2934

3035
export const dialogContext = createContextId<DialogContext>('dialog');
3136

32-
export const Root = component$((props: RootProps) => {
33-
const dialogRef = useSignal<HTMLDialogElement>();
34-
const classes = useComputed$(() => [props.type ?? 'modal']);
35-
37+
export const Root = component$(() => {
3638
const state = useStore({
3739
opened: false,
40+
dialogRef: useSignal<HTMLDialogElement>(),
3841
});
3942

4043
const openDialog$ = $(() => {
41-
const dialog = dialogRef.value;
44+
const dialog = state.dialogRef.value;
4245

4346
if (!dialog) {
4447
throw new Error(
@@ -51,7 +54,7 @@ export const Root = component$((props: RootProps) => {
5154
});
5255

5356
const closeDialog$ = $(() => {
54-
const dialog = dialogRef.value;
57+
const dialog = state.dialogRef.value;
5558

5659
if (!dialog) {
5760
throw new Error(
@@ -63,7 +66,7 @@ export const Root = component$((props: RootProps) => {
6366
state.opened = false;
6467
});
6568

66-
const handleClick$ = $(
69+
const closeOnDialogClick$ = $(
6770
(
6871
event: QwikMouseEvent<HTMLDialogElement, MouseEvent>,
6972
element: HTMLDialogElement
@@ -76,21 +79,47 @@ export const Root = component$((props: RootProps) => {
7679

7780
const context: DialogContext = {
7881
state,
82+
7983
open: openDialog$,
8084
close: closeDialog$,
85+
closeOnDialogClick: closeOnDialogClick$,
8186
};
8287

8388
useContextProvider(dialogContext, context);
8489

85-
useVisibleTask$(async ({ track }) => {
86-
const shallBeOpened = track(() => props.open);
90+
return <Slot />;
91+
});
8792

88-
shallBeOpened ? await openDialog$() : await closeDialog$();
89-
});
93+
export const Trigger = component$(() => {
94+
const context = useContext(dialogContext);
95+
96+
useOn(
97+
'click',
98+
$(() => context.open())
99+
);
100+
101+
return (
102+
<div role="button">
103+
<Slot />
104+
</div>
105+
);
106+
});
107+
108+
export type PortalProps = {
109+
type?: 'modal' | 'bottom-sheet' | 'side-nav';
110+
};
111+
112+
export const Portal = component$((props: PortalProps) => {
113+
const context = useContext(dialogContext);
114+
const classes = useComputed$(() => [props.type ?? 'modal']);
90115

91116
return (
92-
<dialog class={classes} ref={dialogRef} onClick$={handleClick$}>
93-
<Slot></Slot>
117+
<dialog
118+
class={classes}
119+
ref={context.state.dialogRef}
120+
onClick$={context.closeOnDialogClick}
121+
>
122+
<Slot />
94123
</dialog>
95124
);
96125
});

0 commit comments

Comments
 (0)