Files
ragusaitweb/.Jules/palette.md
google-labs-jules[bot] a136c9c236 feat(a11y): add Skip Link component and main content IDs
- Add `SkipLink` component that appears on focus and jumps to main content.
- Update `en.ts` and `de.ts` with "Skip to content" translation.
- Add `id="main-content"`, `tabIndex={-1}`, and `outline: 'none'` to `Home`, `About`, and `Contact` pages to ensure proper focus management.
- Add tests for `SkipLink`.
- Document Skip Link pattern in `.Jules/palette.md`.

This improves accessibility for keyboard and screen reader users by allowing them to bypass navigation.

Co-authored-by: ragusa-it <196988693+ragusa-it@users.noreply.github.com>
2026-02-05 02:00:18 +00:00

16 lines
2.1 KiB
Markdown

## 2024-05-24 - Accessible Input Validation
**Learning:** React 19 renders `aria-invalid={false}` as `aria-invalid="false"`, unlike older versions which might have omitted it. Explicitly handling this in tests is crucial. Also, ensuring DOM cleanup (`cleanup()`) in `afterEach` is vital when testing similar components with same labels across tests to avoid "finding the wrong element" false positives/negatives.
**Action:** Always include `afterEach(() => cleanup())` in `vitest` setup for DOM tests, and expect `aria-invalid="false"` (or explicitly handle `undefined` if omission is desired) when testing valid states in React 19.
## 2024-05-24 - Accessible Loading Buttons
**Learning:** Replacing button text with a spinner destroys the accessible name.
**Action:** Use `aria-busy="true"`, keep children in DOM (visually hidden via opacity/class), and overlay spinner absolutely. Ensure wrapper element replicates flex layout (gap/alignment) to prevent layout shifts.
## 2024-05-24 - Enhancing Inputs Safely
**Learning:** Adding features like character counters to generic input components must handle both controlled and uncontrolled states. Assuming a component is controlled (using `props.value`) can break uncontrolled usage by showing stale data (e.g., sticking at 0/100).
**Action:** When enhancing generic components, detect uncontrolled state (e.g., `props.value === undefined`) and either implement internal state tracking or gracefully degrade (hide the feature) to avoid misleading UX.
## 2025-05-24 - Skip Link Focus Management
**Learning:** For a "Skip to content" link to effectively move focus in an SPA, the target container (e.g., `<main>`) must be programmatically focusable. Simply having an ID is not enough; `tabIndex={-1}` is required. Additionally, standard browser behavior might show a focus ring on the container, which is often undesirable for non-interactive wrappers, so `outline: 'none'` should be applied inline or via CSS.
**Action:** Always add `tabIndex={-1}` and `outline: 'none'` to the target of a Skip Link (`#main-content`) to ensure correct focus behavior without visual clutter.