diff options
| author | Danilo M. <danix@danix.xyz> | 2026-04-29 16:05:31 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-04-29 16:05:31 +0200 |
| commit | 9f74b1a1b6b4dfdfaa3d4aecbf3bbc5215390f14 (patch) | |
| tree | 7719b014ab6798a4a95a00ea138e7ec839236e60 /docs/superpowers/specs | |
| parent | b25628ab7b04eff4fbd9065c8dfacbc8ee27cb10 (diff) | |
| download | danixxyz-9f74b1a1b6b4dfdfaa3d4aecbf3bbc5215390f14.tar.gz danixxyz-9f74b1a1b6b4dfdfaa3d4aecbf3bbc5215390f14.zip | |
docs: add callout spec/plan, actions shortcode in bash-notes, fix IT trailing newline
- docs/superpowers/specs/2026-04-29-callout-shortcode-design.md — approved design spec
- docs/superpowers/plans/2026-04-29-callout-shortcode.md — implementation plan
- content/en/articles/bash-notes: add actions download button
- content/it/articles/bash-notes: fix missing trailing newline
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'docs/superpowers/specs')
| -rw-r--r-- | docs/superpowers/specs/2026-04-29-callout-shortcode-design.md | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-04-29-callout-shortcode-design.md b/docs/superpowers/specs/2026-04-29-callout-shortcode-design.md new file mode 100644 index 0000000..e9c6a3d --- /dev/null +++ b/docs/superpowers/specs/2026-04-29-callout-shortcode-design.md @@ -0,0 +1,225 @@ +# Callout Shortcode — Design Spec + +**Date:** 2026-04-29 +**Status:** Approved + +--- + +## Context + +Articles on danix.xyz need a way to call out notes, tips, warnings, and other semantic asides inline. No callout shortcode exists yet. SHORTCODES.md lists it as a planned future shortcode. This spec defines the design, CSS architecture, A11y requirements, and shortcode API. + +--- + +## Approach + +**Single shortcode + CSS-only variants** (Approach C from brainstorm). + +One `callout.html` template handles all 6 types. Type-specific styling lives entirely in `main.css` via CSS custom properties and Tailwind utility classes. No inline style logic in the template. CSS rebuild required after adding new types. + +Chosen over: +- Single shortcode with inline Hugo logic (more template complexity) +- Separate shortcode per type (6 files, duplicated logic) + +--- + +## Shortcode API + +``` +{{< callout type="note" >}} +Content here. Supports **markdown**. +{{< /callout >}} + +{{< callout type="danger" title="Custom heading" >}} +Overrides the default i18n title. +{{< /callout >}} +``` + +### Parameters + +| Parameter | Required | Default | Description | +|-----------|----------|---------|-------------| +| `type` | Yes | — | One of: `note`, `tip`, `info`, `warning`, `danger`, `success` | +| `title` | No | i18n key for type | Overrides the default translated title | + +--- + +## Visual Design + +**Layout:** Left border accent (4px solid, type color) + fading bottom border (gradient left→transparent, 50% width, 1px, type color). Subtle background tint. Rounded on right side only (`border-radius: 0 6px 6px 0`). + +**Title row:** Feather icon (14×14, `aria-hidden="true"`) + uppercase label in `font-family: var(--font-mono)` (JetBrains Mono), 11px, 0.08em letter-spacing, type color. + +**Body text:** `var(--text)`, 14px, 1.6 line-height. Supports markdown via `.Inner | markdownify`. + +**Spacing:** `my-6` vertical margin, `py-3 px-4` inner padding. + +**Background opacity:** dark 0.08, light 0.06 — consistent with existing toast/badge pattern. + +--- + +## Color System + +All colors via CSS custom properties. No hardcoded hex except the approved Danger exception. + +### CSS Variables (added to `main.css`) + +```css +/* Dark mode (:root) */ +--callout-note: var(--accent); /* purple #a855f7 */ +--callout-tip: var(--accent2); /* green #00ff88 */ +--callout-info: var(--type-link); /* cyan #38bdf8 */ +--callout-warning: var(--type-life); /* amber #f59e0b */ +--callout-danger: #ef4444; /* red — approved exception, universally semantic */ +--callout-success: var(--accent2); /* green #00ff88 */ + +/* Light mode (html.theme-light) */ +--callout-note: var(--accent); /* purple #7c3aed */ +--callout-tip: var(--accent2); /* green #008f5a */ +--callout-info: var(--type-link); /* cyan #0284c7 */ +--callout-warning: var(--type-life); /* amber #d97706 */ +--callout-danger: #ef4444; /* red — same in both themes */ +--callout-success: var(--accent2); /* green #008f5a */ +``` + +### Tailwind Classes (added to `main.css` via `@apply`) + +```css +.callout { @apply relative my-6 py-3 px-4 rounded-r-md; } + +/* Each type sets --callout-color so ::after gradient picks it up automatically */ +.callout-note { --callout-color: var(--callout-note); border-left: 4px solid var(--callout-note); background: rgba(168,85,247,0.08); } +.callout-tip { --callout-color: var(--callout-tip); border-left: 4px solid var(--callout-tip); background: rgba(0,255,136,0.08); } +.callout-info { --callout-color: var(--callout-info); border-left: 4px solid var(--callout-info); background: rgba(56,189,248,0.08); } +.callout-warning { --callout-color: var(--callout-warning); border-left: 4px solid var(--callout-warning); background: rgba(245,158,11,0.08); } +.callout-danger { --callout-color: var(--callout-danger); border-left: 4px solid var(--callout-danger); background: rgba(239,68,68,0.08); } +.callout-success { --callout-color: var(--callout-success); border-left: 4px solid var(--callout-success); background: rgba(0,255,136,0.08); } +``` + +The fading bottom border is a `::after` pseudo-element: +```css +.callout::after { + content: ''; + position: absolute; + bottom: 0; left: 0; + width: 50%; height: 1px; + background: linear-gradient(to right, var(--callout-color), transparent); +} +``` + +**Light mode background opacity** — reduce to 0.06 per theming standard (light needs less emphasis). +rgba values use THEMING-STANDARD.md corrected light vars: `--accent #7c3aed`, `--accent2 #008f5a`, `--type-link #0284c7`, `--type-life #d97706`. + +**Prerequisite:** `html.theme-light` in `main.css` must first be corrected to match THEMING-STANDARD.md (see implementation plan Task 0). + +```css +html.theme-light .callout-note { background: rgba(124,58,237,0.06); } /* #7c3aed */ +html.theme-light .callout-tip { background: rgba(0,143,90,0.06); } /* #008f5a */ +html.theme-light .callout-info { background: rgba(2,132,199,0.06); } /* #0284c7 */ +html.theme-light .callout-warning { background: rgba(217,119,6,0.06); } /* #d97706 */ +html.theme-light .callout-danger { background: rgba(239,68,68,0.06); } /* #ef4444 */ +html.theme-light .callout-success { background: rgba(0,143,90,0.06); } /* #008f5a */ +``` + +--- + +## Feather Icons per Type + +| Type | Feather icon name | Rationale | +|------|-------------------|-----------| +| note | `edit-2` | Writing/annotation | +| tip | `zap` | Quick insight | +| info | `info` | Standard info | +| warning | `alert-triangle` | Universal warning symbol | +| danger | `x-circle` | Stop/error | +| success | `check-circle` | Confirmed/done | + +Icons rendered inline as `<i data-feather="icon-name" class="w-3.5 h-3.5" aria-hidden="true"></i>`. Feather is already loaded site-wide via `baseof.html`. + +--- + +## i18n Keys + +Added to all 4 i18n files: `themes/danix-xyz-hacker/i18n/en.yaml`, `it.yaml` and content repo `i18n/en.yaml`, `it.yaml`. + +```yaml +# en.yaml +callout_note: "Note" +callout_tip: "Tip" +callout_info: "Info" +callout_warning: "Warning" +callout_danger: "Danger" +callout_success: "Success" + +# it.yaml +callout_note: "Nota" +callout_tip: "Suggerimento" +callout_info: "Informazione" +callout_warning: "Attenzione" +callout_danger: "Pericolo" +callout_success: "Successo" +``` + +--- + +## Accessibility + +- `role="note"` on all types — semantic, non-intrusive to screen readers +- `role="alert"` on `danger` type only — interrupts screen readers immediately (appropriate for critical warnings) +- `aria-hidden="true"` on all Feather icons — decorative +- Title text always present (i18n fallback) — color never used alone to convey meaning (WCAG 1.4.1) +- Body text uses `var(--text)` — verified ≥4.5:1 contrast ratio against `var(--bg)` in both themes per THEMING-STANDARD.md +- No animations — `prefers-reduced-motion` not required, but `::after` pseudo is static CSS, no transitions added + +--- + +## Files to Create / Modify + +| File | Action | Notes | +|------|--------|-------| +| `themes/danix-xyz-hacker/layouts/shortcodes/callout.html` | **Create** | Shortcode template | +| `themes/danix-xyz-hacker/assets/css/main.css` | **Modify** | Add `--callout-*` vars + `.callout-*` classes | +| `themes/danix-xyz-hacker/i18n/en.yaml` | **Modify** | Add 6 callout title keys | +| `themes/danix-xyz-hacker/i18n/it.yaml` | **Modify** | Add 6 callout title keys (Italian) | +| `i18n/en.yaml` | **Modify** | Mirror keys in content repo | +| `i18n/it.yaml` | **Modify** | Mirror keys in content repo | +| `SHORTCODES.md` | **Modify** | Document callout shortcode | + +CSS rebuild required (`npm run build`) after CSS changes. + +--- + +## Shortcode Template Sketch + +```html +{{- $type := .Get "type" | default "note" -}} +{{- $title := .Get "title" | default (i18n (printf "callout_%s" $type)) -}} +{{- $role := cond (eq $type "danger") "alert" "note" -}} + +<div class="callout callout-{{ $type }}" role="{{ $role }}"> + <div class="callout-title"> + <i data-feather="{{ /* icon per type */ }}" class="w-3.5 h-3.5" aria-hidden="true"></i> + <span>{{ $title }}</span> + </div> + <div class="callout-body"> + {{ .Inner | markdownify }} + </div> +</div> +``` + +Icon selection via Hugo `dict` lookup — no if/else chain: +``` +{{- $icons := dict "note" "edit-2" "tip" "zap" "info" "info" "warning" "alert-triangle" "danger" "x-circle" "success" "check-circle" -}} +{{- $icon := index $icons $type | default "info" -}} +``` + +--- + +## Verification + +1. Run `hugo server` — render an article with all 6 callout types +2. Toggle dark/light theme — verify colors switch correctly via CSS vars +3. Override title with `title="Custom"` — verify it replaces i18n default +4. Screen reader test: `danger` type must announce immediately (`role="alert"`); others must not interrupt +5. Run `npm run build` — verify CSS compiles without errors and Tailwind includes all `.callout-*` classes +6. Check light theme backgrounds use lower opacity (0.06) vs dark (0.08) |
