summaryrefslogtreecommitdiffstats
path: root/docs/superpowers
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-06-26 17:02:57 +0200
committerDanilo M. <danix@danix.xyz>2026-06-26 17:02:57 +0200
commita1d1b8917ba9a74242bddd049d4e6dd2bec4531f (patch)
tree1f485668b1fed8b41db0c079b1f8f40f2b4ea429 /docs/superpowers
parent19e1c80e154739e4b61385301e55aed97c8eb90f (diff)
downloaddanixxyz-a1d1b8917ba9a74242bddd049d4e6dd2bec4531f.tar.gz
danixxyz-a1d1b8917ba9a74242bddd049d4e6dd2bec4531f.zip
docs: fold A11y + design fixes into slackware plan
Theme-aware status vars, focus rings, honest ARIA, h2 hierarchy, aria-hidden glyph, full-contrast pills, sr-only new-tab notice. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'docs/superpowers')
-rw-r--r--docs/superpowers/plans/2026-06-26-slackware-projects-section.md78
1 files changed, 52 insertions, 26 deletions
diff --git a/docs/superpowers/plans/2026-06-26-slackware-projects-section.md b/docs/superpowers/plans/2026-06-26-slackware-projects-section.md
index 8213367..7a1ac79 100644
--- a/docs/superpowers/plans/2026-06-26-slackware-projects-section.md
+++ b/docs/superpowers/plans/2026-06-26-slackware-projects-section.md
@@ -273,11 +273,14 @@ In `header.html`, replace the desktop menu block (the `<div class="hidden md:fle
{{ $isActive := eq $menuPath $currentPath }}
{{ $isExternal := .Params.external }}
{{ if .HasChildren }}
+ {{/* CSS-only hover/focus popup. No ARIA menu roles: we do not
+ implement arrow-key menu semantics, so claiming role="menu"
+ would lie to AT. focus-within gives keyboard reveal; the
+ parent stays a plain navigable link. */}}
<div class="relative group">
<a
href="{{ .URL }}"
- class="text-sm transition-colors inline-flex items-center gap-1 {{ if $isActive }}text-accent font-bold{{ else }}hover:text-accent{{ end }}"
- aria-haspopup="true"
+ class="text-sm transition-colors inline-flex items-center gap-1 rounded focus:outline-none focus:ring-2 focus:ring-accent {{ if $isActive }}text-accent font-bold{{ else }}hover:text-accent{{ end }}"
{{ if $isActive }}aria-current="page"{{ end }}
>
{{ i18n .Name }}
@@ -285,14 +288,13 @@ In `header.html`, replace the desktop menu block (the `<div class="hidden md:fle
</a>
<!-- Submenu: padding-top bridges the hover gap -->
<div class="absolute left-1/2 -translate-x-1/2 top-full pt-3 hidden group-hover:flex group-focus-within:flex">
- <ul class="frosted-bar border border-border rounded-lg px-4 py-3 flex flex-col gap-2 min-w-max shadow-lg" role="menu">
+ <ul class="frosted-bar border border-border rounded-lg px-4 py-3 flex flex-col gap-2 min-w-max shadow-lg">
{{ range .Children }}
{{ $childExternal := .Params.external }}
- <li role="none">
+ <li>
<a
href="{{ .URL }}"
- role="menuitem"
- class="block text-sm whitespace-nowrap hover:text-accent transition-colors"
+ class="block text-sm whitespace-nowrap hover:text-accent transition-colors rounded focus:outline-none focus:ring-2 focus:ring-accent"
{{ if $childExternal }}target="_blank" rel="noopener noreferrer"{{ end }}
>
{{ if $childExternal }}{{ .Name }}{{ else }}{{ i18n .Name }}{{ end }}
@@ -344,13 +346,19 @@ Renders the light-schema header (tagline, status badge, repo link, optional imag
- [ ] **Step 1: Write the partial**
+A11y/house-style note: status colors map to the existing theme-aware
+`--type-*` vars (each ships a matched WCAG-AA `-text` color), archived uses
+`--text-dim` bg with `--bg` text. No literal hex, no theme-breaking. Tag
+links and the repo link get the project's standard focus-ring pattern.
+
`themes/danix-xyz-hacker/layouts/partials/project-header.html`:
```html
{{ $status := .Params.status | default "active" }}
-{{ $statusColor := "var(--color-accent, #a855f7)" }}
-{{ if eq $status "maintained" }}{{ $statusColor = .Site.Params.secondaryAccent }}{{ end }}
-{{ if eq $status "wip" }}{{ $statusColor = "#f59e0b" }}{{ end }}
-{{ if eq $status "archived" }}{{ $statusColor = "#9ca3af" }}{{ end }}
+{{/* status -> theme-aware bg/text var pair (all defined in main.css) */}}
+{{ $bgVar := "--type-tech" }}{{ $txtVar := "--type-tech-text" }}
+{{ if eq $status "maintained" }}{{ $bgVar = "--type-quote" }}{{ $txtVar = "--type-quote-text" }}{{ end }}
+{{ if eq $status "wip" }}{{ $bgVar = "--type-life" }}{{ $txtVar = "--type-life-text" }}{{ end }}
+{{ if eq $status "archived" }}{{ $bgVar = "--text-dim" }}{{ $txtVar = "--bg" }}{{ end }}
{{ $imageURL := "" }}
{{ if .Params.image }}
@@ -365,7 +373,7 @@ Renders the light-schema header (tagline, status badge, repo link, optional imag
<div class="flex flex-wrap items-center gap-3 mb-2">
<h1 class="text-4xl md:text-5xl font-bold text-accent font-oxanium">{{ .Title }}</h1>
- <span class="px-3 py-1 rounded-full text-xs font-semibold" style="background-color: {{ $statusColor }}; color: #0b0b0b;">
+ <span class="px-3 py-1 rounded-full text-xs font-semibold" style="background-color: var({{ $bgVar }}); color: var({{ $txtVar }});">
{{ i18n (printf "status-%s" $status) }}
</span>
</div>
@@ -379,12 +387,13 @@ Renders the light-schema header (tagline, status badge, repo link, optional imag
<a href="{{ . }}" target="_blank" rel="noopener noreferrer" class="btn btn-sm inline-flex items-center gap-2">
{{ i18n "viewRepo" }}
<i data-feather="external-link" class="w-4 h-4" aria-hidden="true"></i>
+ <span class="sr-only">{{ i18n "opensInNewTab" }}</span>
</a>
{{ end }}
{{ with .Params.tags }}
<ul class="flex flex-wrap gap-2">
{{ range . }}
- <li><a href="/tags/{{ . | urlize }}/" class="px-2 py-1 rounded text-xs bg-surface text-text-dim hover:text-accent transition-colors">{{ . }}</a></li>
+ <li><a href="/tags/{{ . | urlize }}/" class="px-2 py-1 rounded text-xs bg-surface text-text hover:text-accent transition-colors focus:outline-none focus:ring-2 focus:ring-accent">{{ . }}</a></li>
{{ end }}
</ul>
{{ end }}
@@ -486,7 +495,7 @@ In `hamburger-menu.html`, replace the `{{ range .Site.Menus.main }}…{{ end }}`
<a
href="{{ .URL }}"
@click="menuOpen = false"
- class="block py-3 text-base text-text-dim hover:text-accent transition-colors"
+ class="block py-3 text-base text-text-dim hover:text-accent transition-colors rounded focus:outline-none focus:ring-2 focus:ring-accent"
{{ if $childExternal }}target="_blank" rel="noopener noreferrer"{{ end }}
>
{{ if $childExternal }}{{ .Name }}{{ else }}{{ i18n .Name }}{{ end }}
@@ -525,16 +534,23 @@ One full-width hub row: option #3 shape (alternating image side), option #2 styl
Receives a dict: `{ "page": <Page>, "index": <int> }`. Even index → image left; odd → image right.
+A11y/house-style note: same theme-aware `--type-*` status mapping as the
+header partial; row heading is `h2` (direct child of the hub `h1`, no skipped
+level); the decorative glyph link is `aria-hidden` (the titled link carries
+the name); tech pills use full-contrast `text-text`; the repo link gets a
+focus ring + sr-only new-tab notice.
+
`themes/danix-xyz-hacker/layouts/partials/project-row.html`:
```html
{{ $p := .page }}
{{ $reverse := eq (mod .index 2) 1 }}
{{ $status := $p.Params.status | default "active" }}
-{{ $statusColor := "var(--color-accent, #a855f7)" }}
-{{ if eq $status "maintained" }}{{ $statusColor = $p.Site.Params.secondaryAccent }}{{ end }}
-{{ if eq $status "wip" }}{{ $statusColor = "#f59e0b" }}{{ end }}
-{{ if eq $status "archived" }}{{ $statusColor = "#9ca3af" }}{{ end }}
+{{/* status -> theme-aware bg/text var pair (all defined in main.css) */}}
+{{ $bgVar := "--type-tech" }}{{ $txtVar := "--type-tech-text" }}
+{{ if eq $status "maintained" }}{{ $bgVar = "--type-quote" }}{{ $txtVar = "--type-quote-text" }}{{ end }}
+{{ if eq $status "wip" }}{{ $bgVar = "--type-life" }}{{ $txtVar = "--type-life-text" }}{{ end }}
+{{ if eq $status "archived" }}{{ $bgVar = "--text-dim" }}{{ $txtVar = "--bg" }}{{ end }}
{{ $imageURL := "" }}
{{ if $p.Params.image }}
@@ -544,10 +560,10 @@ Receives a dict: `{ "page": <Page>, "index": <int> }`. Even index → image left
{{ $glyph := substr (upper $p.Title) 0 2 }}
<article class="group flex flex-col md:flex-row {{ if $reverse }}md:flex-row-reverse{{ end }} gap-6 items-stretch border-l-4 border-accent bg-surface/30 rounded-lg overflow-hidden transition-all duration-200 hover:-translate-y-1 hover:shadow-lg hover:bg-surface/50">
- <!-- Visual -->
- <a href="{{ $p.RelPermalink }}" tabindex="-1" class="md:w-1/3 flex-shrink-0 flex items-center justify-center bg-bg/40 min-h-[10rem]">
+ <!-- Visual (decorative duplicate of the title link; hidden from AT) -->
+ <a href="{{ $p.RelPermalink }}" tabindex="-1" aria-hidden="true" class="md:w-1/3 flex-shrink-0 flex items-center justify-center bg-bg/40 min-h-[10rem]">
{{ if $imageURL }}
- <img src="{{ $imageURL }}" alt="{{ $p.Title }}" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-200" loading="lazy" />
+ <img src="{{ $imageURL }}" alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-200" loading="lazy" />
{{ else }}
<span class="text-5xl font-bold font-oxanium text-accent/80 select-none">{{ $glyph }}</span>
{{ end }}
@@ -556,10 +572,10 @@ Receives a dict: `{ "page": <Page>, "index": <int> }`. Even index → image left
<!-- Body -->
<div class="flex-1 p-6 flex flex-col gap-3">
<div class="flex items-start justify-between gap-3">
- <h3 class="text-2xl font-bold font-oxanium">
- <a href="{{ $p.RelPermalink }}" class="group-hover:text-accent transition-colors">{{ $p.Title }}</a>
- </h3>
- <span class="flex-shrink-0 px-3 py-1 rounded-full text-xs font-semibold" style="background-color: {{ $statusColor }}; color: #0b0b0b;">
+ <h2 class="text-2xl font-bold font-oxanium">
+ <a href="{{ $p.RelPermalink }}" class="group-hover:text-accent transition-colors rounded focus:outline-none focus:ring-2 focus:ring-accent">{{ $p.Title }}</a>
+ </h2>
+ <span class="flex-shrink-0 px-3 py-1 rounded-full text-xs font-semibold" style="background-color: var({{ $bgVar }}); color: var({{ $txtVar }});">
{{ i18n (printf "status-%s" $status) }}
</span>
</div>
@@ -571,7 +587,7 @@ Receives a dict: `{ "page": <Page>, "index": <int> }`. Even index → image left
{{ with $p.Params.tags }}
<ul class="flex flex-wrap gap-2 mt-1">
{{ range . }}
- <li class="px-2 py-1 rounded text-xs bg-bg/60 text-text-dim">{{ . }}</li>
+ <li class="px-2 py-1 rounded text-xs bg-bg/60 text-text">{{ . }}</li>
{{ end }}
</ul>
{{ end }}
@@ -582,9 +598,10 @@ Receives a dict: `{ "page": <Page>, "index": <int> }`. Even index → image left
<i data-feather="arrow-right" class="w-4 h-4" aria-hidden="true"></i>
</a>
{{ with $p.Params.repo_url }}
- <a href="{{ . }}" target="_blank" rel="noopener noreferrer" class="text-sm text-text-dim hover:text-accent inline-flex items-center gap-1 transition-colors">
+ <a href="{{ . }}" target="_blank" rel="noopener noreferrer" class="text-sm text-text-dim hover:text-accent inline-flex items-center gap-1 transition-colors rounded focus:outline-none focus:ring-2 focus:ring-accent">
{{ i18n "viewRepo" }}
<i data-feather="external-link" class="w-3 h-3" aria-hidden="true"></i>
+ <span class="sr-only">{{ i18n "opensInNewTab" }}</span>
</a>
{{ end }}
</div>
@@ -776,3 +793,12 @@ Per CLAUDE.md: `git checkout production && git merge master && git push origin p
- **Type/name consistency:** status color logic and `status-<x>` i18n keys identical in project-header (T5) and project-row (T8); `dict "page" … "index" …` produced in T9 matches `.page`/`.index` consumed in T8; `slackwareTitle`/`slackwareSubtitle`/`viewRepo`/`status-*` defined in T2 and used in T5/T6/T8/T9.
- **Discovered simplification:** menu rename is i18n-value-only (labels render via `i18n .Name`); no `name=` churn needed. Captured in T2.
- **Bonus fix:** T4 corrects a pre-existing desktop-bar bug where external items lacked `target="_blank"` and wrongly ran `i18n .Name`.
+
+### A11y + design review fixes folded in (2026-06-26)
+- **Status badges (T5/T8):** use theme-aware `--type-*` vars with their matched WCAG-AA `-text` colors (active→type-tech, maintained→type-quote, wip→type-life, archived→text-dim/`--bg`). No literal hex, no broken light/dark, no `--color-accent` (doesn't exist).
+- **Tech pills (T5/T8):** `text-text` (full contrast) instead of `text-text-dim` — dim-on-dim 11px failed AA.
+- **Focus rings:** added `focus:outline-none focus:ring-2 focus:ring-accent` to all bare interactive links (desktop submenu T4, mobile children T7, tag links T5, title + repo links T8) matching the project's existing focus pattern.
+- **Honest ARIA (T4):** dropped `role="menu"/menuitem"/aria-haspopup` — CSS-only popup doesn't implement arrow-key menu semantics; `focus-within` provides keyboard reveal on plain links.
+- **Heading hierarchy (T8):** row heading is `h2` (under hub `h1`), no skipped level.
+- **Decorative glyph (T8):** visual link is `aria-hidden="true"` + `tabindex="-1"`, image `alt=""`; the titled `h2` link carries the accessible name (no duplicate/empty link announced).
+- **New-tab notice:** external repo links get `sr-only` "opensInNewTab" (key exists both langs).