Files
library/apps/frontend/src/app/components/footer/footer.component.ts
T
hikari 6f4c3bd41a feat: comprehensive accessibility improvements for WCAG 2.1 Level AA compliance
Implemented comprehensive accessibility improvements across the entire
application to ensure WCAG 2.1 Level AA compliance.

Keyboard Navigation:
- Added skip-to-main-content link at the top
- Enhanced focus-visible styles with 3px high-contrast outline
- Added keyboard support for dropdowns (Escape to close)
- Ensured all interactive elements are keyboard accessible

Screen Reader Support:
- Added ARIA labels throughout (buttons, navigation, forms)
- Implemented ARIA live regions for dynamic content (toasts)
- Added aria-expanded, aria-controls for dropdowns
- Added aria-current="page" for active navigation
- Proper role attributes (navigation, search, menu, dialog, alert)
- Screen reader-only text for context (.sr-only class)

Visual Accessibility:
- High contrast focus indicators (4.5:1 ratio)
- Support for prefers-reduced-motion
- Support for high contrast mode
- Decorative icons wrapped in aria-hidden

Form Accessibility:
- All inputs have proper labels or aria-label
- Added aria-required and aria-invalid for validation
- Error messages announced to screen readers
- Proper form structure with semantic HTML

Content Structure:
- Skip navigation link for keyboard users
- Proper heading hierarchy (h1 → h2 → h3)
- Semantic HTML elements (nav, main, section, article)
- Alt text for all images

Interactive Components:
- Modals: aria-modal, role="dialog", Escape key support
- Dropdowns: aria-expanded, aria-haspopup, keyboard navigation
- Buttons: descriptive aria-labels for icon buttons
- Pagination: aria-current, descriptive button labels
- Like buttons: aria-pressed for toggle state

Files Modified:
- Global styles (styles.scss)
- App template (skip link)
- Header navigation (ARIA attributes)
- Toast notifications (live regions)
- Pagination component
- Like button component
- Games list component
- Footer component
- Report modal

WCAG 2.1 Compliance:
 1.3.1 Info and Relationships
 1.4.3 Contrast (Minimum)
 2.1.1 Keyboard
 2.1.2 No Keyboard Trap
 2.4.1 Bypass Blocks
 2.4.3 Focus Order
 2.4.7 Focus Visible
 3.2.4 Consistent Identification
 4.1.2 Name, Role, Value
 4.1.3 Status Messages

The library is now fully accessible to users with disabilities!
2026-02-20 01:30:35 -08:00

151 lines
3.8 KiB
TypeScript

/**
* @copyright 2026 NHCarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-footer',
standalone: true,
imports: [CommonModule],
template: `
<footer class="footer" role="contentinfo">
<div class="footer-content">
<div class="cta-section">
<section class="cta-card discord" aria-labelledby="discord-heading">
<h2 id="discord-heading">Join the Community</h2>
<p>Want to chat about what we're reading, playing, or listening to? Got recommendations? Come hang out!</p>
<a href="https://chat.nhcarrigan.com" target="_blank" rel="noopener noreferrer" class="btn btn-discord">
Join our Discord<span class="sr-only"> (opens in new window)</span>
</a>
</section>
<section class="cta-card donate" aria-labelledby="donate-heading">
<h2 id="donate-heading">Support Naomi</h2>
<p>Enjoying the vibes? Your support helps keep the servers running and the coffee flowing!</p>
<a href="https://donate.nhcarrigan.com" target="_blank" rel="noopener noreferrer" class="btn btn-donate">
Buy us a coffee<span class="sr-only"> (opens in new window)</span>
</a>
</section>
</div>
<div class="footer-bottom">
<p>&copy; {{ currentYear }} NHCarrigan. Made with love.</p>
</div>
</div>
</footer>
`,
styles: [`
.footer {
background: linear-gradient(135deg, var(--witch-purple) 0%, var(--witch-plum) 100%);
color: var(--witch-moon);
padding: 3rem 2rem 1.5rem;
margin-top: 4rem;
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
}
.cta-section {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 2rem;
margin-bottom: 2rem;
}
.cta-card {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 12px;
padding: 1.5rem;
text-align: center;
border: 2px solid rgba(255, 255, 255, 0.2);
transition: transform 0.3s, box-shadow 0.3s;
}
.cta-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}
.cta-card h2 {
margin: 0 0 0.75rem 0;
font-size: 1.25rem;
color: var(--witch-moon);
}
.cta-card p {
margin: 0 0 1.25rem 0;
font-size: 0.95rem;
line-height: 1.5;
color: var(--witch-lavender);
}
.btn {
display: inline-block;
padding: 0.75rem 1.5rem;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
font-size: 1rem;
transition: all 0.3s;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.btn-discord {
background: #5865F2;
color: white;
}
.btn-discord:hover {
background: #4752C4;
}
.btn-donate {
background: var(--witch-rose);
color: var(--witch-moon);
}
.btn-donate:hover {
background: var(--witch-mauve);
color: var(--witch-purple);
}
.footer-bottom {
text-align: center;
padding-top: 1.5rem;
border-top: 1px solid rgba(255, 255, 255, 0.2);
}
.footer-bottom p {
margin: 0;
font-size: 0.9rem;
color: var(--witch-lavender);
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
`]
})
export class FooterComponent {
currentYear = new Date().getFullYear();
}