Skip to content

Commit 0da3e6b

Browse files
thejacksheltonGregOnNet
authored andcommitted
feat(modal): transition support, fixed type errors in spec
1 parent cee0023 commit 0da3e6b

File tree

5 files changed

+122
-5
lines changed

5 files changed

+122
-5
lines changed

apps/website/src/routes/docs/headless/(components)/modal/examples.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ import alertDialogExampleCode from './examples/alert-dialog?raw';
2323
import Animation from './examples/animation';
2424
import animationExampleCode from './examples/animation?raw';
2525

26+
import Transition from './examples/transition';
27+
import transitionExampleCode from './examples/transition?raw';
28+
2629
import buildingBlocksSnip from './examples/building-blocks-snip?raw';
2730
import pageLoadSnip from './examples/page-load-snip?raw';
2831
import animationSnip from './examples/animation-snip.css?raw';
@@ -65,6 +68,10 @@ export const examples: Record<string, Example> = {
6568
component: <Animation />,
6669
code: animationExampleCode,
6770
},
71+
transition: {
72+
component: <Transition />,
73+
code: transitionExampleCode,
74+
},
6875
};
6976

7077
export type ShowExampleProps = {
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import {
2+
component$,
3+
useSignal,
4+
type QwikIntrinsicElements,
5+
useStyles$,
6+
} from '@builder.io/qwik';
7+
import { Modal, ModalContent, ModalFooter, ModalHeader } from '@qwik-ui/headless';
8+
// import styles from './animation.css?inline';
9+
10+
export default component$(() => {
11+
const showSig = useSignal(false);
12+
useStyles$(`
13+
.my-transition::backdrop {
14+
background: rgba(0,0,0,0.5);
15+
}
16+
17+
.my-transition, .my-transition::backdrop {
18+
opacity: 0;
19+
transition: opacity 500ms ease;
20+
}
21+
22+
.my-transition.modal-showing, .my-transition.modal-showing::backdrop {
23+
opacity: 1;
24+
}
25+
26+
.my-transition.modal-closing, .my-transition.modal-closing::backdrop {
27+
opacity: 0;
28+
}
29+
`);
30+
31+
return (
32+
<>
33+
<button
34+
onClick$={() => {
35+
showSig.value = true;
36+
}}
37+
class="rounded-md border-2 border-slate-300 bg-slate-700 px-3 py-2 text-white"
38+
>
39+
Open Modal
40+
</button>
41+
<Modal
42+
bind:show={showSig}
43+
class="my-transition shadow-dark-medium max-w-[25rem] rounded-md bg-white p-[28px] text-slate-950"
44+
>
45+
<ModalHeader>
46+
<h2 class="text-lg font-bold">Edit Profile</h2>
47+
</ModalHeader>
48+
<ModalContent class="mb-2 py-4">
49+
<p class="mb-4 leading-5">
50+
You can update your profile here. Hit the save button when finished.
51+
</p>
52+
<fieldset class="mb-1 flex items-baseline justify-between">
53+
<label for="name">Name</label>
54+
<input
55+
class="mt-2 rounded-sm px-4 py-[10px] text-white"
56+
id="name"
57+
type="text"
58+
placeholder="John Doe"
59+
/>
60+
</fieldset>
61+
<fieldset class="flex items-baseline justify-between">
62+
<label for="email">Email</label>
63+
<input
64+
class="mt-2 rounded-sm px-4 py-3 text-white"
65+
id="email"
66+
type="text"
67+
placeholder="johndoe@gmail.com"
68+
/>
69+
</fieldset>
70+
</ModalContent>
71+
<ModalFooter class="flex justify-end gap-4">
72+
<button
73+
class="rounded-sm border border-none bg-slate-200 px-4 py-[10px] text-slate-600 outline-none focus-visible:outline-slate-700"
74+
onClick$={() => (showSig.value = false)}
75+
>
76+
Cancel
77+
</button>
78+
<button
79+
class="rounded-sm border border-none bg-green-200 px-4 py-[10px] text-green-900 outline-none focus-visible:outline-green-700"
80+
onClick$={() => (showSig.value = false)}
81+
>
82+
Save Changes
83+
</button>
84+
</ModalFooter>
85+
<button
86+
onClick$={() => (showSig.value = false)}
87+
class="absolute right-6 top-[26px]"
88+
>
89+
<CloseIcon class="h-8 w-8" />
90+
</button>
91+
</Modal>
92+
</>
93+
);
94+
});
95+
96+
export function CloseIcon(props: QwikIntrinsicElements['svg'], key: string) {
97+
return (
98+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...props} key={key}>
99+
<path
100+
fill="020617"
101+
d="m12 13.4l2.9 2.9q.275.275.7.275t.7-.275q.275-.275.275-.7t-.275-.7L13.4 12l2.9-2.9q.275-.275.275-.7t-.275-.7q-.275-.275-.7-.275t-.7.275L12 10.6L9.1 7.7q-.275-.275-.7-.275t-.7.275q-.275.275-.275.7t.275.7l2.9 2.9l-2.9 2.9q-.275.275-.275.7t.275.7q.275.275.7.275t.7-.275l2.9-2.9Zm0 8.6q-2.075 0-3.9-.788t-3.175-2.137q-1.35-1.35-2.137-3.175T2 12q0-2.075.788-3.9t2.137-3.175q1.35-1.35 3.175-2.137T12 2q2.075 0 3.9.788t3.175 2.137q1.35 1.35 2.138 3.175T22 12q0 2.075-.788 3.9t-2.137 3.175q-1.35 1.35-3.175 2.138T12 22Zm0-2q3.35 0 5.675-2.325T20 12q0-3.35-2.325-5.675T12 4Q8.65 4 6.325 6.325T4 12q0 3.35 2.325 5.675T12 20Zm0-8Z"
102+
></path>
103+
</svg>
104+
);
105+
}

