From 677a3ff64bcc882250d4aa755456c9c1f920a791 Mon Sep 17 00:00:00 2001 From: cnliucheng Date: Wed, 8 Jul 2026 11:35:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20ui-skeleton=20?= =?UTF-8?q?=E9=AA=A8=E6=9E=B6=E5=B1=8F=E7=BB=84=E4=BB=B6=20(card=20/=20lis?= =?UTF-8?q?t-row=20/=20circle)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/ui-skeleton/ui-skeleton.js | 21 ++++++ components/ui-skeleton/ui-skeleton.json | 4 ++ components/ui-skeleton/ui-skeleton.wxml | 28 ++++++++ components/ui-skeleton/ui-skeleton.wxss | 85 +++++++++++++++++++++++++ 4 files changed, 138 insertions(+) create mode 100644 components/ui-skeleton/ui-skeleton.js create mode 100644 components/ui-skeleton/ui-skeleton.json create mode 100644 components/ui-skeleton/ui-skeleton.wxml create mode 100644 components/ui-skeleton/ui-skeleton.wxss diff --git a/components/ui-skeleton/ui-skeleton.js b/components/ui-skeleton/ui-skeleton.js new file mode 100644 index 0000000..9d47f03 --- /dev/null +++ b/components/ui-skeleton/ui-skeleton.js @@ -0,0 +1,21 @@ +Component({ + properties: { + variant: { type: String, value: 'card' }, + count: { type: Number, value: 1 }, + active: { type: Boolean, value: true } + }, + data: { + _minDisplayShown: false + }, + lifetimes: { + attached() { + // 200ms 最小显示,避免骨架闪一下 + this._minTimer = setTimeout(() => { + this.setData({ _minDisplayShown: true }) + }, 200) + }, + detached() { + if (this._minTimer) clearTimeout(this._minTimer) + } + } +}) diff --git a/components/ui-skeleton/ui-skeleton.json b/components/ui-skeleton/ui-skeleton.json new file mode 100644 index 0000000..a89ef4d --- /dev/null +++ b/components/ui-skeleton/ui-skeleton.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} diff --git a/components/ui-skeleton/ui-skeleton.wxml b/components/ui-skeleton/ui-skeleton.wxml new file mode 100644 index 0000000..19a371b --- /dev/null +++ b/components/ui-skeleton/ui-skeleton.wxml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/ui-skeleton/ui-skeleton.wxss b/components/ui-skeleton/ui-skeleton.wxss new file mode 100644 index 0000000..f338605 --- /dev/null +++ b/components/ui-skeleton/ui-skeleton.wxss @@ -0,0 +1,85 @@ +.skeleton { + width: 100%; +} + +.skeleton--active .sk-bar, +.skeleton--active .sk-circle { + animation: skShimmer 1.4s ease-in-out infinite; + background: linear-gradient(90deg, + rgba(0, 0, 0, 0.06) 0%, + rgba(0, 0, 0, 0.12) 50%, + rgba(0, 0, 0, 0.06) 100%); + background-size: 200% 100%; +} + +@keyframes skShimmer { + 0% { background-position: 200% 0; } + 100% { background-position: -200% 0; } +} + +.sk-bar { + height: 24rpx; + border-radius: 8rpx; + margin-bottom: 16rpx; + background-color: rgba(0, 0, 0, 0.08); +} + +.sk-bar--title { width: 60%; height: 32rpx; } +.sk-bar--body { width: 100%; } +.sk-bar--small { width: 40%; height: 20rpx; margin-bottom: 0; } +.sk-bar--center { width: 60%; height: 40rpx; } + +.sk-card { + background: var(--card-bg, #FFFFFF); + border-radius: 24rpx; + padding: 32rpx; + box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06); +} + +.sk-circle { + width: 64rpx; + height: 64rpx; + border-radius: 50%; + background-color: rgba(0, 0, 0, 0.08); + flex-shrink: 0; +} + +.sk-circle--big { + width: 360rpx; + height: 360rpx; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto; +} + +.sk-list { + display: flex; + align-items: center; + padding: 24rpx 0; + gap: 24rpx; +} + +.sk-list-text { + flex: 1; + display: flex; + flex-direction: column; + gap: 8rpx; +} + +/* dark mode */ +@media (prefers-color-scheme: dark) { + .sk-card { background: var(--card-bg, #1C1C1E); } + .skeleton--active .sk-bar, + .skeleton--active .sk-circle { + background: linear-gradient(90deg, + rgba(255, 255, 255, 0.05) 0%, + rgba(255, 255, 255, 0.10) 50%, + rgba(255, 255, 255, 0.05) 100%); + background-size: 200% 100%; + } + .sk-bar, + .sk-circle { + background-color: rgba(255, 255, 255, 0.06); + } +}