From 2ac7405cf43359e1a6fccaec0471f8659a7771b3 Mon Sep 17 00:00:00 2001 From: mi Date: Thu, 13 Nov 2025 10:38:26 +1000 Subject: [PATCH] :lipstick: images for comic nav --- app.py | 5 ++- comics_data.py | 4 ++ static/css/style.css | 42 +++++++++++++++++++++ static/images/icons/first.png | 3 ++ static/images/icons/latest.png | 3 ++ static/images/icons/next.png | 3 ++ static/images/icons/previous.png | 3 ++ static/js/comic-nav.js | 19 ++++++---- templates/comic.html | 64 +++++++++++++++++++++++++------- templates/index.html | 64 +++++++++++++++++++++++++------- 10 files changed, 174 insertions(+), 36 deletions(-) create mode 100644 static/images/icons/first.png create mode 100644 static/images/icons/latest.png create mode 100644 static/images/icons/next.png create mode 100644 static/images/icons/previous.png diff --git a/app.py b/app.py index c1af981..513571c 100644 --- a/app.py +++ b/app.py @@ -1,7 +1,7 @@ import os from datetime import datetime from flask import Flask, render_template, abort, jsonify, request -from comics_data import COMICS, FULL_WIDTH_DEFAULT, PLAIN_DEFAULT, HEADER_IMAGE, FOOTER_IMAGE, COMPACT_FOOTER +from comics_data import COMICS, FULL_WIDTH_DEFAULT, PLAIN_DEFAULT, HEADER_IMAGE, FOOTER_IMAGE, COMPACT_FOOTER, USE_ICON_NAV import markdown app = Flask(__name__) @@ -16,7 +16,8 @@ def inject_global_settings(): return { 'header_image': HEADER_IMAGE, 'footer_image': FOOTER_IMAGE, - 'compact_footer': COMPACT_FOOTER + 'compact_footer': COMPACT_FOOTER, + 'use_icon_nav': USE_ICON_NAV } diff --git a/comics_data.py b/comics_data.py index aeb141b..bf42fb3 100644 --- a/comics_data.py +++ b/comics_data.py @@ -23,6 +23,10 @@ FOOTER_IMAGE = None # 'footer.jpg' # Compact mode: single line, no border, horizontal layout COMPACT_FOOTER = True +# Global setting: Set to True to use icon images for navigation buttons +# Icons should be in static/images/icons/ (first.png, previous.png, next.png, latest.png) +USE_ICON_NAV = True + COMICS = [ { 'number': 1, diff --git a/static/css/style.css b/static/css/style.css index a09ebf9..15f66df 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -360,6 +360,32 @@ main { color: var(--color-disabled); } +/* Icon-based navigation buttons */ +.btn-icon-nav { + display: inline-block; + cursor: pointer; + transition: opacity var(--transition-speed); +} + +.btn-icon-nav img { + height: 2rem; + width: auto; + display: block; +} + +.btn-icon-nav:hover { + opacity: 0.7; +} + +.btn-icon-disabled { + opacity: 0.3; + cursor: not-allowed; +} + +.btn-icon-disabled:hover { + opacity: 0.3; +} + .comic-date-display { padding: 0 var(--space-sm); color: var(--color-text); @@ -469,6 +495,10 @@ main { font-size: var(--font-size-sm); } + .btn-icon-nav img { + height: 1.5rem; + } + .comic-date-display { font-size: var(--font-size-xs); flex-basis: 100%; @@ -476,6 +506,18 @@ main { padding-top: var(--space-xs); } + /* Keep icon navigation on single line on mobile */ + .nav-buttons:has(.btn-icon-nav) { + flex-wrap: nowrap; + } + + .nav-buttons:has(.btn-icon-nav) .comic-date-display { + flex-basis: auto; + padding-top: 0; + font-size: var(--font-size-xs); + white-space: nowrap; + } + .nav-buttons { flex-wrap: wrap; } diff --git a/static/images/icons/first.png b/static/images/icons/first.png new file mode 100644 index 0000000..7d5a3f1 --- /dev/null +++ b/static/images/icons/first.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:36353ca32e04c83c86800a254a4c7e6eabd97985e45701dc9d423ba1644180f1 +size 1222 diff --git a/static/images/icons/latest.png b/static/images/icons/latest.png new file mode 100644 index 0000000..4c61255 --- /dev/null +++ b/static/images/icons/latest.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f3b85debd4498bc0cf78a11a9927b7d63a2f86cc6ff85c18235b7eccffc33b9c +size 1205 diff --git a/static/images/icons/next.png b/static/images/icons/next.png new file mode 100644 index 0000000..7a81576 --- /dev/null +++ b/static/images/icons/next.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9391eb9631c0b1c8cfd8e2960437e578a91fdf1b9b8382972f382f9476b3d64d +size 1120 diff --git a/static/images/icons/previous.png b/static/images/icons/previous.png new file mode 100644 index 0000000..280965c --- /dev/null +++ b/static/images/icons/previous.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9077b921ac9a843df812b51e82e3c73588d8533fa3efda25d4b4870151d2f5da +size 753 diff --git a/static/js/comic-nav.js b/static/js/comic-nav.js index e9ffe55..d30eb11 100644 --- a/static/js/comic-nav.js +++ b/static/js/comic-nav.js @@ -175,23 +175,26 @@ function updateNavButtons(currentNumber, formattedDate) { const navButtons = document.querySelector('.nav-buttons'); + // Detect if using icon navigation + const isIconNav = navButtons.children[0].classList.contains('btn-icon-nav'); + // First button const firstBtn = navButtons.children[0]; if (currentNumber > 1) { - firstBtn.className = 'btn btn-nav'; + firstBtn.className = isIconNav ? 'btn-icon-nav' : 'btn btn-nav'; firstBtn.onclick = (e) => { e.preventDefault(); loadComic(1); }; } else { - firstBtn.className = 'btn btn-nav btn-disabled'; + firstBtn.className = isIconNav ? 'btn-icon-nav btn-icon-disabled' : 'btn btn-nav btn-disabled'; firstBtn.onclick = null; } // Previous button const prevBtn = navButtons.children[1]; if (currentNumber > 1) { - prevBtn.className = 'btn btn-nav'; + prevBtn.className = isIconNav ? 'btn-icon-nav' : 'btn btn-nav'; prevBtn.onclick = (e) => { e.preventDefault(); loadComic(currentNumber - 1); }; } else { - prevBtn.className = 'btn btn-nav btn-disabled'; + prevBtn.className = isIconNav ? 'btn-icon-nav btn-icon-disabled' : 'btn btn-nav btn-disabled'; prevBtn.onclick = null; } @@ -203,20 +206,20 @@ // Next button const nextBtn = navButtons.children[3]; if (currentNumber < totalComics) { - nextBtn.className = 'btn btn-nav'; + nextBtn.className = isIconNav ? 'btn-icon-nav' : 'btn btn-nav'; nextBtn.onclick = (e) => { e.preventDefault(); loadComic(currentNumber + 1); }; } else { - nextBtn.className = 'btn btn-nav btn-disabled'; + nextBtn.className = isIconNav ? 'btn-icon-nav btn-icon-disabled' : 'btn btn-nav btn-disabled'; nextBtn.onclick = null; } // Latest button const latestBtn = navButtons.children[4]; if (currentNumber < totalComics) { - latestBtn.className = 'btn btn-nav'; + latestBtn.className = isIconNav ? 'btn-icon-nav' : 'btn btn-nav'; latestBtn.onclick = (e) => { e.preventDefault(); loadComic(totalComics); }; } else { - latestBtn.className = 'btn btn-nav btn-disabled'; + latestBtn.className = isIconNav ? 'btn-icon-nav btn-icon-disabled' : 'btn btn-nav btn-disabled'; latestBtn.onclick = null; } } diff --git a/templates/comic.html b/templates/comic.html index e14d17a..434f5f3 100644 --- a/templates/comic.html +++ b/templates/comic.html @@ -47,22 +47,60 @@
diff --git a/templates/index.html b/templates/index.html index 4297920..b3c0c02 100644 --- a/templates/index.html +++ b/templates/index.html @@ -30,22 +30,60 @@