apps/website/src/routes/docs/headless/(components)/modal/index.mdx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,6 @@ This means that if a user is navigating through the modal using the Tab key, rea
159159
160160
## Animations
161161

162-
<ShowExample example="animation" />
163-
164162
Animating things to display none has historically been a significant challenge on the web. This is because display none is a `discrete` property, and is **unanimatable**.
165163

166164
> There is currently efforts to solve this problem. [New CSS properties](https://developer.chrome.com/blog/entry-exit-animations/) have been introduced, but currently do not provide good enough browser support.
@@ -169,9 +167,17 @@ Animating things to display none has historically been a significant challenge o
169167

170168
Qwik UI automatically detects any `animation` or `transition` declarations under the hood and waits for them to finish before closing the modal. If there is no animation, then it will close normally.
171169

170+
### Adding a transition
171+
172+
<ShowExample example="transition" />
173+
174+
To add an transition, use the `modal-showing` and `modal-closing` css classes. Above is a snippet where we transition both the modal and backdrop's opacity.
175+
172176
### Adding an animation
173177

174-
To add an animation, use the `modal-showing` and `modal-closing` css classes. Below is a snippet of the animation example above.
178+
<ShowExample example="animation" />
179+
180+
To add an animation, it's the same as with transitions, using the `modal-showing` and `modal-closing` css classes. Below is a snippet of the animation example above.
175181

176182
<AnimationSnip />
177183

packages/kit-headless/src/components/modal/modal-behavior.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,6 @@ export function opening(modal: HTMLDialogElement) {
195195
};
196196

197197
const runTransitionEnd = () => {
198-
modal.classList.remove('modal-showing');
199198
modal.removeEventListener('transitionend', runTransitionEnd);
200199
};
201200

packages/kit-headless/src/components/modal/modal.spec.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { ModalHeader } from './modal-header';
88
* SUT - System under test
99
* Reference: https://en.wikipedia.org/wiki/System_under_test
1010
*/
11-
const Sut = component$((props?: ModalProps) => {
11+
const Sut = component$((props: ModalProps) => {
1212
const showSig = useSignal(false);
1313

1414
useStyles$(`

0 commit comments

Comments
 (0)