Fix a11y icon, FAB label colors, add high-contrast stylesheet, sync theme vars
- Fix faIcon() to use <i> elements (FA7 compatibility) - Fix #mokoThemeFab .label and button colors to white (visible on both light and dark themes) - Fix font-weight typo (600px → 600) - Add --footer-padding-* variables to all 6 theme files - Create a11y-high-contrast.css with WCAG AAA contrast ratios for both light and dark modes - Register high-contrast stylesheet in joomla.asset.json - Lazy-load high-contrast CSS when a11y contrast toggle is activated Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -124,6 +124,12 @@
|
||||
"uri": "media/templates/site/mokocassiopeia/css/theme/dark.custom.min.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "template.a11y-high-contrast",
|
||||
"type": "style",
|
||||
"uri": "media/templates/site/mokocassiopeia/css/a11y-high-contrast.css",
|
||||
"attributes": {"media": "all"}
|
||||
},
|
||||
{
|
||||
"name": "template.js",
|
||||
"type": "script",
|
||||
|
||||
227
src/media/css/a11y-high-contrast.css
Normal file
227
src/media/css/a11y-high-contrast.css
Normal file
@@ -0,0 +1,227 @@
|
||||
@charset "UTF-8";
|
||||
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
*
|
||||
* This file is part of a Moko Consulting project.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* FILE INFORMATION
|
||||
* DEFGROUP: Joomla.Template.Site
|
||||
* INGROUP: MokoCassiopeia.Accessibility
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCassiopeia
|
||||
* PATH: ./media/css/a11y-high-contrast.css
|
||||
* VERSION: 03.09.14
|
||||
* BRIEF: High-contrast stylesheet for accessibility toolbar
|
||||
*/
|
||||
|
||||
/* ===================================================================
|
||||
* HIGH CONTRAST MODE
|
||||
* Applied when .a11y-high-contrast is on <html>.
|
||||
* Overrides theme variables to maximise contrast ratios (WCAG AAA).
|
||||
* =================================================================== */
|
||||
|
||||
/* ── Light mode high contrast ─────────────────────────────────────── */
|
||||
:root[data-bs-theme="light"].a11y-high-contrast {
|
||||
--body-color: #000;
|
||||
--body-color-rgb: 0, 0, 0;
|
||||
--body-bg: #fff;
|
||||
--body-bg-rgb: 255, 255, 255;
|
||||
--heading-color: #000;
|
||||
--emphasis-color: #000;
|
||||
--secondary-color: #000000bf;
|
||||
--tertiary-color: #00000080;
|
||||
--muted-color: #333;
|
||||
|
||||
/* Links — strong blue on white */
|
||||
--color-link: #0000ee;
|
||||
--link-color: #0000ee;
|
||||
--link-color-rgb: 0, 0, 238;
|
||||
--color-hover: #cc0000;
|
||||
--link-hover-color: #cc0000;
|
||||
--link-hover-color-rgb: 204, 0, 0;
|
||||
|
||||
/* Borders — visible on all backgrounds */
|
||||
--border-color: #000;
|
||||
--border-color-soft: #333;
|
||||
|
||||
/* Backgrounds */
|
||||
--secondary-bg: #e0e0e0;
|
||||
--secondary-bg-rgb: 224, 224, 224;
|
||||
--tertiary-bg: #f0f0f0;
|
||||
--tertiary-bg-rgb: 240, 240, 240;
|
||||
|
||||
/* Navigation */
|
||||
--nav-bg-color: #000;
|
||||
--nav-text-color: #fff;
|
||||
--mainmenu-nav-link-color: #fff;
|
||||
|
||||
/* Buttons */
|
||||
--btn-color: #fff;
|
||||
--btn-bg: #000;
|
||||
--btn-border-color: #000;
|
||||
--btn-hover-color: #000;
|
||||
--btn-hover-bg: #ffff00;
|
||||
--btn-hover-border-color: #000;
|
||||
--btn-active-color: #000;
|
||||
--btn-active-bg: #ffff00;
|
||||
--btn-active-border-color: #000;
|
||||
|
||||
/* Forms */
|
||||
--input-color: #000;
|
||||
--input-bg: #fff;
|
||||
--input-border-color: #000;
|
||||
--input-focus-color: #000;
|
||||
--input-focus-bg: #ffffcc;
|
||||
--input-focus-border-color: #0000ee;
|
||||
--input-placeholder-color: #555;
|
||||
|
||||
/* Cards */
|
||||
--card-border-color: #000;
|
||||
--card-bg: #fff;
|
||||
--card-cap-bg: #e0e0e0;
|
||||
|
||||
/* Tables */
|
||||
--table-color: #000;
|
||||
--table-bg: #fff;
|
||||
--table-border-color: #000;
|
||||
--table-striped-bg: #f0f0f0;
|
||||
--table-hover-bg: #ffff99;
|
||||
|
||||
/* Alerts */
|
||||
--alert-border-width: 2px;
|
||||
|
||||
/* Code */
|
||||
--code-color: #000;
|
||||
--code-bg-color: #ffffcc;
|
||||
|
||||
/* Selection */
|
||||
--selection-bg: #0000ee;
|
||||
--selection-ink: #fff;
|
||||
|
||||
/* Focus indicator — always visible */
|
||||
--focus-ring-color: #0000ee;
|
||||
--focus-ring-width: 3px;
|
||||
}
|
||||
|
||||
/* ── Dark mode high contrast ──────────────────────────────────────── */
|
||||
:root[data-bs-theme="dark"].a11y-high-contrast {
|
||||
--body-color: #fff;
|
||||
--body-color-rgb: 255, 255, 255;
|
||||
--body-bg: #000;
|
||||
--body-bg-rgb: 0, 0, 0;
|
||||
--heading-color: #fff;
|
||||
--emphasis-color: #fff;
|
||||
--secondary-color: #ffffffbf;
|
||||
--tertiary-color: #ffffff80;
|
||||
--muted-color: #ccc;
|
||||
|
||||
/* Links — bright yellow on black */
|
||||
--color-link: #ffff00;
|
||||
--link-color: #ffff00;
|
||||
--link-color-rgb: 255, 255, 0;
|
||||
--color-hover: #00ffff;
|
||||
--link-hover-color: #00ffff;
|
||||
--link-hover-color-rgb: 0, 255, 255;
|
||||
|
||||
/* Borders */
|
||||
--border-color: #fff;
|
||||
--border-color-soft: #ccc;
|
||||
|
||||
/* Backgrounds */
|
||||
--secondary-bg: #1a1a1a;
|
||||
--secondary-bg-rgb: 26, 26, 26;
|
||||
--tertiary-bg: #111;
|
||||
--tertiary-bg-rgb: 17, 17, 17;
|
||||
|
||||
/* Navigation */
|
||||
--nav-bg-color: #000;
|
||||
--nav-text-color: #fff;
|
||||
--mainmenu-nav-link-color: #ffff00;
|
||||
|
||||
/* Buttons */
|
||||
--btn-color: #000;
|
||||
--btn-bg: #ffff00;
|
||||
--btn-border-color: #ffff00;
|
||||
--btn-hover-color: #000;
|
||||
--btn-hover-bg: #00ffff;
|
||||
--btn-hover-border-color: #00ffff;
|
||||
--btn-active-color: #000;
|
||||
--btn-active-bg: #00ffff;
|
||||
--btn-active-border-color: #00ffff;
|
||||
|
||||
/* Forms */
|
||||
--input-color: #fff;
|
||||
--input-bg: #000;
|
||||
--input-border-color: #fff;
|
||||
--input-focus-color: #fff;
|
||||
--input-focus-bg: #1a1a1a;
|
||||
--input-focus-border-color: #ffff00;
|
||||
--input-placeholder-color: #aaa;
|
||||
|
||||
/* Cards */
|
||||
--card-border-color: #fff;
|
||||
--card-bg: #000;
|
||||
--card-cap-bg: #1a1a1a;
|
||||
|
||||
/* Tables */
|
||||
--table-color: #fff;
|
||||
--table-bg: #000;
|
||||
--table-border-color: #fff;
|
||||
--table-striped-bg: #111;
|
||||
--table-hover-bg: #333;
|
||||
|
||||
/* Alerts */
|
||||
--alert-border-width: 2px;
|
||||
|
||||
/* Code */
|
||||
--code-color: #00ff00;
|
||||
--code-bg-color: #1a1a1a;
|
||||
|
||||
/* Selection */
|
||||
--selection-bg: #ffff00;
|
||||
--selection-ink: #000;
|
||||
|
||||
/* Focus indicator */
|
||||
--focus-ring-color: #ffff00;
|
||||
--focus-ring-width: 3px;
|
||||
}
|
||||
|
||||
/* ── Shared high-contrast overrides (both modes) ──────────────────── */
|
||||
.a11y-high-contrast * {
|
||||
border-color: var(--border-color) !important;
|
||||
}
|
||||
|
||||
.a11y-high-contrast *:focus-visible {
|
||||
outline: var(--focus-ring-width, 3px) solid var(--focus-ring-color, #0000ee) !important;
|
||||
outline-offset: 2px !important;
|
||||
}
|
||||
|
||||
.a11y-high-contrast img {
|
||||
outline: 2px solid var(--border-color);
|
||||
}
|
||||
|
||||
.a11y-high-contrast a {
|
||||
text-decoration: underline !important;
|
||||
text-decoration-thickness: 2px !important;
|
||||
}
|
||||
|
||||
.a11y-high-contrast button,
|
||||
.a11y-high-contrast .btn,
|
||||
.a11y-high-contrast input,
|
||||
.a11y-high-contrast select,
|
||||
.a11y-high-contrast textarea {
|
||||
border-width: 2px !important;
|
||||
border-style: solid !important;
|
||||
}
|
||||
|
||||
.a11y-high-contrast .badge,
|
||||
.a11y-high-contrast .alert {
|
||||
border: 2px solid var(--border-color) !important;
|
||||
}
|
||||
|
||||
/* Ensure disabled states are still distinguishable */
|
||||
.a11y-high-contrast [disabled],
|
||||
.a11y-high-contrast .disabled {
|
||||
opacity: .5 !important;
|
||||
text-decoration: line-through !important;
|
||||
}
|
||||
@@ -17070,8 +17070,8 @@ form .form-select {
|
||||
background: var(--muted-color, #6d757e);
|
||||
box-shadow: var(--box-shadow, 0 .5rem 1rem #00000066);
|
||||
font: inherit;
|
||||
color: var(--body-bg, #0e1318);
|
||||
font-weight: 600px;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#mokoThemeFab.pos-br {
|
||||
@@ -17133,10 +17133,11 @@ button#mokoThemeSwitch {
|
||||
#mokoThemeFab .label {
|
||||
user-select: none;
|
||||
font-size: .875rem;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#mokoThemeFab button {
|
||||
color: var(--body-bg, #0e1318);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Auto toggle switch (on/off style) */
|
||||
|
||||
@@ -817,6 +817,12 @@ color-scheme: dark;
|
||||
--table-active-color: var(--body-color);
|
||||
--table-active-bg: rgba(var(--white-rgb), 0.1);
|
||||
|
||||
/* ===== FOOTER ===== */
|
||||
--footer-padding-top: 1rem;
|
||||
--footer-padding-bottom: 80px;
|
||||
--footer-grid-padding-y: 2.5rem;
|
||||
--footer-grid-padding-x: 0.5em;
|
||||
|
||||
/* ===== BACKDROP ===== */
|
||||
--backdrop-zindex: 1040;
|
||||
--backdrop-bg: hsl(0, 0%, 0%);
|
||||
|
||||
@@ -817,6 +817,12 @@ color-scheme: dark;
|
||||
--table-active-color: var(--body-color);
|
||||
--table-active-bg: rgba(var(--white-rgb), 0.1);
|
||||
|
||||
/* ===== FOOTER ===== */
|
||||
--footer-padding-top: 1rem;
|
||||
--footer-padding-bottom: 80px;
|
||||
--footer-grid-padding-y: 2.5rem;
|
||||
--footer-grid-padding-x: 0.5em;
|
||||
|
||||
/* ===== BACKDROP ===== */
|
||||
--backdrop-zindex: 1040;
|
||||
--backdrop-bg: hsl(0, 0%, 0%);
|
||||
|
||||
@@ -816,6 +816,12 @@ color-scheme: light;
|
||||
--table-active-color: var(--body-color);
|
||||
--table-active-bg: rgba(var(--black-rgb), 0.075);
|
||||
|
||||
/* ===== FOOTER ===== */
|
||||
--footer-padding-top: 1rem;
|
||||
--footer-padding-bottom: 80px;
|
||||
--footer-grid-padding-y: 2.5rem;
|
||||
--footer-grid-padding-x: 0.5em;
|
||||
|
||||
/* ===== BACKDROP ===== */
|
||||
--backdrop-zindex: 1040;
|
||||
--backdrop-bg: hsl(0, 0%, 0%);
|
||||
|
||||
@@ -816,6 +816,12 @@ color-scheme: light;
|
||||
--table-active-color: var(--body-color);
|
||||
--table-active-bg: rgba(var(--black-rgb), 0.075);
|
||||
|
||||
/* ===== FOOTER ===== */
|
||||
--footer-padding-top: 1rem;
|
||||
--footer-padding-bottom: 80px;
|
||||
--footer-grid-padding-y: 2.5rem;
|
||||
--footer-grid-padding-x: 0.5em;
|
||||
|
||||
/* ===== BACKDROP ===== */
|
||||
--backdrop-zindex: 1040;
|
||||
--backdrop-bg: hsl(0, 0%, 0%);
|
||||
|
||||
@@ -229,6 +229,18 @@
|
||||
|
||||
function applyContrast(on) {
|
||||
root.classList.toggle("a11y-high-contrast", on);
|
||||
// Lazy-load the high-contrast stylesheet
|
||||
var hcId = "mokoA11yHcSheet";
|
||||
var existing = doc.getElementById(hcId);
|
||||
if (on && !existing) {
|
||||
var link = doc.createElement("link");
|
||||
link.id = hcId;
|
||||
link.rel = "stylesheet";
|
||||
link.href = (doc.querySelector('link[href*="mokocassiopeia/css/template"]') || {}).href
|
||||
? (doc.querySelector('link[href*="mokocassiopeia/css/template"]').href.replace(/\/css\/template[^/]*$/, "/css/a11y-high-contrast.css"))
|
||||
: "media/templates/site/mokocassiopeia/css/a11y-high-contrast.css";
|
||||
doc.head.appendChild(link);
|
||||
}
|
||||
}
|
||||
|
||||
function applyLinks(on) {
|
||||
@@ -245,10 +257,10 @@
|
||||
|
||||
/** Create a Font Awesome icon element (safe DOM, no innerHTML). */
|
||||
function faIcon(classes) {
|
||||
var span = doc.createElement("span");
|
||||
span.className = classes;
|
||||
span.setAttribute("aria-hidden", "true");
|
||||
return span;
|
||||
var i = doc.createElement("i");
|
||||
i.className = classes;
|
||||
i.setAttribute("aria-hidden", "true");
|
||||
return i;
|
||||
}
|
||||
|
||||
function buildA11yToolbar() {
|
||||
|
||||
@@ -813,6 +813,12 @@ color-scheme: dark;
|
||||
--table-active-color: var(--body-color);
|
||||
--table-active-bg: rgba(var(--white-rgb), 0.1);
|
||||
|
||||
/* ===== FOOTER ===== */
|
||||
--footer-padding-top: 1rem;
|
||||
--footer-padding-bottom: 80px;
|
||||
--footer-grid-padding-y: 2.5rem;
|
||||
--footer-grid-padding-x: 0.5em;
|
||||
|
||||
/* ===== BACKDROP ===== */
|
||||
--backdrop-zindex: 1040;
|
||||
--backdrop-bg: hsl(0, 0%, 0%);
|
||||
|
||||
@@ -812,6 +812,12 @@ color-scheme: light;
|
||||
--table-active-color: var(--body-color);
|
||||
--table-active-bg: rgba(var(--black-rgb), 0.075);
|
||||
|
||||
/* ===== FOOTER ===== */
|
||||
--footer-padding-top: 1rem;
|
||||
--footer-padding-bottom: 80px;
|
||||
--footer-grid-padding-y: 2.5rem;
|
||||
--footer-grid-padding-x: 0.5em;
|
||||
|
||||
/* ===== BACKDROP ===== */
|
||||
--backdrop-zindex: 1040;
|
||||
--backdrop-bg: hsl(0, 0%, 0%);
|
||||
|
||||
Reference in New Issue
Block a user