colorFromString
They are used wherever we render:
- Chat avatars (chat lists, group lists, chat header).
- Fallback user avatars (e.g. profile cards) when there is no profile image.
Core Utilities
Section titled “Core Utilities”colorFromString (src/utils/colorUtils.ts)
Section titled “colorFromString (src/utils/colorUtils.ts)”Signature:
colorFromString(input: string, opts?: { saturation?: number; lightness?: number; hueOffset?: number; foregroundSaturation?: number; foregroundLightness?: number }): { bg: string; fg: string }
Behaviour:
- Normalises
inputby trimming and lowercasing. - Hashes the string to a deterministic integer.
- Derives a hue from the hash and optional
hueOffset. - Picks saturation and lightness in a friendly range, with small variation per hash.
- Returns:
bg: hex background color.fg: hex foreground color tuned to be readable onbg.
Usage pattern:
- Use
bgas the avatar background. - Use
fgfor the avatar text/initials.
Example:
import { colorFromString } from "@/utils/colorUtils";
const { bg, fg } = colorFromString("Jane Doe");// bg: e.g. "#e1f3ff"// fg: e.g. "#004a80"Advanced usage (tuning):
const colors = colorFromString("Support Bot", { saturation: 0.4, lightness: 0.75, hueOffset: 30, foregroundLightness: 0.2,});Only override these if you have a strong UX/design reason; defaults are good for most use cases.
getInitials & getAvatarColors (src/modules/Chat/utils/avatar.ts)
Section titled “getInitials & getAvatarColors (src/modules/Chat/utils/avatar.ts)”import { colorFromString } from "@/utils/colorUtils";
export function getInitials(label: string, fallback = "U") { ... }
export function getAvatarColors(seed: string) { return colorFromString(seed);}-
getInitials(label, fallback)- Splits
labelon whitespace. - If one part: uses the first two letters.
- If multiple parts: uses the first letter of the first two parts.
- Returns upper‑cased initials (or
fallbackif empty).
- Splits
-
getAvatarColors(seed)- Thin wrapper around
colorFromString(seed). - Preferred for chat‑related avatars where the seed is typically the display name.
- Thin wrapper around
Typical Usage Patterns
Section titled “Typical Usage Patterns”Pattern 1: Chat list avatar with fallback
Section titled “Pattern 1: Chat list avatar with fallback”File: src/modules/Chat/components/chatList/ContactsList.tsx
import { getAvatarColors, getInitials } from "@/modules/Chat/utils/avatar";
const Avatar: React.FC<{ url: string | null; label: string }> = ({ url, label }) => { const [err, setErr] = useState(false); const initials = getInitials(label);
if (!url || err) { const colors = getAvatarColors(label); return ( <div className={styles.avatar} style={{ background: colors.bg, color: colors.fg }} > <span className={styles.avatarInitials}>{initials}</span> </div> ); }
return ( <div className={styles.avatar}> <img src={url} alt={label} onError={() => setErr(true)} /> </div> );};Key points:
- Always compute initials and colors from the same label/seed to keep avatars stable.
- Use the image when present and valid; fall back to initials + colors on error or when missing.
Pattern 2: Profile/User card fallback
Section titled “Pattern 2: Profile/User card fallback”File: src/modules/system/Profile/components/UserCard.tsx
import { colorFromString } from "@/utils/colorUtils";import { toInitials } from "@/utils/string";
const initials = useMemo(() => { const raw = toInitials(username).slice(0, 2); return raw ? raw.toUpperCase() : "U";}, [username]);
const avatarColors = useMemo( () => colorFromString(username || "User"), [username],);
// In JSX, when no image:<ColorBadge bgColor={avatarColors.bg} textColor={avatarColors.fg}> {initials}</ColorBadge>You can use colorFromString directly if you do not want to depend on the chat utils.
Best Practices
Section titled “Best Practices”-
Seed choice
- Prefer stable, human‑readable identifiers:
- Display name:
"Jane Doe","Acme Support". - Email as fallback if name is missing.
- Display name:
- Avoid using transient data (timestamps, random IDs) or numeric IDs alone, as that can cluster colors.
- Prefer stable, human‑readable identifiers:
-
Initials logic
- Use
getInitialsortoInitialsconsistently. - Always upper‑case initials.
- Keep initials length to 2 characters for visual consistency.
- Use
-
Do not hard‑code colors
- Do not manually pick avatar background colors in components.
- Always go through
colorFromStringorgetAvatarColorsso the palette stays cohesive.
-
Accessibility
colorFromStringalready returns a darker foreground for light backgrounds.- If you need additional contrast, you can:
- Increase
foregroundSaturation. - Decrease
foregroundLightness.
- Increase
- For text on arbitrary backgrounds (not avatars), consider
getContrastColor(bgHex)to choose black/white.
When to Use Which Helper
Section titled “When to Use Which Helper”-
Use
getAvatarColors+getInitialswhen:- You are in Chat or another module that already depends on
src/modules/Chat/utils/avatar.ts. - You want the standard chat avatar behaviour (initials + colors).
- You are in Chat or another module that already depends on
-
Use
colorFromStringdirectly when:- You are outside chat and just need “nice deterministic colors” from any string (user name, business name, tag label).
- You need to tune saturation/lightness/hue for a different design context.