theme tooltip

This commit is contained in:
2026-08-23 19:26:21 -07:00
parent d0507481cb
commit 62cbca4a9d
8 changed files with 100 additions and 15 deletions
+1
View File
@@ -17,6 +17,7 @@ interface AuthData {
colorScheme: MantineColorScheme; colorScheme: MantineColorScheme;
theme?: string; theme?: string;
locale?: string; locale?: string;
seenThemesHint?: boolean;
}; };
roles: string[]; roles: string[];
phone: string; phone: string;
@@ -1,8 +1,9 @@
import { UnstyledButton } from "@mantine/core" import { Tooltip, UnstyledButton } from "@mantine/core"
import { GearIcon } from "@phosphor-icons/react" import { GearIcon } from "@phosphor-icons/react"
import { useNavigate } from "@tanstack/react-router" import { useNavigate } from "@tanstack/react-router"
import { useLingui } from "@lingui/react/macro" 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 { interface SettingButtonProps {
to: string; to: string;
@@ -10,21 +11,48 @@ interface SettingButtonProps {
right?: number; right?: number;
} }
const HINT_SHOW_DELAY_MS = 900;
const HINT_VISIBLE_MS = 4000;
const SettingsButton = ({ to }: SettingButtonProps) => { const SettingsButton = ({ to }: SettingButtonProps) => {
const navigate = useNavigate(); const navigate = useNavigate();
const { t } = useLingui(); 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 ( return (
<UnstyledButton <Tooltip
aria-label={t`Settings`} label={t`Try the new themes`}
style={{ cursor: 'pointer', zIndex: 1000, display: 'flex' }} opened={hintOpen}
onClick={() => navigate({ to })} withArrow
pos='absolute' position="bottom-end"
right={20} offset={8}
top={6} transitionProps={{ transition: "fade-down", duration: 250 }}
> >
<GearIcon weight='bold' size={20} /> <UnstyledButton
</UnstyledButton> aria-label={t`Settings`}
style={{ cursor: 'pointer', zIndex: 1000, display: 'flex' }}
onClick={() => navigate({ to })}
pos='absolute'
right={20}
top={6}
>
<GearIcon weight='bold' size={20} />
</UnstyledButton>
</Tooltip>
); );
} }
@@ -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 };
};
+22
View File
@@ -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" }) export const updateUserAccentColor = createServerFn({ method: "POST" })
.validator((data: string) => data) .validator((data: string) => data)
.middleware([superTokensFunctionMiddleware, serverFnLoggingMiddleware]) .middleware([superTokensFunctionMiddleware, serverFnLoggingMiddleware])
+5 -1
View File
@@ -2154,7 +2154,7 @@ msgid "serverFn name"
msgstr "serverFn-Name" msgstr "serverFn-Name"
#: src/app/routes/_authed/settings.tsx:16 #: 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" msgid "Settings"
msgstr "Einstellungen" msgstr "Einstellungen"
@@ -2513,6 +2513,10 @@ msgstr "Turniere"
msgid "trackId is required for playTrack action" msgid "trackId is required for playTrack action"
msgstr "trackId ist für die playTrack-Aktion erforderlich" 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-free-agent.tsx:26
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34 #: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
msgid "Unenroll" msgid "Unenroll"
+5 -1
View File
@@ -2154,7 +2154,7 @@ msgid "serverFn name"
msgstr "serverFn name" msgstr "serverFn name"
#: src/app/routes/_authed/settings.tsx:16 #: 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" msgid "Settings"
msgstr "Settings" msgstr "Settings"
@@ -2513,6 +2513,10 @@ msgstr "Tournaments"
msgid "trackId is required for playTrack action" msgid "trackId is required for playTrack action"
msgstr "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-free-agent.tsx:26
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34 #: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
msgid "Unenroll" msgid "Unenroll"
+5 -1
View File
@@ -2154,7 +2154,7 @@ msgid "serverFn name"
msgstr "nombre de serverFn" msgstr "nombre de serverFn"
#: src/app/routes/_authed/settings.tsx:16 #: 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" msgid "Settings"
msgstr "Configuración" msgstr "Configuración"
@@ -2513,6 +2513,10 @@ msgstr "Torneos"
msgid "trackId is required for playTrack action" msgid "trackId is required for playTrack action"
msgstr "Se requiere trackId para la acción playTrack" 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-free-agent.tsx:26
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34 #: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
msgid "Unenroll" msgid "Unenroll"
+5 -1
View File
@@ -2154,7 +2154,7 @@ msgid "serverFn name"
msgstr "serverFn名" msgstr "serverFn名"
#: src/app/routes/_authed/settings.tsx:16 #: 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" msgid "Settings"
msgstr "設定" msgstr "設定"
@@ -2513,6 +2513,10 @@ msgstr "トーナメント"
msgid "trackId is required for playTrack action" msgid "trackId is required for playTrack action"
msgstr "playTrackアクションにはtrackIdが必要です" 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-free-agent.tsx:26
#: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34 #: src/features/tournaments/components/upcoming-tournament/unenroll-team.tsx:34
msgid "Unenroll" msgid "Unenroll"