diff options
| author | Danilo M. <danix@danix.xyz> | 2026-04-21 23:27:45 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-04-21 23:27:45 +0200 |
| commit | a4edc5815170134875f19c23c028ebf88e971bba (patch) | |
| tree | c210159bdfb339a108821a8737f6464dbcce6392 /docs/superpowers | |
| parent | 3d8c3aa5a6ffc306758e3d7347f96d7bfbe9dc76 (diff) | |
| download | danixxyz-a4edc5815170134875f19c23c028ebf88e971bba.tar.gz danixxyz-a4edc5815170134875f19c23c028ebf88e971bba.zip | |
docs: add tag cloud spiral layout design spec
Diffstat (limited to 'docs/superpowers')
| -rw-r--r-- | docs/superpowers/specs/2026-04-21-tag-cloud-spiral-design.md | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-04-21-tag-cloud-spiral-design.md b/docs/superpowers/specs/2026-04-21-tag-cloud-spiral-design.md new file mode 100644 index 0000000..3d840c9 --- /dev/null +++ b/docs/superpowers/specs/2026-04-21-tag-cloud-spiral-design.md @@ -0,0 +1,79 @@ +# Tag Cloud: Archimedean Spiral Layout + +## Context + +The existing tag cloud partial uses centered flex-wrap with continuous font scaling (weight → size/opacity). Tags appear as a flat weighted list. The goal is a visually striking cloud: big tags centered, smaller tags scattered organically around the outside — deterministic per tag, not random per load. + +## Approach: Archimedean Spiral + CSS Fallback + +Two layers: +- **Hugo partial** (existing) renders tags in DOM with added `data-weight` attribute +- **Vanilla JS module** reads weights, sorts tags, places them via Archimedean spiral + +CSS fallback (no JS / narrow viewport): existing centered flex layout unchanged. + +## Components + +### 1. `tag-cloud.html` partial (modify) + +- Add `data-weight="{{ $ratio }}"` to each `.tag-cloud-link` element +- Add `data-tag-cloud` attribute to the `.tag-cloud` container div +- No other changes to markup or existing CSS classes + +### 2. `assets/js/tag-cloud-spiral.js` (new, ~60 lines) + +**Algorithm:** +1. Find all `[data-tag-cloud]` containers on page +2. For each container: collect tags, sort descending by `data-weight` +3. Per tag: derive deterministic angle seed from tag text hash +4. Place along Archimedean spiral `r = a * θ` stepping `θ` until AABB collision-free +5. Set container `position: relative`, tags `position: absolute` with computed `left/top` +6. Set container explicit height = bounding box of all placed tags + 2rem padding +7. Remove flex layout class from container after placement + +**Determinism:** simple string hash (sum of charCodes) → starting `θ` offset. Same tag text always seeds same angle. + +**Collision detection:** AABB check against array of already-placed rects. O(n²) — fine for ≤50 tags. + +**Responsive guard:** if container `offsetWidth < 400px`, skip spiral entirely, leave flex layout intact. + +### 3. Script loading + +Inline `<script>` at bottom of `tag-cloud.html` partial using Hugo Pipes: +``` +{{ $js := resources.Get "js/tag-cloud-spiral.js" | minify }} +<script src="{{ $js.RelPermalink }}"></script> +``` +Or inline if small enough. Loaded only when partial is rendered. + +## A11y Compliance (WCAG 2.1 AA) + +- **DOM order** = weight order (biggest first) — logical reading sequence +- **Tab order** = DOM order — keyboard navigation follows prominence, acceptable +- **No animation** — `prefers-reduced-motion` not affected +- **Container:** `overflow: visible` to prevent clipping at zoom levels +- **Existing** `aria-label` on links preserved unchanged + +## CSS Changes + +- Container: add `overflow: visible` and `min-height` guard (set by JS, not CSS) +- No color/spacing changes — theming via CSS variables unaffected + +## Fallback Behavior + +| Condition | Behavior | +|-----------|----------| +| JS disabled | Centered flex wrap (current layout) | +| Container < 400px | Centered flex wrap (JS skips spiral) | +| JS enabled, container ≥ 400px | Archimedean spiral | + +## Verification + +1. `npm run build` — CSS compiles clean +2. `hugo serve` — tag cloud renders on homepage, sidebar, 404 +3. JS enabled wide viewport: spiral layout, big tags centered +4. JS enabled narrow viewport (< 400px): flex fallback +5. JS disabled (devtools): flex fallback +6. Keyboard Tab through tags: logical order, all focusable +7. Dark/light mode toggle: colors correct (CSS vars) +8. Screen reader (or axe DevTools): no new violations |
