From a2414515a74f03549cc0bdf63f072c5ec1106792 Mon Sep 17 00:00:00 2001 From: Shane Neubauer Date: Mon, 19 Oct 2026 18:17:30 +1100 Subject: [PATCH] feat(claim-db-worker): apply 2026 Prisma brand Port the prisma.io brand (web/apps/site, /brand-kit) to the create-db web app: ink-and-paper surfaces, Sora + Inter, the prism cyan/yellow/red palette, new logo/favicons, CSS port of the PrismButton, the spectral wash + grain + prism ray, and Prismo on success/error/claim states. Also restyles the Monaco schema editor (light theme), Prisma Studio theme, toasts and modals; replaces the OG image with the site's generated card; removes unused old-brand assets. --- apps/claim-db-worker/__tests__/claim.test.tsx | 6 +- .../__tests__/success.test.tsx | 4 +- apps/claim-db-worker/app/apple-icon.png | Bin 0 -> 1701 bytes apps/claim-db-worker/app/claim/page.tsx | 58 ++- .../app/db-unavailable/page.tsx | 30 +- apps/claim-db-worker/app/error/page.tsx | 67 +-- apps/claim-db-worker/app/favicon.ico | Bin 2340 -> 1568 bytes apps/claim-db-worker/app/globals.css | 350 ++++++++++++---- apps/claim-db-worker/app/icon.svg | 14 + apps/claim-db-worker/app/layout.tsx | 32 +- apps/claim-db-worker/app/page.tsx | 383 ++++++++---------- apps/claim-db-worker/app/success/page.tsx | 75 +--- apps/claim-db-worker/app/web/connect/page.tsx | 46 +-- apps/claim-db-worker/app/web/layout.tsx | 153 +++---- apps/claim-db-worker/app/web/schema/page.tsx | 36 +- .../app/web/studio/StudioClient.tsx | 87 ++-- .../components/CodeSnippet.tsx | 12 +- apps/claim-db-worker/components/Footer.tsx | 96 ++--- .../components/LoadingScreen.tsx | 24 +- apps/claim-db-worker/components/Modal.tsx | 8 +- apps/claim-db-worker/components/Navbar.tsx | 164 ++++---- .../components/PrismaPostgresLogo.tsx | 16 +- .../components/brand/Brand.tsx | 143 +++++++ .../components/brand/PrismButton.tsx | 118 ++++++ .../components/brand/StatePanel.tsx | 26 ++ .../prismaSchemaEditor/BusyPanel.tsx | 6 +- .../prismaSchemaEditor/InfoNote.tsx | 6 +- .../prismaSchemaEditor/InitOverlay.tsx | 24 +- .../prismaSchemaEditor/SidebarActions.tsx | 16 +- apps/claim-db-worker/lib/custom-toast.ts | 43 +- .../lib/prismaSchemaEditor/monacoConfig.ts | 77 ++-- apps/claim-db-worker/public/arrow-right.svg | 3 - apps/claim-db-worker/public/arrow-up.svg | 3 - .../public/brand/logo-mark.svg | 14 + apps/claim-db-worker/public/brand/logo.svg | 20 + .../public/brand/mascot/happy.png | Bin 0 -> 93904 bytes .../public/brand/mascot/sad.png | Bin 0 -> 90098 bytes .../public/brand/mascot/salute.png | Bin 0 -> 106397 bytes .../public/brand/mascot/thinking.png | Bin 0 -> 96483 bytes apps/claim-db-worker/public/brand/texture.jpg | Bin 0 -> 855704 bytes apps/claim-db-worker/public/copy-icon.svg | 3 - apps/claim-db-worker/public/db-icon.svg | 3 - apps/claim-db-worker/public/db-img.svg | 99 ----- apps/claim-db-worker/public/discord.svg | 2 +- apps/claim-db-worker/public/gdpr.svg | 2 +- apps/claim-db-worker/public/github.svg | 2 +- .../public/hero-background.svg | 51 --- apps/claim-db-worker/public/hipaa.svg | 2 +- apps/claim-db-worker/public/iso27.svg | 2 +- apps/claim-db-worker/public/logo-dark.svg | 1 - .../public/magic-wand-icon.svg | 3 - apps/claim-db-worker/public/og-card.png | Bin 0 -> 141907 bytes apps/claim-db-worker/public/og-image.png | Bin 531834 -> 0 bytes .../public/prisma-postgres-logo.svg | 4 - apps/claim-db-worker/public/soc2.svg | 2 +- apps/claim-db-worker/public/whatsapp.svg | 1 - apps/claim-db-worker/public/xtwitter.svg | 2 +- apps/claim-db-worker/public/youtube.svg | 2 +- 58 files changed, 1234 insertions(+), 1107 deletions(-) create mode 100644 apps/claim-db-worker/app/apple-icon.png create mode 100644 apps/claim-db-worker/app/icon.svg create mode 100644 apps/claim-db-worker/components/brand/Brand.tsx create mode 100644 apps/claim-db-worker/components/brand/PrismButton.tsx create mode 100644 apps/claim-db-worker/components/brand/StatePanel.tsx delete mode 100644 apps/claim-db-worker/public/arrow-right.svg delete mode 100644 apps/claim-db-worker/public/arrow-up.svg create mode 100644 apps/claim-db-worker/public/brand/logo-mark.svg create mode 100644 apps/claim-db-worker/public/brand/logo.svg create mode 100644 apps/claim-db-worker/public/brand/mascot/happy.png create mode 100644 apps/claim-db-worker/public/brand/mascot/sad.png create mode 100644 apps/claim-db-worker/public/brand/mascot/salute.png create mode 100644 apps/claim-db-worker/public/brand/mascot/thinking.png create mode 100644 apps/claim-db-worker/public/brand/texture.jpg delete mode 100644 apps/claim-db-worker/public/copy-icon.svg delete mode 100644 apps/claim-db-worker/public/db-icon.svg delete mode 100644 apps/claim-db-worker/public/db-img.svg delete mode 100644 apps/claim-db-worker/public/hero-background.svg delete mode 100644 apps/claim-db-worker/public/logo-dark.svg delete mode 100644 apps/claim-db-worker/public/magic-wand-icon.svg create mode 100644 apps/claim-db-worker/public/og-card.png delete mode 100644 apps/claim-db-worker/public/og-image.png delete mode 100644 apps/claim-db-worker/public/prisma-postgres-logo.svg delete mode 100644 apps/claim-db-worker/public/whatsapp.svg diff --git a/apps/claim-db-worker/__tests__/claim.test.tsx b/apps/claim-db-worker/__tests__/claim.test.tsx index 75ed59b..936c7be 100644 --- a/apps/claim-db-worker/__tests__/claim.test.tsx +++ b/apps/claim-db-worker/__tests__/claim.test.tsx @@ -57,7 +57,7 @@ describe("claim page", () => { mockSearchParams.set("projectID", "test-project-123"); render(); - const claimButton = screen.getByText("Claim database"); + const claimButton = screen.getByRole("button", { name: "Claim database" }); expect(claimButton).not.toBeDisabled(); fireEvent.click(claimButton); @@ -102,7 +102,7 @@ describe("claim page", () => { mockSearchParams.set("projectID", "test-project-123"); render(); - const claimButton = screen.getByText("Claim database"); + const claimButton = screen.getByRole("button", { name: "Claim database" }); fireEvent.click(claimButton); await waitFor(() => { @@ -138,7 +138,7 @@ describe("claim page", () => { render(); - const claimButton = screen.getByText("Claim database"); + const claimButton = screen.getByRole("button", { name: "Claim database" }); fireEvent.click(claimButton); diff --git a/apps/claim-db-worker/__tests__/success.test.tsx b/apps/claim-db-worker/__tests__/success.test.tsx index 597b297..2347d61 100644 --- a/apps/claim-db-worker/__tests__/success.test.tsx +++ b/apps/claim-db-worker/__tests__/success.test.tsx @@ -45,7 +45,9 @@ describe("success page", () => { mockSearchParams.set("projectID", "test-project-123"); render(); - expect(screen.getByAltText("Database Success")).toBeInTheDocument(); + expect( + screen.getByAltText("Prismo, the Prisma mascot, smiling") + ).toBeInTheDocument(); }); }); }); diff --git a/apps/claim-db-worker/app/apple-icon.png b/apps/claim-db-worker/app/apple-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..13b780bd97d9fe134e0e48e38f0db67e708b64fe GIT binary patch literal 1701 zcmWkvYg7|Q6b?iajWL1^>O!g@iW|gY29ULd8XzVliYAelVvCln*h*~zJ^)3LNI+c> z=!yu0rbVi#NaRq3YEMz(5|)?L$ML8X6RcpRT2u;EDxLh;-EZ%mxsUJOxpPFhPBxR{ z&S5YZGv$#IHT*U@o@vhT-B4eQGZ?H*a!FWpdgXAR{Md&v^Qe(Q-ZQS`gH8JIh0myL zCvTp~g-nr5&C6}lCf_O8;mUUn@?Ch;e#4m9VqEIV4h(Y%yWTWyD4g)23PgLB7`vmE z^abzU&?ld@7d!JO_vOCs*NLmNbH`*cDt^pgJFgt`G?u^oeRA-itUK}W(-(b>FJ2o5 zD%@vQkJi?{m{D&VpN?J_dGvloPT((M{_$R8uw{KGfmQqm@RPfc!o* z5!;4F9Q<6%2lL-P=i}RZLgAX@gCB|0NT)#z^{&}$kBp!~J%mZ3WNh2jBi8W}P@1ZT z2DQFmMKBbzF$L1!qn3Vk_hxZ5aXVn8RU9QaMW>I5c|ggQojJA^pE$tJh<25E4O~hh zi_>GYB;Xm1`lo1;<{otM-LO_EjotXzL_BI}2}7FkqXWfBlN+Qv5gV%6ACxw~{AyZ6 z1xWEI@ScezuHP&}E*G>E6T~udYyWZqS)9Stg&e2^sr9Q0!>QzC)O+mhV-q*_vO60$ zFRgPPGTYu}Xz;`<*=cKgGeZS`V*;`N=X zQPL*5iE)sArJ<+Mj^f0XPEF-=r8GC%ZY~{pl|ZVzvaoYj?3G7Z77fF<2HH$SOYQYA z#CH3T9{g~c!Nx6$k9l-{*>(Zx8r%%?%na8l4Tl%moA3*(k=e8Js*7~m5+GSLLncg0 zIR9nikKCT=H^PwLN^3zd2nU! z`Ve>bwl31^*Q|XW^&!W%1)z|F@2As6p9!n)hFfndgag#&Q$+JhI{y|xrWsl{QO{qh zr9-i_c%C3eGx26dy!D<{%z&+6IshJfuyJ&IHaGnywC?W5e6JmbY}-A2nN`|1nzd@f zu(UmUmY|0Ckn~!~M6`u^z}NUNcf!1K2)xA$c2!XUcb9(?_zIdkR#B#~kFF zYfoZXQajvy0#Fn|QDC_s&q(~6LFX3*BlB_~84njgGWOFgo{)_FW6XGKNQXGl;bsz; z=d_J3qg@hRkoa6jsZuL}WUhi$I)LKC^8>CXD-ab2WyZmh zdTsT13v;K!%+iq| z+qgY}p4L~@_X;=VB|Y_vw{nn|*L)LM&iiYR)SV?S>GZwWIj)QBR&+Z zVdNREOWxQW2*kO{vE#nKf|cJI=cd{9{*XDpH9~G>=$ic9pt5c8BBsUG z(5T7ADo<3x%@u0W$*xuY0K|gbYvNe>)v@vphA!HFH{w}%6!&CWR5c-R@r4d4w0N-+ zLO*&fgpCsr5)Xn-8HulFebKhTB03jN?PI5Y+uJmn6}ZVFYE)A{RTNP2_Mz*Zh1dUB z#Tq!)*XH~ypX!YmM?B)`kt{mJeMR_}r9yRqqZBd0$o%Kp18;Nvji+U(* zjrr0s$o}@hn|!_C;TfruCeh1LHvvN5PdyojL{5=aft{20&vQ>_L(g?le^;goNLxS` q^qh7Q-Z7Jt8wJh}Az(Rf875 literal 0 HcmV?d00001 diff --git a/apps/claim-db-worker/app/claim/page.tsx b/apps/claim-db-worker/app/claim/page.tsx index 4b28299..fea7e3a 100644 --- a/apps/claim-db-worker/app/claim/page.tsx +++ b/apps/claim-db-worker/app/claim/page.tsx @@ -1,8 +1,11 @@ "use client"; import { PrismaPostgresLogo } from "@/components/PrismaPostgresLogo"; +import { PrismButton } from "@/components/brand/PrismButton"; +import { Mascot } from "@/components/brand/Brand"; +import { StatePanel } from "@/components/brand/StatePanel"; +import { ArrowRight } from "lucide-react"; import { useSearchParams, useRouter, usePathname } from "next/navigation"; -import Image from "next/image"; import { useEffect, useState, Suspense } from "react"; function ClaimContent() { @@ -56,43 +59,30 @@ function ClaimContent() { }; return ( -
-
- + + + -

