Skip to content

Commit 6e98403

Browse files
committed
refactor(styled modal): add sheet variants 👀
1 parent 888d7d1 commit 6e98403

File tree

4 files changed

+130
-23
lines changed

4 files changed

+130
-23
lines changed

‎apps/website/src/routes/docs/styled/modal/examples/hero.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import { Button, Input, Label, Modal, buttonVariants } from '~/components/ui';
55

66
export default component$(() => {
77
const show = useSignal(false);
8-
98
return (
109
<Modal.Root bind:show={show}>
11-
<Modal.Trigger>Open modal</Modal.Trigger>
10+
<Modal.Trigger class={[buttonVariants({ look: 'outline' })]}>
11+
Open modal
12+
</Modal.Trigger>
1213
<Modal.Panel>
1314
<Modal.Title>Edit Profile</Modal.Title>
1415
<Modal.Description>
@@ -40,7 +41,7 @@ export default component$(() => {
4041
</footer>
4142
<Modal.Close
4243
class={cn(
43-
buttonVariants({ size: 'icon', look: 'ghost' }),
44+
buttonVariants({ size: 'icon', look: 'link' }),
4445
'absolute right-3 top-2',
4546
)}
4647
type="submit"
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { PropsOf, Slot, component$, useSignal } from '@builder.io/qwik';
2+
import { cn } from '@qwik-ui/utils';
3+
import { LuX } from '@qwikest/icons/lucide';
4+
import { Button, Input, Label, Modal, buttonVariants } from '~/components/ui';
5+
6+
export default component$(() => {
7+
return (
8+
<>
9+
<Sheet position="top">Top</Sheet>
10+
<div class="my-4 flex space-x-24">
11+
<Sheet position="left">Left</Sheet>
12+
<Sheet position="right">Right</Sheet>
13+
</div>
14+
15+
<Sheet position="bottom">Bottom</Sheet>
16+
</>
17+
);
18+
});
19+
20+
export const Sheet = component$<PropsOf<typeof Modal.Panel>>(({ ...props }) => {
21+
const show = useSignal(false);
22+
return (
23+
<Modal.Root bind:show={show}>
24+
<Modal.Trigger class={[buttonVariants({ look: 'ghost' }), 'w-20']}>
25+
<Slot />
26+
</Modal.Trigger>
27+
<Modal.Panel {...props}>
28+
<Modal.Title>Edit Profile</Modal.Title>
29+
<Modal.Description>
30+
Make changes to your profile here. Click save when you're done.
31+
</Modal.Description>
32+
<div class="mt-6">
33+
<Label for="name" class="text-right">
34+
Name
35+
</Label>
36+
<Input
37+
name="name"
38+
id="name"
39+
defaultValue="Pedro Duarte"
40+
class="col-span-3 w-[300px]"
41+
/>
42+
</div>
43+
<footer class="mt-6">
44+
<Button look="primary" onClick$={() => (show.value = false)}>
45+
Save
46+
</Button>
47+
</footer>
48+
<Modal.Close
49+
class={cn(
50+
buttonVariants({ size: 'icon', look: 'link' }),
51+
'absolute right-3 top-2',
52+
)}
53+
type="submit"
54+
>
55+
<LuX class="h-5 w-5" />
56+
</Modal.Close>
57+
</Modal.Panel>
58+
</Modal.Root>
59+
);
60+
});

‎apps/website/src/routes/docs/styled/modal/index.mdx

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,45 @@ qwik-ui add modal
2424
import { PropsOf, Slot, component$ } from '@builder.io/qwik';
2525
import { Modal as HeadlessModal } from '@qwik-ui/headless';
2626
import { cn } from '@qwik-ui/utils';
27+
import { cva, type VariantProps } from 'class-variance-authority';
2728

2829
const Root = HeadlessModal.Root;
2930

3031
const Trigger = HeadlessModal.Trigger;
3132

3233
const Close = HeadlessModal.Close;
3334

34-
const Panel = component$<PropsOf<typeof HeadlessModal.Panel>>((props) => {
35+
export const panelVariants = cva(
36+
[
37+
'fixed w-full bg-background p-6 text-foreground transition-all backdrop:brightness-50 backdrop:backdrop-blur-sm',
38+
'data-[closing]:duration-300 data-[open]:duration-300 data-[open]:animate-in data-[closing]:animate-out',
39+
'backdrop:data-[closing]:duration-300 backdrop:data-[open]:duration-300 backdrop:data-[open]:animate-in backdrop:data-[closing]:animate-out backdrop:data-[closing]:fade-out backdrop:data-[open]:fade-in',
40+
],
41+
{
42+
variants: {
43+
position: {
44+
center:
45+
'max-w-lg rounded-base shadow-lg data-[state=closed]:fade-out data-[state=open]:fade-in data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=open]:slide-in-from-bottom-2 backdrop:data-[closing]:fade-out backdrop:data-[open]:fade-in',
46+
top: 'inset-x-0 top-0 mt-0 rounded-b-base border-b data-[closing]:slide-out-to-top data-[open]:slide-in-from-top',
47+
bottom:
48+
'inset-x-0 bottom-0 mb-0 rounded-t-base border-t data-[closing]:slide-out-to-bottom data-[open]:slide-in-from-bottom',
49+
left: 'inset-y-0 left-0 ml-0 h-full max-w-sm rounded-r-base border-r data-[closing]:slide-out-to-left data-[open]:slide-in-from-left',
50+
right:
51+
'inset-y-0 right-0 mr-0 h-full max-w-sm rounded-l-base border-l data-[closing]:slide-out-to-right data-[open]:slide-in-from-right',
52+
},
53+
},
54+
defaultVariants: {
55+
position: 'center',
56+
},
57+
},
58+
);
59+
60+
type PanelProps = PropsOf<typeof HeadlessModal.Panel> &
61+
VariantProps<typeof panelVariants>;
62+
63+
const Panel = component$<PanelProps>(({ position, ...props }) => {
3564
return (
36-
<HeadlessModal.Panel
37-
{...props}
38-
class={cn(
39-
'max-w-sm rounded-base border bg-background p-6 text-foreground shadow-md backdrop:brightness-50 backdrop:backdrop-blur-sm',
40-
'data-[closed]:duration-300 data-[open]:duration-300 data-[open]:animate-in data-[closing]:animate-out data-[closing]:fade-out data-[open]:fade-in',
41-
'backdrop:data-[closed]:duration-300 backdrop:data-[open]:duration-300 backdrop:data-[open]:animate-in backdrop:data-[closing]:animate-out backdrop:data-[closing]:fade-out backdrop:data-[open]:fade-in',
42-
props.class,
43-
)}
44-
>
65+
<HeadlessModal.Panel {...props} class={cn(panelVariants({ position }), props.class)}>
4566
<Slot />
4667
</HeadlessModal.Panel>
4768
);
@@ -103,3 +124,7 @@ import { Button, Modal } from '~/components/ui';
103124
</Modal.Panel>
104125
</Modal.Root>
105126
```
127+
128+
## Examples
129+
130+
<Showcase name="sheet" />

‎packages/kit-styled/src/components/modal/modal.tsx

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,45 @@
11
import { PropsOf, Slot, component$ } from '@builder.io/qwik';
22
import { Modal as HeadlessModal } from '@qwik-ui/headless';
33
import { cn } from '@qwik-ui/utils';
4+
import { cva, type VariantProps } from 'class-variance-authority';
45

56
const Root = HeadlessModal.Root;
67

78
const Trigger = HeadlessModal.Trigger;
89

910
const Close = HeadlessModal.Close;
1011

11-
const Panel = component$<PropsOf<typeof HeadlessModal.Panel>>((props) => {
12+
export const panelVariants = cva(
13+
[
14+
'fixed w-full bg-background p-6 text-foreground transition-all backdrop:brightness-50 backdrop:backdrop-blur-sm',
15+
'data-[closing]:duration-300 data-[open]:duration-300 data-[open]:animate-in data-[closing]:animate-out',
16+
'backdrop:data-[closing]:duration-300 backdrop:data-[open]:duration-300 backdrop:data-[open]:animate-in backdrop:data-[closing]:animate-out backdrop:data-[closing]:fade-out backdrop:data-[open]:fade-in',
17+
],
18+
{
19+
variants: {
20+
position: {
21+
center:
22+
'max-w-lg rounded-base shadow-lg data-[state=closed]:fade-out data-[state=open]:fade-in data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=open]:slide-in-from-bottom-2 backdrop:data-[closing]:fade-out backdrop:data-[open]:fade-in',
23+
top: 'inset-x-0 top-0 mt-0 rounded-b-base border-b data-[closing]:slide-out-to-top data-[open]:slide-in-from-top',
24+
bottom:
25+
'inset-x-0 bottom-0 mb-0 rounded-t-base border-t data-[closing]:slide-out-to-bottom data-[open]:slide-in-from-bottom',
26+
left: 'inset-y-0 left-0 ml-0 h-full max-w-sm rounded-r-base border-r data-[closing]:slide-out-to-left data-[open]:slide-in-from-left',
27+
right:
28+
'inset-y-0 right-0 mr-0 h-full max-w-sm rounded-l-base border-l data-[closing]:slide-out-to-right data-[open]:slide-in-from-right',
29+
},
30+
},
31+
defaultVariants: {
32+
position: 'center',
33+
},
34+
},
35+
);
36+
37+
type PanelProps = PropsOf<typeof HeadlessModal.Panel> &
38+
VariantProps<typeof panelVariants>;
39+
40+
const Panel = component$<PanelProps>(({ position, ...props }) => {
1241
return (
13-
<HeadlessModal.Panel
14-
{...props}
15-
class={cn(
16-
'max-w-sm rounded-base border bg-background p-6 text-foreground shadow-md backdrop:brightness-50 backdrop:backdrop-blur-sm',
17-
'data-[closed]:duration-300 data-[open]:duration-300 data-[open]:animate-in data-[closing]:animate-out data-[closing]:fade-out data-[open]:fade-in',
18-
'backdrop:data-[closed]:duration-300 backdrop:data-[open]:duration-300 backdrop:data-[open]:animate-in backdrop:data-[closing]:animate-out backdrop:data-[closing]:fade-out backdrop:data-[open]:fade-in',
19-
props.class,
20-
)}
21-
>
42+
<HeadlessModal.Panel {...props} class={cn(panelVariants({ position }), props.class)}>
2243
<Slot />
2344
</HeadlessModal.Panel>
2445
);

0 commit comments

Comments
 (0)