1+ import { rgba } from 'polished'
12import { type ReactNode } from 'react'
2- import { Text } from 'rebass'
3- import styled from 'styled-components'
3+ import { Box , Text } from 'rebass'
4+ import styled , { keyframes } from 'styled-components'
45
56import Skeleton from 'components/Skeleton'
67import { HStack , Stack } from 'components/Stack'
@@ -13,8 +14,35 @@ export const PoolChartWrapper = styled.div<{ $height?: number }>`
1314 height: ${ ( { $height } ) => $height ?? DEFAULT_CHART_HEIGHT } px;
1415`
1516
17+ const shimmer = keyframes `
18+ 0% { transform: translateX(-100%); }
19+ 100% { transform: translateX(100%); }
20+ `
21+
22+ const SkeletonBar = styled . div < { $height : number } > `
23+ position: relative;
24+ flex: 1 1 0;
25+ min-width: 4px;
26+ max-width: 12px;
27+ height: ${ ( { $height } ) => $height } %;
28+ border-top-left-radius: 4px;
29+ border-top-right-radius: 4px;
30+ background: ${ ( { theme } ) => rgba ( theme . text , 0.04 ) } ;
31+ overflow: hidden;
32+ `
33+
34+ const SkeletonBarShimmer = styled . div `
35+ position: absolute;
36+ inset: 0;
37+ background: ${ ( { theme } ) =>
38+ `linear-gradient(90deg, ${ rgba ( theme . text , 0 ) } 0%, ${ rgba ( theme . text , 0.04 ) } 50%, ${ rgba ( theme . text , 0 ) } 100%)` } ;
39+ opacity: 0.7;
40+ animation: ${ shimmer } 1.8s linear infinite;
41+ `
42+
1643type PoolChartSkeletonProps = {
1744 height ?: number
45+ type ?: 'line' | 'bar' | 'candle'
1846}
1947
2048type PoolChartMessageProps = {
@@ -31,6 +59,7 @@ type PoolChartStateProps = {
3159 isEmpty ?: boolean
3260 isError ?: boolean
3361 isLoading ?: boolean
62+ skeletonType ?: PoolChartSkeletonProps [ 'type' ]
3463}
3564
3665const PoolChartStateLayout = ( {
@@ -61,18 +90,149 @@ const PoolChartStateLayout = ({
6190 )
6291}
6392
64- export const PoolChartSkeleton = ( { height = DEFAULT_CHART_HEIGHT } : PoolChartSkeletonProps ) => {
93+ const LineChartSkeleton = ( { height } : { height : number } ) => {
94+ const theme = useTheme ( )
95+
96+ return (
97+ < Box height = { `${ Math . max ( height - 64 , 0 ) } px` } width = "100%" >
98+ < svg height = "100%" preserveAspectRatio = "none" viewBox = "0 0 600 240" width = "100%" >
99+ < defs >
100+ < linearGradient id = "pool-chart-line-skeleton-gradient" x1 = "0%" x2 = "100%" y1 = "0%" y2 = "0%" >
101+ < stop offset = "0%" stopColor = { rgba ( theme . text , 0.04 ) } />
102+ < stop offset = "50%" stopColor = { rgba ( theme . text , 0.14 ) } >
103+ < animate attributeName = "offset" dur = "1.8s" repeatCount = "indefinite" values = "-0.5; 0.5; 1.5" />
104+ </ stop >
105+ < stop offset = "100%" stopColor = { rgba ( theme . text , 0.04 ) } />
106+ </ linearGradient >
107+ </ defs >
108+
109+ < path
110+ d = "M24 182 C78 168, 110 116, 152 126 S246 196, 302 148 S390 68, 444 88 S526 164, 576 134"
111+ fill = "none"
112+ stroke = "url(#pool-chart-line-skeleton-gradient)"
113+ strokeLinecap = "round"
114+ strokeLinejoin = "round"
115+ strokeWidth = "4"
116+ />
117+ </ svg >
118+ </ Box >
119+ )
120+ }
121+
122+ const BarChartSkeleton = ( { height } : { height : number } ) => {
123+ const barHeights = [ 15 , 20 , 5 , 10 , 15 , 30 , 10 , 15 , 60 , 70 , 85 , 90 , 100 , 70 , 80 , 40 , 55 , 60 , 15 , 20 , 25 , 15 , 10 , 5 ]
124+
125+ return (
126+ < Box height = { `${ Math . max ( height - 64 , 0 ) } px` } width = "100%" >
127+ < HStack align = "flex-end" gap = { 8 } height = "100%" justify = "center" p = "8px" width = "100%" >
128+ { barHeights . map ( ( barHeight , index ) => (
129+ < SkeletonBar $height = { barHeight * 0.8 } key = { index } >
130+ < SkeletonBarShimmer />
131+ </ SkeletonBar >
132+ ) ) }
133+ </ HStack >
134+ </ Box >
135+ )
136+ }
137+
138+ const CandleChartSkeleton = ( { height } : { height : number } ) => {
139+ const theme = useTheme ( )
140+ const candles = [
141+ { bodyHeight : 34 , bodyY : 142 , wickTop : 88 , wickBottom : 202 , x : 38 } ,
142+ { bodyHeight : 52 , bodyY : 116 , wickTop : 74 , wickBottom : 198 , x : 96 } ,
143+ { bodyHeight : 38 , bodyY : 136 , wickTop : 102 , wickBottom : 206 , x : 154 } ,
144+ { bodyHeight : 58 , bodyY : 102 , wickTop : 66 , wickBottom : 194 , x : 212 } ,
145+ { bodyHeight : 42 , bodyY : 128 , wickTop : 92 , wickBottom : 210 , x : 270 } ,
146+ { bodyHeight : 66 , bodyY : 84 , wickTop : 48 , wickBottom : 186 , x : 328 } ,
147+ { bodyHeight : 44 , bodyY : 122 , wickTop : 80 , wickBottom : 202 , x : 386 } ,
148+ { bodyHeight : 56 , bodyY : 104 , wickTop : 64 , wickBottom : 192 , x : 444 } ,
149+ { bodyHeight : 36 , bodyY : 140 , wickTop : 106 , wickBottom : 212 , x : 502 } ,
150+ { bodyHeight : 48 , bodyY : 118 , wickTop : 78 , wickBottom : 200 , x : 560 } ,
151+ ]
152+
153+ return (
154+ < Box height = { `${ Math . max ( height - 64 , 0 ) } px` } width = "100%" >
155+ < svg height = "100%" preserveAspectRatio = "none" viewBox = "0 0 600 240" width = "100%" >
156+ < defs >
157+ < linearGradient id = "pool-chart-candle-skeleton-shimmer" x1 = "0%" x2 = "100%" y1 = "0%" y2 = "0%" >
158+ < stop offset = "0%" stopColor = { rgba ( theme . text , 0 ) } />
159+ < stop offset = "50%" stopColor = { rgba ( theme . text , 0.12 ) } />
160+ < stop offset = "100%" stopColor = { rgba ( theme . text , 0 ) } />
161+ </ linearGradient >
162+ < mask id = "pool-chart-candle-skeleton-mask" >
163+ { candles . map ( candle => (
164+ < g key = { candle . x } >
165+ < line
166+ stroke = "white"
167+ strokeLinecap = "round"
168+ strokeWidth = "2"
169+ x1 = { candle . x }
170+ x2 = { candle . x }
171+ y1 = { candle . wickTop }
172+ y2 = { candle . wickBottom }
173+ />
174+ < rect height = { candle . bodyHeight } rx = "4" width = "24" x = { candle . x - 12 } y = { candle . bodyY } fill = "white" />
175+ </ g >
176+ ) ) }
177+ </ mask >
178+ </ defs >
179+
180+ { candles . map ( candle => (
181+ < g key = { candle . x } >
182+ < line
183+ stroke = { rgba ( theme . text , 0.05 ) }
184+ strokeLinecap = "round"
185+ strokeWidth = "2"
186+ x1 = { candle . x }
187+ x2 = { candle . x }
188+ y1 = { candle . wickTop }
189+ y2 = { candle . wickBottom }
190+ />
191+ < rect
192+ fill = { rgba ( theme . text , 0.05 ) }
193+ height = { candle . bodyHeight }
194+ rx = "4"
195+ width = "24"
196+ x = { candle . x - 12 }
197+ y = { candle . bodyY }
198+ />
199+ </ g >
200+ ) ) }
201+ < rect
202+ fill = "url(#pool-chart-candle-skeleton-shimmer)"
203+ height = "240"
204+ mask = "url(#pool-chart-candle-skeleton-mask)"
205+ width = "240"
206+ x = "-240"
207+ y = "0"
208+ >
209+ < animateTransform
210+ attributeName = "transform"
211+ dur = "2.4s"
212+ repeatCount = "indefinite"
213+ type = "translate"
214+ values = "-240 0; 600 0"
215+ />
216+ </ rect >
217+ </ svg >
218+ </ Box >
219+ )
220+ }
221+
222+ export const PoolChartSkeleton = ( { height = DEFAULT_CHART_HEIGHT , type = 'line' } : PoolChartSkeletonProps ) => {
65223 return (
66224 < PoolChartStateLayout gap = { 12 } height = { height } >
67- < Skeleton height = { height } width = "100%" />
225+ { type === 'line' ? < LineChartSkeleton height = { height } /> : null }
226+ { type === 'bar' ? < BarChartSkeleton height = { height } /> : null }
227+ { type === 'candle' ? < CandleChartSkeleton height = { height } /> : null }
68228 </ PoolChartStateLayout >
69229 )
70230}
71231
72232const LiquidityFlowChartSkeleton = ( { height = DEFAULT_CHART_HEIGHT } : PoolChartSkeletonProps ) => {
73233 return (
74234 < Stack gap = { 12 } >
75- < PoolChartSkeleton height = { height } />
235+ < PoolChartSkeleton height = { height } type = "bar" />
76236 < HStack gap = { 16 } justify = "center" wrap = "wrap" >
77237 { Array . from ( { length : 3 } ) . map ( ( _ , index ) => (
78238 < HStack align = "center" gap = { 16 } key = { index } >
@@ -90,7 +250,7 @@ const EarningChartSkeleton = ({ height = DEFAULT_CHART_HEIGHT }: PoolChartSkelet
90250
91251 return (
92252 < Stack gap = { 16 } >
93- < PoolChartSkeleton height = { height } />
253+ < PoolChartSkeleton height = { height } type = "bar" />
94254 < Stack
95255 align = "center"
96256 direction = { isCompact ? 'column' : 'row' }
@@ -131,6 +291,7 @@ const PoolChartState = ({
131291 isEmpty,
132292 isError,
133293 isLoading,
294+ skeletonType,
134295} : PoolChartStateProps ) => {
135296 if ( isLoading ) {
136297 if ( exclusiveType === 'liquidity-flow' ) {
@@ -141,7 +302,7 @@ const PoolChartState = ({
141302 return < EarningChartSkeleton height = { height } />
142303 }
143304
144- return < PoolChartSkeleton height = { height } />
305+ return < PoolChartSkeleton height = { height } type = { skeletonType } />
145306 }
146307
147308 if ( isError && errorMessage ) {
0 commit comments