diff --git a/src/contexts/auth-context.tsx b/src/contexts/auth-context.tsx
index fa8fca7..a7e0e07 100644
--- a/src/contexts/auth-context.tsx
+++ b/src/contexts/auth-context.tsx
@@ -17,6 +17,7 @@ interface AuthData {
colorScheme: MantineColorScheme;
theme?: string;
locale?: string;
+ seenThemesHint?: boolean;
};
roles: string[];
phone: string;
diff --git a/src/features/core/components/settings-button.tsx b/src/features/core/components/settings-button.tsx
index a5f8faa..96162b7 100644
--- a/src/features/core/components/settings-button.tsx
+++ b/src/features/core/components/settings-button.tsx
@@ -1,8 +1,9 @@
-import { UnstyledButton } from "@mantine/core"
+import { Tooltip, UnstyledButton } from "@mantine/core"
import { GearIcon } from "@phosphor-icons/react"
import { useNavigate } from "@tanstack/react-router"
import { useLingui } from "@lingui/react/macro"
-import { memo } from "react";
+import { memo, useEffect, useState } from "react";
+import { useThemeDiscovery } from "@/features/settings/hooks/use-theme-discovery";
interface SettingButtonProps {
to: string;
@@ -10,21 +11,48 @@ interface SettingButtonProps {
right?: number;
}
+const HINT_SHOW_DELAY_MS = 900;
+const HINT_VISIBLE_MS = 4000;
+
const SettingsButton = ({ to }: SettingButtonProps) => {
const navigate = useNavigate();
const { t } = useLingui();
+ const { showHint, markSeen } = useThemeDiscovery();
+ const [hintOpen, setHintOpen] = useState(false);
+
+ useEffect(() => {
+ if (!showHint) return;
+ const show = setTimeout(() => setHintOpen(true), HINT_SHOW_DELAY_MS);
+ const hide = setTimeout(() => {
+ setHintOpen(false);
+ markSeen();
+ }, HINT_SHOW_DELAY_MS + HINT_VISIBLE_MS);
+ return () => {
+ clearTimeout(show);
+ clearTimeout(hide);
+ };
+ }, [showHint, markSeen]);
return (
- navigate({ to })}
- pos='absolute'
- right={20}
- top={6}
+
-
-
+ navigate({ to })}
+ pos='absolute'
+ right={20}
+ top={6}
+ >
+
+
+
);
}
diff --git a/src/features/settings/hooks/use-theme-discovery.ts b/src/features/settings/hooks/use-theme-discovery.ts
new file mode 100644
index 0000000..0ca1408
--- /dev/null
+++ b/src/features/settings/hooks/use-theme-discovery.ts
@@ -0,0 +1,18 @@
+import { useCallback } from "react";
+import { useAuth } from "@/contexts/auth-context";
+import { updateUserSeenThemesHint } from "@/features/settings/server";
+
+/** Drives the one-time "new themes" tooltip on the profile settings gear.
+ * markSeen persists the flag, so each account sees the hint only once. */
+export const useThemeDiscovery = () => {
+ const { metadata, user, set } = useAuth();
+ const showHint = !!user && !metadata.seenThemesHint;
+
+ const markSeen = useCallback(() => {
+ if (!user || metadata.seenThemesHint) return;
+ set({ metadata: { ...metadata, seenThemesHint: true } });
+ void updateUserSeenThemesHint();
+ }, [user, metadata, set]);
+
+ return { showHint, markSeen };
+};
diff --git a/src/features/settings/server.ts b/src/features/settings/server.ts
index d60a582..32df0eb 100644
--- a/src/features/settings/server.ts
+++ b/src/features/settings/server.ts
@@ -95,6 +95,28 @@ export const updateUserTheme = createServerFn({ method: "POST" })
};
});
+export const updateUserSeenThemesHint = createServerFn({ method: "POST" })
+ .middleware([superTokensFunctionMiddleware, serverFnLoggingMiddleware])
+ .handler(async ({ context }) => {
+ const { userAuthId, metadata } = context;
+ if (!userAuthId) return;
+
+ const { updateUserMetadataFields } = await import(
+ "@/utils/supertokens-core.server"
+ );
+
+ await updateUserMetadataFields(userAuthId, {
+ seenThemesHint: true,
+ });
+
+ return {
+ metadata: {
+ ...metadata,
+ seenThemesHint: true,
+ },
+ };
+ });
+
export const updateUserAccentColor = createServerFn({ method: "POST" })
.validator((data: string) => data)
.middleware([superTokensFunctionMiddleware, serverFnLoggingMiddleware])
diff --git a/src/locales/de/messages.po b/src/locales/de/messages.po
index 2c1f76f..76ba343 100644
--- a/src/locales/de/messages.po
+++ b/src/locales/de/messages.po
@@ -2152,7 +2152,7 @@ msgid "serverFn name"
msgstr "serverFn-Name"
#: src/app/routes/_authed/settings.tsx:16
-#: src/features/core/components/settings-button.tsx:19
+#: src/features/core/components/settings-button.tsx:46
msgid "Settings"
msgstr "Einstellungen"
@@ -2515,6 +2515,10 @@ msgstr "Turniere"
msgid "trackId is required for playTrack action"
msgstr "trackId ist für die playTrack-Aktion erforderlich"
+#: src/features/core/components/settings-button.tsx:38
+msgid "Try the new themes"
+msgstr "Probier die neuen Designs aus"
+
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
msgid "Unenroll"
diff --git a/src/locales/en/messages.po b/src/locales/en/messages.po
index 65dbc22..6fa5db5 100644
--- a/src/locales/en/messages.po
+++ b/src/locales/en/messages.po
@@ -2152,7 +2152,7 @@ msgid "serverFn name"
msgstr "serverFn name"
#: src/app/routes/_authed/settings.tsx:16
-#: src/features/core/components/settings-button.tsx:19
+#: src/features/core/components/settings-button.tsx:46
msgid "Settings"
msgstr "Settings"
@@ -2515,6 +2515,10 @@ msgstr "Tournaments"
msgid "trackId is required for playTrack action"
msgstr "trackId is required for playTrack action"
+#: src/features/core/components/settings-button.tsx:38
+msgid "Try the new themes"
+msgstr "Try the new themes"
+
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
msgid "Unenroll"
diff --git a/src/locales/es/messages.po b/src/locales/es/messages.po
index c399db6..92cc0f4 100644
--- a/src/locales/es/messages.po
+++ b/src/locales/es/messages.po
@@ -2152,7 +2152,7 @@ msgid "serverFn name"
msgstr "nombre de serverFn"
#: src/app/routes/_authed/settings.tsx:16
-#: src/features/core/components/settings-button.tsx:19
+#: src/features/core/components/settings-button.tsx:46
msgid "Settings"
msgstr "Configuración"
@@ -2515,6 +2515,10 @@ msgstr "Torneos"
msgid "trackId is required for playTrack action"
msgstr "Se requiere trackId para la acción playTrack"
+#: src/features/core/components/settings-button.tsx:38
+msgid "Try the new themes"
+msgstr "Prueba los nuevos temas"
+
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
msgid "Unenroll"
diff --git a/src/locales/ja/messages.po b/src/locales/ja/messages.po
index 5b6e10a..64466e7 100644
--- a/src/locales/ja/messages.po
+++ b/src/locales/ja/messages.po
@@ -2152,7 +2152,7 @@ msgid "serverFn name"
msgstr "serverFn名"
#: src/app/routes/_authed/settings.tsx:16
-#: src/features/core/components/settings-button.tsx:19
+#: src/features/core/components/settings-button.tsx:46
msgid "Settings"
msgstr "設定"
@@ -2515,6 +2515,10 @@ msgstr "トーナメント"
msgid "trackId is required for playTrack action"
msgstr "playTrackアクションにはtrackIdが必要です"
+#: src/features/core/components/settings-button.tsx:38
+msgid "Try the new themes"
+msgstr "新しいテーマを試してみましょう"
+
#: src/features/tournaments/components/upcoming-tournament/unenroll-free-agent.tsx:26
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
msgid "Unenroll"