# Back-to-Top Button Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Add a fixed bottom-right back-to-top button that appears after 33% scroll depth on article/single pages, with slide-up animation, full accessibility, and hacker-theme styling.

**Architecture:** A new `back-to-top.html` partial uses inline Alpine.js `x-data` with `@scroll.window` to track scroll depth; the button is conditionally included in `baseof.html` on `.Kind "page"` pages (same condition as reading progress bar). CSS lives in a new `.back-to-top` component class in `main.css`.

**Tech Stack:** Hugo partials, Alpine.js 3.x (inline x-data), Tailwind CSS (@apply), Feather Icons (chevron-up inlined SVG)

---

## File Map

| Action | File | Responsibility |
|---|---|---|
| Create | `themes/danix-xyz-hacker/layouts/partials/back-to-top.html` | Button markup + Alpine logic |
| Modify | `themes/danix-xyz-hacker/assets/css/main.css` | `.back-to-top` component class |
| Modify | `themes/danix-xyz-hacker/layouts/_default/baseof.html` | Include partial on `.Kind "page"` |
| Modify | `themes/danix-xyz-hacker/i18n/en.yaml` | `back_to_top` key |
| Modify | `themes/danix-xyz-hacker/i18n/it.yaml` | `back_to_top` key (Italian) |

---

### Task 1: Add `.back-to-top` CSS component class

**Files:**
- Modify: `themes/danix-xyz-hacker/assets/css/main.css` (append inside `@layer components`, after `.toast-container`)

- [ ] **Step 1: Open `main.css` and locate the end of `@layer components`**

Find the closing `}` of `@layer components`. It ends around line 1165 (after `.tooltip-text`). Add the new class block just before that closing brace.

- [ ] **Step 2: Add the `.back-to-top` class**

```css
  /* Back to top button */
  .back-to-top {
    @apply fixed bottom-6 right-6 z-40 w-11 h-11 rounded-full flex items-center justify-content-center;
    background: var(--accent);
    box-shadow: 0 0 12px rgba(168, 85, 247, 0.4);
    transition: background 200ms ease, box-shadow 200ms ease;
    color: #fff;
  }
  .back-to-top:hover {
    background: #9333ea;
    box-shadow: 0 0 20px var(--accent);
  }
  .back-to-top:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }
```

- [ ] **Step 3: Rebuild CSS**

```bash
cd /home/danix/Programming/GIT/danix.xyz-hacker-theme && npm run build
```

Expected: exits 0, `themes/danix-xyz-hacker/static/css/main.min.css` updated.

- [ ] **Step 4: Commit**

```bash
git add themes/danix-xyz-hacker/assets/css/main.css themes/danix-xyz-hacker/static/css/main.min.css
git commit -m "style: add .back-to-top component class"
```

---

### Task 2: Create `back-to-top.html` partial

**Files:**
- Create: `themes/danix-xyz-hacker/layouts/partials/back-to-top.html`

- [ ] **Step 1: Create the partial file**

```html
<div
  x-data="{ visible: false }"
  @scroll.window="visible = (window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) >= 0.33"
>
  <button
    x-show="visible"
    x-cloak
    x-transition:enter="transition ease-out duration-300"
    x-transition:enter-start="opacity-0 translate-y-4"
    x-transition:enter-end="opacity-100 translate-y-0"
    x-transition:leave="transition ease-in duration-200"
    x-transition:leave-start="opacity-100 translate-y-0"
    x-transition:leave-end="opacity-0 translate-y-4"
    class="back-to-top"
    aria-label="{{ i18n "back_to_top" | default "Back to top" }}"
    type="button"
    @click="window.scrollTo({ top: 0, behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth' })"
  >
    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
      <polyline points="18 15 12 9 6 15"></polyline>
    </svg>
  </button>
</div>
```

Note: SVG is Feather `chevron-up` inlined to avoid race condition with `feather.replace()` running before Alpine shows the button. `aria-hidden="true"` on the SVG because the button has `aria-label`.

- [ ] **Step 2: Add i18n keys**

In `themes/danix-xyz-hacker/i18n/en.yaml`, add:
```yaml
back_to_top: "Back to top"
```

In `themes/danix-xyz-hacker/i18n/it.yaml`, add:
```yaml
back_to_top: "Torna in cima"
```

- [ ] **Step 3: Commit**

```bash
git add themes/danix-xyz-hacker/layouts/partials/back-to-top.html themes/danix-xyz-hacker/i18n/en.yaml themes/danix-xyz-hacker/i18n/it.yaml
git commit -m "feat: add back-to-top partial with Alpine.js and i18n"
```

---

### Task 3: Include partial in `baseof.html`

**Files:**
- Modify: `themes/danix-xyz-hacker/layouts/_default/baseof.html`

- [ ] **Step 1: Locate the `.Kind "page"` block for reading-progress (lines ~28–34)**

```html
{{ if eq .Kind "page" }}
<div
  id="reading-progress"
  class="fixed top-0 left-0 h-1 transition-all duration-100"
  style="width: 0%; background: linear-gradient(to right, var(--accent), var(--accent2)); z-index: 9999;"
></div>
{{ end }}
```

- [ ] **Step 2: Add the partial include inside the same condition block**

```html
{{ if eq .Kind "page" }}
<div
  id="reading-progress"
  class="fixed top-0 left-0 h-1 transition-all duration-100"
  style="width: 0%; background: linear-gradient(to right, var(--accent), var(--accent2)); z-index: 9999;"
></div>
{{ partial "back-to-top.html" . }}
{{ end }}
```

- [ ] **Step 3: Commit**

```bash
git add themes/danix-xyz-hacker/layouts/_default/baseof.html
git commit -m "feat: include back-to-top button on single pages"
```

---

### Task 4: Verify end-to-end

- [ ] **Step 1: Start Hugo dev server**

```bash
cd /home/danix/Programming/GIT/danix.xyz-hacker-theme && hugo server -D
```

- [ ] **Step 2: Open an article page and scroll past 33%**

Navigate to any article. Confirm the purple circle button slides up from bottom-right.

- [ ] **Step 3: Scroll back above 33%**

Confirm button fades/slides out.

- [ ] **Step 4: Click button**

Confirm smooth scroll to top.

- [ ] **Step 5: Keyboard accessibility**

Tab to the button when visible. Confirm focus ring (purple outline). Press Enter — confirm scroll to top.

- [ ] **Step 6: Reduced motion**

DevTools → Rendering → "Emulate prefers-reduced-motion: reduce". Scroll past 33% — button appears instantly (no animation). Click — page jumps instantly (no smooth scroll).

- [ ] **Step 7: z-index layering**

Confirm button sits below fixed header, search modal, and toast notifications.

- [ ] **Step 8: Non-article pages**

Navigate to home or list page. Confirm no button appears.

- [ ] **Step 9: Final CSS rebuild and commit**

```bash
npm run build
git add themes/danix-xyz-hacker/static/css/main.min.css
git commit -m "build: rebuild CSS for back-to-top button"
```

- [ ] **Step 10: Update TODO.md**

```markdown
- [✅] add back-to-top button
```

```bash
git add TODO.md
git commit -m "chore: mark back-to-top as complete in TODO"
```
