Show tracker type in cookie banner trackers list

The themed banner and headless cookie list exposed only the tracker
name, description, and duration, so trackers that share a name but
differ in technology were indistinguishable to visitors.

Add the tracker type to the headless CookieItem model and render it as a
labeled "Type: <value>" detail under the tracker name, with an explicit
aria-label for assistive technology. Tracker type names are Web platform
API names (Cookie, Local storage, IndexedDB, ...), so they are kept
canonical while only the surrounding label is localized.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-06-02 14:14:02 +02:00
parent f702edabf0
commit 300e1b6688
5 changed files with 41 additions and 5 deletions

View File

@@ -14,7 +14,7 @@
import type { CookieItem } from "../types";
import { humanizeDuration } from "../cookie-utils";
import { getCookieDetailLabels } from "../i18n";
import { getCookieDetailLabels, getTrackerTypeLabel, interpolate } from "../i18n";
import { ProboElement } from "./base";
import type { ProboCategory } from "./category";
import type { ProboCookieBannerRoot } from "./cookie-banner-root";
@@ -55,19 +55,28 @@ export class ProboCookieList extends ProboElement {
? humanizeDuration(cookie.max_age_seconds, lang)
: humanizeDuration(0, lang);
const type = getTrackerTypeLabel(cookie.tracker_type);
const wrapper = document.createElement("probo-cookie");
wrapper.setAttribute("name", cookie.name);
const clone = this.template.content.cloneNode(true) as DocumentFragment;
this.fillSlots(clone, {
name: cookie.name,
type,
duration,
description: cookie.description,
});
this.fillLabels(clone, labels, {
type,
description: cookie.description,
duration,
});
const typeEl = clone.querySelector<HTMLElement>(".cookie-type");
if (typeEl && labels.label_type) {
typeEl.setAttribute("aria-label", interpolate(labels.label_type, { value: type }));
}
wrapper.appendChild(clone);
this.appendChild(wrapper);
}

View File

@@ -43,16 +43,30 @@ export function interpolate(
}
const COOKIE_DETAIL_LABELS: Record<string, Record<string, string>> = {
en: { label_description: "Description: {{value}}", label_duration: "Duration: {{value}}" },
fr: { label_description: "Description : {{value}}", label_duration: "Durée : {{value}}" },
de: { label_description: "Beschreibung: {{value}}", label_duration: "Dauer: {{value}}" },
es: { label_description: "Descripción: {{value}}", label_duration: "Duración: {{value}}" },
en: { label_type: "Type: {{value}}", label_description: "Description: {{value}}", label_duration: "Duration: {{value}}" },
fr: { label_type: "Type : {{value}}", label_description: "Description : {{value}}", label_duration: "Durée : {{value}}" },
de: { label_type: "Typ: {{value}}", label_description: "Beschreibung: {{value}}", label_duration: "Dauer: {{value}}" },
es: { label_type: "Tipo: {{value}}", label_description: "Descripción: {{value}}", label_duration: "Duración: {{value}}" },
};
export function getCookieDetailLabels(lang: string): Record<string, string> {
return COOKIE_DETAIL_LABELS[lang] ?? COOKIE_DETAIL_LABELS.en;
}
// Tracker type names are Web platform API names (proper nouns), so they are
// not translated; only the surrounding "Type:" label is localized.
const TRACKER_TYPE_LABELS: Record<string, string> = {
COOKIE: "Cookie",
LOCAL_STORAGE: "Local storage",
SESSION_STORAGE: "Session storage",
INDEXED_DB: "IndexedDB",
CACHE_STORAGE: "Cache storage",
};
export function getTrackerTypeLabel(type: string): string {
return TRACKER_TYPE_LABELS[type] ?? type;
}
const GPC_LABELS: Record<string, string> = {
en: "Opt-Out Preference Signal Honored",
fr: "Signal de préférence de désinscription respecté",

View File

@@ -353,6 +353,10 @@ export const THEMED_STYLES = `
font-family: monospace;
}
.cookie-type {
font-size: calc(var(--_font-size) - 3px);
}
.cookie-detail {
color: var(--_text);
font-weight: 500;

View File

@@ -99,6 +99,7 @@ export class ProboThemedBanner extends HTMLElement {
<template>
<div class="cookie-item">
<span class="cookie-name" data-slot="name"></span>
<span class="cookie-detail cookie-type" data-label="label_type"><span data-slot="type"></span></span>
<span class="cookie-detail" data-label="label_description"><span data-slot="description"></span></span>
<span class="cookie-detail" data-label="label_duration"><span data-slot="duration"></span></span>
</div>

View File

@@ -14,8 +14,16 @@
import type { BannerTexts } from "./i18n";
export type TrackerType =
| "COOKIE"
| "LOCAL_STORAGE"
| "SESSION_STORAGE"
| "INDEXED_DB"
| "CACHE_STORAGE";
export interface CookieItem {
name: string;
tracker_type: TrackerType;
max_age_seconds: number | null;
description: string;
}