Theme post code blocks + a11y fixes (impeccable audit) (#25)

Code blocks in posts rendered with the markdown plugin's default light highlight.js theme — white blocks on the dark ledger. This adds dark velvet pre/code styling and a Westgate-toned syntax palette (gold keywords, ledger-ink titles, muted green strings) for post content and the composer preview.

Also picks up the quick wins from an impeccable audit:

- Visible focus ring on the mobile drawer search (input had `outline: 0` with no replacement)
- Input placeholder contrast raised to pass WCAG 4.5:1; tagsinput placeholder reuses the token instead of `$gray-500`
- `prefers-reduced-motion` block zeroing transitions/animations (there were none before)
- Fixed a stray `</li>` closing a `<div>` in `quick-search-results.tpl`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: #25
Co-authored-by: vickydotbat <vickydotbat@tutamail.com>
Co-committed-by: vickydotbat <vickydotbat@tutamail.com>
This commit was merged in pull request #25.
This commit is contained in:
2026-07-16 14:44:39 +00:00
committed by archvillainette
parent 9ec0170e37
commit c3851107ab
21 changed files with 274 additions and 94 deletions
+31 -3
View File
@@ -115,13 +115,15 @@
return element && element.offsetWidth ? element.offsetWidth : 0;
}
function setMobileTableMinWidth(table, wrapper) {
function measureMobileTableMinWidth(table) {
const columnCount = getTableColumnCount(table);
const measuredWidth = getRenderedWidth(table);
const columnWidthFloor = getTableColumnWidthFloor(table, columnCount);
const desktopWidthFloor = tableUsesFluidWidth(table) && columnCount >= 8 ? WIKI_TABLE_DESKTOP_MIN_WIDTH : 0;
const minWidth = Math.ceil(Math.max(measuredWidth, columnWidthFloor, desktopWidthFloor));
return Math.ceil(Math.max(measuredWidth, columnWidthFloor, desktopWidthFloor));
}
function applyMobileTableMinWidth(wrapper, minWidth) {
if (minWidth > 0 && wrapper && wrapper.style && typeof wrapper.style.setProperty === 'function') {
wrapper.style.setProperty('--wg-mobile-table-min-width', `${minWidth}px`);
}
@@ -133,6 +135,7 @@
return;
}
const wrapped = [];
toArray(scope.querySelectorAll(WIKI_TABLE_SELECTOR)).forEach((table) => {
if (!table || !table.parentNode || table.closest(SKIP_TABLE_SELECTOR)) {
return;
@@ -144,8 +147,16 @@
wrapper.setAttribute('aria-label', 'Scrollable table');
table.parentNode.insertBefore(wrapper, table);
wrapper.appendChild(table);
setMobileTableMinWidth(table, wrapper);
wrapped.push({ table, wrapper });
});
// batch: measure every table first, then write, so reads and writes
// don't interleave and force repeated reflows
wrapped
.map(({ table, wrapper }) => ({ wrapper, minWidth: measureMobileTableMinWidth(table) }))
.forEach(({ wrapper, minWidth }) => {
applyMobileTableMinWidth(wrapper, minWidth);
});
}
function getWestgateTopbar() {
@@ -223,6 +234,20 @@
$(document).ready(function () {
wrapWestgateWikiTables(document);
initWestgateTopbar();
// topic-select checkboxes are <i> elements; make them keyboard-operable
$(document).on('keydown', 'i[component="topic/select"]', function (ev) {
if (ev.key === 'Enter' || ev.key === ' ') {
ev.preventDefault();
$(this).trigger('click');
}
});
$(document).on('click', 'i[component="topic/select"]', function () {
// core toggles the icon class in its own click handler; sync after it runs
setTimeout(() => {
this.setAttribute('aria-checked', this.classList.contains('fa-check-square') ? 'true' : 'false');
}, 0);
});
$(window).on('action:ajaxify.end', function () {
wrapWestgateWikiTables(document);
initWestgateTopbar();
@@ -272,6 +297,9 @@
class: category.class || classMap[String(category.cid)] || '',
}));
callback(null, payload);
}).catch(() => {
// class map is cosmetic; never block search results on it
callback(null, payload);
});
});
};