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:
parent
dd69c17c3b
commit
b6b10159ad
5 changed files with 140 additions and 50 deletions
|
|
@ -4,7 +4,7 @@ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|||
import { useState, useRef, useEffect } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { PlayerAvatar } from "@/components/PlayerAvatar";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
|
|
@ -69,12 +69,16 @@ export function ChatBridge() {
|
|||
|
||||
const typeColors: Record<string, string> = {
|
||||
chat: "text-foreground",
|
||||
join: "text-emerald-400",
|
||||
leave: "text-amber-400",
|
||||
death: "text-red-400",
|
||||
server: "text-blue-400",
|
||||
join: "text-emerald-300",
|
||||
leave: "text-amber-300",
|
||||
death: "text-red-300",
|
||||
server: "text-blue-300",
|
||||
};
|
||||
|
||||
const MAX_NAME = 16;
|
||||
const truncateName = (n: string) =>
|
||||
n.length > MAX_NAME ? `${n.slice(0, MAX_NAME - 1)}…` : n;
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
|
|
@ -95,34 +99,43 @@ export function ChatBridge() {
|
|||
No chat messages yet
|
||||
</p>
|
||||
) : (
|
||||
messages.map((msg, i) => (
|
||||
<div key={`${msg.time}-${i}`} className="flex gap-2 text-sm leading-relaxed min-w-0">
|
||||
<span className="text-muted-foreground text-xs shrink-0 mt-0.5 font-mono">
|
||||
{msg.time}
|
||||
</span>
|
||||
{msg.type === "chat" ? (
|
||||
<span className={`${typeColors.chat} break-words min-w-0`}>
|
||||
<strong><{msg.player}></strong> {msg.message}
|
||||
messages.map((msg, i) => {
|
||||
const hasPlayer = msg.type !== "server";
|
||||
const shortName = truncateName(msg.player);
|
||||
return (
|
||||
<div
|
||||
key={`${msg.time}-${i}`}
|
||||
className="flex items-start gap-2 text-sm leading-relaxed min-w-0"
|
||||
>
|
||||
<span className="text-muted-foreground text-xs shrink-0 mt-0.5 font-mono">
|
||||
{msg.time}
|
||||
</span>
|
||||
) : msg.type === "join" ? (
|
||||
<span className={`${typeColors.join} break-words`}>
|
||||
{msg.player} joined the game
|
||||
{hasPlayer ? (
|
||||
<PlayerAvatar name={msg.player} size={20} className="mt-0.5" />
|
||||
) : (
|
||||
<div className="w-5 h-5 rounded bg-blue-500/20 shrink-0 mt-0.5 flex items-center justify-center text-[10px] text-blue-300 font-bold">
|
||||
S
|
||||
</div>
|
||||
)}
|
||||
<span
|
||||
className={`${typeColors[msg.type]} break-words min-w-0 flex-1`}
|
||||
title={hasPlayer ? msg.player : undefined}
|
||||
>
|
||||
{msg.type === "chat" ? (
|
||||
<><strong>{shortName}</strong> {msg.message}</>
|
||||
) : msg.type === "join" ? (
|
||||
<>{shortName} joined the game</>
|
||||
) : msg.type === "leave" ? (
|
||||
<>{shortName} left the game</>
|
||||
) : msg.type === "death" ? (
|
||||
<>{shortName} {msg.message}</>
|
||||
) : (
|
||||
<>[Server] {msg.message}</>
|
||||
)}
|
||||
</span>
|
||||
) : msg.type === "leave" ? (
|
||||
<span className={`${typeColors.leave} break-words`}>
|
||||
{msg.player} left the game
|
||||
</span>
|
||||
) : msg.type === "death" ? (
|
||||
<span className={`${typeColors.death} break-words`}>
|
||||
{msg.player} {msg.message}
|
||||
</span>
|
||||
) : (
|
||||
<span className={`${typeColors.server} break-words`}>
|
||||
[Server] {msg.message}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
</div>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue