Implement loading state for purchase page and enhance styling (#1586)

<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/hexclave/hexclave/blob/dev/CONTRIBUTING.md

-->

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds a skeleton loading state for the purchase flow and scopes
background styles to stop the first-paint flash across purchase views.
Improves perceived performance and keeps light/dark backgrounds
consistent.

- **New Features**
- Added skeleton `loading.tsx` for `/purchase/[code]` with responsive
placeholders.

- **Bug Fixes**
- Scoped `body` background with `:has([data-hexclave-purchase-page])`
for light/dark, and disabled `body::before` to prevent flash.
- Applied `data-hexclave-purchase-page` to the purchase page (including
invalid-code state) and return page to activate the scoped styles.

<sup>Written for commit 280eab0a5f.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/hexclave/hexclave/pull/1586?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a full-screen loading screen with animated skeleton placeholders
for the purchase flow.

* **Style**
* Applied theme overrides for purchase pages in light and dark modes to
ensure consistent backgrounds.
* Updated purchase page container layout and added a data attribute hook
for targeted styling and layout consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Armaan Jain 2026-06-12 16:37:05 -07:00 committed by GitHub
parent 5eedb484e1
commit 9b767cc35e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 43 additions and 3 deletions

View File

@ -0,0 +1,25 @@
export default function Loading() {
return (
<div data-hexclave-purchase-page className="relative min-h-screen bg-white dark:bg-zinc-950">
<div className="relative flex min-h-screen w-full flex-col lg:flex-row">
<div className="flex flex-1 flex-col border-b border-border/40 bg-white dark:bg-zinc-950 lg:w-1/2 lg:border-b-0 lg:border-r">
<div className="mx-auto w-full max-w-md px-6 pb-12 pt-16 lg:pt-20">
<div className="space-y-5">
<div className="size-12 animate-pulse rounded-full bg-foreground/10" />
<div className="h-10 w-2/3 animate-pulse rounded-lg bg-foreground/10" />
<div className="h-5 w-full animate-pulse rounded-md bg-foreground/10" />
<div className="mt-8 h-20 w-full animate-pulse rounded-xl bg-foreground/10" />
<div className="h-24 w-full animate-pulse rounded-xl bg-foreground/10" />
</div>
</div>
</div>
<div className="flex flex-1 flex-col justify-center bg-zinc-200 dark:bg-black lg:w-1/2">
<div className="mx-auto w-full max-w-md px-6 py-12">
<div className="h-64 w-full animate-pulse rounded-2xl bg-background/70 dark:bg-white/10" />
</div>
</div>
</div>
</div>
);
}

View File

@ -168,7 +168,7 @@ export default function PageClient({ code }: { code: string }) {
if (showInvalidPurchaseCode) {
return (
<div className="relative flex min-h-screen items-center justify-center bg-white px-6 dark:bg-zinc-950">
<div data-hexclave-purchase-page className="relative flex min-h-screen items-center justify-center bg-white px-6 dark:bg-zinc-950">
<div className="w-full max-w-md text-center">
<DesignCard glassmorphic contentClassName="flex flex-col items-center gap-4 p-8">
<div className="flex size-12 items-center justify-center rounded-full bg-destructive/10">
@ -189,7 +189,7 @@ export default function PageClient({ code }: { code: string }) {
}
return (
<div className="relative min-h-screen bg-white dark:bg-zinc-950">
<div data-hexclave-purchase-page className="relative min-h-screen bg-white dark:bg-zinc-950">
<div className="relative flex min-h-screen w-full flex-col lg:flex-row">
{/* Left Panel: Product & Pricing Selection */}
<div className="flex flex-1 flex-col border-b border-border/40 bg-white dark:bg-zinc-950 lg:w-1/2 lg:border-b-0 lg:border-r">

View File

@ -106,7 +106,7 @@ export default function ReturnClient({ clientSecret, stripeAccountId, purchaseFu
}, [updateViewState]);
return (
<div className="relative flex min-h-screen items-center justify-center bg-white px-4 py-12 dark:bg-black">
<div data-hexclave-purchase-page className="relative flex min-h-screen items-center justify-center bg-white px-4 py-12 dark:bg-black">
<DesignCard glassmorphic className="relative w-full max-w-md" contentClassName="flex flex-col items-center gap-5 p-8 text-center">
{state.kind === "loading" && (
<>

View File

@ -285,6 +285,21 @@
opacity: 0;
background-image: none;
}
html:not(.dark) body:has([data-hexclave-purchase-page]) {
background-color: white;
background-image: none;
}
.dark body:has([data-hexclave-purchase-page]) {
background-color: hsl(240 10% 3.9%);
}
html:not(.dark) body:has([data-hexclave-purchase-page])::before,
.dark body:has([data-hexclave-purchase-page])::before {
opacity: 0;
background-image: none;
}
}
::view-transition-old(root),