- Claim your database - * -

+

+ Claim your database + * +

- - -

- *your database will be deleted 24 hours after creation unless - you claim it -

+ +
-
+ +

+ *Your database will be{" "} + + deleted 24 hours after creation + {" "} + unless you claim it. +

+ ); } diff --git a/apps/claim-db-worker/app/db-unavailable/page.tsx b/apps/claim-db-worker/app/db-unavailable/page.tsx index a86b1d5..a22c346 100644 --- a/apps/claim-db-worker/app/db-unavailable/page.tsx +++ b/apps/claim-db-worker/app/db-unavailable/page.tsx @@ -1,7 +1,9 @@ "use client"; import { cookieUtils } from "@/lib/utils"; -import { Info } from "lucide-react"; +import { Mascot } from "@/components/brand/Brand"; +import { PrismButton } from "@/components/brand/PrismButton"; +import { StatePanel } from "@/components/brand/StatePanel"; const DB_KEY = "temp_db_info"; @@ -11,21 +13,17 @@ export default function DBUnavailablePage() { }; return ( -
-
-

- Database - already claimed or deleted -

-

Please create a new one

- - Create New Database - + + +

+ Database already claimed or deleted +

+

Please create a new one

+
+ + Create new database +
-
+ ); } diff --git a/apps/claim-db-worker/app/error/page.tsx b/apps/claim-db-worker/app/error/page.tsx index 3668306..15dd3b5 100644 --- a/apps/claim-db-worker/app/error/page.tsx +++ b/apps/claim-db-worker/app/error/page.tsx @@ -2,6 +2,8 @@ import { useSearchParams } from "next/navigation"; import { Suspense } from "react"; +import { Mascot } from "@/components/brand/Brand"; +import { StatePanel } from "@/components/brand/StatePanel"; function ErrorContent() { const searchParams = useSearchParams(); @@ -11,57 +13,24 @@ function ErrorContent() { const details = searchParams.get("details"); return ( -
-
-
-
-
- -
-

- {title} -

-
+ + +

+ + Something went wrong +

+

{title}

-

- {message} -

+

+ {message} +

- {details && ( -
-              {details}
-            
- )} -
-
-
+ {details && ( +
+          {details}
+        
+ )} + ); } diff --git a/apps/claim-db-worker/app/favicon.ico b/apps/claim-db-worker/app/favicon.ico index a4cea674aad41ef8b4e50f3c1b5b1f3bff8b291b..812fb4c05fd1a5b0243ffd69db52f4c8d3669b12 100644 GIT binary patch literal 1568 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 KMNUMnLSTYU3q~&h diff --git a/apps/claim-db-worker/app/globals.css b/apps/claim-db-worker/app/globals.css index dc33b9f..2e4e303 100644 --- a/apps/claim-db-worker/app/globals.css +++ b/apps/claim-db-worker/app/globals.css @@ -1,115 +1,317 @@ @import "tailwindcss"; +/* Brand tokens, ported from the prisma.io site (web/apps/site globals.css and + the /brand-kit page): ink and paper carry the surface, the three prism + colours (cyan / yellow / red) are the only accents. Keep these values in + step with the site rather than tuning them locally. */ :root { - --background: #0a0a0a; - --foreground: #ededed; - --background-dark: #0f1217; - --background-card: #161a20; - --background-code: #13161b; - --background-step: #181b21; - --background-table-header: #1c1f26; - --background-button: #2d3138; - --background-button-hover: #2d3748; - - --brand-surface-main: #161d2b; - --brand-surface-accent: #0d3a38; - --brand-surface-highlight: #71e8df; - - --text-muted: #a0aec0; - --text-dim: #3f4b5b; - --text-accent: #71e8df; - --text-error: #fc8181; - - --border-subtle: #202734; - --border-accent: #71e8df; - - --gradient-start: #71e8df; - --gradient-end: #3f827d; - - --button: #2d3138; - --button-hover: #2d3748; - - --button-blue: #16a394; - --button-blue-hover: #16a395ba; + --background: #ffffff; + --foreground: #3a3b3c; /* brand text primary */ + --ink: #151515; + --paper: #f9faf5; + --muted-foreground: #646567; /* brand text secondary */ + --border: #e5e5e5; + --code: #f6f7f2; } @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); - --font-barlow: var(--font-barlow); - --color-dark: var(--background-dark); - --color-card: var(--background-card); - --color-code: var(--background-code); - --color-step: var(--background-step); - --color-table-header: var(--background-table-header); - --color-button: var(--background-button); + --color-ink: var(--ink); + --color-paper: var(--paper); + --color-muted-foreground: var(--muted-foreground); + --color-border: var(--border); + --color-code: var(--code); - --color-white: var(--text-white); - --color-muted: var(--text-muted); - --color-dim: var(--text-dim); - --color-accent: var(--text-accent); - --color-error: var(--text-error); + --font-sans: var(--font-inter); + --font-heading: var(--font-sora); + /* The site maps mono to Inter; connection strings and commands need real + fixed-width glyphs, so code stays on the system mono stack. */ + --font-mono: + ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; - --color-brand-surface-main: var(--brand-surface-main); - --color-brand-surface-accent: var(--brand-surface-accent); - --color-brand-surface-highlight: var(--brand-surface-highlight); + --color-prism-cyan-50: #eeffff; + --color-prism-cyan-100: #dcfdff; + --color-prism-cyan-200: #b3f4f9; + --color-prism-cyan-300: #7be7f0; + --color-prism-cyan-400: #01d7e4; + --color-prism-cyan-500: #00bbcb; + --color-prism-cyan-600: #009aaa; + --color-prism-cyan-700: #007f8d; + --color-prism-cyan-800: #006772; + --color-prism-cyan-900: #00545d; + --color-prism-cyan-950: #00353c; - --color-subtle: var(--border-subtle); - --color-accent: var(--border-accent); + --color-prism-red-50: #ffeeee; + --color-prism-red-100: #ffdfdf; + --color-prism-red-200: #ffc2c4; + --color-prism-red-300: #ff9fa4; + --color-prism-red-400: #ff7682; + --color-prism-red-500: #f34a60; + --color-prism-red-600: #d02344; + --color-prism-red-700: #af0a33; + --color-prism-red-800: #8e0b29; + --color-prism-red-900: #740f22; + --color-prism-red-950: #4b0211; - --color-button: var(--button); - --color-button-hover: var(--button-hover); + --color-prism-yellow-50: #fff7e0; + --color-prism-yellow-100: #fcedc2; + --color-prism-yellow-200: #f8da85; + --color-prism-yellow-300: #f3c306; + --color-prism-yellow-400: #eaa700; + --color-prism-yellow-500: #d48700; + --color-prism-yellow-600: #b46700; + --color-prism-yellow-700: #965100; + --color-prism-yellow-800: #7a4200; + --color-prism-yellow-900: #633700; + --color-prism-yellow-950: #402000; - --color-button-blue: var(--button-blue); - --color-button-blue-hover: var(--button-blue-hover); + --animate-hero-rise: hero-rise 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.15s both; + @keyframes hero-rise { + from { + opacity: 0; + transform: translateY(16px); + } + to { + opacity: 1; + transform: translateY(0); + } + } +} - --color-gradient-start: var(--gradient-start); - --color-gradient-end: var(--gradient-end); +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground font-sans antialiased; + /* Inter renders optically darker than SF Pro at 400; the site pulls + regular text back to 380 to match. */ + font-weight: 380; + } + button:not(:disabled), + [role="button"]:not([aria-disabled="true"]) { + cursor: pointer; + } } -body { - background: var(--background); - color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; +/* Brand rule (from the site): headings are always Sora at Medium with natural + tracking, in ink. Unlayered so it beats leftover weight/tracking utilities. */ +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: var(--font-heading); + font-weight: 500; + letter-spacing: normal; +} +@layer base { + h1, + h2, + h3, + h4, + h5, + h6 { + color: var(--ink); + } } -.bg-custom-gradient { - background: - radial-gradient(circle at 30% 30%, rgba(0, 128, 128, 0.2), transparent 50%), - radial-gradient(circle at 70% 70%, rgba(0, 128, 128, 0.2), transparent 50%), - var(--color-dark); +/* The brand spectrum: cyan → yellow → orange → red → magenta. */ +.prism-spectrum { + background-image: linear-gradient( + 85deg, + #01d7e4 0%, + #f3c306 25%, + #f37a03 50%, + #f43531 74%, + #f00e5c 100% + ); +} + +/* Primary CTA — CSS port of the site's PrismButton (components/PrismButton + renders the markup): a black pill with a spectrum glow drifting behind it, + which blooms and fills prismatic on hover. The site version runs on + framer-motion and a WebGL burst; this keeps the look without shipping + either to the worker. The glow and bloom sit in the wrapper, behind the + pill, so only their blurred spill shows around its edge. */ +@keyframes prism-drift { + 0%, + 100% { + transform: translateX(0); + } + 50% { + transform: translateX(-58%); + } +} +.prism-cta { + position: relative; + display: inline-flex; + align-items: center; +} +.prism-cta-glow { + position: absolute; + inset: 0; + overflow: hidden; + border-radius: 9999px; + filter: blur(3.2px); + pointer-events: none; +} +.prism-cta-glow > span { + position: absolute; + inset-block: 0; + left: 0; + width: 240%; + animation: prism-drift 7s ease-in-out infinite; +} +.prism-cta-bloom { + position: absolute; + inset: 0; + border-radius: 9999px; + filter: blur(10px); + opacity: 0; + transition: opacity 0.35s ease; + pointer-events: none; +} +.prism-cta-button { + position: relative; + display: flex; + align-self: stretch; + width: 100%; + align-items: center; + justify-content: center; + overflow: hidden; + border-radius: 9999px; + background: #000; + color: #fff; + font-weight: 600; + line-height: 1.5; + white-space: nowrap; + transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); } -button { - cursor: pointer; +/* The prismatic fill erupting from the centre — a radial reveal standing in + for the site's WebGL burst. */ +.prism-cta-fill { + position: absolute; + inset: 0; + background: radial-gradient( + circle at 50% 50%, + #f00e5c 0%, + #f43531 18%, + #f37a03 34%, + #f3c306 52%, + #01d7e4 78%, + #01d7e4 100% + ); + clip-path: circle(0% at 50% 50%); + transition: clip-path 0.5s cubic-bezier(0.22, 1, 0.36, 1); + pointer-events: none; +} +.prism-cta-label { + position: relative; + z-index: 1; + display: inline-flex; + align-items: center; + gap: 0.5rem; +} +.prism-cta:hover:not(:has(:disabled)) .prism-cta-bloom { + opacity: 0.7; +} +.prism-cta:hover:not(:has(:disabled)) .prism-cta-button { + transform: scale(1.04); +} +.prism-cta:hover:not(:has(:disabled)) .prism-cta-fill { + clip-path: circle(75% at 50% 50%); +} +.prism-cta-button:focus-visible { + outline: 2px solid var(--ink); + outline-offset: 3px; +} +.prism-cta:has(:disabled) { + opacity: 0.5; +} +.prism-cta-button:disabled { + cursor: not-allowed; +} + +/* Secondary pill — thin neutral border that reveals the moving spectrum on + hover (the site's .spectrum-border). */ +@keyframes spectrum-slide { + from { + background-position: 0% 50%; + } + to { + background-position: 200% 50%; + } +} +.spectrum-border { + position: relative; +} +.spectrum-border::before { + content: ""; + position: absolute; + inset: 0; + border-radius: inherit; + padding: 1px; + background-image: linear-gradient(85deg, #01d7e4, #f3c306, #f37a03, #f43531, #f00e5c, #01d7e4); + background-size: 200% 100%; + -webkit-mask: + linear-gradient(#fff 0 0) content-box, + linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + mask: + linear-gradient(#fff 0 0) content-box, + linear-gradient(#fff 0 0); + mask-composite: exclude; + opacity: 0; + transition: opacity 0.5s ease; + pointer-events: none; +} +.spectrum-border:hover::before, +.spectrum-border:focus-visible::before { + opacity: 1; + animation: spectrum-slide 2.5s linear infinite; +} + +@media (prefers-reduced-motion: reduce) { + .prism-cta-button, + .prism-cta-fill, + .prism-cta-bloom { + transition: none; + } + .prism-cta-glow > span, + .spectrum-border:hover::before, + .spectrum-border:focus-visible::before { + animation: none; + } + .prism-cta:hover .prism-cta-button { + transform: none; + } } html { - /* Firefox - Hides track and changes thumb color */ - scrollbar-color: hsla(0, 0%, 46%, 0.5) transparent; + scrollbar-color: rgb(0 0 0 / 0.2) transparent; } -/* Chrome - Hides track and width/height set for vertical/horizontal scrollbars */ ::-webkit-scrollbar { background-color: transparent; width: 7px; height: 7px; } -/* Chrome - Changes thumb color and rounds scrollbar edges, in Chrome any -scrollbar changes disables default styling and rounding so corners appear squared */ ::-webkit-scrollbar-thumb { - background-color: hsla(0, 0%, 46%, 0.5); + background-color: rgb(0 0 0 / 0.2); border-radius: 8px; } -/* Utility class to hide scrollbars */ .scrollbar-hide { - -ms-overflow-style: none; /* Internet Explorer 10+ */ - scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; + scrollbar-width: none; } .scrollbar-hide::-webkit-scrollbar { - display: none; /* Safari and Chrome */ + display: none; } .monaco-editor { diff --git a/apps/claim-db-worker/app/icon.svg b/apps/claim-db-worker/app/icon.svg new file mode 100644 index 0000000..c9d58ef --- /dev/null +++ b/apps/claim-db-worker/app/icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/apps/claim-db-worker/app/layout.tsx b/apps/claim-db-worker/app/layout.tsx index baffa8b..3567564 100644 --- a/apps/claim-db-worker/app/layout.tsx +++ b/apps/claim-db-worker/app/layout.tsx @@ -1,5 +1,5 @@ import type { Metadata } from "next"; -import { Barlow } from "next/font/google"; +import { Inter, Sora } from "next/font/google"; import Script from "next/script"; import "./globals.css"; import { Navbar } from "../components/Navbar"; @@ -8,10 +8,15 @@ import { DropProvider } from "./contexts/DropContext"; import { Toaster } from "react-hot-toast"; import { PostHogProvider } from "@/components/PostHogProvider"; -const barlow = Barlow({ - weight: ["400", "500", "700", "800", "900"], +// Brand type: Sora for headings, Inter for everything else. +const sora = Sora({ subsets: ["latin"], - variable: "--font-barlow", + variable: "--font-sora", +}); + +const inter = Inter({ + subsets: ["latin"], + variable: "--font-inter", }); export const metadata: Metadata = { @@ -23,7 +28,7 @@ export const metadata: Metadata = { title: "Want a free, instant Prisma Postgres database?", description: "Get a temporary Prisma Postgres database instantly. No account or config needed. Just run npx create-db.", - images: ["/og-image.png"], + images: ["/og-card.png"], type: "website", url: "https://create-db.prisma.io/", }, @@ -32,10 +37,7 @@ export const metadata: Metadata = { title: "Want a free, instant Prisma Postgres database?", description: "Get a temporary Prisma Postgres database instantly. No account or config needed. Just run npx create-db.", - images: ["/og-image.png"], - }, - icons: { - shortcut: "/favicon.png", + images: ["/og-card.png"], }, }; @@ -45,10 +47,12 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - + +