feat(leader): WCAG accessibility with 9 accordions, keyboard navigation

- Converted all 9 accordion divs to semantic <button> elements
- Added ARIA attributes: aria-expanded, aria-controls, id for each button
- Accordion content: role="region" and aria-labelledby for screen readers
- Keyboard support: Enter and Space keys toggle accordions (WAI-ARIA pattern)
- Mobile optimization: 44px/48px touch targets, touch-action: manipulation
- iOS tap feedback: -webkit-tap-highlight-color
- Footer i18n: No footer object in leader.json (uses common.json correctly)
- Updated leader-page.js with keyboard handlers and ARIA state management
- Version 1.5.0

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
TheFlow 2025-10-23 00:19:23 +13:00
parent 50d1644bf4
commit b69b7167a9
3 changed files with 95 additions and 37 deletions

48
public/js/leader-page.js Normal file
View file

@ -0,0 +1,48 @@
/**
* Leader Page - Accordion Functionality
* Handles expandable/collapsible sections for leadership content
* Implements WAI-ARIA Authoring Practices for accordions
*/
document.addEventListener('DOMContentLoaded', function() {
// Get all accordion buttons
const accordionButtons = document.querySelectorAll('[data-accordion]');
accordionButtons.forEach(button => {
// Click handler
button.addEventListener('click', function() {
const accordionId = this.dataset.accordion;
toggleAccordion(accordionId, this);
});
// Keyboard handler (Enter and Space)
button.addEventListener('keydown', function(e) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
const accordionId = this.dataset.accordion;
toggleAccordion(accordionId, this);
}
});
});
/**
* Toggle accordion section open/closed
* @param {string} id - Accordion section ID
* @param {HTMLElement} button - The button element that triggered toggle
*/
function toggleAccordion(id, button) {
const content = document.getElementById(id + '-content');
const icon = document.getElementById(id + '-icon');
if (content && icon) {
const isExpanded = content.classList.contains('active');
// Toggle CSS classes for visual state
content.classList.toggle('active');
icon.classList.toggle('active');
// Update ARIA state
button.setAttribute('aria-expanded', isExpanded ? 'false' : 'true');
}
}
});

View file

@ -17,9 +17,9 @@
<link rel="apple-touch-icon" href="/images/tractatus-icon-new.svg">
<link rel="icon" type="image/svg+xml" href="/favicon-new.svg">
<link rel="stylesheet" href="/css/fonts.css">
<link rel="stylesheet" href="/css/tailwind.css?v=0.1.0.1760254958072">
<link rel="stylesheet" href="/css/tractatus-theme.min.css?v=1760816800">
<link rel="stylesheet" href="/css/fonts.css?v=1761131829">
<link rel="stylesheet" href="/css/tailwind.css?v=1761131829">
<link rel="stylesheet" href="/css/tractatus-theme.min.css?v=1761131829">
<style>
.hover-lift { transition: all 0.3s ease; }
.hover-lift:hover { transform: translateY(-2px); }
@ -31,6 +31,16 @@
.accordion-button {
cursor: pointer;
user-select: none;
touch-action: manipulation; /* Prevent double-tap zoom on mobile */
-webkit-tap-highlight-color: rgba(217, 119, 6, 0.1); /* iOS tap feedback */
min-height: 44px; /* WCAG touch target minimum */
border: none;
background: none;
width: 100%;
text-align: left;
}
@media (max-width: 640px) {
.accordion-button { min-height: 48px; } /* Larger touch target on small screens */
}
.accordion-content {
max-height: 0;
@ -53,7 +63,7 @@
<a href="#main-content" class="skip-link">Skip to main content</a>
<script src="/js/components/navbar.js?v=0.1.0.1760254958072"></script>
<script src="/js/components/navbar.js?v=1761131829"></script>
<!-- Breadcrumb Navigation -->
<nav class="bg-gray-50 border-b border-gray-200 py-3" aria-label="Breadcrumb">
@ -106,13 +116,13 @@
<!-- Three-Layer Architecture Card -->
<div class="border border-gray-300 rounded-lg mb-4">
<div class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="arch-layers">
<button type="button" class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="arch-layers" aria-expanded="false" aria-controls="arch-layers-content" id="arch-layers-button">
<h3 class="font-semibold text-gray-900" data-i18n="sections.architectural_approach.three_layer_title">Three-Layer Architecture</h3>
<svg id="arch-layers-icon" class="accordion-icon w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
<div id="arch-layers-content" class="accordion-content">
<div id="arch-layers-content" class="accordion-content" role="region" aria-labelledby="arch-layers-button">
<div class="p-5 border-t border-gray-200 space-y-3 text-sm text-gray-700">
<div class="flex gap-3">
<span class="font-mono text-gray-500">1.</span>
@ -138,13 +148,13 @@
<!-- Six Governance Services Card -->
<div class="border border-gray-300 rounded-lg">
<div class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="services">
<button type="button" class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="services" aria-expanded="false" aria-controls="services-content" id="services-button">
<h3 class="font-semibold text-gray-900" data-i18n="sections.architectural_approach.services_title">Six Governance Services</h3>
<svg id="services-icon" class="accordion-icon w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
<div id="services-content" class="accordion-content">
<div id="services-content" class="accordion-content" role="region" aria-labelledby="services-button">
<div class="p-5 border-t border-gray-200 space-y-3 text-sm">
<div class="border-l-2 border-amber-500 pl-4">
<div class="font-semibold text-gray-900">BoundaryEnforcer</div>
@ -184,7 +194,7 @@
<!-- Demo 1: Audit Trail & Compliance Evidence -->
<div class="border border-gray-300 rounded-lg mb-4">
<div class="accordion-button bg-gradient-to-r from-blue-50 to-indigo-50 p-5 flex justify-between items-center" data-accordion="demo-audit">
<button type="button" class="accordion-button bg-gradient-to-r from-blue-50 to-indigo-50 p-5 flex justify-between items-center" data-accordion="demo-audit" aria-expanded="false" aria-controls="demo-audit-content" id="demo-audit-button">
<div>
<h3 class="font-semibold text-gray-900" data-i18n="sections.governance_capabilities.audit_trail_title">Audit Trail & Compliance Evidence Generation</h3>
<p class="text-sm text-gray-600 mt-1" data-i18n="sections.governance_capabilities.audit_trail_desc">Immutable logging, evidence extraction, regulatory reporting</p>
@ -193,7 +203,7 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
<div id="demo-audit-content" class="accordion-content">
<div id="demo-audit-content" class="accordion-content" role="region" aria-labelledby="demo-audit-button">
<div class="p-5 border-t border-gray-200">
<div class="bg-white rounded border border-gray-200 p-4 mb-4">
<h4 class="text-sm font-semibold text-gray-900 mb-3">Sample Audit Log Structure</h4>
@ -241,7 +251,7 @@
<!-- Demo 2: Continuous Improvement Cycle -->
<div class="border border-gray-300 rounded-lg mb-4">
<div class="accordion-button bg-gradient-to-r from-green-50 to-emerald-50 p-5 flex justify-between items-center" data-accordion="demo-learning">
<button type="button" class="accordion-button bg-gradient-to-r from-green-50 to-emerald-50 p-5 flex justify-between items-center" data-accordion="demo-learning" aria-expanded="false" aria-controls="demo-learning-content" id="demo-learning-button">
<div>
<h3 class="font-semibold text-gray-900" data-i18n="sections.governance_capabilities.continuous_improvement_title">Continuous Improvement: Incident → Rule Creation</h3>
<p class="text-sm text-gray-600 mt-1" data-i18n="sections.governance_capabilities.continuous_improvement_desc">Learning from failures, automated rule generation, validation</p>
@ -250,7 +260,7 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
<div id="demo-learning-content" class="accordion-content">
<div id="demo-learning-content" class="accordion-content" role="region" aria-labelledby="demo-learning-button">
<div class="p-5 border-t border-gray-200">
<div class="space-y-4">
<!-- Flow diagram -->
@ -309,7 +319,7 @@
<!-- Demo 3: PluralisticDeliberationOrchestrator -->
<div class="border border-gray-300 rounded-lg">
<div class="accordion-button bg-gradient-to-r from-purple-50 to-pink-50 p-5 flex justify-between items-center" data-accordion="demo-deliberation">
<button type="button" class="accordion-button bg-gradient-to-r from-purple-50 to-pink-50 p-5 flex justify-between items-center" data-accordion="demo-deliberation" aria-expanded="false" aria-controls="demo-deliberation-content" id="demo-deliberation-button">
<div>
<h3 class="font-semibold text-gray-900" data-i18n="sections.governance_capabilities.pluralistic_deliberation_title">Pluralistic Deliberation: Values Conflict Resolution</h3>
<p class="text-sm text-gray-600 mt-1" data-i18n="sections.governance_capabilities.pluralistic_deliberation_desc">Multi-stakeholder engagement, non-hierarchical process, moral remainder documentation</p>
@ -318,7 +328,7 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
<div id="demo-deliberation-content" class="accordion-content">
<div id="demo-deliberation-content" class="accordion-content" role="region" aria-labelledby="demo-deliberation-button">
<div class="p-5 border-t border-gray-200">
<div class="space-y-4">
<!-- Abstract conflict scenario -->
@ -416,13 +426,13 @@
</div>
<div class="border border-gray-300 rounded-lg">
<div class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="validation">
<button type="button" class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="validation" aria-expanded="false" aria-controls="validation-content" id="validation-button">
<h3 class="font-semibold text-gray-900" data-i18n="sections.development_status.validation_title">Validated vs. Not Validated</h3>
<svg id="validation-icon" class="accordion-icon w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
<div id="validation-content" class="accordion-content">
<div id="validation-content" class="accordion-content" role="region" aria-labelledby="validation-button">
<div class="p-5 border-t border-gray-200 space-y-4 text-sm text-gray-700">
<div>
<strong class="text-gray-900">Validated:</strong> Framework successfully governs Claude Code in development workflows. User reports order-of-magnitude improvement in productivity for non-technical operators building production systems.
@ -443,13 +453,13 @@
<h2 class="text-2xl font-bold text-gray-900 mb-6" data-i18n="sections.eu_ai_act.heading">EU AI Act Considerations</h2>
<div class="border border-gray-300 rounded-lg">
<div class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="euaiact">
<button type="button" class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="euaiact" aria-expanded="false" aria-controls="euaiact-content" id="euaiact-button">
<h3 class="font-semibold text-gray-900" data-i18n="sections.eu_ai_act.article_14_title">Regulation 2024/1689, Article 14: Human Oversight</h3>
<svg id="euaiact-icon" class="accordion-icon w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
<div id="euaiact-content" class="accordion-content">
<div id="euaiact-content" class="accordion-content" role="region" aria-labelledby="euaiact-button">
<div class="p-5 border-t border-gray-200 prose prose-sm max-w-none text-gray-700">
<p class="mb-4">
The EU AI Act (Regulation 2024/1689) establishes human oversight requirements for high-risk AI systems (Article 14). Organisations must ensure AI systems are "effectively overseen by natural persons" with authority to interrupt or disregard AI outputs.
@ -479,13 +489,13 @@
<h2 class="text-2xl font-bold text-gray-900 mb-6" data-i18n="sections.research_foundations.heading">Research Foundations</h2>
<div class="border border-gray-300 rounded-lg">
<div class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="research">
<button type="button" class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="research" aria-expanded="false" aria-controls="research-content" id="research-button">
<h3 class="font-semibold text-gray-900" data-i18n="sections.research_foundations.org_theory_title">Organisational Theory & Philosophical Basis</h3>
<svg id="research-icon" class="accordion-icon w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
<div id="research-content" class="accordion-content">
<div id="research-content" class="accordion-content" role="region" aria-labelledby="research-button">
<div class="p-5 border-t border-gray-200 text-sm text-gray-700 space-y-3">
<p>
Tractatus draws on 40+ years of organisational theory research: time-based organisation (Bluedorn, Ancona), knowledge orchestration (Crossan), post-bureaucratic authority (Laloux), structural inertia (Hannan & Freeman).
@ -529,13 +539,13 @@
<h2 class="text-2xl font-bold text-gray-900 mb-6" data-i18n="sections.scope_limitations.heading">Scope & Limitations</h2>
<div class="border border-gray-300 rounded-lg">
<div class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="scope">
<button type="button" class="accordion-button bg-gray-50 p-5 flex justify-between items-center" data-accordion="scope" aria-expanded="false" aria-controls="scope-content" id="scope-button">
<h3 class="font-semibold text-gray-900" data-i18n="sections.scope_limitations.title">What This Is Not • What It Offers</h3>
<svg id="scope-icon" class="accordion-icon w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
</svg>
</div>
<div id="scope-content" class="accordion-content">
<div id="scope-content" class="accordion-content" role="region" aria-labelledby="scope-button">
<div class="p-5 border-t border-gray-200 space-y-4 text-sm text-gray-700">
<div>
<strong class="text-gray-900" data-i18n="sections.scope_limitations.not_title">Tractatus is not:</strong>
@ -595,20 +605,20 @@
<!-- Footer -->
<!-- Internationalization (must load first for footer translations) -->
<script src="/js/i18n-simple.js?v=1761130172"></script>
<script src="/js/components/language-selector.js?v=1760818106"></script>
<script src="/js/i18n-simple.js?v=1761131829"></script>
<script src="/js/components/language-selector.js?v=1761131829"></script>
<!-- Scroll Animations (Phase 3) -->
<script src="/js/scroll-animations.js"></script>
<script src="/js/scroll-animations.js?v=1761131829"></script>
<!-- Page Transitions (Phase 3) -->
<script src="/js/page-transitions.js"></script>
<script src="/js/page-transitions.js?v=1761131829"></script>
<!-- Version Management & PWA -->
<script src="/js/version-manager.js?v=0.1.0.1760680958072"></script>
<script src="/js/leader-page.js?v=0.1.0.1760680958072"></script>
<script src="/js/version-manager.js?v=1761131829"></script>
<script src="/js/leader-page.js?v=1761131829"></script>
<!-- Footer Component -->
<script src="/js/components/footer.js?v=1761129862"></script>
<script src="/js/components/footer.js?v=1761131829"></script>
</body>
</html>

View file

@ -1,13 +1,13 @@
{
"version": "1.4.0",
"buildDate": "2025-10-23T00:04:00Z",
"version": "1.5.0",
"buildDate": "2025-10-23T00:17:00Z",
"changelog": [
"Implementer page: Full WCAG accessibility, diagrams from public repo, mobile optimization",
"Added diagrams: architecture-main-flow.svg, trigger-decision-tree.svg (6.6KB each)",
"Fixed skip link: Added id='main-content' to main element",
"Improved touch targets: 44px minimum on all interactive elements",
"Enhanced code blocks: ARIA labels, better mobile scrolling, 11px font on mobile",
"Previous: Footer i18n deep merge fix, Researcher page Berlin/Weil foundations"
"Leader page: Full WCAG accessibility, 9 accordions with proper ARIA, keyboard navigation",
"Converted accordion divs to semantic <button> elements with aria-expanded, aria-controls",
"Added keyboard support: Enter and Space keys toggle accordions",
"Mobile optimization: 44px/48px touch targets, touch-action: manipulation",
"Accordion content panels: role='region' and aria-labelledby for screen readers",
"Previous: Implementer diagrams, Researcher Berlin/Weil, Footer i18n deep merge"
],
"forceUpdate": true,
"minVersion": "1.1.5"