From 61d345d80e39106f7bc4bc2c89a7059d8846834c Mon Sep 17 00:00:00 2001 From: Wonsuk Choi Date: Mon, 9 Nov 2026 20:53:43 +0900 Subject: [PATCH 1/7] feat(ds/skeleton): add a non-inverting 'Skeleton' primitive --- src/components/ds/ds-nav.ts | 10 +++ src/components/ds/ui/index.tsx | 53 +++++++++++++ src/routeTree.gen.ts | 25 +++++- src/routes/ds.index.tsx | 2 + src/routes/ds.skeleton.tsx | 138 +++++++++++++++++++++++++++++++++ 5 files changed, 224 insertions(+), 4 deletions(-) create mode 100644 src/routes/ds.skeleton.tsx diff --git a/src/components/ds/ds-nav.ts b/src/components/ds/ds-nav.ts index 027387d0b..d0e91ccfc 100644 --- a/src/components/ds/ds-nav.ts +++ b/src/components/ds/ds-nav.ts @@ -226,6 +226,16 @@ export const dsNav: Array = [ to: '/ds/partner-rail', sections: ['Rail', 'Tiers', 'Per-logo scale'], }, + { + label: 'Skeleton', + to: '/ds/skeleton', + sections: [ + 'Skeleton', + 'On any surface', + 'Grouping and accessibility', + 'Match the real layout', + ], + }, { label: 'Spinner', to: '/ds/spinner', diff --git a/src/components/ds/ui/index.tsx b/src/components/ds/ui/index.tsx index 7557cc96c..074851a67 100644 --- a/src/components/ds/ui/index.tsx +++ b/src/components/ds/ui/index.tsx @@ -628,6 +628,59 @@ export function Spinner({ className }: { className?: string }) { ) } +/* --------------------------------------------------------------- Skeleton -- */ + +/** + * Placeholder block shown while content loads. + * + * The tint is an alpha overlay rather than an opaque surface token, so it keeps + * the same contrast on the page background and on an elevated card — an opaque + * `background-subtle` reads lighter than the page in dark mode but darker than + * a card, inverting as it moves between surfaces. + * + * The pulse is wrapped in `motion-safe:` so it holds still under + * `prefers-reduced-motion`. + */ +export function Skeleton({ + className, + ...rest +}: React.ComponentPropsWithoutRef<'div'>) { + return ( +