History

fix(web): unify skeleton loading animations on one pulse (#9448)

maria committed 2 months ago

Commit 21b9dda1 parent d4ba2a14 files · +39 −45Browse files

Showing the changes to apps/web/src/components/pullRequest (1 of 4 files). Show all

Unified · Split

apps/web/src/components/pullRequest/PullRequestGhosts.tsx+16−10
@@ -3,11 +3,9 @@ · 2 unmodified lines
3 * and a detail panel opening — use bars in the geometry of the content they stand for, pulsing3 * and a detail panel opening — use bars in the geometry of the content they stand for, pulsing
4 * on one composited layer. Diff loading uses the shared diff-panel skeleton instead.4 * on one composited layer. Diff loading uses the shared diff-panel skeleton instead.
5 *5 *
6 * Deliberately not the app's shimmer skeleton. The sweep is a `transform` animation per bar —6 * The bars share the app-wide `Skeleton` tone (`muted-foreground` at low alpha, which reads on
7 * compositor-safe, but a layer for every bar on screen — and its white highlight over the7 * both themes) and the single `animate-skeleton` pulse, applied once on the container so any
8 * near-white `muted` base all but disappears in light mode. Here one `animate-ghost-pulse` on the8 * number of bars costs one opacity animation.
9 * container is a single opacity animation however many bars sit under it, and the bars take
10 * their tone from `muted-foreground` at low alpha, which reads on both themes.
11 */9 */
12import { cn } from "~/lib/utils";10import { cn } from "~/lib/utils";
13 11
@@ -32,7 +30,7 @@ export function PullRequestListGhost({ · 18 unmodified lines
32 <div30 <div
33 role="status"31 role="status"
34 aria-label={caption ?? "Loading pull requests"}32 aria-label={caption ?? "Loading pull requests"}
35 className="animate-ghost-pulse space-y-0.5"33 className="motion-safe:animate-skeleton space-y-0.5"
36 >34 >
37 {caption ? (35 {caption ? (
38 <p className="px-3 pb-1 text-xs font-medium text-muted-foreground/70">{caption}</p>36 <p className="px-3 pb-1 text-xs font-medium text-muted-foreground/70">{caption}</p>
@@ -67,7 +65,7 @@ export function PullRequestDetailGhost() { · 28 unmodified lines
67 <div65 <div
68 role="status"66 role="status"
69 aria-label="Loading pull request"67 aria-label="Loading pull request"
70 className="animate-ghost-pulse flex h-full min-h-0 flex-col overflow-hidden bg-background"68 className="motion-safe:animate-skeleton flex h-full min-h-0 flex-col overflow-hidden bg-background"
71 >69 >
72 <div className="shrink-0 border-b border-border/60">70 <div className="shrink-0 border-b border-border/60">
73 <div className="flex h-7 items-center justify-between gap-3 px-4">71 <div className="flex h-7 items-center justify-between gap-3 px-4">
@@ -160,7 +158,11 @@ export function PullRequestDetailGhost() { · 86 unmodified lines
160/** People-shaped: an avatar and a name, in the reviewer picker's own row height. */158/** People-shaped: an avatar and a name, in the reviewer picker's own row height. */
161export function PullRequestPeopleGhost({ rows = 4 }: { rows?: number }) {159export function PullRequestPeopleGhost({ rows = 4 }: { rows?: number }) {
162 return (160 return (
163 <div role="status" aria-label="Loading people" className="animate-ghost-pulse space-y-1 p-1">161 <div
162 role="status"
163 aria-label="Loading people"
164 className="motion-safe:animate-skeleton space-y-1 p-1"
165 >
164 {Array.from({ length: rows }, (_, index) => (166 {Array.from({ length: rows }, (_, index) => (
165 <div key={index} className="flex h-7 items-center gap-2 rounded-md px-2">167 <div key={index} className="flex h-7 items-center gap-2 rounded-md px-2">
166 <GhostBar className="size-4 rounded-full" />168 <GhostBar className="size-4 rounded-full" />
@@ -174,7 +176,11 @@ export function PullRequestPeopleGhost({ rows = 4 }: { rows?: number }) { · 7 unmodified lines
174/** The timeline's own shape: dots on the rail, a line and a date to each. */176/** The timeline's own shape: dots on the rail, a line and a date to each. */
175export function PullRequestTimelineGhost({ rows = 6 }: { rows?: number }) {177export function PullRequestTimelineGhost({ rows = 6 }: { rows?: number }) {
176 return (178 return (
177 <div role="status" aria-label="Loading timeline" className="animate-ghost-pulse px-4 py-5">179 <div
180 role="status"
181 aria-label="Loading timeline"
182 className="motion-safe:animate-skeleton px-4 py-5"
183 >
178 <div className="relative ml-2 border-l border-border/70 pl-5">184 <div className="relative ml-2 border-l border-border/70 pl-5">
179 {Array.from({ length: rows }, (_, index) => (185 {Array.from({ length: rows }, (_, index) => (
180 <div key={index} className="relative pb-5">186 <div key={index} className="relative pb-5">
@@ -194,7 +200,7 @@ export function PullRequestConversationGhost({ rows = 3 }: { rows?: number }) { · 13 unmodified lines
194 <div200 <div
195 role="status"201 role="status"
196 aria-label="Loading pull request conversation"202 aria-label="Loading pull request conversation"
197 className="animate-ghost-pulse space-y-4 py-2"203 className="motion-safe:animate-skeleton space-y-4 py-2"
198 >204 >
199 {Array.from({ length: rows }, (_, index) => (205 {Array.from({ length: rows }, (_, index) => (
200 <div key={index} className="flex items-start gap-2">206 <div key={index} className="flex items-start gap-2">