Skip to content

Commit c66c1d9

Browse files
committed
feat: scroll layout
1 parent b87c575 commit c66c1d9

File tree

4 files changed

+171
-0
lines changed

4 files changed

+171
-0
lines changed

src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,4 @@ export { default as Video } from './stateless/Video'
149149
export { default as Watermark } from './stateless/Watermark'
150150
// export { default as WaveBackground } from './stateless/WaveBackground'
151151
export { default as WordRotate } from './stateless/WordRotate'
152+
export { default as ScrollLayout } from './stateless/ScrollLayout'
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
.container {
2+
display: flex;
3+
flex-direction: column;
4+
width: 100%;
5+
height: 100%;
6+
overflow: hidden;
7+
}
8+
9+
.header {
10+
flex-shrink: 0;
11+
width: 100%;
12+
z-index: 10;
13+
}
14+
15+
.content {
16+
flex: 1;
17+
width: 100%;
18+
overflow-y: auto;
19+
overflow-x: hidden;
20+
position: relative;
21+
22+
// &::-webkit-scrollbar {
23+
// width: 8px;
24+
// }
25+
26+
// &::-webkit-scrollbar-track {
27+
// background: #f1f1f1;
28+
// border-radius: 4px;
29+
// }
30+
31+
// &::-webkit-scrollbar-thumb {
32+
// background: #888;
33+
// border-radius: 4px;
34+
// transition: background 0.2s ease;
35+
36+
// &:hover {
37+
// background: #555;
38+
// }
39+
40+
// &:active {
41+
// background: #333;
42+
// }
43+
// }
44+
45+
// scrollbar-width: thin;
46+
// scrollbar-color: #888 #f1f1f1;
47+
}
48+
49+
.footer {
50+
flex-shrink: 0;
51+
width: 100%;
52+
z-index: 10;
53+
}
54+
55+
// :global(.dark) {
56+
// .header,
57+
// .footer {
58+
// background-color: #1f2937;
59+
// border-color: #374151;
60+
// }
61+
62+
// .content {
63+
// &::-webkit-scrollbar-track {
64+
// background: #1f2937;
65+
// }
66+
67+
// &::-webkit-scrollbar-thumb {
68+
// background: #4b5563;
69+
70+
// &:hover {
71+
// background: #6b7280;
72+
// }
73+
74+
// &:active {
75+
// background: #9ca3af;
76+
// }
77+
// }
78+
79+
// scrollbar-color: #4b5563 #1f2937;
80+
// }
81+
// }
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'use client'
2+
3+
import type { ReactNode, CSSProperties } from 'react'
4+
import styles from './index.module.less'
5+
6+
interface ScrollLayoutProps {
7+
header?: ReactNode
8+
footer?: ReactNode
9+
children: ReactNode
10+
headerHeight?: number
11+
footerHeight?: number
12+
className?: string
13+
headerClassName?: string
14+
footerClassName?: string
15+
contentClassName?: string
16+
headerStyle?: CSSProperties
17+
footerStyle?: CSSProperties
18+
contentStyle?: CSSProperties
19+
}
20+
21+
const ScrollLayout = ({
22+
header,
23+
footer,
24+
children,
25+
headerHeight = 60,
26+
footerHeight = 60,
27+
className = '',
28+
headerClassName = '',
29+
footerClassName = '',
30+
contentClassName = '',
31+
headerStyle = {},
32+
footerStyle = {},
33+
contentStyle = {},
34+
}: ScrollLayoutProps) => {
35+
return (
36+
<div className={`${styles.container} ${className}`}>
37+
{header && (
38+
<header
39+
className={`${styles.header} ${headerClassName}`}
40+
style={{ height: `${headerHeight}px`, ...headerStyle }}
41+
>
42+
{header}
43+
</header>
44+
)}
45+
<main className={`${styles.content} ${contentClassName}`} style={contentStyle}>
46+
{children}
47+
</main>
48+
{footer && (
49+
<footer
50+
className={`${styles.footer} ${footerClassName}`}
51+
style={{ height: `${footerHeight}px`, ...footerStyle }}
52+
>
53+
{footer}
54+
</footer>
55+
)}
56+
</div>
57+
)
58+
}
59+
60+
export default ScrollLayout

src/pages/demo/index.jsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import GradientStats from '@stateless/GradientStats'
1919
import WaveBackground from '@stateless/WaveBackground'
2020
import MarketingHero from '@stateless/MarketingHero'
2121
import ScriptView from '@stateless/ScriptView'
22+
import ScrollLayout from '@stateless/ScrollLayout'
2223
import AnimatedList from '@stateless/AnimatedList'
2324
// import AnimationTabs from '@stateless/AnimationTabs'
2425
import StickyCard from '@stateless/StickyCard'
@@ -266,6 +267,34 @@ const ProDemo = () => {
266267
<FixTabPanel>
267268
<PageContainer>
268269
<OneTimePasscode length={6} variant="compact" onComplete={() => {}} />
270+
<div style={{ height: '400px' }}>
271+
<ScrollLayout
272+
headerHeight={60}
273+
footerHeight={60}
274+
header={
275+
<div className="flex h-full items-center justify-between px-6">
276+
<h1 className="text-xl font-bold">ScrollLayout 组件示例</h1>
277+
</div>
278+
}
279+
footer={
280+
<div className="flex h-full items-center justify-center text-sm">
281+
<p>© 2025 ScrollLayout - 支持自定义样式</p>
282+
</div>
283+
}
284+
>
285+
<div className="space-y-4 p-6">
286+
<h2 className="text-lg font-semibold">中间内容区域(可滚动)</h2>
287+
{Array.from({ length: 30 }, (_, i) => (
288+
<div key={i} className="rounded-lg p-4 shadow-sm">
289+
<h3 className="font-medium">内容块 {i + 1}</h3>
290+
<p className="text-muted-foreground mt-2 text-sm">
291+
这是一个灵活的布局组件,支持可选的 header/footer,自定义高度和样式
292+
</p>
293+
</div>
294+
))}
295+
</div>
296+
</ScrollLayout>
297+
</div>
269298
<MusicPlayer />
270299
<TransferHistory />
271300
<FixCarousel />

0 commit comments

Comments
 (0)