WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 009bdd9

Browse files
committed
CSS is generic, add more example cases
1 parent acff051 commit 009bdd9

File tree

3 files changed

+312
-169
lines changed

3 files changed

+312
-169
lines changed

src/pages/silky-modal/index.tsx

Lines changed: 113 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import styles from './styles.module.css'
33
import { Head } from "#components/Head"
44
import type { RouteMeta } from "#router"
5-
import { useId, type MouseEvent } from "react"
5+
import { useId, type MouseEvent, type ReactNode } from "react"
66
import src from './lorem.jpg'
77

88
export const meta: RouteMeta = {
@@ -22,61 +22,138 @@ export default function SilkyModalPage() {
2222
<>
2323
<div className={styles.main}>
2424
<Head />
25-
{/* <First /> */}
25+
</div>
26+
<div className={styles.examples}>
2627
<Second />
28+
<BottomSheet />
29+
<SideSheet />
30+
<HorizontalStartModal />
2731
</div>
2832
</>
2933
)
3034
}
3135

3236
const onClose = (e: MouseEvent) => {
3337
e.preventDefault()
34-
e.currentTarget.closest<HTMLDialogElement>('dialog')!.scrollTo({ top: 0, behavior: 'smooth' })
38+
const dialog = e.currentTarget.closest<HTMLDialogElement>('dialog')!
39+
if (dialog.dataset.orientation === 'vertical') {
40+
if (dialog.dataset.align === 'start') {
41+
dialog.scrollTo({ top: dialog.offsetHeight, behavior: 'smooth' })
42+
} else {
43+
dialog.scrollTo({ top: 0, behavior: 'smooth' })
44+
}
45+
} else {
46+
if (dialog.dataset.align === 'start') {
47+
dialog.scrollTo({ left: dialog.offsetWidth, behavior: 'smooth' })
48+
} else {
49+
dialog.scrollTo({ left: 0, behavior: 'smooth' })
50+
}
51+
}
3552
}
3653

37-
function First() {
54+
55+
function Second() {
56+
const id = useId()
57+
3858
return (
39-
<div className={styles.first}>
40-
<button commandfor="mydialog" command="show-modal">Show modal dialog</button>
41-
<dialog id="mydialog" ref={(e) => {
42-
if (!e) return
43-
const content = e.querySelector<HTMLDivElement>('[data-dialog-area]')!
44-
let visible = false
45-
const observer = new IntersectionObserver(([entry]) => {
46-
visible = entry.isIntersecting
47-
if (!visible) e.close()
48-
})
49-
observer.observe(content)
50-
return () => observer.disconnect()
51-
}}>
52-
<div data-dialog-bumper="top" />
53-
<div data-dialog-area onClick={onClose}>
54-
<div data-dialog-content onClick={(e) => e.stopPropagation()}>
55-
<Content id="mydialog" />
56-
</div>
57-
</div>
58-
<div data-dialog-bumper="bottom" />
59-
</dialog>
60-
</div>
59+
<>
60+
<button commandfor={id} command="show-modal">Vertical center sheet</button>
61+
<Dialog
62+
id={id}
63+
orientation="vertical"
64+
align="center"
65+
className={styles.verticalCenter}
66+
>
67+
<Content id={id} />
68+
</Dialog>
69+
</>
6170
)
6271
}
6372

73+
function BottomSheet() {
74+
const id = useId()
6475

65-
function Second() {
76+
return (
77+
<>
78+
<button commandfor={id} command="show-modal">Vertical end sheet</button>
79+
<Dialog
80+
id={id}
81+
orientation="vertical"
82+
align="end"
83+
className={styles.verticalBottom}
84+
>
85+
<Content id={id} />
86+
</Dialog>
87+
</>
88+
)
89+
}
90+
91+
function SideSheet() {
92+
const id = useId()
93+
94+
return (
95+
<>
96+
<button commandfor={id} command="show-modal">Horizontal end sheet</button>
97+
<Dialog
98+
id={id}
99+
orientation="horizontal"
100+
align="end"
101+
className={styles.horizontalEnd}
102+
>
103+
<Content id={id} />
104+
</Dialog>
105+
</>
106+
)
107+
}
108+
109+
function HorizontalStartModal() {
66110
const id = useId()
67111

68112
return (
69-
<div className={styles.second}>
70-
<button commandfor={id} command="show-modal">Show modal dialog</button>
71-
<dialog id={id} ref={(e) => {
113+
<>
114+
<button commandfor={id} command="show-modal">Horizontal start sheet</button>
115+
<Dialog
116+
id={id}
117+
orientation="horizontal"
118+
align="start"
119+
className={styles.horizontalStart}
120+
>
121+
<Content id={id} />
122+
</Dialog>
123+
</>
124+
)
125+
}
126+
127+
function Dialog({
128+
id,
129+
children,
130+
className,
131+
orientation = 'vertical',
132+
align = 'center'
133+
}: {
134+
id: string
135+
children: ReactNode
136+
className?: string
137+
orientation?: 'horizontal' | 'vertical'
138+
align?: 'start' | 'center' | 'end'
139+
}) {
140+
return (
141+
<dialog
142+
className={styles.dialog}
143+
id={id}
144+
data-orientation={orientation}
145+
data-align={align}
146+
ref={(e) => {
72147
if (!e) return
73148
const observer = new IntersectionObserver(([entry]) => !entry.isIntersecting && e.close(), { rootMargin: '-1px' })
74149
const area = e.querySelector<HTMLDivElement>('[data-dialog-area]')!
75-
observer.observe(area)
150+
const content = area.querySelector<HTMLDivElement>('[data-dialog-content]')!
151+
observer.observe(content)
76152
const controller = new AbortController()
77153
e.addEventListener('beforetoggle', (event) => {
78154
if (event.newState === 'open') requestAnimationFrame(() => {
79155
e.scrollTop = area.offsetTop
156+
e.scrollLeft = area.offsetLeft
80157
e.querySelector<HTMLDivElement>('[data-dialog-content]')!.scrollTop = 0
81158
})
82159
}, { signal: controller.signal })
@@ -85,13 +162,12 @@ function Second() {
85162
observer.disconnect()
86163
}
87164
}}>
88-
<div data-dialog-area onClick={onClose}>
89-
<div data-dialog-content onClick={(e) => e.stopPropagation()}>
90-
<Content id={id} />
91-
</div>
165+
<div data-dialog-area onClick={onClose}>
166+
<div className={className} data-dialog-content onClick={(e) => e.stopPropagation()}>
167+
{children}
92168
</div>
93-
</dialog>
94-
</div>
169+
</div>
170+
</dialog>
95171
)
96172
}
97173

0 commit comments

Comments
 (0)