From 660eb4a944c753bccf9ea604d9de48da5e372780 Mon Sep 17 00:00:00 2001
From: Philipinho <16838612+Philipinho@users.noreply.github.com>
Date: Mon, 4 May 2026 20:35:55 +0100
Subject: [PATCH] fix contrast
---
.../src/components/common/search-input.tsx | 3 ++
.../src/components/ui/custom-avatar.tsx | 34 +++++++++++++++++--
2 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/apps/client/src/components/common/search-input.tsx b/apps/client/src/components/common/search-input.tsx
index 08cbbee0..27e50fd4 100644
--- a/apps/client/src/components/common/search-input.tsx
+++ b/apps/client/src/components/common/search-input.tsx
@@ -6,12 +6,14 @@ import { useTranslation } from "react-i18next";
export interface SearchInputProps {
placeholder?: string;
+ ariaLabel?: string;
debounceDelay?: number;
onSearch: (value: string) => void;
}
export function SearchInput({
placeholder,
+ ariaLabel,
debounceDelay = 500,
onSearch,
}: SearchInputProps) {
@@ -28,6 +30,7 @@ export function SearchInput({
}
value={value}
onChange={(e) => setValue(e.currentTarget.value)}
diff --git a/apps/client/src/components/ui/custom-avatar.tsx b/apps/client/src/components/ui/custom-avatar.tsx
index 1342cdfb..5f38e804 100644
--- a/apps/client/src/components/ui/custom-avatar.tsx
+++ b/apps/client/src/components/ui/custom-avatar.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { Avatar } from "@mantine/core";
+import { Avatar, MantineColor } from "@mantine/core";
import { getAvatarUrl } from "@/lib/config.ts";
import { AvatarIconType } from "@/features/attachments/types/attachment.types.ts";
@@ -16,11 +16,39 @@ interface CustomAvatarProps {
mt?: string | number;
}
+// `color.shade` pairs whose filled background meets WCAG AA (4.5:1) against
+// white text. Avoids lime/yellow/green/orange — even their dark shades have
+// weak white-text contrast.
+const SAFE_INITIALS_COLORS: MantineColor[] = [
+ "blue.8",
+ "cyan.9",
+ "grape.7",
+ "indigo.7",
+ "pink.8",
+ "red.8",
+ "violet.7",
+];
+
+function hashName(input: string) {
+ let hash = 0;
+ for (let i = 0; i < input.length; i += 1) {
+ hash = (hash << 5) - hash + input.charCodeAt(i);
+ hash |= 0;
+ }
+ return Math.abs(hash);
+}
+
+function pickInitialsColor(name: string) {
+ return SAFE_INITIALS_COLORS[hashName(name) % SAFE_INITIALS_COLORS.length];
+}
+
export const CustomAvatar = React.forwardRef<
HTMLInputElement,
CustomAvatarProps
->(({ avatarUrl, name, type, ...props }: CustomAvatarProps, ref) => {
+>(({ avatarUrl, name, type, color, ...props }: CustomAvatarProps, ref) => {
const avatarLink = getAvatarUrl(avatarUrl, type);
+ const resolvedColor =
+ !color || color === "initials" ? pickInitialsColor(name ?? "") : color;
return (
);