@flamingo-stack/openframe-frontend-core 0.0.484 → 0.0.485
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-DVYTY2GK.js → chunk-2BMYCH3D.js} +2 -2
- package/dist/{chunk-F3UM6ZPO.js → chunk-5WZGZ6B2.js} +4 -4
- package/dist/{chunk-KN7MUVNB.js → chunk-6QJ2QRQE.js} +4 -4
- package/dist/{chunk-IB4YMANE.cjs → chunk-BVHMDHQY.cjs} +31 -31
- package/dist/{chunk-IB4YMANE.cjs.map → chunk-BVHMDHQY.cjs.map} +1 -1
- package/dist/{chunk-SGUKPH7Z.cjs → chunk-C4QKMOQK.cjs} +7 -7
- package/dist/{chunk-SGUKPH7Z.cjs.map → chunk-C4QKMOQK.cjs.map} +1 -1
- package/dist/{chunk-ZQXNTV66.cjs → chunk-F3BH5B7M.cjs} +11 -11
- package/dist/{chunk-ZQXNTV66.cjs.map → chunk-F3BH5B7M.cjs.map} +1 -1
- package/dist/{chunk-V36NQIAO.cjs → chunk-HQITFULS.cjs} +9 -9
- package/dist/{chunk-V36NQIAO.cjs.map → chunk-HQITFULS.cjs.map} +1 -1
- package/dist/{chunk-3MTN5XHZ.js → chunk-J5KX5K5T.js} +2 -2
- package/dist/{chunk-KHDLNPAM.js → chunk-KA4ILVCX.js} +2 -2
- package/dist/{chunk-OTJMDYZ5.js → chunk-KRKNTK5Y.js} +2 -2
- package/dist/{chunk-HSVQ7W5M.js → chunk-MD5E5BKO.js} +4 -4
- package/dist/{chunk-CGEC7YIX.cjs → chunk-NTHTORJ3.cjs} +59 -59
- package/dist/{chunk-CGEC7YIX.cjs.map → chunk-NTHTORJ3.cjs.map} +1 -1
- package/dist/{chunk-UFPGVLHZ.cjs → chunk-NZYUSFMI.cjs} +72 -19
- package/dist/chunk-NZYUSFMI.cjs.map +1 -0
- package/dist/{chunk-X3KQ3B35.js → chunk-OW33LYO2.js} +4 -4
- package/dist/{chunk-AVN6WGIV.cjs → chunk-PHYEC3EG.cjs} +26 -26
- package/dist/{chunk-AVN6WGIV.cjs.map → chunk-PHYEC3EG.cjs.map} +1 -1
- package/dist/{chunk-HTHR7KWB.cjs → chunk-RB6HX4KC.cjs} +26 -26
- package/dist/{chunk-HTHR7KWB.cjs.map → chunk-RB6HX4KC.cjs.map} +1 -1
- package/dist/{chunk-SSMNDK3Z.js → chunk-REURWDBC.js} +1659 -1606
- package/dist/chunk-REURWDBC.js.map +1 -0
- package/dist/{chunk-P3Q7KMPQ.cjs → chunk-RILRBUDL.cjs} +62 -62
- package/dist/{chunk-P3Q7KMPQ.cjs.map → chunk-RILRBUDL.cjs.map} +1 -1
- package/dist/{chunk-3VZJHXPE.cjs → chunk-RR6XPEEG.cjs} +15 -15
- package/dist/{chunk-3VZJHXPE.cjs.map → chunk-RR6XPEEG.cjs.map} +1 -1
- package/dist/{chunk-YSA7KE2P.cjs → chunk-XJ6VL3AP.cjs} +37 -37
- package/dist/{chunk-YSA7KE2P.cjs.map → chunk-XJ6VL3AP.cjs.map} +1 -1
- package/dist/{chunk-G2L46BDG.js → chunk-XOIKQW2H.js} +2 -2
- package/dist/{chunk-WZ3YAIQQ.js → chunk-Z3V42W7P.js} +2 -2
- package/dist/{chunk-4PVTF36S.js → chunk-ZTRRB2Y2.js} +2 -2
- package/dist/{chunk-SAVJIRUK.cjs → chunk-ZVFH4LTD.cjs} +5 -5
- package/dist/{chunk-SAVJIRUK.cjs.map → chunk-ZVFH4LTD.cjs.map} +1 -1
- package/dist/components/case-studies/index.cjs +8 -8
- package/dist/components/case-studies/index.js +2 -2
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/docs/index.cjs +5 -5
- package/dist/components/docs/index.js +4 -4
- package/dist/components/embeds/index.cjs +3 -3
- package/dist/components/embeds/index.js +2 -2
- package/dist/components/faq/index.cjs +3 -3
- package/dist/components/faq/index.js +2 -2
- package/dist/components/features/index.cjs +2 -2
- package/dist/components/features/index.js +1 -1
- package/dist/components/help-center-pages/index.cjs +20 -20
- package/dist/components/help-center-pages/index.js +11 -11
- package/dist/components/index.cjs +132 -130
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +11 -9
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/index.cjs +2 -2
- package/dist/components/navigation/index.js +1 -1
- package/dist/components/onboarding-guides/index.cjs +5 -5
- package/dist/components/onboarding-guides/index.js +4 -4
- package/dist/components/related-content/index.cjs +3 -3
- package/dist/components/related-content/index.js +2 -2
- package/dist/components/tickets/index.cjs +5 -5
- package/dist/components/tickets/index.js +4 -4
- package/dist/components/ui/data-table/data-table-skeleton.d.ts +7 -3
- package/dist/components/ui/data-table/data-table-skeleton.d.ts.map +1 -1
- package/dist/components/ui/index.cjs +4 -2
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +3 -1
- package/dist/components/ui/scroll-fade.d.ts +47 -7
- package/dist/components/ui/scroll-fade.d.ts.map +1 -1
- package/dist/components/ui/table/table-skeleton.d.ts +2 -2
- package/dist/components/ui/table/table-skeleton.d.ts.map +1 -1
- package/dist/index.cjs +4 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -1
- package/package.json +1 -1
- package/src/components/ui/data-table/.data-table-skeleton.md +2 -2
- package/src/components/ui/data-table/data-table-header.tsx +3 -1
- package/src/components/ui/data-table/data-table-row.tsx +1 -1
- package/src/components/ui/data-table/data-table-skeleton.tsx +7 -3
- package/src/components/ui/scroll-fade.tsx +115 -16
- package/src/components/ui/table/.table-skeleton.md +2 -2
- package/src/components/ui/table/table-skeleton.tsx +4 -2
- package/src/stories/ScrollShadow.stories.tsx +132 -0
- package/dist/chunk-SSMNDK3Z.js.map +0 -1
- package/dist/chunk-UFPGVLHZ.cjs.map +0 -1
- /package/dist/{chunk-DVYTY2GK.js.map → chunk-2BMYCH3D.js.map} +0 -0
- /package/dist/{chunk-F3UM6ZPO.js.map → chunk-5WZGZ6B2.js.map} +0 -0
- /package/dist/{chunk-KN7MUVNB.js.map → chunk-6QJ2QRQE.js.map} +0 -0
- /package/dist/{chunk-3MTN5XHZ.js.map → chunk-J5KX5K5T.js.map} +0 -0
- /package/dist/{chunk-KHDLNPAM.js.map → chunk-KA4ILVCX.js.map} +0 -0
- /package/dist/{chunk-OTJMDYZ5.js.map → chunk-KRKNTK5Y.js.map} +0 -0
- /package/dist/{chunk-HSVQ7W5M.js.map → chunk-MD5E5BKO.js.map} +0 -0
- /package/dist/{chunk-X3KQ3B35.js.map → chunk-OW33LYO2.js.map} +0 -0
- /package/dist/{chunk-G2L46BDG.js.map → chunk-XOIKQW2H.js.map} +0 -0
- /package/dist/{chunk-WZ3YAIQQ.js.map → chunk-Z3V42W7P.js.map} +0 -0
- /package/dist/{chunk-4PVTF36S.js.map → chunk-ZTRRB2Y2.js.map} +0 -0
|
@@ -3,27 +3,39 @@
|
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import { cn } from '../../utils/cn'
|
|
5
5
|
|
|
6
|
+
export type ScrollFadeAxis = 'vertical' | 'horizontal' | 'both'
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
|
-
* Tracks whether a scrollable element is scrolled away from its
|
|
8
|
-
* edge
|
|
9
|
-
*
|
|
9
|
+
* Tracks whether a scrollable element is scrolled away from its edges, so
|
|
10
|
+
* edge fades ("scroll shadows") can be shown only where content continues.
|
|
11
|
+
* Attach `scrollRef` to the scrollable element and `update` to its
|
|
10
12
|
* `onScroll`; content/size changes are re-measured via ResizeObserver.
|
|
11
13
|
*
|
|
12
|
-
*
|
|
14
|
+
* `axis` picks which edges are tracked: 'vertical' (top/bottom — default,
|
|
15
|
+
* matches the original hook), 'horizontal' (left/right), or 'both'.
|
|
16
|
+
*
|
|
17
|
+
* Canonical fade pattern shared by chat lists, FilterModal, and the
|
|
18
|
+
* `ScrollShadow` wrapper below.
|
|
13
19
|
*/
|
|
14
|
-
export function useScrollFade<T extends HTMLElement = HTMLDivElement>() {
|
|
20
|
+
export function useScrollFade<T extends HTMLElement = HTMLDivElement>(axis: ScrollFadeAxis = 'vertical') {
|
|
15
21
|
const scrollRef = React.useRef<T | null>(null)
|
|
16
|
-
const [fade, setFade] = React.useState({ top: false, bottom: false })
|
|
22
|
+
const [fade, setFade] = React.useState({ top: false, bottom: false, left: false, right: false })
|
|
17
23
|
|
|
18
24
|
const update = React.useCallback(() => {
|
|
19
25
|
const el = scrollRef.current
|
|
20
26
|
if (!el) return
|
|
21
27
|
setFade((prev) => {
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
28
|
+
const vertical = axis !== 'horizontal'
|
|
29
|
+
const horizontal = axis !== 'vertical'
|
|
30
|
+
const top = vertical && el.scrollTop > 0
|
|
31
|
+
const bottom = vertical && el.scrollHeight - el.scrollTop - el.clientHeight > 1
|
|
32
|
+
const left = horizontal && el.scrollLeft > 0
|
|
33
|
+
const right = horizontal && el.scrollWidth - el.scrollLeft - el.clientWidth > 1
|
|
34
|
+
return prev.top === top && prev.bottom === bottom && prev.left === left && prev.right === right
|
|
35
|
+
? prev
|
|
36
|
+
: { top, bottom, left, right }
|
|
25
37
|
})
|
|
26
|
-
}, [])
|
|
38
|
+
}, [axis])
|
|
27
39
|
|
|
28
40
|
React.useLayoutEffect(() => {
|
|
29
41
|
update()
|
|
@@ -47,25 +59,44 @@ export function useScrollFade<T extends HTMLElement = HTMLDivElement>() {
|
|
|
47
59
|
}
|
|
48
60
|
}, [update])
|
|
49
61
|
|
|
50
|
-
return {
|
|
62
|
+
return {
|
|
63
|
+
scrollRef,
|
|
64
|
+
fadeTop: fade.top,
|
|
65
|
+
fadeBottom: fade.bottom,
|
|
66
|
+
fadeLeft: fade.left,
|
|
67
|
+
fadeRight: fade.right,
|
|
68
|
+
update,
|
|
69
|
+
}
|
|
51
70
|
}
|
|
52
71
|
|
|
72
|
+
export type ScrollFadeEdge = 'top' | 'bottom' | 'left' | 'right'
|
|
73
|
+
|
|
53
74
|
export interface ScrollFadeOverlayProps {
|
|
54
75
|
/** Which edge of the scroll container the fade sits on. */
|
|
55
|
-
edge:
|
|
76
|
+
edge: ScrollFadeEdge
|
|
56
77
|
/** Whether the fade is currently shown (content continues past this edge). */
|
|
57
78
|
visible: boolean
|
|
58
79
|
/**
|
|
59
80
|
* CSS color the content fades into — should match the surface behind the
|
|
60
|
-
* list. Defaults to the page background token
|
|
81
|
+
* list. Defaults to the page background token, which is theme-aware (the
|
|
82
|
+
* light theme redefines the token, so the fade flips with it).
|
|
61
83
|
*/
|
|
62
84
|
color?: string
|
|
63
85
|
className?: string
|
|
64
86
|
}
|
|
65
87
|
|
|
88
|
+
const EDGE_GRADIENT_ANGLE: Record<ScrollFadeEdge, string> = {
|
|
89
|
+
top: '0deg',
|
|
90
|
+
bottom: '180deg',
|
|
91
|
+
left: '270deg',
|
|
92
|
+
right: '90deg',
|
|
93
|
+
}
|
|
94
|
+
|
|
66
95
|
/**
|
|
67
96
|
* Edge overlay that fades scrollable content into the surface behind it.
|
|
68
97
|
* Render inside a `relative` wrapper around the scrollable element.
|
|
98
|
+
* Vertical fades are 64px tall (legacy chat/FilterModal size); horizontal
|
|
99
|
+
* fades are 40px wide per the ODS "scroll gradient" spec.
|
|
69
100
|
*/
|
|
70
101
|
export function ScrollFadeOverlay({
|
|
71
102
|
edge,
|
|
@@ -73,18 +104,86 @@ export function ScrollFadeOverlay({
|
|
|
73
104
|
color = 'var(--color-bg)',
|
|
74
105
|
className,
|
|
75
106
|
}: ScrollFadeOverlayProps) {
|
|
107
|
+
const isVertical = edge === 'top' || edge === 'bottom'
|
|
76
108
|
return (
|
|
77
109
|
<div
|
|
78
110
|
aria-hidden
|
|
79
111
|
className={cn(
|
|
80
|
-
'pointer-events-none absolute
|
|
81
|
-
|
|
112
|
+
'pointer-events-none absolute transition-opacity duration-150',
|
|
113
|
+
isVertical ? 'inset-x-0 h-16' : 'inset-y-0 w-10',
|
|
114
|
+
edge === 'top' && 'top-0',
|
|
115
|
+
edge === 'bottom' && 'bottom-0',
|
|
116
|
+
edge === 'left' && 'left-0',
|
|
117
|
+
edge === 'right' && 'right-0',
|
|
82
118
|
visible ? 'opacity-100' : 'opacity-0',
|
|
83
119
|
className,
|
|
84
120
|
)}
|
|
85
121
|
style={{
|
|
86
|
-
background: `linear-gradient(${edge
|
|
122
|
+
background: `linear-gradient(${EDGE_GRADIENT_ANGLE[edge]}, transparent 0%, ${color} 100%)`,
|
|
87
123
|
}}
|
|
88
124
|
/>
|
|
89
125
|
)
|
|
90
126
|
}
|
|
127
|
+
|
|
128
|
+
export interface ScrollShadowProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
129
|
+
/** Which scroll direction(s) to track and fade. */
|
|
130
|
+
axis?: ScrollFadeAxis
|
|
131
|
+
/**
|
|
132
|
+
* CSS color of the fade — the surface the content visually sits on.
|
|
133
|
+
* Defaults to the page background token; pass e.g. `var(--color-bg-card)`
|
|
134
|
+
* when the scrollable sits on a card. Tokens are theme-aware, so the same
|
|
135
|
+
* component works in light and dark themes (dark by default).
|
|
136
|
+
*/
|
|
137
|
+
color?: string
|
|
138
|
+
/** Classes for the inner scrollable element (heights, paddings, etc.). */
|
|
139
|
+
scrollClassName?: string
|
|
140
|
+
/** Extra classes for every fade overlay (e.g. custom size). */
|
|
141
|
+
overlayClassName?: string
|
|
142
|
+
children: React.ReactNode
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Drop-in wrapper that makes its child scrollable and fades the edges where
|
|
147
|
+
* more content exists — right/left for horizontal overflow (wide tables),
|
|
148
|
+
* top/bottom for vertical (long lists). Fades appear and hide automatically
|
|
149
|
+
* as the user scrolls or the content resizes.
|
|
150
|
+
*
|
|
151
|
+
* ```tsx
|
|
152
|
+
* <ScrollShadow axis="horizontal">
|
|
153
|
+
* <WideTable />
|
|
154
|
+
* </ScrollShadow>
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
export function ScrollShadow({
|
|
158
|
+
axis = 'vertical',
|
|
159
|
+
color = 'var(--color-bg)',
|
|
160
|
+
className,
|
|
161
|
+
scrollClassName,
|
|
162
|
+
overlayClassName,
|
|
163
|
+
children,
|
|
164
|
+
...rest
|
|
165
|
+
}: ScrollShadowProps) {
|
|
166
|
+
const { scrollRef, fadeTop, fadeBottom, fadeLeft, fadeRight, update } = useScrollFade<HTMLDivElement>(axis)
|
|
167
|
+
const vertical = axis !== 'horizontal'
|
|
168
|
+
const horizontal = axis !== 'vertical'
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<div className={cn('relative', className)} {...rest}>
|
|
172
|
+
<div
|
|
173
|
+
ref={scrollRef}
|
|
174
|
+
onScroll={update}
|
|
175
|
+
className={cn(horizontal && 'overflow-x-auto', vertical && 'overflow-y-auto', scrollClassName)}
|
|
176
|
+
>
|
|
177
|
+
{children}
|
|
178
|
+
</div>
|
|
179
|
+
{vertical && <ScrollFadeOverlay edge="top" visible={fadeTop} color={color} className={overlayClassName} />}
|
|
180
|
+
{vertical && (
|
|
181
|
+
<ScrollFadeOverlay edge="bottom" visible={fadeBottom} color={color} className={overlayClassName} />
|
|
182
|
+
)}
|
|
183
|
+
{horizontal && <ScrollFadeOverlay edge="left" visible={fadeLeft} color={color} className={overlayClassName} />}
|
|
184
|
+
{horizontal && (
|
|
185
|
+
<ScrollFadeOverlay edge="right" visible={fadeRight} color={color} className={overlayClassName} />
|
|
186
|
+
)}
|
|
187
|
+
</div>
|
|
188
|
+
)
|
|
189
|
+
}
|
|
@@ -18,8 +18,8 @@ Main export. Renders `n` skeleton card rows with responsive desktop (`md:flex`)
|
|
|
18
18
|
| `rowClassName` | `string` | — | Extra classes on the inner flex row |
|
|
19
19
|
|
|
20
20
|
### Constants *(deprecated)*
|
|
21
|
-
- `ROW_HEIGHT_DESKTOP` — `'h-[
|
|
22
|
-
- `ROW_HEIGHT_MOBILE` — `'h-[
|
|
21
|
+
- `ROW_HEIGHT_DESKTOP` — `'h-[66px] md:h-[78px]'` (inner; +2px border = 68/80 total)
|
|
22
|
+
- `ROW_HEIGHT_MOBILE` — `'h-[66px]'` (inner)
|
|
23
23
|
|
|
24
24
|
**Primary column detection:** The component automatically identifies the widest (`flex-1` or `flex-[n]`) column as "primary" and renders a second skeleton line on every other row to simulate multi-line content.
|
|
25
25
|
|
|
@@ -4,8 +4,10 @@ import React from 'react'
|
|
|
4
4
|
import { cn } from '../../../utils/cn'
|
|
5
5
|
import type { TableCardSkeletonProps } from './types'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
// INNER row heights: the bordered row card adds 1px top + bottom, so the
|
|
8
|
+
// outer block totals the designed 68px / 80px.
|
|
9
|
+
const ROW_HEIGHT_DESKTOP = 'h-[66px] md:h-[78px]'
|
|
10
|
+
const ROW_HEIGHT_MOBILE = 'h-[66px]'
|
|
9
11
|
|
|
10
12
|
/** @deprecated Use `DataTableSkeleton` from `data-table` instead. */
|
|
11
13
|
export function TableCardSkeleton({
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/nextjs-vite';
|
|
2
|
+
import { ScrollShadow } from '../components/ui/scroll-fade';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'UI/ScrollShadow',
|
|
6
|
+
component: ScrollShadow,
|
|
7
|
+
argTypes: {
|
|
8
|
+
axis: {
|
|
9
|
+
control: 'select',
|
|
10
|
+
options: ['vertical', 'horizontal', 'both'],
|
|
11
|
+
},
|
|
12
|
+
color: { control: 'text' },
|
|
13
|
+
},
|
|
14
|
+
parameters: {
|
|
15
|
+
docs: {
|
|
16
|
+
description: {
|
|
17
|
+
component:
|
|
18
|
+
'Wrapper that makes its child scrollable and fades the edges where more content exists. ' +
|
|
19
|
+
'The fade color defaults to the page background token and is theme-aware; pass a card/light ' +
|
|
20
|
+
'surface color when the scrollable sits on another surface.',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
} satisfies Meta<typeof ScrollShadow>;
|
|
25
|
+
|
|
26
|
+
export default meta;
|
|
27
|
+
type Story = StoryObj<typeof meta>;
|
|
28
|
+
|
|
29
|
+
const COLUMNS = ['HOSTNAME', 'PID', 'NAME', 'PATH', 'STATE', 'UID', 'RESIDENT', 'THREADS', 'START TIME'];
|
|
30
|
+
|
|
31
|
+
const WideTable = () => (
|
|
32
|
+
<div className="w-max min-w-full">
|
|
33
|
+
<div className="flex px-[var(--spacing-system-mf)] gap-[var(--spacing-system-mf)]">
|
|
34
|
+
{COLUMNS.map(col => (
|
|
35
|
+
<div key={col} className="flex h-12 w-[160px] shrink-0 items-center">
|
|
36
|
+
<span className="text-h5 text-ods-text-secondary uppercase">{col}</span>
|
|
37
|
+
</div>
|
|
38
|
+
))}
|
|
39
|
+
</div>
|
|
40
|
+
{[1, 2, 3].map(row => (
|
|
41
|
+
<div key={row} className="rounded-md bg-ods-card border border-ods-border overflow-hidden mb-[var(--spacing-system-xsf)]">
|
|
42
|
+
<div className="flex h-[78px] items-center px-[var(--spacing-system-mf)] gap-[var(--spacing-system-mf)]">
|
|
43
|
+
{COLUMNS.map(col => (
|
|
44
|
+
<div key={col} className="w-[160px] shrink-0">
|
|
45
|
+
<span className="text-h4 text-ods-text-primary truncate">
|
|
46
|
+
{col.toLowerCase()}-{row}
|
|
47
|
+
</span>
|
|
48
|
+
</div>
|
|
49
|
+
))}
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
))}
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
/** Wide table: right fade on load, left fade appears once scrolled. */
|
|
57
|
+
export const HorizontalTable: Story = {
|
|
58
|
+
args: {
|
|
59
|
+
axis: 'horizontal',
|
|
60
|
+
children: <WideTable />,
|
|
61
|
+
},
|
|
62
|
+
render: args => (
|
|
63
|
+
<div className="max-w-[720px] bg-ods-bg p-[var(--spacing-system-mf)]">
|
|
64
|
+
<ScrollShadow {...args} />
|
|
65
|
+
</div>
|
|
66
|
+
),
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const LongList = () => (
|
|
70
|
+
<div className="flex flex-col gap-[var(--spacing-system-xsf)] p-[var(--spacing-system-mf)]">
|
|
71
|
+
{Array.from({ length: 20 }).map((_, i) => (
|
|
72
|
+
<div key={i} className="rounded-md bg-ods-card border border-ods-border p-[var(--spacing-system-mf)]">
|
|
73
|
+
<span className="text-h4 text-ods-text-primary">Message {i + 1}</span>
|
|
74
|
+
</div>
|
|
75
|
+
))}
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
/** Long list: bottom fade on load, top fade appears once scrolled down. */
|
|
80
|
+
export const VerticalList: Story = {
|
|
81
|
+
args: {
|
|
82
|
+
axis: 'vertical',
|
|
83
|
+
children: <LongList />,
|
|
84
|
+
scrollClassName: 'h-[320px]',
|
|
85
|
+
},
|
|
86
|
+
render: args => (
|
|
87
|
+
<div className="max-w-[480px] bg-ods-bg">
|
|
88
|
+
<ScrollShadow {...args} />
|
|
89
|
+
</div>
|
|
90
|
+
),
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Light-surface usage (e.g. ChatMessageList themes): pass the surface color
|
|
95
|
+
* the content sits on — with theme-aware tokens the same prop value works in
|
|
96
|
+
* both themes; a literal color is shown here to make the story self-contained.
|
|
97
|
+
*/
|
|
98
|
+
export const LightSurface: Story = {
|
|
99
|
+
args: {
|
|
100
|
+
axis: 'vertical',
|
|
101
|
+
color: '#ffffff',
|
|
102
|
+
children: (
|
|
103
|
+
<div className="flex flex-col gap-2 p-4">
|
|
104
|
+
{Array.from({ length: 20 }).map((_, i) => (
|
|
105
|
+
<div key={i} className="rounded-md border border-gray-200 bg-gray-50 p-4">
|
|
106
|
+
<span className="text-gray-900">Light message {i + 1}</span>
|
|
107
|
+
</div>
|
|
108
|
+
))}
|
|
109
|
+
</div>
|
|
110
|
+
),
|
|
111
|
+
scrollClassName: 'h-[320px]',
|
|
112
|
+
},
|
|
113
|
+
render: args => (
|
|
114
|
+
<div className="max-w-[480px] bg-white rounded-md">
|
|
115
|
+
<ScrollShadow {...args} />
|
|
116
|
+
</div>
|
|
117
|
+
),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/** Both axes at once. */
|
|
121
|
+
export const BothAxes: Story = {
|
|
122
|
+
args: {
|
|
123
|
+
axis: 'both',
|
|
124
|
+
children: <WideTable />,
|
|
125
|
+
scrollClassName: 'h-[200px]',
|
|
126
|
+
},
|
|
127
|
+
render: args => (
|
|
128
|
+
<div className="max-w-[720px] bg-ods-bg p-[var(--spacing-system-mf)]">
|
|
129
|
+
<ScrollShadow {...args} />
|
|
130
|
+
</div>
|
|
131
|
+
),
|
|
132
|
+
};
|