Skip to content

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.

Signature:

  • colorFromString(input: string, opts?: { saturation?: number; lightness?: number; hueOffset?: number; foregroundSaturation?: number; foregroundLightness?: number }): { bg: string; fg: string }

Behaviour:

  • Normalises input by 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 on bg.

Usage pattern:

  • Use bg as the avatar background.
  • Use fg for 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 label on 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 fallback if empty).
  • getAvatarColors(seed)

    • Thin wrapper around colorFromString(seed).
    • Preferred for chat‑related avatars where the seed is typically the display name.

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.

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.


  • Seed choice

    • Prefer stable, human‑readable identifiers:
      • Display name: "Jane Doe", "Acme Support".
      • Email as fallback if name is missing.
    • Avoid using transient data (timestamps, random IDs) or numeric IDs alone, as that can cluster colors.
  • Initials logic

    • Use getInitials or toInitials consistently.
    • Always upper‑case initials.
    • Keep initials length to 2 characters for visual consistency.
  • Do not hard‑code colors

    • Do not manually pick avatar background colors in components.
    • Always go through colorFromString or getAvatarColors so the palette stays cohesive.
  • Accessibility

    • colorFromString already returns a darker foreground for light backgrounds.
    • If you need additional contrast, you can:
      • Increase foregroundSaturation.
      • Decrease foregroundLightness.
    • For text on arbitrary backgrounds (not avatars), consider getContrastColor(bgHex) to choose black/white.

  • Use getAvatarColors + getInitials when:

    • 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).
  • Use colorFromString directly 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.