skeleton · glass-apple · 灵感来源:Skeleton Screen 模式 + 本站材质配方
数据到达后整块替换,不闪烁。
Skeleton Screen · 玻璃骨架 · 骨架 / Glass
做一个 Skeleton Screen(玻璃骨架):
- role=status + aria-busy,占位块全部 aria-hidden,读屏只播一句加载状态
- avatar + lines 还原最终版式;行宽递减,最后一行天然变短
- 静态占位不闪烁,减少动效下无需额外降级
- 半透明底 + 发丝边 + inset 高光,与玻璃输入框同一层语言
用这些 CSS 变量:--color-text-muted --glass-bg --glass-border --glass-inset
灵感参考:Skeleton Screen 模式 + 本站材质配方--color-text-muted --glass-bg --glass-border --glass-inset
(无必缺状态)
(尚未接进整页场景)
/r/skeleton--glass-apple.json
免外壳的 markdown 版:/llms/components/skeleton--glass-apple.mdrole="status" + aria-busy="true" + aria-label 说明正在加载什么;
所有占位块 aria-hidden,读屏只听到一句状态avatar + lines 两件事决定:头像圆位、正文行数;
行宽按 100 / 86 / 72 … 递减,最后一行天然变短--glass-bg 半透明底 + 发丝边 + inset 高光,和玻璃输入框同一层语言变量:--glass-bg / --glass-border / --glass-inset。
interface Props {
/** 正文行数 */
lines?: number;
/** 左侧头像位 */
avatar?: boolean;
label?: string;
className?: string;
}
/**
* 玻璃骨架:加载中的占位块。
* 保持最终版式的高度与节奏,数据到达后整块替换;不做闪烁。
*/
export function GlassAppleSkeleton({
lines = 3,
avatar = false,
label = '加载中',
className = '',
}: Props) {
return (
<div
role="status"
aria-busy="true"
aria-label={label}
className={`flex items-start gap-3 ${className}`}
>
{avatar && (
<span
aria-hidden="true"
className="
size-10 shrink-0 rounded-full
bg-[var(--glass-bg)] border border-[var(--glass-border)]
backdrop-blur-xl shadow-[var(--glass-inset)]
"
/>
)}
<div className="flex-1 space-y-2.5 pt-0.5">
{Array.from({ length: lines }).map((_, i) => (
<span
key={i}
aria-hidden="true"
className="
block h-3 rounded-full
bg-[var(--glass-bg)] border border-[var(--glass-border)]
shadow-[var(--glass-inset)]
"
style={{ width: `${Math.max(42, 100 - i * 14)}%` }}
/>
))}
</div>
</div>
);
}
src/components/skeleton/glass-apple/