diff --git a/package.json b/package.json index 283bebea7..37dc5f314 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,6 @@ "react-i18next": "^16.3.3", "react-icons": "^5.5.0", "react-image": "^4.1.0", - "react-loading-skeleton": "^3.5.0", "react-player": "^2.16.0", "react-router": "^7.9.6", "react-split-pane": "^3.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 11cc3e3b5..f235addf3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -185,9 +185,6 @@ importers: react-image: specifier: ^4.1.0 version: 4.1.0(@babel/runtime@7.28.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react-loading-skeleton: - specifier: ^3.5.0 - version: 3.5.0(react@19.1.0) react-player: specifier: ^2.16.0 version: 2.16.0(react@19.1.0) @@ -4572,11 +4569,6 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - react-loading-skeleton@3.5.0: - resolution: {integrity: sha512-gxxSyLbrEAdXTKgfbpBEFZCO/P153DnqSCQau2+o6lNy1jgMRr2MmRmOzMmyrwSaSYLRB8g7b0waYPmUjz7IhQ==} - peerDependencies: - react: '>=16.8.0' - react-number-format@5.4.4: resolution: {integrity: sha512-wOmoNZoOpvMminhifQYiYSTCLUDOiUbBunrMrMjA+dV52sY+vck1S4UhR6PkgnoCquvvMSeJjErXZ4qSaWCliA==} peerDependencies: @@ -10579,10 +10571,6 @@ snapshots: react-is@16.13.1: {} - react-loading-skeleton@3.5.0(react@19.1.0): - dependencies: - react: 19.1.0 - react-number-format@5.4.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 diff --git a/src/shared/components/skeleton/skeleton.module.css b/src/shared/components/skeleton/skeleton.module.css index 24644ea1f..6e028923e 100644 --- a/src/shared/components/skeleton/skeleton.module.css +++ b/src/shared/components/skeleton/skeleton.module.css @@ -13,6 +13,28 @@ width: 100%; height: 100%; + background: linear-gradient( + 90deg, + var(--base-color) 0%, + var(--highlight-color) 50%, + var(--base-color) 100% + ); + background-size: 200% 100%; + border-radius: var(--skeleton-border-radius, 0.25rem); +} + +.skeleton.animated { + animation: shimmer var(--animation-duration) ease-in-out infinite; +} + +@keyframes shimmer { + 0% { + background-position: 200% 0; + } + + 100% { + background-position: -200% 0; + } } .skeleton-container { @@ -22,6 +44,31 @@ height: 100%; } -.centered { +.skeleton-container.inline { + display: inline-flex; +} + +.skeleton-container.centered { justify-content: center; } + +.skeleton-container.rtl { + flex-direction: row-reverse; +} + +.skeleton-wrapper { + display: flex; + flex-direction: column; + gap: 0.5rem; + align-items: stretch; + width: 100%; + height: 100%; +} + +.skeleton-wrapper.inline { + display: inline-flex; +} + +.skeleton-wrapper.rtl { + direction: rtl; +} diff --git a/src/shared/components/skeleton/skeleton.tsx b/src/shared/components/skeleton/skeleton.tsx index 98ce15ff0..3f2cb7a87 100644 --- a/src/shared/components/skeleton/skeleton.tsx +++ b/src/shared/components/skeleton/skeleton.tsx @@ -1,11 +1,8 @@ import clsx from 'clsx'; import { type CSSProperties, memo } from 'react'; -import RSkeleton from 'react-loading-skeleton'; import styles from './skeleton.module.css'; -import 'react-loading-skeleton/dist/skeleton.css'; - interface SkeletonProps { baseColor?: string; borderRadius?: string; @@ -26,8 +23,8 @@ export function BaseSkeleton({ borderRadius, className, containerClassName, - count, - direction, + count = 1, + direction = 'ltr', enableAnimation = false, height, inline, @@ -35,22 +32,40 @@ export function BaseSkeleton({ style, width, }: SkeletonProps) { + const skeletonStyle: CSSProperties = { + ...style, + ...(baseColor && { ['--base-color' as string]: baseColor }), + ...(borderRadius && { ['--skeleton-border-radius' as string]: borderRadius }), + ...(height !== undefined && { + height: typeof height === 'number' ? `${height}px` : height, + }), + ...(width !== undefined && { width: typeof width === 'number' ? `${width}px` : width }), + }; + + const containerClasses = clsx(styles.skeletonContainer, containerClassName, { + [styles.centered]: isCentered, + [styles.inline]: inline, + [styles.rtl]: direction === 'rtl', + }); + + const skeletonClasses = clsx(styles.skeleton, className, { + [styles.animated]: enableAnimation, + }); + + if (count <= 1) { + return ( +