feat(ui): add rcred badge + orange 'r' prefix in all badge pills

Add r badge for rcred in favicon, app-switcher, and tab-bar badge
maps. Render 'r' with #dc8300 orange in badge pills across all three
components (favicon SVG tspan, app-switcher HTML spans, tab-bar HTML
spans). App names (e.g. "rDocs") intentionally left uncolored.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-04-15 16:41:31 -04:00
parent f2b125a72f
commit a92b5fc100
3 changed files with 13 additions and 10 deletions

View File

@ -55,6 +55,7 @@ const FAVICON_BADGE_MAP: Record<string, { badge: string; color: string }> = {
rdata: { badge: "r📊", color: "#d8b4fe" }, rdata: { badge: "r📊", color: "#d8b4fe" },
ragents: { badge: "r🤖", color: "#6ee7b7" }, ragents: { badge: "r🤖", color: "#6ee7b7" },
rids: { badge: "r🪪", color: "#6ee7b7" }, rids: { badge: "r🪪", color: "#6ee7b7" },
rcred: { badge: "r⭐", color: "#fbbf24" },
rstack: { badge: "r✨", color: "#c4b5fd" }, rstack: { badge: "r✨", color: "#c4b5fd" },
}; };
@ -63,7 +64,7 @@ function faviconScript(moduleId: string): string {
const b = FAVICON_BADGE_MAP[moduleId]; const b = FAVICON_BADGE_MAP[moduleId];
if (!b) return ''; if (!b) return '';
const json = JSON.stringify(b); const json = JSON.stringify(b);
return `<script>(function(){var b=${json};var s='<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64"><rect width="64" height="64" rx="14" fill="'+b.color+'"/><text x="32" y="44" text-anchor="middle" font-size="26" font-family="sans-serif">'+b.badge+'</text></svg>';var l=document.querySelector('link[rel="icon"]');if(l)l.href="data:image/svg+xml,"+encodeURIComponent(s)})()</script>`; return `<script>(function(){var b=${json};var e=b.badge.slice(1);var s='<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64"><rect width="64" height="64" rx="14" fill="'+b.color+'"/><text x="32" y="44" text-anchor="middle" font-size="26" font-family="sans-serif"><tspan fill="#dc8300">r</tspan><tspan>'+e+'</tspan></text></svg>';var l=document.querySelector('link[rel="icon"]');if(l)l.href="data:image/svg+xml,"+encodeURIComponent(s)})()</script>`;
} }
// ── Content-hash cache busting ── // ── Content-hash cache busting ──

View File

