Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/view/frontend/web/css/toolbar/_footer.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@
padding-top: 6px;
}

/* ── Theme toggle ────────────────────────────────────────────────────────── */
/* ── Footer toolbar row (credit + theme + export) ─────────────────────────── */

.mageforge-footer-theme-row {
.mageforge-footer-toolbar-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 6px 6px 16px;
gap: 8px;
}

.mageforge-footer-theme-label {
.mageforge-footer-toolbar-label {
font-family: var(--mageforge-font-family);
font-size: 10px;
font-weight: 500;
Expand All @@ -33,7 +33,7 @@
padding: 3px 6px 3px 8px;
}

.mageforge-theme-toggle {
.mageforge-segmented-toggle {
display: flex;
align-items: center;
gap: 2px;
Expand All @@ -42,7 +42,7 @@
padding: 2px;
}

.mageforge-theme-btn {
.mageforge-segmented-btn {
padding: 3px 8px;
border-radius: 4px;
border: none;
Expand All @@ -56,23 +56,23 @@
line-height: 1;
}

.mageforge-theme-btn:hover {
.mageforge-segmented-btn:hover {
color: var(--mageforge-color-white);
background: rgba(var(--mageforge-color-white-rgb), 0.08);
}

.mageforge-theme-btn--active,
.mageforge-theme-btn[aria-pressed="true"] {
.mageforge-segmented-btn--active,
.mageforge-segmented-btn[aria-pressed="true"] {
background: var(--mageforge-color-blue);
color: var(--mageforge-color-white);
}

.mageforge-theme-btn:focus-visible {
.mageforge-segmented-btn:focus-visible {
outline: 2px solid var(--mageforge-color-blue);
outline-offset: 1px;
}

.mageforge-theme-btn:disabled {
.mageforge-segmented-btn:disabled {
opacity: 0.35;
cursor: not-allowed;
pointer-events: none;
Expand Down
22 changes: 22 additions & 0 deletions src/view/frontend/web/css/toolbar/_health.css
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,25 @@
text-align: center;
line-height: 1;
}

/* ============================================================================
Dynamic score colours
========================================================================== */

.mageforge-score--low .mageforge-toolbar-health-score-number,
.mageforge-score--low .mageforge-score-number,
.mageforge-score--low.mageforge-dashboard-category-score {
color: var(--mageforge-color-red);
}

.mageforge-score--mid .mageforge-toolbar-health-score-number,
.mageforge-score--mid .mageforge-score-number,
.mageforge-score--mid.mageforge-dashboard-category-score {
color: var(--mageforge-color-amber);
}
Comment thread
Copilot marked this conversation as resolved.

.mageforge-score--high .mageforge-toolbar-health-score-number,
.mageforge-score--high .mageforge-score-number,
.mageforge-score--high.mageforge-dashboard-category-score {
color: var(--mageforge-color-green);
}
51 changes: 51 additions & 0 deletions src/view/frontend/web/css/toolbar/_menu.css
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,57 @@
outline-offset: 2px;
}

/* ============================================================================
Menu Header Actions (theme toggle + close)
========================================================================== */

.mageforge-toolbar-menu-actions {
display: flex;
align-items: center;
gap: 6px;
}

.mageforge-theme-icon-group {
display: flex;
align-items: center;
gap: 2px;
background: rgba(var(--mageforge-color-white-rgb), 0.06);
border-radius: 6px;
padding: 2px;
}

.mageforge-theme-icon-btn {
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
padding: 0;
border: none;
border-radius: 4px;
background: transparent;
color: var(--mageforge-color-slate-400);
cursor: pointer;
transition: all 0.15s ease;
line-height: 0;
}

.mageforge-theme-icon-btn:hover {
color: var(--mageforge-color-white);
background: rgba(var(--mageforge-color-white-rgb), 0.08);
}

.mageforge-theme-icon-btn--active,
.mageforge-theme-icon-btn[aria-pressed="true"] {
background: var(--mageforge-color-blue);
color: var(--mageforge-color-white);
}

.mageforge-theme-icon-btn:focus-visible {
outline: 2px solid var(--mageforge-color-blue);
outline-offset: 2px;
}

/* ============================================================================
Menu Items
========================================================================== */
Expand Down
12 changes: 8 additions & 4 deletions src/view/frontend/web/css/toolbar/_themes.css
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,13 @@
}

/* Theme toggle pill: replace hardcoded white alpha with dark */
.mageforge-toolbar[data-theme="light"] .mageforge-theme-toggle {
.mageforge-toolbar[data-theme="light"] .mageforge-segmented-toggle,
.mageforge-toolbar[data-theme="light"] .mageforge-theme-icon-group {
background: rgba(var(--mageforge-color-black-rgb), 0.06);
}

.mageforge-toolbar[data-theme="light"] .mageforge-theme-btn:hover {
.mageforge-toolbar[data-theme="light"] .mageforge-segmented-btn:hover,
.mageforge-toolbar[data-theme="light"] .mageforge-theme-icon-btn:hover {
background: rgba(var(--mageforge-color-black-rgb), 0.08);
}

Expand Down Expand Up @@ -130,11 +132,13 @@
background: rgba(var(--mageforge-color-teal-rgb), 0.14);
}

.mageforge-toolbar[data-theme="auto"] .mageforge-theme-toggle {
.mageforge-toolbar[data-theme="auto"] .mageforge-segmented-toggle,
.mageforge-toolbar[data-theme="auto"] .mageforge-theme-icon-group {
background: rgba(var(--mageforge-color-black-rgb), 0.06);
}

.mageforge-toolbar[data-theme="auto"] .mageforge-theme-btn:hover {
.mageforge-toolbar[data-theme="auto"] .mageforge-segmented-btn:hover,
.mageforge-toolbar[data-theme="auto"] .mageforge-theme-icon-btn:hover {
background: rgba(var(--mageforge-color-black-rgb), 0.08);
}

Expand Down
92 changes: 69 additions & 23 deletions src/view/frontend/web/js/toolbar/ui/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import {
createLogoSvg,
generateId,
ICON_HOME,
ICON_THEME_DARK,
ICON_THEME_LIGHT,
ICON_THEME_AUTO,
GROUP_ICONS,
GAUGE_ARC_LENGTH,
SCORE_RING_CIRCUMFERENCE,
Expand Down Expand Up @@ -93,7 +96,7 @@ export const buildMethods = {
},

/**
* Sticky title bar: logo + name + close button.
* Sticky title bar: logo + name + theme toggle + close button.
*
* @returns {HTMLDivElement}
*/
Expand All @@ -105,15 +108,54 @@ export const buildMethods = {
<div>${createLogoSvg("#E5622A")}</div>
<span class="mageforge-toolbar-menu-title-text">MageForge</span>
</div>
<button type="button" class="mageforge-toolbar-menu-close" title="Close & deactivate all" aria-label="Close & deactivate all">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6L6 18M6 6l12 12"></path></svg>
</button>
<div class="mageforge-toolbar-menu-actions"></div>
`;
header.querySelector(".mageforge-toolbar-menu-close").onclick = (e) => {

const actions = header.querySelector(".mageforge-toolbar-menu-actions");

// Theme toggle
const themeGroup = document.createElement("div");
themeGroup.className = "mageforge-theme-icon-group";
themeGroup.setAttribute("role", "group");
themeGroup.setAttribute("aria-label", "Colour theme");
[
["dark", ICON_THEME_DARK, "Dark theme"],
["auto", ICON_THEME_AUTO, "Auto theme"],
["light", ICON_THEME_LIGHT, "Light theme"],
].forEach(([value, icon, label]) => {
const btn = document.createElement("button");
btn.type = "button";
btn.className = "mageforge-theme-icon-btn";
btn.dataset.themeValue = value;
btn.innerHTML = icon;
btn.setAttribute("aria-label", label);
btn.title = label;
btn.setAttribute("aria-pressed", "false");
btn.onclick = (e) => {
e.stopPropagation();
this.setTheme(/** @type {'dark'|'auto'|'light'} */ (value));
};
themeGroup.appendChild(btn);
});
actions.appendChild(themeGroup);
this._themeToggleGroup = themeGroup;

// Close button
const closeBtn = document.createElement("button");
closeBtn.type = "button";
closeBtn.className = "mageforge-toolbar-menu-close";
closeBtn.title = "Close & deactivate all";
closeBtn.setAttribute("aria-label", "Close & deactivate all");
closeBtn.innerHTML =
'<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6L6 18M6 6l12 12"></path></svg>';
closeBtn.onclick = (e) => {
e.stopPropagation();
this.deactivateAllAudits();
this.closeMenu();
};
actions.appendChild(closeBtn);

this._updateThemeToggle();
return header;
},

Expand Down Expand Up @@ -718,24 +760,34 @@ export const buildMethods = {
const footer = document.createElement("div");
footer.className = "mageforge-toolbar-menu-footer";

// Export format row ──────────────────────────────────────────────────
const exportRow = document.createElement("div");
exportRow.className = "mageforge-footer-theme-row";
this._exportBtnRow = exportRow;
const exportGroup = document.createElement("div");
exportGroup.className = "mageforge-theme-toggle";
// Footer toolbar row: credit + theme toggle + export formats
const footerRow = document.createElement("div");
footerRow.className = "mageforge-footer-toolbar-row";

// Credit line
const credit = document.createElement("div");
credit.className = "mageforge-toolbar-menu-credit";
credit.innerHTML =
'Built with <span class="mageforge-toolbar-menu-credit-heart">\u2764</span> by <a href="https://github.com/OpenForgeProject/mageforge" target="_blank" rel="noopener noreferrer" class="mageforge-toolbar-menu-credit-link">MageForge</a>';
footerRow.appendChild(credit);

// Export format toggle
this._exportBtnRow = document.createElement("div");
this._exportBtnRow.className = "mageforge-segmented-toggle";
this._exportBtnRow.setAttribute("role", "group");
this._exportBtnRow.setAttribute("aria-label", "Export format");
const exportLabel = document.createElement("span");
exportLabel.className = "mageforge-footer-theme-label";
exportLabel.className = "mageforge-footer-toolbar-label";
exportLabel.textContent = "Export";
exportGroup.appendChild(exportLabel);
this._exportBtnRow.appendChild(exportLabel);
[
["json", "JSON"],
["md", "MD"],
["txt", "TXT"],
].forEach(([fmt, label]) => {
const btn = document.createElement("button");
btn.type = "button";
btn.className = "mageforge-theme-btn mageforge-export-btn--disabled";
btn.className = "mageforge-segmented-btn mageforge-export-btn--disabled";
btn.dataset.exportFormat = fmt;
btn.textContent = label;
btn.disabled = true;
Expand All @@ -745,17 +797,11 @@ export const buildMethods = {
e.stopPropagation();
this.exportFindings(fmt);
};
exportGroup.appendChild(btn);
this._exportBtnRow.appendChild(btn);
});
exportRow.appendChild(exportGroup);
footer.appendChild(exportRow);
footerRow.appendChild(this._exportBtnRow);

// Credit line (left side of export row) ─────────────────────────────
const credit = document.createElement("div");
credit.className = "mageforge-toolbar-menu-credit";
credit.innerHTML =
'Built with <span class="mageforge-toolbar-menu-credit-heart">\u2764</span> by <a href="https://github.com/OpenForgeProject/mageforge" target="_blank" rel="noopener noreferrer" class="mageforge-toolbar-menu-credit-link">MageForge</a>';
exportRow.insertBefore(credit, exportRow.firstChild);
footer.appendChild(footerRow);

// Populate nav action bar for the initially active tab (home).
// footerActionBar was already created in _buildTabNav().
Expand Down
9 changes: 9 additions & 0 deletions src/view/frontend/web/js/toolbar/ui/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ export const LOGO_SVG_PATH =
export const ICON_HOME =
'<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>';

export const ICON_THEME_DARK =
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>';

export const ICON_THEME_LIGHT =
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>';

export const ICON_THEME_AUTO =
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><path d="M12 2a10 10 0 0 1 0 20v-20z"></path></svg>';

export const GROUP_ICONS = {
wcag: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7z"></path><circle cx="12" cy="12" r="3"></circle></svg>',
"html-quality":
Expand Down
16 changes: 16 additions & 0 deletions src/view/frontend/web/js/toolbar/ui/controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export const controls = {
this.runAllButton = null;
this.resetButton = null;
this._exportBtnRow = null;
this._themeToggleGroup = null;
this.menuOpen = false;
},

Expand All @@ -110,5 +111,20 @@ export const controls = {
localStorage.setItem("mageforge-theme", theme);
} catch (_) {}
if (this.container) this.container.setAttribute("data-theme", theme);
this._updateThemeToggle();
},

/**
* Reflect the current theme in the header icon toggle buttons.
*/
_updateThemeToggle() {
if (!this._themeToggleGroup) return;
this._themeToggleGroup
.querySelectorAll(".mageforge-theme-icon-btn")
.forEach((btn) => {
const active = btn.dataset.themeValue === this.currentTheme;
btn.classList.toggle("mageforge-theme-icon-btn--active", active);
btn.setAttribute("aria-pressed", String(active));
});
},
};
Loading
Loading