Polish remaining UX items: avatar fallback, chat truncation, delete confirmations

- PlayerAvatar component with onError fallback to initial badge; used in
  PlayerManager and ChatBridge.
- ChatBridge: truncate long usernames to 16 chars with tooltip, add avatar
  column, bump tinted text colors to -300 for better dark-mode contrast.
- BackupManager: confirm step for Delete (was one-click).
- ModManager: confirm step for snapshot Delete, clearer "Confirm Restore" /
  "Confirm Delete" labels, unify outer spacing with the rest of admin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hurkicorgi 2026-04-13 00:51:35 -06:00
parent dd69c17c3b
commit b6b10159ad
5 changed files with 140 additions and 50 deletions

View file

@ -121,6 +121,7 @@ export function ModManager() {
} | null>(null);
const [confirmRemove, setConfirmRemove] = useState<string | null>(null);
const [confirmRestore, setConfirmRestore] = useState<string | null>(null);
const [confirmDeleteSnap, setConfirmDeleteSnap] = useState<string | null>(null);
const debounceRef = useRef<ReturnType<typeof setTimeout>>(null);
// Installed mods
@ -340,7 +341,7 @@ export function ModManager() {
};
return (
<div className="space-y-6">
<div className="space-y-4 sm:space-y-6">
{/* ── Mod Manager Card ──────────────────────────────── */}
<Card>
<CardHeader>
@ -799,7 +800,7 @@ export function ModManager() {
disabled={isBusy}
className="text-xs h-9"
>
Confirm
Confirm Restore
</Button>
<Button
size="sm"
@ -810,6 +811,29 @@ export function ModManager() {
Cancel
</Button>
</>
) : confirmDeleteSnap === snap.dirName ? (
<>
<Button
size="sm"
variant="destructive"
onClick={() => {
deleteSnap.mutate(snap.dirName);
setConfirmDeleteSnap(null);
}}
disabled={isBusy}
className="text-xs h-9"
>
Confirm Delete
</Button>
<Button
size="sm"
variant="ghost"
onClick={() => setConfirmDeleteSnap(null)}
className="text-xs h-9"
>
Cancel
</Button>
</>
) : (
<>
<Button
@ -824,7 +848,7 @@ export function ModManager() {
<Button
size="sm"
variant="ghost"
onClick={() => deleteSnap.mutate(snap.dirName)}
onClick={() => setConfirmDeleteSnap(snap.dirName)}
disabled={isBusy}
className="text-xs h-9 text-muted-foreground sm:opacity-0 sm:group-hover:opacity-100 transition"
>