Enhance accessibility and structure across multiple components

- Updated the ContactForm component to include labels and aria-describedby attributes for better accessibility.
- Improved the Button component by conditionally adding aria-labels based on text input.
- Enhanced the Form component with aria-describedby attributes for validation feedback.
- Refactored the Layout component to include semantic HTML5 elements for better structure and accessibility.
- Updated the 404 page metadata for improved SEO and user experience.
This commit is contained in:
2025-06-24 21:05:49 +02:00
parent 0b16ad5a28
commit 3847f415d6
5 changed files with 41 additions and 13 deletions

View File

@@ -1,6 +1,10 @@
<form id="contact-form">
<input type="email" name="email" id="email" required />
<textarea name="message" id="message" required></textarea>
<label for="email">Email</label>
<input type="email" name="email" id="email" required aria-describedby="email-help" />
<div id="email-help" class="sr-only">Enter your email address</div>
<label for="message">Message</label>
<textarea name="message" id="message" required aria-describedby="message-help"></textarea>
<div id="message-help" class="sr-only">Enter your message</div>
<button type="submit">Send</button>
</form>
@@ -10,8 +14,12 @@
If you believe this is a mistake, you can request a manual review.
</p>
<form id="manual-review-form">
<input type="email" id="manual-email" readonly />
<textarea id="manual-justification" placeholder="Why is this not spam? (optional)"></textarea>
<label for="manual-email">Email</label>
<input type="email" id="manual-email" readonly aria-describedby="manual-email-help" />
<div id="manual-email-help" class="sr-only">Re-enter your email address for confirmation</div>
<label for="manual-justification">Why is this not spam? (optional)</label>
<textarea id="manual-justification" placeholder="Why is this not spam? (optional)" aria-describedby="manual-justification-help"></textarea>
<div id="manual-justification-help" class="sr-only">Explain why your message is legitimate</div>
<input type="hidden" id="manual-token" />
<button type="submit">Request Manual Review</button>
</form>

View File

@@ -19,11 +19,13 @@ const variants = {
tertiary: 'btn btn-tertiary',
link: 'cursor-pointer hover:text-primary',
};
const ariaLabel = !text || (typeof text === 'string' && text.trim() === '') ? Astro.props['aria-label'] : undefined;
---
{
type === 'button' || type === 'submit' || type === 'reset' ? (
<button type={type} class={twMerge(variants[variant] || '', className)} {...rest}>
<button type={type} class={twMerge(variants[variant] || '', className)} {...rest} {...(ariaLabel ? { 'aria-label': ariaLabel } : {})}>
<Fragment set:html={text} />
{icon && <Icon name={icon} class="w-5 h-5 ml-1 -mr-1.5 rtl:mr-1 rtl:-ml-1.5 inline-block" />}
</button>
@@ -32,6 +34,7 @@ const variants = {
class={twMerge(variants[variant] || '', className)}
{...(target ? { target: target, rel: 'noopener noreferrer' } : {})}
{...rest}
{...(ariaLabel ? { 'aria-label': ariaLabel } : {})}
>
<Fragment set:html={text} />
{icon && <Icon name={icon} class="w-5 h-5 ml-1 -mr-1.5 rtl:mr-1 rtl:-ml-1.5 inline-block" />}

View File

@@ -59,8 +59,9 @@ const { inputs, textarea, disclaimer, button = 'Contact us', description = '' }
placeholder={placeholder}
class="py-3 px-4 block w-full text-md rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-slate-900"
required={required}
aria-describedby={`invalid-feedback-${name}`}
/>
<div class="invalid-feedback hidden text-red-600 text-sm mt-1" />
<div id={`invalid-feedback-${name}`} class="invalid-feedback hidden text-red-600 text-sm mt-1" />
</div>
)
)
@@ -80,8 +81,9 @@ const { inputs, textarea, disclaimer, button = 'Contact us', description = '' }
placeholder={textarea.placeholder}
class="py-3 px-4 block w-full text-md rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-slate-900"
required
aria-describedby="invalid-feedback-textarea"
/>
<div class="invalid-feedback hidden text-red-600 text-sm mt-1" />
<div id="invalid-feedback-textarea" class="invalid-feedback hidden text-red-600 text-sm mt-1" />
</div>
)
}
@@ -96,6 +98,7 @@ const { inputs, textarea, disclaimer, button = 'Contact us', description = '' }
type="checkbox"
class="cursor-pointer mt-1 py-3 px-4 block w-full text-md rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-slate-900"
required
aria-describedby="invalid-feedback-disclaimer"
/>
</div>
<div class="ml-3">
@@ -103,7 +106,7 @@ const { inputs, textarea, disclaimer, button = 'Contact us', description = '' }
{disclaimer.label}
<span class="text-red-600">*</span>
</label>
<div class="invalid-feedback hidden text-red-600 text-sm mt-1" />
<div id="invalid-feedback-disclaimer" class="invalid-feedback hidden text-red-600 text-sm mt-1" />
</div>
</div>
)

View File

@@ -67,9 +67,19 @@ const { language, textDirection } = I18N;
<body class="antialiased text-default bg-page tracking-tight">
<GlobalBackground />
<header role="banner">
<slot name="header" />
</header>
<nav role="navigation" aria-label="Main navigation">
<slot name="navigation" />
</nav>
<main role="main">
<slot name="structured-data" />
<slot />
</main>
<footer role="contentinfo">
<slot name="footer" />
</footer>
<BasicScripts />
<LanguagePersistence />
<CookieBanner />

View File

@@ -2,7 +2,11 @@
import Layout from '~/layouts/Layout.astro';
import { getHomePermalink } from '~/utils/permalinks';
const title = `Error 404`;
const metadata = {
title: '404 Not Found | 365DevNet',
description: 'Sorry, the page you are looking for does not exist. Return to the homepage or explore other sections of 365DevNet.',
robots: { index: false, follow: false },
};
---
<style>
@@ -382,7 +386,7 @@ const title = `Error 404`;
}
</style>
<Layout metadata={{ title }}>
<Layout metadata={metadata}>
<section class="clean-404-bg">
<div class="floating-elements-404">
<div class="floating-shape-404 shape-404-1"></div>