summaryrefslogtreecommitdiffstats
path: root/themes/danix-xyz-hacker/layouts/partials
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-04-21 22:56:01 +0200
committerDanilo M. <danix@danix.xyz>2026-04-21 22:56:01 +0200
commit88d46796cb84e81e1c502ccdf02ea22890e511d5 (patch)
tree251a9b99f9d0a8cd8361e1216566954981cb7b08 /themes/danix-xyz-hacker/layouts/partials
parent2236d07a5247cab38e0e6b524bdfb26c12c143a8 (diff)
downloaddanixxyz-88d46796cb84e81e1c502ccdf02ea22890e511d5.tar.gz
danixxyz-88d46796cb84e81e1c502ccdf02ea22890e511d5.zip
feat: Add reusable tag cloud partial with A11y and dark/light mode support
- Create tag-cloud.html partial with flexible dict interface: * showCount (bool): Toggle count badges * wrapInWidget (bool): Sidebar widget wrapper with .sidebar-widget class * maxTags (int): Limit shown tags (used for sidebar: 15 max) * headingLevel (h2|h3): Configurable heading element - Implement visual tier scaling by frequency (3 tiers): * low: 0.75rem, 0.75 opacity — uncommon tags * medium: 0.875rem, 0.88 opacity — moderate frequency * high: 1rem, 1 opacity, accent border — popular tags - Add .tag-cloud and .tag-tier-* CSS classes (main.css): * Uses CSS variables (--accent, --border, --text-dim) for dark/light compatibility * Focus ring matches site standard (outline-offset: 2px) * Hover state: accent border + subtle bg tint * prefers-reduced-motion: transitions disabled - Integrate in 3 locations: * Homepage (layouts/index.html): Full cloud with counts * Article sidebar (layouts/partials/sidebar.html): Compact widget, 15 max, no counts * 404 pages (404.en.html, 404.it.html): Full cloud between recent articles and nav - A11y implementation: * <section aria-labelledby> landmark (non-sidebar mode) * <nav aria-label="Browse by topic"> named navigation * Each link aria-label includes count text even when visual badge hidden * <span aria-hidden="true"> on count badge to avoid duplication * Proper heading hierarchy (h2 homepage, h3 on 404) - Add i18n keys (en.yaml, it.yaml): * tagCloud: "Explore Topics" / "Esplora gli argomenti" * exploreTopics: "Browse by topic" / "Sfoglia per argomento" - URL handling: Use .Page.RelPermalink from OrderedTaxonomyEntry — no manual /tags/ construction, language-aware paths work automatically Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Diffstat (limited to 'themes/danix-xyz-hacker/layouts/partials')
-rw-r--r--themes/danix-xyz-hacker/layouts/partials/sidebar.html5
-rw-r--r--themes/danix-xyz-hacker/layouts/partials/tag-cloud.html85
2 files changed, 90 insertions, 0 deletions
diff --git a/themes/danix-xyz-hacker/layouts/partials/sidebar.html b/themes/danix-xyz-hacker/layouts/partials/sidebar.html
index dc263e6..a2225f1 100644
--- a/themes/danix-xyz-hacker/layouts/partials/sidebar.html
+++ b/themes/danix-xyz-hacker/layouts/partials/sidebar.html
@@ -46,4 +46,9 @@
{{ end }}
</div>
{{ end }}
+
+ <hr class="sidebar-hr">
+
+ <!-- Tag Cloud Widget -->
+ {{ partial "tag-cloud.html" (dict "page" . "showCount" false "wrapInWidget" true "maxTags" 15) }}
</aside>
diff --git a/themes/danix-xyz-hacker/layouts/partials/tag-cloud.html b/themes/danix-xyz-hacker/layouts/partials/tag-cloud.html
new file mode 100644
index 0000000..0d59e3c
--- /dev/null
+++ b/themes/danix-xyz-hacker/layouts/partials/tag-cloud.html
@@ -0,0 +1,85 @@
+{{/* tag-cloud.html
+ Reusable tag cloud partial for homepage, sidebar, and 404 pages.
+
+ Params (dict):
+ page Page required — calling page context (provides .Site.Taxonomies.tags, .Lang)
+ showCount bool optional — show post count per tag (default true)
+ heading string optional — heading text override (default: i18n "tagCloud")
+ headingLevel string optional — h2|h3|p for non-widget mode (default "h2")
+ wrapInWidget bool optional — wrap in .sidebar-widget for sidebar placement (default false)
+ maxTags int optional — max tags to show, 0 = all (default 0)
+*/}}
+
+{{- $page := .page -}}
+{{- $showCount := .showCount | default true -}}
+{{- $heading := .heading | default (i18n "tagCloud") -}}
+{{- $headingLevel := .headingLevel | default "h2" -}}
+{{- $wrapInWidget := .wrapInWidget | default false -}}
+{{- $maxTags := .maxTags | default 0 -}}
+
+{{- $tags := $page.Site.Taxonomies.tags -}}
+
+{{/* Early exit if no tags */}}
+{{- if $tags -}}
+
+{{/* Compute max count for tier thresholds */}}
+{{- $maxCount := 0 -}}
+{{- range $tags -}}
+ {{- if gt .Count $maxCount -}}{{- $maxCount = .Count -}}{{- end -}}
+{{- end -}}
+
+{{/* Tier thresholds (integer division) */}}
+{{- $tierMedThreshold := div $maxCount 3 -}}
+{{- $tierHighThreshold := mul (div $maxCount 3) 2 -}}
+
+{{/* Ordered tag list (descending by count) */}}
+{{- $orderedTags := $tags.ByCount -}}
+{{- if gt $maxTags 0 -}}
+ {{- $orderedTags = first $maxTags $orderedTags -}}
+{{- end -}}
+
+{{/* Render based on placement mode */}}
+{{- if $wrapInWidget -}}
+<div class="sidebar-widget">
+ <p class="sidebar-widget-label"># {{ i18n "tags" }}</p>
+ <nav aria-label="{{ i18n "exploreTopics" }}">
+ <div class="tag-cloud">
+{{- else -}}
+<section aria-labelledby="tag-cloud-heading">
+ <{{ $headingLevel }} id="tag-cloud-heading" class="text-lg font-semibold text-accent mb-4">
+ {{ $heading }}
+ </{{ $headingLevel }}>
+ <nav aria-label="{{ i18n "exploreTopics" }}">
+ <div class="tag-cloud">
+{{- end -}}
+
+ {{- range $orderedTags -}}
+ {{- $count := .Count -}}
+ {{- $tier := "low" -}}
+ {{- if gt $count $tierHighThreshold -}}
+ {{- $tier = "high" -}}
+ {{- else if gt $count $tierMedThreshold -}}
+ {{- $tier = "medium" -}}
+ {{- end -}}
+ <a
+ href="{{ .Page.RelPermalink }}"
+ class="tag-cloud-link tag-tier-{{ $tier }}"
+ aria-label="{{ .Name }}{{- if $showCount }} ({{ i18n "postCount" $count }}){{- end -}}"
+ >
+ {{- .Name -}}
+ {{- if $showCount -}}
+ <span class="tag-cloud-count" aria-hidden="true">{{ $count }}</span>
+ {{- end -}}
+ </a>
+ {{- end -}}
+
+ </div>
+ </nav>
+
+{{- if $wrapInWidget -}}
+</div>
+{{- else -}}
+</section>
+{{- end -}}
+
+{{- end -}}{{/* end if $tags */}}