@ -54,6 +54,7 @@ const MODULE_BADGES: Record<string, { badge: string; color: string }> = {
rauctions: { badge: "r🎭", color: "#fca5a5" }, // red-300 rauctions: { badge: "r🎭", color: "#fca5a5" }, // red-300
// Govern // Govern
rgov: { badge: "r⚖", color: "#94a3b8" }, // slate-400 rgov: { badge: "r⚖", color: "#94a3b8" }, // slate-400
rcred: { badge: "r⭐", color: "#fbbf24" }, // amber-400
// Media // Media
rphotos: { badge: "r📸", color: "#f9a8d4" }, // pink-200 rphotos: { badge: "r📸", color: "#f9a8d4" }, // pink-200
rfiles: { badge: "r📁", color: "#67e8f9" }, // cyan-300 rfiles: { badge: "r📁", color: "#67e8f9" }, // cyan-300
@ -351,7 +352,7 @@ export class RStackAppSwitcher extends HTMLElement {
#renderCatalogItem(m: AppSwitcherModule, enabled: boolean): string { #renderCatalogItem(m: AppSwitcherModule, enabled: boolean): string {
const badgeInfo = MODULE_BADGES[m.id]; const badgeInfo = MODULE_BADGES[m.id];
const badgeHtml = badgeInfo const badgeHtml = badgeInfo
? `<span class="item-badge" style="background:${badgeInfo.color}${enabled ? '' : ';opacity:0.5'}">${badgeInfo.badge}</span>` ? `<span class="item-badge" style="background:${badgeInfo.color}${enabled ? '' : ';opacity:0.5'}"><span style="color:#dc8300">r</span>${badgeInfo.badge.slice(1)}</span>`
: `<span class="item-icon" style="${enabled ? '' : 'opacity:0.5'}">${m.icon}</span>`; : `<span class="item-icon" style="${enabled ? '' : 'opacity:0.5'}">${m.icon}</span>`;
const cat = MODULE_CATEGORIES[m.id] || ''; const cat = MODULE_CATEGORIES[m.id] || '';
@ -375,7 +376,7 @@ export class RStackAppSwitcher extends HTMLElement {
#renderItem(m: AppSwitcherModule, current: string): string { #renderItem(m: AppSwitcherModule, current: string): string {
const badgeInfo = MODULE_BADGES[m.id]; const badgeInfo = MODULE_BADGES[m.id];
const badgeHtml = badgeInfo const badgeHtml = badgeInfo
? `<span class="item-badge" style="background:${badgeInfo.color}">${badgeInfo.badge}</span>` ? `<span class="item-badge" style="background:${badgeInfo.color}"><span style="color:#dc8300">r</span>${badgeInfo.badge.slice(1)}</span>`
: `<span class="item-icon">${m.icon}</span>`; : `<span class="item-icon">${m.icon}</span>`;
const space = this.#getSpaceSlug(); const space = this.#getSpaceSlug();
@ -400,7 +401,7 @@ export class RStackAppSwitcher extends HTMLElement {
${badgeHtml} ${badgeHtml}
<div class="item-text"> <div class="item-text">
<span class="item-name-row"> <span class="item-name-row">
<span class="item-name">${brandR(m.name)}</span> <span class="item-name">${m.name}</span>
${scopeBadge} ${scopeBadge}
</span> </span>
<span class="item-desc">${m.description}</span> <span class="item-desc">${m.description}</span>
@ -419,10 +420,10 @@ export class RStackAppSwitcher extends HTMLElement {
const badgeInfo = currentMod ? MODULE_BADGES[currentMod.id] : null; const badgeInfo = currentMod ? MODULE_BADGES[currentMod.id] : null;
const triggerContent = badgeInfo const triggerContent = badgeInfo
? `<span class="trigger-badge" style="background:${badgeInfo.color}">${badgeInfo.badge}</span> ${brandR(currentMod!.name)}` ? `<span class="trigger-badge" style="background:${badgeInfo.color}"><span style="color:#dc8300">r</span>${badgeInfo.badge.slice(1)}</span> ${currentMod!.name}`
: currentMod : currentMod
? `${currentMod.icon} ${brandR(currentMod.name)}` ? `${currentMod.icon} ${currentMod.name}`
: `<span class="trigger-badge rstack-gradient">r✨</span> <span style="color:#dc8300">r</span>Space`; : `<span class="trigger-badge rstack-gradient"><span style="color:#dc8300">r</span>✨</span> rSpace`;
this.#shadow.innerHTML = ` this.#shadow.innerHTML = `
<style>${STYLES}</style> <style>${STYLES}</style>

View File

@ -55,6 +55,7 @@ const MODULE_BADGES: Record<string, { badge: string; color: string }> = {
rtasks: { badge: "r📋", color: "#cbd5e1" }, rtasks: { badge: "r📋", color: "#cbd5e1" },
rschedule: { badge: "r⏱", color: "#a5b4fc" }, rschedule: { badge: "r⏱", color: "#a5b4fc" },
rids: { badge: "r🪪", color: "#6ee7b7" }, rids: { badge: "r🪪", color: "#6ee7b7" },
rcred: { badge: "r⭐", color: "#fbbf24" },
rstack: { badge: "r✨", color: "" }, rstack: { badge: "r✨", color: "" },
}; };
@ -464,7 +465,7 @@ export class RStackTabBar extends HTMLElement {
${isSpaceLayer ? `data-space-slug="${layer.spaceSlug}"` : ""} ${isSpaceLayer ? `data-space-slug="${layer.spaceSlug}"` : ""}
draggable="true"> draggable="true">
<span class="tab-indicator" style="background:${badgeColor}"></span> <span class="tab-indicator" style="background:${badgeColor}"></span>
<span class="tab-badge" style="background:${badgeColor}">${badge?.badge || layer.moduleId.slice(0, 2)}</span> <span class="tab-badge" style="background:${badgeColor}">${badge ? `<span style="color:#dc8300">r</span>${badge.badge.slice(1)}` : layer.moduleId.slice(0, 2)}</span>
<span class="tab-label">${layer.label}</span> <span class="tab-label">${layer.label}</span>
${spaceTag}${readOnlyTag} ${spaceTag}${readOnlyTag}
<button class="tab-close" data-close="${layer.id}">&times;</button> <button class="tab-close" data-close="${layer.id}">&times;</button>
@ -538,7 +539,7 @@ export class RStackTabBar extends HTMLElement {
#renderAddMenuItem(m: { id: string; name: string; icon: string; description: string }, isOpen: boolean): string { #renderAddMenuItem(m: { id: string; name: string; icon: string; description: string }, isOpen: boolean): string {
const badge = MODULE_BADGES[m.id]; const badge = MODULE_BADGES[m.id];
const badgeHtml = badge const badgeHtml = badge
? `<span class="add-menu-badge" style="background:${badge.color}">${badge.badge}</span>` ? `<span class="add-menu-badge" style="background:${badge.color}"><span style="color:#dc8300">r</span>${badge.badge.slice(1)}</span>`
: `<span class="add-menu-icon">${m.icon}</span>`; : `<span class="add-menu-icon">${m.icon}</span>`;
const openClass = isOpen ? " add-menu-item--open" : ""; const openClass = isOpen ? " add-menu-item--open" : "";
@ -605,7 +606,7 @@ export class RStackTabBar extends HTMLElement {
data-layer-id="${layer.id}" data-layer-id="${layer.id}"
style="--layer-color:${color}; transform: translateZ(${z}px);"> style="--layer-color:${color}; transform: translateZ(${z}px);">
<div class="layer-header"> <div class="layer-header">
<span class="layer-badge" style="background:${color}">${badge?.badge || layer.moduleId.slice(0, 2)}</span> <span class="layer-badge" style="background:${color}">${badge ? `<span style="color:#dc8300">r</span>${badge.badge.slice(1)}` : layer.moduleId.slice(0, 2)}</span>
<span class="layer-name">${layer.label}</span> <span class="layer-name">${layer.label}</span>
</div> </div>
${hasIO ? `<div class="layer-io"> ${hasIO ? `<div class="layer-io">