Skip to content

Commit 831dd89

Browse files
thejacksheltonGregOnNet
authored andcommitted
feat(modal): hero example changed, fixed copy button and border radius issue, semantic markup
1 parent 98a3f4d commit 831dd89

File tree

11 files changed

+92
-55
lines changed

11 files changed

+92
-55
lines changed

apps/website/src/routes/docs/_components/highlight/highlight.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,18 @@ export const Highlight = component$(
5050
<div
5151
{...props}
5252
class={[
53-
'tab-size relative max-w-full overflow-hidden overflow-x-auto rounded-xl bg-slate-50 p-12 text-sm dark:bg-slate-800',
53+
'tab-size relative max-w-full overflow-hidden overflow-x-auto rounded-b-xl bg-slate-50 p-12 text-sm dark:bg-slate-800',
5454
props.class,
5555
]}
5656
>
5757
<div dangerouslySetInnerHTML={codeSig.value} />
58-
<CodeCopy class={['absolute right-2 top-2', copyCodeClass]} code={code} />
58+
<CodeCopy
59+
class={[
60+
'absolute right-2 top-2 bg-slate-200 text-slate-950 hover:bg-slate-300 dark:bg-slate-700 dark:text-white dark:hover:bg-slate-600',
61+
copyCodeClass,
62+
]}
63+
code={code}
64+
/>
5965
</div>
6066
);
6167
},

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const ShowExample = component$(({ example }: ShowExampleProps) => {
2727
const { component, code, cssClasses = '' } = examples[example];
2828
return (
2929
<PreviewCodeExampleTabs code={code}>
30-
<div q:slot="actualComponent" class={['tabs-example mr-auto', cssClasses]}>
30+
<div q:slot="actualComponent" class={['tabs-example mx-auto', cssClasses]}>
3131
{component}
3232
</div>
3333
</PreviewCodeExampleTabs>
Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,78 @@
1-
import { component$, useSignal } from '@builder.io/qwik';
1+
import { QwikIntrinsicElements, component$, useSignal } from '@builder.io/qwik';
22
import {
33
Modal,
4+
ModalPopup,
45
ModalContent,
56
ModalFooter,
67
ModalHeader,
7-
ModalPortal,
88
ModalTrigger,
9+
ModalClose,
910
} from '@qwik-ui/headless';
1011

1112
export default component$(() => {
1213
const showSignal = useSignal(false);
1314

1415
return (
1516
<Modal bind:show={showSignal}>
16-
<ModalTrigger>
17-
<button class="p-1 focus:shadow-[0_0_0_2px] focus:shadow-[var(--qwik-light-blue)] focus:outline-none">
18-
Open Modal
19-
</button>
17+
<ModalTrigger class="rounded-md border-2 border-slate-300 bg-slate-700 px-3 py-2 text-white">
18+
Open Modal
2019
</ModalTrigger>
21-
<ModalPortal class="rounded-md p-4 shadow-md">
22-
<ModalHeader>
23-
<h2 class="text:md font-bold">Are your sure?</h2>
20+
<ModalPopup class="shadow-dark-medium max-w-[25rem] rounded-md bg-white p-[28px] text-slate-950">
21+
<ModalHeader class="relative">
22+
<h2 class="mb-2 text-lg font-bold">Edit Profile</h2>
23+
<p class="leading-5">
24+
You can update your profile here. Hit the save button when finished.
25+
</p>
2426
</ModalHeader>
25-
<ModalContent class="pb-4 pt-4">
26-
<p>Yes, I want to remove my account.</p>
27+
<ModalContent class="mb-2 py-4">
28+
<fieldset class="mb-1 flex items-baseline justify-between">
29+
<label for="name">Name</label>
30+
<input
31+
class="mt-2 rounded-sm px-4 py-[10px] text-white"
32+
id="name"
33+
type="text"
34+
placeholder="John Doe"
35+
/>
36+
</fieldset>
37+
<fieldset class="flex items-baseline justify-between">
38+
<label for="email">Email</label>
39+
<input
40+
class="mt-2 rounded-sm px-4 py-3 text-white"
41+
id="email"
42+
type="text"
43+
placeholder="johndoe@gmail.com"
44+
/>
45+
</fieldset>
2746
</ModalContent>
2847
<ModalFooter class="flex justify-end gap-4">
2948
<button
30-
class="rounded-sm border border-[var(--qwik-light-blue)] p-2 text-[var(--qwik-light-blue)]"
49+
class="rounded-sm border border-none bg-slate-200 px-4 py-[10px] text-slate-600 outline-none focus-visible:outline-slate-700"
3150
onClick$={() => (showSignal.value = false)}
3251
>
33-
No
52+
Cancel
3453
</button>
3554
<button
36-
class="rounded-sm bg-[var(--qwik-light-blue)] p-2"
55+
class="rounded-sm border border-none bg-green-200 px-4 py-[10px] text-green-900 outline-none focus-visible:outline-green-700"
3756
onClick$={() => (showSignal.value = false)}
3857
>
39-
Yes
58+
Save Changes
4059
</button>
4160
</ModalFooter>
42-
</ModalPortal>
61+
<ModalClose class="absolute right-6 top-6">
62+
<CloseIcon class="h-8 w-8" />
63+
</ModalClose>
64+
</ModalPopup>
4365
</Modal>
4466
);
4567
});
68+
69+
export function CloseIcon(props: QwikIntrinsicElements['svg'], key: string) {
70+
return (
71+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...props} key={key}>
72+
<path
73+
fill="020617"
74+
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"
75+
></path>
76+
</svg>
77+
);
78+
}

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,20 @@ import {
1616

1717
# Modal
1818

19-
#### A window overlaid on either the primary window or another dialog window, rendering the content underneath inert. ([Definition comes from Radix-UI](https://www.radix-ui.com/docs/primitives/components/dialog))
20-
21-
{' '}
19+
A window overlaid on either the primary window or another dialog window. Modal content is placed in the [top layer](https://developer.mozilla.org/en-US/docs/Glossary/Top_layer), rendering the underneath content as [inert](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert) meaning non-interactive.
2220

2321
<ShowExample example="first"/>
2422

23+
Modals are used when an important choice needs to be made in the application. The rest of the content isn't interactive until a certain action has been performed.
24+
25+
> For non-modal UI elements, it is preferred to use [Qwik UI's popover component](../../../docs/headless/popover/) *(in progress)*. In the near future, Qwik's popover component can be applied to the most-semantically-relevant HTML element, including the `<dialog>` element itself.
26+
27+
##### ✨ Features
28+
29+
- Managed focus order
30+
- Controlled or uncontrolled
31+
- Controlled or uncontrolled
32+
2533
## Accessibility
2634

2735
### Keyboard interaction

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export * from './modal-close';
22
export * from './modal-content';
33
export * from './modal-footer';
44
export * from './modal-header';
5-
export * from './modal-portal';
5+
export * from './modal-popup';
66
export * from './modal';
77
export * from './modal-trigger';
88
export * from './types';
Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
1-
import { $, Slot, component$, useContext, useOn } from '@builder.io/qwik';
1+
import { QwikIntrinsicElements, Slot, component$, useContext } from '@builder.io/qwik';
22
import { modalContextId } from './modal-context-id';
33

4-
export const ModalClose = component$(() => {
5-
const modalContext = useContext(modalContextId);
4+
type ModalCloseProps = QwikIntrinsicElements['button'];
65

7-
useOn(
8-
'click',
9-
$(function closeModal() {
10-
modalContext.showSig.value = false;
11-
}),
12-
);
6+
export const ModalClose = component$((props: ModalCloseProps) => {
7+
const modalContext = useContext(modalContextId);
138

149
return (
15-
<div>
10+
<button onClick$={() => (modalContext.showSig.value = false)} {...props}>
1611
<Slot />
17-
</div>
12+
</button>
1813
);
1914
});

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { Slot, component$ } from '@builder.io/qwik';
1+
import { QwikIntrinsicElements, Slot, component$ } from '@builder.io/qwik';
22

3-
export const ModalHeader = component$(() => {
3+
export const ModalHeader = component$((props: QwikIntrinsicElements['header']) => {
44
return (
5-
<header>
5+
<header {...props}>
66
<Slot />
77
</header>
88
);

packages/kit-headless/src/components/modal/modal-portal.tsx renamed to packages/kit-headless/src/components/modal/modal-popup.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
import { FocusTrap, createFocusTrap } from 'focus-trap';
1313
import { modalContextId } from './modal-context-id';
1414

15-
export const ModalPortal = component$(
15+
export const ModalPopup = component$(
1616
(props: Omit<QwikIntrinsicElements['dialog'], 'open'>) => {
1717
const modalContext = useContext(modalContextId);
1818
const refSig = useSignal<HTMLDialogElement>();
Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
1-
import { $, Slot, component$, useContext, useOn } from '@builder.io/qwik';
1+
import { QwikIntrinsicElements, Slot, component$, useContext } from '@builder.io/qwik';
22
import { modalContextId } from './modal-context-id';
33

4-
export const ModalTrigger = component$(() => {
5-
const modalContext = useContext(modalContextId);
4+
export type ModalTriggerProps = QwikIntrinsicElements['button'];
65

7-
useOn(
8-
'click',
9-
$(function openModal() {
10-
modalContext.showSig.value = true;
11-
}),
12-
);
6+
export const ModalTrigger = component$((props: ModalTriggerProps) => {
7+
const modalContext = useContext(modalContextId);
138

149
return (
15-
<div>
10+
<button onClick$={() => (modalContext.showSig.value = true)} {...props}>
1611
<Slot />
17-
</div>
12+
</button>
1813
);
1914
});

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ModalClose } from './modal-close';
44
import { ModalContent } from './modal-content';
55
import { ModalFooter } from './modal-footer';
66
import { ModalHeader } from './modal-header';
7-
import { ModalPortal } from './modal-portal';
7+
import { ModalPopup } from './modal-popup';
88
import { ModalTrigger } from './modal-trigger';
99

1010
/**
@@ -17,7 +17,7 @@ const Sut = component$(() => {
1717
<ModalTrigger>
1818
<button data-test="modal-trigger">Open Modal</button>
1919
</ModalTrigger>
20-
<ModalPortal>
20+
<ModalPopup>
2121
<ModalHeader>
2222
<h2 data-test="modal-header">Hello 👋</h2>
2323
</ModalHeader>
@@ -27,7 +27,7 @@ const Sut = component$(() => {
2727
<button data-test="modal-close-button">Close Modal</button>
2828
</ModalClose>
2929
</ModalFooter>
30-
</ModalPortal>
30+
</ModalPopup>
3131
</Modal>
3232
);
3333
});

0 commit comments

Comments
 (0)