fix: show a tag's letter in its dot and its full name with colour names on

This commit is contained in:
Linus Rath
2026-10-29 17:53:37 +01:00
parent f23784a488
commit 3962900035
2 changed files with 34 additions and 4 deletions
+15 -1
View File
@@ -10,7 +10,7 @@ const TAGS: KeywordDefinition[] = [
describe('TagBadge', () => {
beforeEach(() => {
useSettingsStore.setState({ emailKeywords: TAGS, nestedTags: true });
useSettingsStore.setState({ emailKeywords: TAGS, nestedTags: true, showColorNames: false });
});
it('names the tag by its full path', () => {
@@ -38,4 +38,18 @@ describe('TagBadge', () => {
expect(screen.queryByRole('button')).not.toBeInTheDocument();
expect(screen.getByText('Work')).toHaveClass('sr-only');
});
// CV-01: a dot was colour only for sighted users.
it('puts the first letter in the dot', () => {
const { container } = render(<TagBadge tagId="work" variant="dot" />);
const dot = container.querySelector('[data-tag-dot]')!;
expect(dot.querySelector('[aria-hidden="true"]')).toHaveTextContent('W');
});
it('names the tag in full where a dot would go with colour names on', () => {
useSettingsStore.setState({ showColorNames: true });
const { container } = render(<TagBadge tagId="work/clients" variant="dot" />);
expect(container.querySelector('[data-tag-dot]')).toBeNull();
expect(screen.getByText('Work/Clients')).not.toHaveClass('sr-only');
});
});
+19 -3
View File
@@ -6,10 +6,12 @@ import { cn } from "@/lib/utils";
import { useKeywordFormat } from "@/hooks/use-keyword-format";
import type { TagScope } from "@/hooks/use-account-tags";
import { useShortenedText } from "@/hooks/use-shortened-text";
import { useSettingsStore } from "@/stores/settings-store";
/**
* How much room the surface has for a tag.
* - `badge` names the tag; `dot` only identifies it by colour.
* - `badge` names the tag; `dot` shows its colour and first letter (and the
* whole name with "Show colour names" on).
*/
export type TagBadgeVariant = "badge" | "dot";
@@ -61,13 +63,27 @@ export function TagBadge({
const [labelRef, shortenedName] = useShortenedText(tagNameCandidates(tagId));
const color = tagColor(tagId);
const name = tagName(tagId);
const showColorNames = useSettingsStore((st) => st.showColorNames);
if (variant === "dot") {
// "Show colour names" (Settings > Accessibility): the named form even where
// only a dot fits, so no tag is told apart by its colour alone.
if (variant === "dot" && !showColorNames) {
// Not colour alone either way: the dot carries the tag's first letter,
// in the lozenge's own colours (WCAG 1.4.1).
const initial = [...name.trim()][0]?.toLocaleUpperCase() ?? "";
return (
<span
className={cn("h-2.5 w-2.5 shrink-0 rounded-full", color.dot, className)}
className={cn(
"inline-flex h-4 min-w-4 shrink-0 items-center justify-center rounded-full border px-0.5 text-[9px] font-bold leading-none",
color.fill,
color.border,
color.text,
className,
)}
title={name}
data-tag-dot=""
>
<span aria-hidden="true">{initial}</span>
<span className="sr-only">{name}</span>
</span>
);