fix(webui): make the app detail category tag clickable and its icon legible

The category pill on the app detail header was rendered inert — no click
handler at all — while the identical pill on the app cards navigated to that
category's filter view. Both now come from one AppsManager.renderCategoryTag(),
so the detail pill behaves like the card pill and the two can't drift again.

The pill's glyph was an <img> of a category SVG, and those SVGs hardcode
#1e90ff. That only ever matched the dark-blue theme; on nebula (the default,
accent #00d4ff) and any other theme the icon read as a dark smudge next to its
own label. It's now painted as a CSS mask filled with currentColor, so it
always matches the pill's text on every theme.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
librelad 2026-08-18 21:00:45 +01:00
parent c2fdfaccdb
commit 4a95b4c41e
3 changed files with 31 additions and 10 deletions

View File

@ -163,6 +163,20 @@
transform: translateY(-1px);
}
/* The category glyph is drawn as a mask filled with the pill's own text
colour. The category SVGs ship a hardcoded #1e90ff, which disappears into
the pill on any theme whose accent isn't that blue masking keeps icon and
label the same colour on every theme. --cat-icon is set inline per tag. */
.category-tag-icon {
width: 12px;
height: 12px;
flex-shrink: 0;
display: inline-block;
background-color: currentColor;
-webkit-mask: var(--cat-icon) center / contain no-repeat;
mask: var(--cat-icon) center / contain no-repeat;
}
/* Description tags - White to match title */
.app-tag.description-tag {
background: rgba(var(--text-rgb), 0.1);

View File

@ -181,13 +181,9 @@ Object.assign(AppsManager.prototype, {
const status = app.installed ? 'Installed' : 'Not Installed';
// Get category icon and name
const categoryIcon = this.getCategoryIcon(app.category);
const categoryName = this.getCategoryName(app.category);
// Create rich tags like original
const descriptionTag = app.description ? `<span class="app-tag description-tag"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg> ${app.description}</span>` : '';
const categoryTag = `<span class="app-tag category-tag clickable" onclick="event.stopPropagation(); appsManager.switchCategory('${app.category}')"><img src="${categoryIcon}"/> ${categoryName}</span>`;
const categoryTag = this.renderCategoryTag(app.category);
// Format long description with period if missing
let formattedLongDescription = '';

View File

@ -678,14 +678,12 @@ class AppsManager {
}
const status = app.installed ? 'Installed' : 'Not Installed';
const categoryName = this.getCategoryName(app.category);
const categoryIcon = this.getCategoryIcon(app.category);
// Create tags matching app center style
const installedTag = app.installed
? `<span class="app-tag installed-tag">${status}</span>`
: `<span class="app-tag not-installed-tag">${status}</span>`;
const categoryTag = `<span class="app-tag category-tag"><img src="${categoryIcon}"/> ${categoryName}</span>`;
const categoryTag = this.renderCategoryTag(app.category);
// Render app header section (always define, but only update DOM if app changed)
const headerHTML = `
<div class="app-info">
@ -879,7 +877,20 @@ class AppsManager {
return category ? category.name : categoryId;
}
// The category pill (icon + name), shared by the grid cards and the app
// detail header so both click through to that category's filter view.
// The icon is painted as a CSS mask filled with currentColor rather than a
// plain <img>: the source SVGs hardcode #1e90ff, which reads as a dark
// smudge inside the pill on any theme whose accent isn't that blue. As a
// mask it always matches the pill's own text colour.
renderCategoryTag(categoryId) {
const name = this.getCategoryName(categoryId);
const iconPath = this.getCategoryIcon(categoryId);
const icon = iconPath
? `<i class="category-tag-icon" style="--cat-icon: url('${iconPath}')"></i>`
: '';
return `<span class="app-tag category-tag clickable" onclick="event.stopPropagation(); appsManager.switchCategory('${categoryId}')">${icon}${name}</span>`;
}
// Check if a service is installed
checkServiceInstalled(serviceName) {