Studio: confirm saved Hugging Face token with a tick (#6630)

* Studio: confirm saved Hugging Face token with a tick

Pasting a token and clicking away saved it silently with no feedback.
Show a green tick in the field once a non-empty token is committed and
the input still matches the stored value, so the save is visible. Adds
the tokenSaved label to the en and zh-CN locales.

* Studio: let clicks pass through the saved-token tick

The decorative tick sat over the input and swallowed clicks, so clicking
it would not focus the field. Add pointer-events-none so clicks reach the
input; drop the now-unreachable title and keep an aria-label via role=img.
This commit is contained in:
Michael Han 2026-06-24 03:47:32 -07:00 committed by GitHub
commit 75166f2043
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 25 additions and 2 deletions

View file

@ -25,8 +25,9 @@ import {
useShowLlamaUpdateBanner,
} from "@/hooks/use-llama-update-pref";
import { LOCALE_STORAGE_KEY, useT } from "@/i18n";
import { cn } from "@/lib/utils";
import { useNavigate, useRouterState } from "@tanstack/react-router";
import { Eye, EyeOff } from "lucide-react";
import { Check, Eye, EyeOff } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import {
type HelperPrecacheSettings,
@ -171,6 +172,12 @@ export function GeneralTab() {
if (trimmed !== hfToken) setHfToken(trimmed);
};
// Show an "accepted" tick once a non-empty token has been committed to the
// store and the field still matches it (i.e. not mid-edit). Gives the user
// feedback that a pasted token was saved.
const tokenSaved =
draftToken.trim().length > 0 && draftToken.trim() === (hfToken ?? "");
useEffect(() => {
let cancelled = false;
void loadUploadLimitSettings()
@ -319,8 +326,22 @@ export function GeneralTab() {
value={draftToken}
onChange={(e) => setDraftToken(e.target.value)}
onBlur={commitToken}
className="h-8 w-full pr-8 font-mono text-xs"
className={cn(
"h-8 w-full font-mono text-xs",
tokenSaved ? "pr-14" : "pr-8",
)}
/>
{tokenSaved ? (
// Decorative: pointer-events-none lets clicks reach the input
// underneath so the field still focuses anywhere.
<span
className="pointer-events-none absolute right-7 top-1/2 flex size-5 -translate-y-1/2 items-center justify-center text-emerald-600 duration-150 animate-in fade-in zoom-in dark:text-emerald-500"
role="img"
aria-label={t("settings.general.tokenSaved")}
>
<Check className="size-4" strokeWidth={2.5} />
</span>
) : null}
<button
type="button"
onClick={() => setShowToken((s) => !s)}

View file

@ -106,6 +106,7 @@ export const en = {
"Used to load gated models and push artifacts.",
hideToken: "Hide token",
showToken: "Show token",
tokenSaved: "Token saved",
password: "Password",
passwordDescription: "Change the password for this Studio account.",
passwordDialog: {

View file

@ -105,6 +105,7 @@ export const zhCN = {
huggingFaceTokenDescription: "用于加载受限模型和推送产物。",
hideToken: "隐藏 token",
showToken: "显示 token",
tokenSaved: "Token 已保存",
password: "密码",
passwordDescription: "更改此 Studio 账号的密码。",
passwordDialog: {