From bb74c301d640e8285ad87dfb956565700684f2ab Mon Sep 17 00:00:00 2001 From: ivorycrayon Date: Sun, 24 May 2026 15:21:01 -0700 Subject: [PATCH] fix(a11y): touch targets, dark color-scheme, focus rings --- src/app/globals.css | 8 ++++++++ src/app/layout.tsx | 13 ++++++++++--- src/app/logged-out/page.tsx | 4 ++-- src/app/page.tsx | 2 +- src/components/picker/PlaylistRow.tsx | 2 +- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 9369a3e..bc92033 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -13,6 +13,14 @@ --color-foreground: #e3e3e3; } +html { + /* Opt the page into dark-mode UA styling so native form controls, + scrollbars, autofill highlights, and the iOS Safari status-bar tint + pick up dark theming. bg-zinc-950 on only paints the canvas + — UA chrome reads color-scheme. */ + color-scheme: dark; +} + body { /* No background here — the page canvas colour is bg-zinc-950 on (layout.tsx) and the fixed Background component paints over diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 79d5016..2551f4f 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,4 +1,4 @@ -import type { Metadata } from "next"; +import type { Metadata, Viewport } from "next"; import { Geist } from "next/font/google"; import "./globals.css"; import Background from "@/components/Background"; @@ -10,6 +10,13 @@ const geistSans = Geist({ subsets: ["latin"], }); +// Next 15 moved themeColor out of metadata into a dedicated viewport export. +// Matches bg-zinc-950 (#09090b) so mobile browser chrome (iOS Safari address +// bar, Android Chrome notification bar) blends into the page background. +export const viewport: Viewport = { + themeColor: "#09090b", +}; + // Public URL is hardcoded because the app is reverse-proxied at a fixed // path (swagcounty.com/shuffleify) and basePath alone doesn't give the // OpenGraph crawler an absolute URL. If shuffleify ever moves to its own @@ -67,7 +74,7 @@ export default function RootLayout({ href="https://github.com/LLMATIONS/shuffleify" target="_blank" rel="noreferrer noopener" - className="text-zinc-400 underline transition-colors hover:text-zinc-200" + className="inline-block py-1.5 text-zinc-400 underline transition-colors hover:text-zinc-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand" > GitHub @@ -76,7 +83,7 @@ export default function RootLayout({ Bug reports, kind words, weird ideas →{" "} nerds@swagcounty.com diff --git a/src/app/logged-out/page.tsx b/src/app/logged-out/page.tsx index c6dd72d..74995cf 100644 --- a/src/app/logged-out/page.tsx +++ b/src/app/logged-out/page.tsx @@ -34,7 +34,7 @@ export default function LoggedOut() { href="https://www.spotify.com/account/apps/" target="_blank" rel="noreferrer noopener" - className="underline transition-colors hover:text-brand-hover" + className="inline-block py-0.5 underline decoration-2 underline-offset-2 transition-colors hover:text-brand-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand" > authorized apps list {" "} @@ -46,7 +46,7 @@ export default function LoggedOut() { body={ Log in again diff --git a/src/app/page.tsx b/src/app/page.tsx index 57b8218..77de550 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -70,7 +70,7 @@ export default async function Home({ <> Log in with Spotify diff --git a/src/components/picker/PlaylistRow.tsx b/src/components/picker/PlaylistRow.tsx index 43344c6..8f14e36 100644 --- a/src/components/picker/PlaylistRow.tsx +++ b/src/components/picker/PlaylistRow.tsx @@ -58,7 +58,7 @@ export function PlaylistRow({ type="button" onClick={onShuffle} disabled={locked} - className={`${CTA_CLASS} shrink-0 px-2 py-2 text-xs disabled:cursor-not-allowed disabled:opacity-50 sm:min-w-[9.5rem] sm:px-4 sm:text-sm`} + className={`${CTA_CLASS} shrink-0 min-h-[44px] px-3 py-2 text-xs disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand sm:min-w-[9.5rem] sm:px-4 sm:text-sm`} > {isShuffling ? "Shuffling…" : "Shuffle for real"}