Skip to content

Commit a030c17

Browse files
thejacksheltonGregOnNet
authored andcommitted
docs(docs): sheet docs examp;le
1 parent cabdea4 commit a030c17

File tree

5 files changed

+172
-10
lines changed

5 files changed

+172
-10
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
@@ -26,6 +26,9 @@ import animationExampleCode from './examples/animation?raw';
2626
import Transition from './examples/transition';
2727
import transitionExampleCode from './examples/transition?raw';
2828

29+
import Sheet from './examples/sheet';
30+
import sheetExampleCode from './examples/sheet?raw';
31+
2932
import buildingBlocksSnip from './examples/building-blocks-snip?raw';
3033
import pageLoadSnip from './examples/page-load-snip?raw';
3134
import animationSnip from './examples/animation-snip.css?raw';
@@ -72,6 +75,10 @@ export const examples: Record<string, Example> = {
7275
component: <Transition />,
7376
code: transitionExampleCode,
7477
},
78+
sheet: {
79+
component: <Sheet />,
80+
code: sheetExampleCode,
81+
},
7582
};
7683

7784
export type ShowExampleProps = {
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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+
9+
export default component$(() => {
10+
const showSig = useSignal(false);
11+
useStyles$(`
12+
.sheet::backdrop {
13+
background: hsla(0, 0%, 0%, 0.5);
14+
}
15+
16+
.sheet.modal-showing {
17+
animation: sheetOpen 0.75s forwards cubic-bezier(0.6, 0.6, 0, 1);
18+
}
19+
20+
.sheet.modal-showing::backdrop {
21+
animation: sheetFadeIn 0.75s forwards cubic-bezier(0.6, 0.6, 0, 1);
22+
}
23+
24+
.sheet.modal-closing {
25+
animation: sheetClose 0.45s forwards cubic-bezier(0.6, 0.6, 0, 1);
26+
}
27+
28+
.sheet.modal-closing::backdrop {
29+
animation: sheetFadeOut 0.45s forwards cubic-bezier(0.6, 0.6, 0, 1);
30+
}
31+
32+
@keyframes sheetOpen {
33+
from {
34+
opacity: 0;
35+
transform: translateX(calc(100%));
36+
}
37+
to {
38+
opacity: 1;
39+
transform: translateX(0%);
40+
}
41+
}
42+
43+
@keyframes sheetClose {
44+
from {
45+
opacity: 1;
46+
transform: translateX(0%);
47+
}
48+
to {
49+
opacity: 0;
50+
transform: translateX(calc(100%));
51+
}
52+
}
53+
54+
@keyframes sheetFadeIn {
55+
from {
56+
opacity: 0;
57+
}
58+
to {
59+
opacity: 1;
60+
}
61+
}
62+
63+
@keyframes sheetFadeOut {
64+
from {
65+
opacity: 1;
66+
}
67+
to {
68+
opacity: 0;
69+
}
70+
}
71+
72+
`);
73+
74+
return (
75+
<>
76+
<button
77+
onClick$={() => {
78+
showSig.value = true;
79+
}}
80+
class="rounded-md border-2 border-slate-300 bg-slate-700 px-3 py-2 text-white"
81+
>
82+
Open Modal
83+
</button>
84+
<Modal
85+
bind:show={showSig}
86+
class="sheet shadow-dark-medium fixed bottom-[50%] right-0 top-[50%] mr-0 h-[30rem] max-w-[25rem] rounded-md border-0 bg-white p-[28px] text-slate-950 backdrop:backdrop-blur backdrop:backdrop-brightness-50 dark:backdrop:backdrop-brightness-100"
87+
>
88+
<ModalHeader>
89+
<h2 class="text-lg font-bold">Edit Profile</h2>
90+
</ModalHeader>
91+
<ModalContent class="mb-2 py-4">
92+
<p class="mb-4 leading-5">
93+
You can update your profile here. Hit the save button when finished.
94+
</p>
95+
<fieldset class="mb-1 flex items-baseline justify-between">
96+
<label for="name">Name</label>
97+
<input
98+
class="mt-2 rounded-sm px-4 py-[10px] text-white"
99+
id="name"
100+
type="text"
101+
placeholder="John Doe"
102+
/>
103+
</fieldset>
104+
<fieldset class="flex items-baseline justify-between">
105+
<label for="email">Email</label>
106+
<input
107+
class="mt-2 rounded-sm px-4 py-3 text-white"
108+
id="email"
109+
type="text"
110+
placeholder="[email protected]"
111+
/>
112+
</fieldset>
113+
</ModalContent>
114+
<ModalFooter class="flex justify-end gap-4">
115+
<button
116+
class="rounded-sm border border-none bg-slate-200 px-4 py-[10px] text-slate-600 outline-none focus-visible:outline-slate-700"
117+
onClick$={() => (showSig.value = false)}
118+
>
119+
Cancel
120+
</button>
121+
<button
122+
class="rounded-sm border border-none bg-green-200 px-4 py-[10px] text-green-900 outline-none focus-visible:outline-green-700"
123+
onClick$={() => (showSig.value = false)}
124+
>
125+
Save Changes
126+
</button>
127+
</ModalFooter>
128+
<button
129+
onClick$={() => (showSig.value = false)}
130+
class="absolute right-6 top-[26px]"
131+
>
132+
<CloseIcon class="h-8 w-8" />
133+
</button>
134+
</Modal>
135+
</>
136+
);
137+
});
138+
139+
export function CloseIcon(props: QwikIntrinsicElements['svg'], key: string) {
140+
return (
141+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...props} key={key}>
142+
<path
143+
fill="020617"
144+
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"
145+
></path>
146+
</svg>
147+
);
148+
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ To add a backdrop animation, make sure to use the `::backdrop` pseudo selector t
191191

192192
> Firefox currently does not support backdrop animations. The fallback for browsers that do not support animated backdrops is the same as a non-animated backdrop.
193193
194+
## Custom Modal Placement
195+
196+
### Sheet
197+
198+
<ShowExample example="sheet" />
199+
194200
## Open on page load
195201

196202
There might come a time where a modal is needed open as soon as the page loads. Unfortunately, to create modals a client-side API is currently needed regardless of implementation.

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,22 @@ export function wasModalBackdropClicked(
7575
/**
7676
* Locks scrolling of the document.
7777
*/
78-
export function lockScroll() {
78+
export function lockScroll(scrollbar: WidthState) {
79+
if (scrollbar.width === null) {
80+
scrollbar.width = window.innerWidth - document.documentElement.clientWidth;
81+
}
82+
7983
window.document.body.style.overflow = 'hidden';
84+
document.body.style.paddingRight = `${scrollbar.width}px`;
8085
}
8186

8287
/**
8388
* Unlocks scrolling of the document.
8489
* Adjusts padding of the given scrollbar.
8590
*/
86-
export function unlockScroll(scrollbar: WidthState) {
91+
export function unlockScroll() {
8792
window.document.body.style.overflow = '';
88-
89-
const currentPadding = parseInt(document.body.style.paddingRight);
90-
if (scrollbar.width) {
91-
document.body.style.paddingRight = `${currentPadding - scrollbar.width}px`;
92-
}
93+
document.body.style.paddingRight = '';
9394
}
9495

9596
/**
@@ -105,7 +106,7 @@ export function adjustScrollbar(scrollbar: WidthState, modal: HTMLDialogElement)
105106
scrollbar.width = window.innerWidth - document.documentElement.clientWidth;
106107
}
107108

108-
modal.style.left = `0px`;
109+
modal.style.left = 0 + 'px';
109110
document.body.style.paddingRight = `${scrollbar.width}px`;
110111
}
111112

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ export const Modal = component$((props: ModalProps) => {
6161
props.onShow$?.();
6262
adjustScrollbar(scrollbar, modal);
6363
activateFocusTrap(focusTrap);
64-
lockScroll();
64+
lockScroll(scrollbar);
6565
} else {
66-
unlockScroll(scrollbar);
66+
unlockScroll();
6767
closeModal(modal);
6868
props.onClose$?.();
6969
}

0 commit comments

Comments
 (0)