docs: add ACCESSIBILITY_AUDIT, SECURITY_PRIVACY_AUDIT, PRODUCT_BRIEF with file-specific actions; a11y: add skip link, lang+hreflang, ARIA for menu/carousel/dialog/form; noValidate+honeypot
This commit is contained in:
@@ -1,26 +1,34 @@
|
||||
---
|
||||
// src/layouts/BaseLayout.astro
|
||||
import '../styles/global.css';
|
||||
import '../styles/main.css';
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
description?: string;
|
||||
lang?: string;
|
||||
}
|
||||
|
||||
const { title = "Omoluabi Association Netherlands", description = "Preserving Nigerian culture and heritage in the Netherlands" } = Astro.props;
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang={Astro.props.lang ?? 'en'}>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="alternate" hreflang="en" href="/en/" />
|
||||
<link rel="alternate" hreflang="nl" href="/nl/" />
|
||||
<link rel="alternate" hreflang="x-default" href="/" />
|
||||
</head>
|
||||
|
||||
<body class="bg-gray-50">
|
||||
<a href="#main" class="sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-50 focus:bg-white focus:text-black focus:px-3 focus:py-2 focus:rounded">
|
||||
Skip to main content
|
||||
</a>
|
||||
<!-- Navigation Header -->
|
||||
<header class="bg-white shadow-sm sticky top-0 z-50">
|
||||
<nav class="container mx-auto px-4 py-4">
|
||||
@@ -58,7 +66,7 @@ const { title = "Omoluabi Association Netherlands", description = "Preserving Ni
|
||||
</div>
|
||||
|
||||
<!-- Mobile menu button -->
|
||||
<button class="md:hidden" id="mobile-menu-button">
|
||||
<button class="md:hidden" id="mobile-menu-button" aria-controls="mobile-menu" aria-expanded="false">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
|
||||
</svg>
|
||||
@@ -85,7 +93,7 @@ const { title = "Omoluabi Association Netherlands", description = "Preserving Ni
|
||||
</header>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main>
|
||||
<main id="main" tabindex="-1">
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
@@ -136,34 +144,22 @@ const { title = "Omoluabi Association Netherlands", description = "Preserving Ni
|
||||
|
||||
<!-- Scripts -->
|
||||
<script>
|
||||
// Mobile menu toggle
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const mobileMenuButton = document.getElementById('mobile-menu-button');
|
||||
const mobileMenu = document.getElementById('mobile-menu');
|
||||
|
||||
if (mobileMenuButton && mobileMenu) {
|
||||
mobileMenuButton.addEventListener('click', () => {
|
||||
mobileMenu.classList.toggle('hidden');
|
||||
const isHidden = mobileMenu.classList.toggle('hidden');
|
||||
mobileMenuButton.setAttribute('aria-expanded', String(!isHidden));
|
||||
});
|
||||
}
|
||||
|
||||
// Intersection Observer for scroll animations
|
||||
const observerOptions = {
|
||||
threshold: 0.1,
|
||||
rootMargin: '0px 0px -50px 0px'
|
||||
};
|
||||
|
||||
const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' };
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('visible');
|
||||
}
|
||||
});
|
||||
entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('visible'); } });
|
||||
}, observerOptions);
|
||||
|
||||
// Observe all elements with animation attributes
|
||||
const animatedElements = document.querySelectorAll('[data-animate-on-scroll]');
|
||||
animatedElements.forEach(el => observer.observe(el));
|
||||
document.querySelectorAll('[data-animate-on-scroll]').forEach(el => observer.observe(el));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
Reference in New Issue
Block a user