Fixed theme issues

This commit is contained in:
Landon & Emma 2026-04-24 14:42:30 -04:00
parent 3dfba9701d
commit 282a1d3938
7 changed files with 94 additions and 166 deletions

View file

@ -43,14 +43,14 @@ export default function Header() {
<Link
to={`${import.meta.env.VITE_API_URL}/random`}
aria-label="Go to Random Link"
className="pill button p-0! h-full aspect-square"
className="pill button p-0! h-full aspect-square dark:bg-orange-300 dark:border-orange-400"
data-tooltip="Go to a Random Mii"
>
<Icon icon="mdi:dice-3" fontSize={28} />
</Link>
</li>
<li>
<Link to={"/submit"} className="pill button h-full">
<Link to={"/submit"} className="pill button h-full dark:bg-orange-300 dark:border-orange-400">
Submit
</Link>
</li>
@ -60,7 +60,7 @@ export default function Header() {
<ThemeToggle size="md" />
</li>
<li>
<Link to={"/login"} className="pill button h-full">
<Link to={"/login"} className="pill button h-full dark:bg-orange-300 dark:border-orange-400">
Login
</Link>
</li>
@ -71,7 +71,7 @@ export default function Header() {
<Link
to={`/profile/${$session?.user?.id}`}
aria-label="Go to profile"
className="pill button gap-2! p-0! h-full max-w-64"
className="pill button gap-2! p-0! h-full max-w-64 dark:bg-orange-300 dark:border-orange-400"
data-tooltip="Your Profile"
>
<img
@ -95,7 +95,7 @@ export default function Header() {
<Link
to={`${import.meta.env.VITE_API_URL}/api/auth/signout`}
aria-label="Log Out"
className="pill button p-2! aspect-square h-full"
className="pill button p-2! aspect-square h-full dark:bg-orange-300 dark:border-orange-400"
data-tooltip="Log Out"
>
<Icon icon="ic:round-logout" fontSize={24} />

View file

@ -1,5 +1,4 @@
import { useState, useEffect } from "react";
import { useStore } from "@nanostores/react";
import { useState } from "react";
import { userNameSchema } from "@tomodachi-share/shared/schemas";
@ -8,8 +7,6 @@ import SubmitDialogButton from "./submit-dialog-button";
import DeleteAccount from "./delete-account";
import z from "zod";
import { useNavigate } from "react-router";
import { session } from "../../session";
import { type Theme, applyTheme } from "../../lib/theme";
interface Props {
currentDescription: string | null | undefined;
@ -17,22 +14,12 @@ interface Props {
export default function ProfileSettings({ currentDescription }: Props) {
const navigate = useNavigate();
const $session = useStore(session);
const [description, setDescription] = useState(currentDescription);
const [name, setName] = useState("");
const [selectedTheme, setSelectedTheme] = useState<Theme>("SYSTEM");
const [themeSaveError, setThemeSaveError] = useState<string | undefined>(undefined);
const [descriptionChangeError, setDescriptionChangeError] = useState<string | undefined>(undefined);
const [nameChangeError, setNameChangeError] = useState<string | undefined>(undefined);
// Initialize theme from session when it loads
useEffect(() => {
if ($session?.user?.theme) {
setSelectedTheme($session.user.theme);
}
}, [$session?.user?.theme]);
const handleSubmitDescriptionChange = async (close: () => void) => {
const parsed = z.string().trim().max(256).safeParse(description);
if (!parsed.success) {
@ -81,31 +68,11 @@ export default function ProfileSettings({ currentDescription }: Props) {
navigate(0);
};
const handleThemeSave = async (close: () => void) => {
const response = await fetch(`${import.meta.env.VITE_API_URL}/api/auth/theme`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ theme: selectedTheme }),
credentials: "include",
});
if (!response.ok) {
const { error } = await response.json();
setThemeSaveError(error);
return;
}
// Apply the theme immediately
applyTheme(selectedTheme);
close();
navigate(0);
};
return (
<div className="bg-amber-50 border-2 border-amber-500 rounded-2xl shadow-lg p-4 flex flex-col gap-4 dark:bg-slate-900 dark:border-slate-700">
<div>
<h2 className="text-2xl font-bold dark:text-slate-100">Settings</h2>
<p className="text-sm text-zinc-500 dark:text-slate-400">Update your account info, username, and site-wide theme.</p>
<p className="text-sm text-zinc-500 dark:text-slate-400">Update your account info and username.</p>
</div>
{/* Separator */}
@ -172,39 +139,6 @@ export default function ProfileSettings({ currentDescription }: Props) {
</div>
</div>
{/* Separator - Personalization */}
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium my-1 dark:text-slate-400">
<hr className="grow border-zinc-300 dark:border-slate-600" />
<span>Personalization</span>
<hr className="grow border-zinc-300 dark:border-slate-600" />
</div>
{/* Theme Selection */}
<div className="grid grid-cols-5 gap-4 max-lg:grid-cols-1">
<div className="col-span-3">
<label className="font-semibold dark:text-slate-100">Site Theme</label>
<p className="text-sm text-zinc-500 dark:text-slate-400">Choose your preferred color theme for the site</p>
</div>
<div className="flex justify-end gap-1 h-min col-span-2">
<select
className="pill input flex-1 rounded-xl! cursor-pointer"
value={selectedTheme}
onChange={(e) => setSelectedTheme(e.target.value as Theme)}
>
<option value="LIGHT">Light</option>
<option value="DARK">Dark</option>
<option value="SYSTEM">System</option>
</select>
<SubmitDialogButton
title="Confirm Theme Change"
description="Are you sure you want to save this theme preference to your account?"
error={themeSaveError}
onSubmit={handleThemeSave}
/>
</div>
</div>
{/* Separator - Danger Zone */}
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium my-1 dark:text-slate-400">
<hr className="grow border-zinc-300 dark:border-slate-600" />

View file

@ -31,14 +31,8 @@ export default function ThemeToggle({ size = "md", className = "" }: ThemeToggle
const getIcon = () => {
if (theme === "DARK") return <Icon icon="mdi:moon" fontSize={iconSizes[size]} />;
if (theme === "LIGHT") return <Icon icon="mdi:white-balance-sunny" fontSize={iconSizes[size]} />;
// SYSTEM or undefined - show both
return (
<div className="flex items-center">
<Icon icon="mdi:white-balance-sunny" fontSize={iconSizes[size] - 4} />
<span className="mx-0.5 text-xs">/</span>
<Icon icon="mdi:moon" fontSize={iconSizes[size] - 4} />
</div>
);
// SYSTEM or undefined - show computer/monitor icon
return <Icon icon="mdi:monitor" fontSize={iconSizes[size]} />;
};
const getTooltip = () => {

View file

@ -9,7 +9,7 @@ export default function IndexPage() {
<h1 className="sr-only">
{searchParams.get("tags") ? `Miis tagged with '${searchParams.get("tags")}' - TomodachiShare` : "TomodachiShare - index mii list"}
</h1>
<p className="text-center mb-4">We're currently going through some major code changes therefore some features won't work.</p>
<p className="text-center mb-4 dark:text-slate-300">We're currently going through some major code changes therefore some features won't work.</p>
<MiiList />
</>
);

View file

@ -12,13 +12,13 @@ export default function LoginPage() {
return (
<div className="grow flex items-center justify-center">
<div className="bg-amber-50 border-2 border-amber-500 rounded-2xl shadow-lg px-10 py-12 max-w-md text-center">
<h1 className="text-3xl font-bold mb-4">Welcome to TomodachiShare!</h1>
<div className="bg-amber-50 border-2 border-amber-500 rounded-2xl shadow-lg px-10 py-12 max-w-md text-center dark:bg-slate-800 dark:border-slate-600">
<h1 className="text-3xl font-bold mb-4 dark:text-slate-100">Welcome to TomodachiShare!</h1>
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mb-8">
<hr className="grow border-zinc-300" />
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mb-8 dark:text-slate-400">
<hr className="grow border-zinc-300 dark:border-slate-600" />
<span>Choose your login method</span>
<hr className="grow border-zinc-300" />
<hr className="grow border-zinc-300 dark:border-slate-600" />
</div>
<div className="flex flex-col items-center gap-2">
@ -48,13 +48,13 @@ export default function LoginPage() {
</Link>
</div>
<p className="mt-8 text-xs text-zinc-400">
<p className="mt-8 text-xs text-zinc-400 dark:text-slate-500">
By signing up, you agree to the{" "}
<Link to="/terms-of-service" className="underline hover:text-zinc-600">
<Link to="/terms-of-service" className="underline hover:text-zinc-600 dark:hover:text-slate-300">
Terms of Service
</Link>{" "}
and{" "}
<Link to="/privacy" className="underline hover:text-zinc-600">
<Link to="/privacy" className="underline hover:text-zinc-600 dark:hover:text-slate-300">
Privacy Policy
</Link>
.

View file

@ -92,7 +92,7 @@ export default function MiiPage() {
</div>
)}
{mii.in_queue && (
<div className="bg-zinc-50 border-2 border-zinc-400 rounded-2xl shadow-lg p-4 flex items-start gap-3 text-zinc-600">
<div className="bg-zinc-50 border-2 border-zinc-400 rounded-2xl shadow-lg p-4 flex items-start gap-3 text-zinc-600 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-300">
<Icon icon="material-symbols:timer" className="text-2xl shrink-0" />
<p className="font-medium">
This Mii is waiting to be manually reviewed and is hidden from the main page. The review could take between a few hours and a few days.
@ -102,9 +102,9 @@ export default function MiiPage() {
</div>
)}
<div className="relative grid grid-cols-3 gap-4 max-md:grid-cols-1">
<div className="bg-amber-50 rounded-3xl border-2 border-amber-500 shadow-lg p-4 h-min flex flex-col items-center max-w-md w-full max-md:place-self-center max-md:row-start-2">
<div className="bg-amber-50 rounded-3xl border-2 border-amber-500 shadow-lg p-4 h-min flex flex-col items-center max-w-md w-full max-md:place-self-center max-md:row-start-2 dark:bg-slate-800 dark:border-slate-600">
{/* Mii Image */}
<div className="bg-linear-to-b from-amber-100 to-amber-200 overflow-hidden rounded-xl w-full mb-4 flex justify-center">
<div className="bg-linear-to-b from-amber-100 to-amber-200 overflow-hidden rounded-xl w-full mb-4 flex justify-center dark:from-slate-700 dark:to-slate-800">
<ImageViewer
src={`${API_URL}/mii/${mii.id}/image?type=mii`}
alt="mii headshot"
@ -115,13 +115,13 @@ export default function MiiPage() {
</div>
{/* QR Code */}
{mii.platform === "THREE_DS" ? (
<div className="bg-amber-200 overflow-hidden rounded-xl w-full mb-4 flex justify-center p-2">
<div className="bg-amber-200 overflow-hidden rounded-xl w-full mb-4 flex justify-center p-2 dark:bg-slate-700">
<ImageViewer
src={`${API_URL}/mii/${mii.id}/image?type=qr-code`}
alt="mii qr code"
width={128}
height={128}
className="border-2 border-amber-300 rounded-lg hover:brightness-90 transition-all"
className="border-2 border-amber-300 rounded-lg hover:brightness-90 transition-all dark:border-slate-600"
/>
</div>
) : (
@ -133,11 +133,11 @@ export default function MiiPage() {
className="rounded-lg hover:brightness-90 mb-4 transition-all"
/>
)}
<hr className="w-full border-t-2 border-t-amber-400" />
<hr className="w-full border-t-2 border-t-amber-400 dark:border-t-slate-600" />
{/* Mii Info */}
{mii.platform === "THREE_DS" && (
<ul className="text-sm w-full p-2 *:flex *:justify-between *:items-center *:my-1">
<ul className="text-sm w-full p-2 *:flex *:justify-between *:items-center *:my-1 dark:text-slate-300">
<li>
Name:{" "}
<span className="text-right font-medium">
@ -154,10 +154,10 @@ export default function MiiPage() {
)}
{/* Mii Platform */}
<div className={`flex items-center gap-4 text-zinc-500 text-sm font-medium mb-2 w-full ${mii.platform !== "THREE_DS" && "mt-2"}`}>
<hr className="grow border-zinc-300" />
<div className={`flex items-center gap-4 text-zinc-500 text-sm font-medium mb-2 w-full ${mii.platform !== "THREE_DS" && "mt-2"} dark:text-slate-400`}>
<hr className="grow border-zinc-300 dark:border-slate-600" />
<span>Platform</span>
<hr className="grow border-zinc-300" />
<hr className="grow border-zinc-300 dark:border-slate-600" />
</div>
<div data-tooltip-span title={mii.platform} className="grid grid-cols-2 gap-2 mb-2">
@ -171,7 +171,7 @@ export default function MiiPage() {
<div
className={`rounded-xl flex justify-center items-center size-13 text-3xl border-2 shadow-sm ${
mii.platform === "THREE_DS" ? "bg-sky-100 border-sky-400" : "bg-white border-gray-300"
mii.platform === "THREE_DS" ? "bg-sky-100 border-sky-400" : "bg-white border-gray-300 dark:bg-slate-800 dark:border-slate-600"
}`}
>
<Icon icon="cib:nintendo-3ds" className="text-sky-500" />
@ -179,7 +179,7 @@ export default function MiiPage() {
<div
className={`rounded-xl flex justify-center items-center size-13 text-3xl border-2 shadow-sm ${
mii.platform === "SWITCH" ? "bg-red-100 border-red-400" : "bg-white border-gray-300"
mii.platform === "SWITCH" ? "bg-red-100 border-red-400" : "bg-white border-gray-300 dark:bg-slate-800 dark:border-slate-600"
}`}
>
<Icon icon="cib:nintendo-switch" className="text-red-400" />
@ -187,10 +187,10 @@ export default function MiiPage() {
</div>
{/* Mii Gender */}
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mb-2 w-full">
<hr className="grow border-zinc-300" />
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mb-2 w-full dark:text-slate-400">
<hr className="grow border-zinc-300 dark:border-slate-600" />
<span>Gender</span>
<hr className="grow border-zinc-300" />
<hr className="grow border-zinc-300 dark:border-slate-600" />
</div>
<div data-tooltip-span title={mii.gender ?? "NULL"} className="flex gap-1">
@ -208,7 +208,7 @@ export default function MiiPage() {
<div
className={`rounded-xl flex justify-center items-center size-13 text-5xl border-2 shadow-sm ${
mii.gender === "MALE" ? "bg-blue-100 border-blue-400" : "bg-white border-gray-300"
mii.gender === "MALE" ? "bg-blue-100 border-blue-400" : "bg-white border-gray-300 dark:bg-slate-800 dark:border-slate-600"
}`}
>
<Icon icon="foundation:male" className="text-blue-400" />
@ -216,7 +216,7 @@ export default function MiiPage() {
<div
className={`rounded-xl flex justify-center items-center size-13 text-5xl border-2 shadow-sm ${
mii.gender === "FEMALE" ? "bg-pink-100 border-pink-400" : "bg-white border-gray-300"
mii.gender === "FEMALE" ? "bg-pink-100 border-pink-400" : "bg-white border-gray-300 dark:bg-slate-800 dark:border-slate-600"
}`}
>
<Icon icon="foundation:female" className="text-pink-400" />
@ -225,7 +225,7 @@ export default function MiiPage() {
{mii.platform !== "THREE_DS" && (
<div
className={`rounded-xl flex justify-center items-center size-13 text-5xl border-2 shadow-sm ${
mii.gender === "NONBINARY" ? "bg-purple-100 border-purple-400" : "bg-white border-gray-300"
mii.gender === "NONBINARY" ? "bg-purple-100 border-purple-400" : "bg-white border-gray-300 dark:bg-slate-800 dark:border-slate-600"
}`}
>
<Icon icon="mdi:gender-non-binary" className="text-purple-400" />
@ -236,10 +236,10 @@ export default function MiiPage() {
{/* Makeup */}
{mii.platform === "SWITCH" && (
<>
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mb-2 mt-2 w-full">
<hr className="grow border-zinc-300" />
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mb-2 mt-2 w-full dark:text-slate-400">
<hr className="grow border-zinc-300 dark:border-slate-600" />
<span>Makeup</span>
<hr className="grow border-zinc-300" />
<hr className="grow border-zinc-300 dark:border-slate-600" />
</div>
<div data-tooltip-span title={mii.makeup ?? "NULL"} className="flex gap-1">
@ -259,7 +259,7 @@ export default function MiiPage() {
{/* Full Makeup */}
<div
className={`rounded-xl flex justify-center items-center size-13 text-5xl border-2 shadow-sm ${
mii.makeup === "FULL" ? "bg-pink-100 border-pink-400" : "bg-white border-gray-300"
mii.makeup === "FULL" ? "bg-pink-100 border-pink-400" : "bg-white border-gray-300 dark:bg-slate-800 dark:border-slate-600"
}`}
>
<Icon icon="mdi:palette" className="text-pink-400" />
@ -268,7 +268,7 @@ export default function MiiPage() {
{/* Partial Makeup */}
<div
className={`rounded-xl flex justify-center items-center size-13 text-5xl border-2 shadow-sm ${
mii.makeup === "PARTIAL" ? "bg-purple-100 border-purple-400" : "bg-white border-gray-300"
mii.makeup === "PARTIAL" ? "bg-purple-100 border-purple-400" : "bg-white border-gray-300 dark:bg-slate-800 dark:border-slate-600"
}`}
>
<Icon icon="mdi:lipstick" className="text-purple-400" />
@ -277,10 +277,10 @@ export default function MiiPage() {
{/* No Makeup */}
<div
className={`rounded-xl flex justify-center items-center size-13 text-5xl border-2 shadow-sm ${
mii.makeup === "NONE" ? "bg-gray-200 border-gray-400" : "bg-white border-gray-300"
mii.makeup === "NONE" ? "bg-gray-200 border-gray-400 dark:bg-gray-600 dark:border-gray-700" : "bg-white border-gray-300 dark:bg-slate-800 dark:border-slate-600"
}`}
>
<Icon icon="codex:cross" className="text-gray-400" />
<Icon icon="codex:cross" className="text-gray-400 dark:text-gray-200" />
</div>
</div>
</>
@ -289,10 +289,10 @@ export default function MiiPage() {
<div className="col-span-2 flex flex-col gap-4 max-md:col-span-1">
{/* Information */}
<div className="bg-amber-50 border-2 border-amber-500 rounded-2xl shadow-lg p-4 flex flex-col gap-1">
<div className="bg-amber-50 border-2 border-amber-500 rounded-2xl shadow-lg p-4 flex flex-col gap-1 dark:bg-slate-800 dark:border-slate-600">
<div className="flex justify-between items-start">
{/* Submission name */}
<h1 className="text-4xl font-extrabold wrap-break-word whitespace-break-spaces text-amber-700 flex-1 min-w-0">{mii.name}</h1>
<h1 className="text-4xl font-extrabold wrap-break-word whitespace-break-spaces text-amber-700 flex-1 min-w-0 dark:text-amber-500">{mii.name}</h1>
{/* Like button */}
<LikeButton likes={mii.likeCount ?? 0} miiId={mii.id} isLiked={isLiked} big />
</div>
@ -306,11 +306,11 @@ export default function MiiPage() {
</div>
{/* Author and Created date */}
<div className="mt-2">
<Link to={`/profile/${mii.userId}`} className="text-lg wrap-break-word">
<div className="mt-2 dark:text-slate-300">
<Link to={`/profile/${mii.userId}`} className="text-lg wrap-break-word dark:text-slate-200">
By <span className="font-bold">{mii.user.name}</span>
</Link>
<h4 className="text-sm">
<h4 className="text-sm dark:text-slate-400">
Created:{" "}
{new Date(mii.createdAt).toLocaleString("en-GB", {
day: "2-digit",
@ -330,7 +330,7 @@ export default function MiiPage() {
</div>
{/* Buttons */}
<div className="flex gap-3 w-fit bg-amber-50 border-2 border-amber-500 rounded-2xl shadow-lg p-4 text-3xl text-orange-400 max-md:place-self-center *:size-12 *:flex *:flex-col *:items-center *:gap-1 **:transition-discrete **:duration-150 *:hover:brightness-75 *:hover:scale-[1.08] *:[&_span]:text-xs">
<div className="flex gap-3 w-fit bg-amber-50 border-2 border-amber-500 rounded-2xl shadow-lg p-4 text-3xl text-orange-400 max-md:place-self-center dark:bg-slate-800 dark:border-slate-600 *:size-12 *:flex *:flex-col *:items-center *:gap-1 **:transition-discrete **:duration-150 *:hover:brightness-75 *:hover:scale-[1.08] *:[&_span]:text-xs">
<AuthorButtons mii={mii} />
<ShareMiiButton miiId={mii.id} />
@ -343,8 +343,8 @@ export default function MiiPage() {
{/* Instructions */}
{mii.platform === "SWITCH" && (
<div className="bg-amber-50 border-2 border-amber-500 rounded-2xl shadow-lg p-4 flex flex-col gap-3 max-h-96 overflow-y-auto">
<h2 className="text-xl font-semibold text-amber-700 flex items-center gap-2">
<div className="bg-amber-50 border-2 border-amber-500 rounded-2xl shadow-lg p-4 flex flex-col gap-3 max-h-96 overflow-y-auto dark:bg-slate-800 dark:border-slate-600">
<h2 className="text-xl font-semibold text-amber-700 flex items-center gap-2 dark:text-amber-500">
<Icon icon="fa7-solid:list" />
Instructions
</h2>

View file

@ -173,7 +173,7 @@ export default function SubmitPage() {
return (
<div className="flex justify-center gap-4 w-full max-lg:flex-col max-lg:items-center">
<div className="flex justify-center">
<div className="w-75 h-min flex flex-col bg-zinc-50 rounded-3xl border-2 border-zinc-300 shadow-lg p-3">
<div className="w-75 h-min flex flex-col bg-zinc-50 rounded-3xl border-2 border-zinc-300 shadow-lg p-3 dark:bg-slate-800 dark:border-slate-600">
<Carousel
images={[
miiPortraitUri ?? "/loading.svg",
@ -183,7 +183,7 @@ export default function SubmitPage() {
/>
<div className="p-4 flex flex-col gap-1 h-full">
<h1 className="font-bold text-2xl line-clamp-1" title={name}>
<h1 className="font-bold text-2xl line-clamp-1 dark:text-slate-100" title={name}>
{name || "Mii name"}
</h1>
<div id="tags" className="flex flex-wrap gap-1">
@ -206,19 +206,19 @@ export default function SubmitPage() {
<div className="bg-amber-50 border-2 border-amber-500 rounded-2xl shadow-lg p-4 flex flex-col gap-2 w-full">
<div>
<h2 className="text-2xl font-bold">Submit your Mii</h2>
<p className="text-sm text-zinc-500">Share your creation for others to see.</p>
<p className="text-sm text-zinc-500 dark:text-slate-400">Share your creation for others to see.</p>
</div>
{/* Separator */}
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium my-1">
<hr className="grow border-zinc-300" />
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium my-1 dark:text-slate-400">
<hr className="grow border-zinc-300 dark:border-slate-600" />
<span>Info</span>
<hr className="grow border-zinc-300" />
<hr className="grow border-zinc-300 dark:border-slate-600" />
</div>
{/* Platform select */}
<div className="w-full grid grid-cols-3 items-center">
<label htmlFor="name" className="font-semibold">
<label htmlFor="name" className="font-semibold dark:text-slate-100">
Platform
</label>
<div className="relative col-span-2 grid grid-cols-2 bg-orange-300 border-2 border-orange-400 rounded-4xl shadow-md inset-shadow-sm/10">
@ -258,7 +258,7 @@ export default function SubmitPage() {
{/* Name */}
<div className="w-full grid grid-cols-3 items-center">
<label htmlFor="name" className="font-semibold">
<label htmlFor="name" className="font-semibold dark:text-slate-100">
Name
</label>
<input
@ -274,7 +274,7 @@ export default function SubmitPage() {
</div>
<div className="w-full grid grid-cols-3 items-center">
<label htmlFor="tags" className="font-semibold">
<label htmlFor="tags" className="font-semibold dark:text-slate-100">
Tags
</label>
<TagSelector tags={tags} setTags={setTags} showTagLimit />
@ -282,7 +282,7 @@ export default function SubmitPage() {
{/* Description */}
<div className="w-full grid grid-cols-3 items-start">
<label htmlFor="description" className="font-semibold py-2">
<label htmlFor="description" className="font-semibold py-2 dark:text-slate-100">
Description
</label>
<textarea
@ -298,7 +298,7 @@ export default function SubmitPage() {
{/* Gender (switch only) */}
<div className={`w-full grid grid-cols-3 items-start z-20 ${platform === "SWITCH" ? "" : "hidden"}`}>
<label htmlFor="gender" className="font-semibold py-2">
<label htmlFor="gender" className="font-semibold py-2 dark:text-slate-100">
Gender
</label>
<div className="col-span-2 flex gap-1">
@ -308,7 +308,7 @@ export default function SubmitPage() {
aria-label="Filter for Male Miis"
data-tooltip="Male"
className={`cursor-pointer rounded-xl flex justify-center items-center size-11 text-4xl border-2 transition-all after:bg-blue-400! after:border-blue-400! before:border-b-blue-400! ${
gender === "MALE" ? "bg-blue-100 border-blue-400 shadow-md" : "bg-white border-gray-300 hover:border-gray-400"
gender === "MALE" ? "bg-blue-100 border-blue-400 shadow-md" : "bg-white border-gray-300 hover:border-gray-400 dark:bg-slate-800 dark:border-slate-600 dark:hover:border-slate-500"
}`}
>
<Icon icon="foundation:male" className="text-blue-400" />
@ -320,7 +320,7 @@ export default function SubmitPage() {
aria-label="Filter for Female Miis"
data-tooltip="Female"
className={`cursor-pointer rounded-xl flex justify-center items-center size-11 text-4xl border-2 transition-all after:bg-pink-400! after:border-pink-400! before:border-b-pink-400! ${
gender === "FEMALE" ? "bg-pink-100 border-pink-400 shadow-md" : "bg-white border-gray-300 hover:border-gray-400"
gender === "FEMALE" ? "bg-pink-100 border-pink-400 shadow-md" : "bg-white border-gray-300 hover:border-gray-400 dark:bg-slate-800 dark:border-slate-600 dark:hover:border-slate-500"
}`}
>
<Icon icon="foundation:female" className="text-pink-400" />
@ -332,7 +332,7 @@ export default function SubmitPage() {
aria-label="Filter for Nonbinary Miis"
data-tooltip="Nonbinary"
className={`cursor-pointer rounded-xl flex justify-center items-center size-11 text-4xl border-2 transition-all after:bg-purple-400! after:border-purple-400! before:border-b-purple-400! ${
gender === "NONBINARY" ? "bg-purple-100 border-purple-400 shadow-md" : "bg-white border-gray-300 hover:border-gray-400"
gender === "NONBINARY" ? "bg-purple-100 border-purple-400 shadow-md" : "bg-white border-gray-300 hover:border-gray-400 dark:bg-slate-800 dark:border-slate-600 dark:hover:border-slate-500"
}`}
>
<Icon icon="mdi:gender-non-binary" className="text-purple-400" />
@ -342,7 +342,7 @@ export default function SubmitPage() {
{/* Makeup (switch only) */}
<div className={`w-full grid grid-cols-3 items-start ${platform === "SWITCH" ? "" : "hidden"}`}>
<label className="font-semibold py-2">Face Paint</label>
<label className="font-semibold py-2 dark:text-slate-100">Face Paint</label>
<div className="col-span-2 flex flex-col gap-1.5">
{[
@ -355,11 +355,11 @@ export default function SubmitPage() {
type="button"
onClick={() => setMakeup(value as MiiMakeup)}
className={`cursor-pointer rounded-xl text-left px-3 py-2 border-2 transition-all ${
makeup === value ? `bg-${color}-100 border-${color}-400 shadow-md` : "bg-white border-gray-300 hover:border-gray-400"
makeup === value ? `bg-${color}-100 border-${color}-400 shadow-md` : "bg-white border-gray-300 hover:border-gray-400 dark:bg-slate-800 dark:border-slate-600 dark:hover:border-slate-500"
}`}
>
<div className={`font-medium text-sm ${makeup === value ? `text-${color}-500` : "text-gray-500"}`}>{label}</div>
<div className="text-xs text-gray-500 mt-0.5">{desc}</div>
<div className={`font-medium text-sm ${makeup === value ? `text-${color}-500` : "text-gray-500 dark:text-slate-400"}`}>{label}</div>
<div className="text-xs text-gray-500 mt-0.5 dark:text-slate-500">{desc}</div>
</button>
))}
</div>
@ -368,10 +368,10 @@ export default function SubmitPage() {
{/* (Switch Only) Mii Screenshots */}
<div className={`${platform === "SWITCH" ? "" : "hidden"}`}>
{/* Separator */}
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mt-8 mb-2">
<hr className="grow border-zinc-300" />
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mt-8 mb-2 dark:text-slate-400">
<hr className="grow border-zinc-300 dark:border-slate-600" />
<span>Mii Screenshots</span>
<hr className="grow border-zinc-300" />
<hr className="grow border-zinc-300 dark:border-slate-600" />
</div>
<div className="flex flex-col items-center gap-4 w-full">
@ -379,7 +379,7 @@ export default function SubmitPage() {
<div className="flex flex-col items-center gap-2 w-full">
<div className="flex items-center gap-2 self-start">
<span className="bg-orange-400 text-white text-xs font-bold rounded-full size-5 flex items-center justify-center shrink-0">1</span>
<span className="text-sm font-semibold text-zinc-600">Portrait screenshot</span>
<span className="text-sm font-semibold text-zinc-600 dark:text-slate-300">Portrait screenshot</span>
</div>
<div className="flex gap-3 w-full items-start max-sm:flex-col max-sm:items-center">
<div data-tooltip="Your screenshot should look like this">
@ -388,7 +388,7 @@ export default function SubmitPage() {
alt="Example portrait screenshot"
width={80}
height={80}
className="size-20 object-cover rounded-xl border-2 border-orange-300 shrink-0 opacity-70"
className="size-20 object-cover rounded-xl border-2 border-orange-300 shrink-0 opacity-70 dark:border-slate-600"
/>
</div>
<SwitchFileUpload text="a screenshot of your Mii here" image={miiPortraitUri} setImage={setMiiPortraitUri} forceCrop />
@ -399,8 +399,8 @@ export default function SubmitPage() {
<div className="flex flex-col items-center gap-2 w-full">
<div className="flex items-center gap-2 self-start">
<span className="bg-orange-400 text-white text-xs font-bold rounded-full size-5 flex items-center justify-center shrink-0">2</span>
<span className="text-sm font-semibold text-zinc-600">
Features screenshot <span className="text-orange-500">(the features panel - see example)</span>
<span className="text-sm font-semibold text-zinc-600 dark:text-slate-300">
Features screenshot <span className="text-orange-500 dark:text-orange-400">(the features panel - see example)</span>
</span>
</div>
<div className="flex gap-3 w-full items-start max-sm:flex-col max-sm:items-center">
@ -410,7 +410,7 @@ export default function SubmitPage() {
alt="Example features screenshot showing the parts panel"
width={80}
height={80}
className="size-20 object-cover rounded-xl border-2 border-orange-300 shrink-0 opacity-70"
className="size-20 object-cover rounded-xl border-2 border-orange-300 shrink-0 opacity-70 dark:border-slate-600"
/>
</div>
<SwitchFileUpload text="a screenshot of your Mii's features here" image={miiFeaturesUri} setImage={setMiiFeaturesUri} />
@ -420,20 +420,20 @@ export default function SubmitPage() {
<SwitchSubmitTutorialButton />
</div>
<p className="text-xs text-zinc-400 text-center mt-2">A tutorial on how to screenshot the features is above.</p>
<p className="text-xs text-zinc-400 text-center mt-2 dark:text-slate-500">A tutorial on how to screenshot the features is above.</p>
</div>
{/* (3DS only) QR code scanning */}
<div className={`${platform === "THREE_DS" ? "" : "hidden"}`}>
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mt-8 mb-2">
<hr className="grow border-zinc-300" />
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mt-8 mb-2 dark:text-slate-400">
<hr className="grow border-zinc-300 dark:border-slate-600" />
<span>QR Code</span>
<hr className="grow border-zinc-300" />
<hr className="grow border-zinc-300 dark:border-slate-600" />
</div>
<div className="flex flex-col items-center gap-2">
<QrUpload setQrBytesRaw={setQrBytesRaw} />
<span>or</span>
<span className="dark:text-slate-300">or</span>
<button type="button" aria-label="Use your camera" onClick={() => setIsQrScannerOpen(true)} className="pill button gap-2">
<Icon icon="mdi:camera" fontSize={20} />
@ -443,22 +443,22 @@ export default function SubmitPage() {
<Camera isOpen={isQrScannerOpen} setIsOpen={setIsQrScannerOpen} setQrBytesRaw={setQrBytesRaw} />
<ThreeDsScanTutorialButton />
<span className="text-xs text-zinc-400">For emulators, aes_keys.txt is required.</span>
<span className="text-xs text-zinc-400 dark:text-slate-500">For emulators, aes_keys.txt is required.</span>
</div>
</div>
{/* (Switch only) Mii instructions */}
<div className={`${platform === "SWITCH" ? "" : "hidden"}`}>
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mt-8 mb-2">
<hr className="grow border-zinc-300" />
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mt-8 mb-2 dark:text-slate-400">
<hr className="grow border-zinc-300 dark:border-slate-600" />
<span>Mii Instructions</span>
<hr className="grow border-zinc-300" />
<hr className="grow border-zinc-300 dark:border-slate-600" />
</div>
<div className="flex flex-col items-center gap-2">
{/* YouTube */}
<div className="w-full grid grid-cols-3 items-center">
<label htmlFor="youtube" className="font-semibold">
<label htmlFor="youtube" className="font-semibold dark:text-slate-100">
YouTube Video
</label>
<input
@ -479,34 +479,34 @@ export default function SubmitPage() {
<MiiEditor instructions={instructions} />
<SwitchSubmitTutorialButton />
<span className="text-xs text-zinc-400 text-center px-32 max-sm:px-8">
<span className="text-xs text-zinc-400 text-center px-32 max-sm:px-8 dark:text-slate-500">
Mii editor may be inaccurate. Instructions are REALLY recommended, but you do not have to add every instruction.
</span>
</div>
</div>
{/* Custom images selector */}
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mt-6 mb-2">
<hr className="grow border-zinc-300" />
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium mt-6 mb-2 dark:text-slate-400">
<hr className="grow border-zinc-300 dark:border-slate-600" />
<span>Custom images</span>
<hr className="grow border-zinc-300" />
<hr className="grow border-zinc-300 dark:border-slate-600" />
</div>
<div className="max-w-md w-full self-center flex flex-col items-center">
<Dropzone onDrop={handleDrop}>
<p className="text-center text-sm">
<p className="text-center text-sm dark:text-slate-300">
Drag and drop your images here
<br />
or click to open
</p>
</Dropzone>
<span className="text-xs text-zinc-400 mt-2">Animated images currently not supported.</span>
<span className="text-xs text-zinc-400 mt-2 dark:text-slate-500">Animated images currently not supported.</span>
</div>
<ImageList files={files} setFiles={setFiles} />
<hr className="border-zinc-300 my-2" />
<hr className="border-zinc-300 my-2 dark:border-slate-600" />
<div className="flex justify-between items-center">
{error && <span className="text-red-400 font-bold">Error: {error}</span>}