ui(admin): solid env-colored circle in place of name-hash Avatar
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 2m7s
CI / docker (push) Successful in 1m21s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 41s
SonarQube / sonarqube (push) Successful in 6m8s

Previous ring approach was too subtle against most env colors. Replace
the DS Avatar with a purpose-built circle rendered in the environment's
chosen color, showing 1–2 letter initials in white. Fills the full
circle so the color reads at a glance from across the list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-23 01:02:10 +02:00
parent f8dccaae2b
commit 4371372a26

View File

@@ -1,6 +1,5 @@
import { useState, useMemo, useEffect } from 'react';
import {
Avatar,
Badge,
Button,
Input,
@@ -394,24 +393,50 @@ export default function EnvironmentsPage() {
// ── Env-colored Avatar ──────────────────────────────────────────────
// Custom circular initial badge filled with the environment's color. We don't
// wrap the DS `Avatar` because it picks its background from a name hash with
// no color override — we need the env color to be the dominant signal.
const ENV_AVATAR_SIZES = { sm: 24, md: 28, lg: 40 } as const;
const ENV_AVATAR_FONT = { sm: 10, md: 12, lg: 16 } as const;
function envInitials(displayName: string): string {
const words = displayName.trim().split(/\s+/).filter(Boolean);
if (words.length === 0) return '?';
if (words.length === 1) return words[0].slice(0, 2).toUpperCase();
return (words[0][0] + words[1][0]).toUpperCase();
}
function EnvColoredAvatar({ name, color, size }: {
name: string;
color: string | null | undefined;
size: 'sm' | 'md' | 'lg';
}) {
const ringWidth = size === 'lg' ? 3 : 2;
const dimension = ENV_AVATAR_SIZES[size];
const fontSize = ENV_AVATAR_FONT[size];
return (
<span
aria-label={name}
title={name}
style={{
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
width: dimension,
height: dimension,
borderRadius: '50%',
boxShadow: `0 0 0 ${ringWidth}px ${envColorVar(color)}`,
// inner white gap so the ring reads as a distinct band, not a border
outline: '1px solid var(--bg-surface)',
outlineOffset: 0,
background: envColorVar(color),
color: '#fff',
fontSize,
fontWeight: 600,
flexShrink: 0,
// subtle border so the circle still reads on bg-surface when the env
// color itself is very light (amber, green)
border: '1px solid var(--border-subtle)',
userSelect: 'none',
textShadow: '0 1px 1px rgba(0,0,0,0.25)',
}}
>
<Avatar name={name} size={size} />
{envInitials(name)}
</span>
);
}