nandi/gleanpublic Fork 0
1612dcc
Commits
Clone
git clone https://git.rickub.com/nandi/glean.git
git clone ssh://git@rickub.com/nandi/glean.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Improve cards and buttons in UI and simplify themeUnverified

Julien Robert committed 2026-05-05T10:18:35+02:00 Browse files
1612dcc parent: 3bb7755
modified docs/design.md +12 -0
@@ -91,12 +91,24 @@ All buttons use full-pill radius (`rounded-pill` = `9999px`).
9191 bg-spot-green text-white rounded-pill px-5 py-2 text-sm font-bold uppercase tracking-button hover:brightness-110 transition
9292 ```
9393
94+Used for CTAs: "Add", "Subscribe", "Annotate", "Save", "Sign in", "Get started", "Login".
95+
9496 **Primary Outlined:**
9597
9698 ```
9799 border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:border-spot-text transition
98100 ```
99101
102+Used for secondary actions: "Refresh feeds", "Mark all read", "Import OPML", "Export OPML", "Fetch full content", "See what's trending", dialog Cancel/Close.
103+
104+**Toolbar Micro:**
105+
106+```
107+text-spot-text bg-spot-hover text-[10px] uppercase tracking-button px-2.5 py-1 rounded-pill transition
108+```
109+
110+Used in-card and in-toolbar for small actions: Like, Read, Original, Share. Default text is `text-spot-text` (never grey). Semantic hover colors override the default on certain buttons: Like → red, Read → green, Share → blue, Original stays `text-spot-text`.
111+
100112 ### Cards
101113
102114 `rounded-xl` (12px) radius, `shadow-spot` elevation, `bg-spot-surface` background.
@@ -91,12 +91,24 @@ All buttons use full-pill radius (`rounded-pill` = `9999px`).
91 bg-spot-green text-white rounded-pill px-5 py-2 text-sm font-bold uppercase tracking-button hover:brightness-110 transition91 bg-spot-green text-white rounded-pill px-5 py-2 text-sm font-bold uppercase tracking-button hover:brightness-110 transition
92 ```92 ```
93 93
94+Used for CTAs: "Add", "Subscribe", "Annotate", "Save", "Sign in", "Get started", "Login".
95+
94 **Primary Outlined:**96 **Primary Outlined:**
95 97
96 ```98 ```
97 border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:border-spot-text transition99 border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:border-spot-text transition
98 ```100 ```
99 101
102+Used for secondary actions: "Refresh feeds", "Mark all read", "Import OPML", "Export OPML", "Fetch full content", "See what's trending", dialog Cancel/Close.
103+
104+**Toolbar Micro:**
105+
106+```
107+text-spot-text bg-spot-hover text-[10px] uppercase tracking-button px-2.5 py-1 rounded-pill transition
108+```
109+
110+Used in-card and in-toolbar for small actions: Like, Read, Original, Share. Default text is `text-spot-text` (never grey). Semantic hover colors override the default on certain buttons: Like → red, Read → green, Share → blue, Original stays `text-spot-text`.
111+
100 ### Cards112 ### Cards
101 113
102 `rounded-xl` (12px) radius, `shadow-spot` elevation, `bg-spot-surface` background.114 `rounded-xl` (12px) radius, `shadow-spot` elevation, `bg-spot-surface` background.
modified internal/tmpl/article_detail.html +13 -10
@@ -33,30 +33,33 @@
3333
3434 <div class="flex items-center gap-2 mt-6">
3535 <button hx-post="/articles/{{.Article.ID}}/like?bordered=true" hx-target="this" hx-swap="outerHTML"
36- class="border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:border-spot-text transition inline-flex items-center gap-1.5">
37- <svg class="w-3.5 h-3.5 {{if .HasLiked}}text-spot-red{{else}}text-spot-muted{{end}}" fill="{{if .HasLiked}}currentColor{{else}}none{{end}}" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">{{template "icon-heart"}}</svg>
36+ title="{{if .HasLiked}}Unlike{{else}}Like{{end}}"
37+ class="group inline-flex items-center gap-1.5 text-[10px] uppercase tracking-button px-2.5 py-1 rounded-pill transition {{if .HasLiked}}text-spot-red bg-spot-red/15 hover:bg-spot-red/25{{else}}text-spot-text bg-spot-hover hover:text-spot-red hover:bg-spot-red/15{{end}}">
38+ <svg class="w-3.5 h-3.5" fill="{{if .HasLiked}}currentColor{{else}}none{{end}}" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">{{template "icon-heart"}}</svg>
3839 <span>{{.LikeCount}}</span>
3940 </button>
4041
4142 <button hx-post="/articles/{{.Article.ID}}/{{if .ReadState.IsRead}}unread{{else}}read{{end}}"
4243 hx-target="#read-btn" hx-swap="outerHTML"
4344 id="read-btn"
44- class="border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:border-spot-text transition">
45- {{if .ReadState.IsRead}}Mark unread{{else}}Mark read{{end}}
45+ title="{{if .ReadState.IsRead}}Mark as Unread{{else}}Mark as Read{{end}}"
46+ class="group inline-flex items-center gap-1.5 text-[10px] uppercase tracking-button px-2.5 py-1 rounded-pill transition {{if .ReadState.IsRead}}text-spot-text bg-spot-hover hover:text-spot-green hover:bg-spot-green/15{{else}}text-spot-text bg-spot-hover hover:text-spot-green hover:bg-spot-green/15{{end}}">
47+ <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"/></svg>
48+ <span>{{if .ReadState.IsRead}}Unread{{else}}Read{{end}}</span>
4649 </button>
4750
4851 {{if .Article.URL.Valid}}
49- <a href="{{.Article.URL.String}}" target="_blank" rel="noopener noreferrer"
50- class="border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:border-spot-text transition inline-flex items-center gap-1.5">
52+ <a href="{{.Article.URL.String}}" target="_blank" rel="noopener noreferrer" title="Open original"
53+ class="group inline-flex items-center gap-1.5 text-[10px] text-spot-text uppercase tracking-button px-2.5 py-1 rounded-pill bg-spot-hover hover:brightness-110 transition">
5154 <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-4.5-6H18m0 0v4.5m0-4.5L10.5 13.5"/></svg>
52- Original
55+ <span>Original</span>
5356 </a>
5457
5558 <a href="https://bsky.app/intent/compose?text={{.Article.Title}}%20{{.Article.URL.String}}"
56- target="_blank" rel="noopener noreferrer"
57- class="border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:border-spot-text transition inline-flex items-center gap-1.5">
59+ target="_blank" rel="noopener noreferrer" title="Share on Bluesky"
60+ class="group inline-flex items-center gap-1.5 text-[10px] text-spot-text uppercase tracking-button px-2.5 py-1 rounded-pill bg-spot-hover hover:text-spot-blue hover:bg-spot-blue/15 transition">
5861 <span class="w-3.5 h-3.5 inline-flex shrink-0">{{template "icon-bluesky"}}</span>
59- Share
62+ <span>Share</span>
6063 </a>
6164 {{end}}
6265 </div>
@@ -33,30 +33,33 @@
33 33
34 <div class="flex items-center gap-2 mt-6">34 <div class="flex items-center gap-2 mt-6">
35 <button hx-post="/articles/{{.Article.ID}}/like?bordered=true" hx-target="this" hx-swap="outerHTML"35 <button hx-post="/articles/{{.Article.ID}}/like?bordered=true" hx-target="this" hx-swap="outerHTML"
36- class="border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:border-spot-text transition inline-flex items-center gap-1.5">36+ title="{{if .HasLiked}}Unlike{{else}}Like{{end}}"
37- <svg class="w-3.5 h-3.5 {{if .HasLiked}}text-spot-red{{else}}text-spot-muted{{end}}" fill="{{if .HasLiked}}currentColor{{else}}none{{end}}" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">{{template "icon-heart"}}</svg>37+ class="group inline-flex items-center gap-1.5 text-[10px] uppercase tracking-button px-2.5 py-1 rounded-pill transition {{if .HasLiked}}text-spot-red bg-spot-red/15 hover:bg-spot-red/25{{else}}text-spot-text bg-spot-hover hover:text-spot-red hover:bg-spot-red/15{{end}}">
38+ <svg class="w-3.5 h-3.5" fill="{{if .HasLiked}}currentColor{{else}}none{{end}}" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">{{template "icon-heart"}}</svg>
38 <span>{{.LikeCount}}</span>39 <span>{{.LikeCount}}</span>
39 </button>40 </button>
40 41
41 <button hx-post="/articles/{{.Article.ID}}/{{if .ReadState.IsRead}}unread{{else}}read{{end}}"42 <button hx-post="/articles/{{.Article.ID}}/{{if .ReadState.IsRead}}unread{{else}}read{{end}}"
42 hx-target="#read-btn" hx-swap="outerHTML"43 hx-target="#read-btn" hx-swap="outerHTML"
43 id="read-btn"44 id="read-btn"
44- class="border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:border-spot-text transition">45+ title="{{if .ReadState.IsRead}}Mark as Unread{{else}}Mark as Read{{end}}"
45- {{if .ReadState.IsRead}}Mark unread{{else}}Mark read{{end}}46+ class="group inline-flex items-center gap-1.5 text-[10px] uppercase tracking-button px-2.5 py-1 rounded-pill transition {{if .ReadState.IsRead}}text-spot-text bg-spot-hover hover:text-spot-green hover:bg-spot-green/15{{else}}text-spot-text bg-spot-hover hover:text-spot-green hover:bg-spot-green/15{{end}}">
47+ <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"/></svg>
48+ <span>{{if .ReadState.IsRead}}Unread{{else}}Read{{end}}</span>
46 </button>49 </button>
47 50
48 {{if .Article.URL.Valid}}51 {{if .Article.URL.Valid}}
49- <a href="{{.Article.URL.String}}" target="_blank" rel="noopener noreferrer"52+ <a href="{{.Article.URL.String}}" target="_blank" rel="noopener noreferrer" title="Open original"
50- class="border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:border-spot-text transition inline-flex items-center gap-1.5">53+ class="group inline-flex items-center gap-1.5 text-[10px] text-spot-text uppercase tracking-button px-2.5 py-1 rounded-pill bg-spot-hover hover:brightness-110 transition">
51 <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-4.5-6H18m0 0v4.5m0-4.5L10.5 13.5"/></svg>54 <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-4.5-6H18m0 0v4.5m0-4.5L10.5 13.5"/></svg>
52- Original55+ <span>Original</span>
53 </a>56 </a>
54 57
55 <a href="https://bsky.app/intent/compose?text={{.Article.Title}}%20{{.Article.URL.String}}"58 <a href="https://bsky.app/intent/compose?text={{.Article.Title}}%20{{.Article.URL.String}}"
56- target="_blank" rel="noopener noreferrer"59+ target="_blank" rel="noopener noreferrer" title="Share on Bluesky"
57- class="border border-spot-outline text-spot-text rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:border-spot-text transition inline-flex items-center gap-1.5">60+ class="group inline-flex items-center gap-1.5 text-[10px] text-spot-text uppercase tracking-button px-2.5 py-1 rounded-pill bg-spot-hover hover:text-spot-blue hover:bg-spot-blue/15 transition">
58 <span class="w-3.5 h-3.5 inline-flex shrink-0">{{template "icon-bluesky"}}</span>61 <span class="w-3.5 h-3.5 inline-flex shrink-0">{{template "icon-bluesky"}}</span>
59- Share62+ <span>Share</span>
60 </a>63 </a>
61 {{end}}64 {{end}}
62 </div>65 </div>
modified internal/tmpl/base.html +25 -49
@@ -6,7 +6,7 @@
66 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
77 <title>Glean</title>
88 <script>
9- (function(){var p=localStorage.getItem('theme')||'system';var r=p==='system'?(window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light'):p;document.documentElement.setAttribute('data-theme',r);var s=localStorage.getItem('shape');if(s)document.documentElement.setAttribute('data-shape',s)})();
9+ (function(){var p=localStorage.getItem('theme')||'system';var r=p==='system'?(window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light'):p;document.documentElement.setAttribute('data-theme',r)})();
1010 </script>
1111 <link rel="stylesheet" href="/static/output.css">
1212 <script src="/static/htmx.min.js"></script>
@@ -46,7 +46,7 @@
4646 <dialog id="confirm-dialog" class="bg-spot-surface rounded-xl p-6 max-w-sm shadow-spot-elevated border border-spot-divider backdrop:bg-black/50" onclick="if(event.target===this)this.close()">
4747 <p id="confirm-dialog-msg" class="text-spot-text text-sm mb-6"></p>
4848 <div class="flex justify-end gap-3">
49- <button onclick="document.getElementById('confirm-dialog').close(false)" class="text-sm text-spot-secondary hover:text-spot-text px-4 py-2 rounded-pill border border-spot-outline transition">Cancel</button>
49+ <button onclick="document.getElementById('confirm-dialog').close(false)" class="text-sm text-spot-text px-4 py-2 rounded-pill border border-spot-outline hover:border-spot-text transition">Cancel</button>
5050 <button id="confirm-dialog-ok" class="text-sm text-white bg-spot-red hover:brightness-110 px-4 py-2 rounded-pill font-bold uppercase tracking-button transition">Confirm</button>
5151 </div>
5252 </dialog>
@@ -69,7 +69,7 @@
6969 <kbd class="text-spot-text bg-spot-hover rounded px-1.5 py-0.5 text-xs font-mono text-center min-w-[28px]">m</kbd><span class="text-spot-secondary">Toggle read</span>
7070 </div>
7171 </div>
72- <button onclick="document.getElementById('shortcuts-dialog').close()" class="mt-4 w-full text-sm text-spot-secondary hover:text-spot-text px-4 py-2 rounded-pill border border-spot-outline transition">Close</button>
72+ <button onclick="document.getElementById('shortcuts-dialog').close()" class="mt-4 w-full text-sm text-spot-text px-4 py-2 rounded-pill border border-spot-outline hover:border-spot-text transition">Close</button>
7373 </dialog>
7474 {{if or .User (or (eq .ActivePath "/trending") (eq .ActivePath "/stats"))}}
7575 <aside class="hidden lg:flex flex-col w-60 bg-spot-bg h-screen fixed left-0 top-0 px-3 py-4 z-20">
@@ -120,7 +120,7 @@
120120 </div>
121121 </aside>
122122
123- <nav class="lg:hidden fixed bottom-0 left-0 right-0 bg-spot-surface border-t border-spot-divider z-30 px-2 py-2">
123+ <nav id="mobile-nav" class="lg:hidden fixed bottom-0 left-0 right-0 bg-spot-surface/80 backdrop-blur-xl border-t border-spot-divider z-30 px-2 py-2">
124124 <div class="flex items-center justify-around">
125125 <a href="/dashboard" class="flex flex-col items-center gap-0.5 {{activeClass .ActivePath "/dashboard"}} text-[10px] px-2 py-1">
126126 <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-4 0a1 1 0 01-1-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 01-1 1"/></svg>
@@ -134,6 +134,14 @@
134134 <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/></svg>
135135 Trending
136136 </a>
137+ <a href="/feeds" class="flex flex-col items-center gap-0.5 {{activeClass .ActivePath "/feeds"}} text-[10px] px-2 py-1">
138+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 5c7.18 0 13 5.82 13 13M6 11a7 7 0 017 7m-7-1a1 1 0 11-2 0 1 1 0 012 0z"/></svg>
139+ Feeds
140+ </a>
141+ <a href="/library" class="flex flex-col items-center gap-0.5 {{activeClass .ActivePath "/library"}} text-[10px] px-2 py-1">
142+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"/></svg>
143+ Library
144+ </a>
137145 </div>
138146 </nav>
139147 {{end}}
@@ -196,14 +204,10 @@
196204 <span class="theme-text-light hidden">Light</span>
197205 <span class="theme-text-system hidden">System</span>
198206 </button>
199- <button onclick="toggleShape()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left">
200- <svg class="w-3.5 h-3.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4h16v16H4z"/></svg>
201- <span class="shape-text">Squared</span>
202- </button>
203- <button onclick="document.getElementById('shortcuts-dialog').showModal()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left">
204- <svg class="w-3.5 h-3.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0 0 21 18V6a2.25 2.25 0 0 0-2.25-2.25H5.25A2.25 2.25 0 0 0 3 6v12a2.25 2.25 0 0 0 2.25 2.25Z"/></svg>
205- Shortcuts
206- </button>
207+ <button onclick="document.getElementById('shortcuts-dialog').showModal()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left">
208+ <svg class="w-3.5 h-3.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0 0 21 18V6a2.25 2.25 0 0 0-2.25-2.25H5.25A2.25 2.25 0 0 0 3 6v12a2.25 2.25 0 0 0 2.25 2.25Z"/></svg>
209+ Shortcuts
210+ </button>
207211 </div>
208212 </div>
209213 <div class="text-right">
@@ -228,19 +232,15 @@
228232 </div>
229233 <div class="border-t border-spot-divider pt-4">
230234 <div class="flex flex-wrap items-center gap-3">
231- <button onclick="toggleTheme()" class="text-xs text-spot-secondary hover:text-spot-text inline-flex gap-1.5 items-center transition">
232- <svg class="w-3.5 h-3.5 theme-icon-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg>
233- <svg class="w-3.5 h-3.5 theme-icon-light hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg>
234- <svg class="w-3.5 h-3.5 theme-icon-system hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25A2.25 2.25 0 0 1 5.25 3h13.5A2.25 2.25 0 0 1 21 5.25Z"/></svg>
235- <span class="theme-text-dark">Dark</span>
236- <span class="theme-text-light hidden">Light</span>
237- <span class="theme-text-system hidden">System</span>
238- </button>
239- <button onclick="toggleShape()" class="text-xs text-spot-secondary hover:text-spot-text inline-flex gap-1.5 items-center transition">
240- <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4h16v16H4z"/></svg>
241- <span class="shape-text">Squared</span>
242- </button>
243- </div>
235+ <button onclick="toggleTheme()" class="text-xs text-spot-secondary hover:text-spot-text inline-flex gap-1.5 items-center transition">
236+ <svg class="w-3.5 h-3.5 theme-icon-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg>
237+ <svg class="w-3.5 h-3.5 theme-icon-light hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg>
238+ <svg class="w-3.5 h-3.5 theme-icon-system hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25A2.25 2.25 0 0 1 5.25 3h13.5A2.25 2.25 0 0 1 21 5.25Z"/></svg>
239+ <span class="theme-text-dark">Dark</span>
240+ <span class="theme-text-light hidden">Light</span>
241+ <span class="theme-text-system hidden">System</span>
242+ </button>
243+ </div>
244244 <div class="border-t border-spot-divider mt-4 pt-3">
245245 <span class="text-xs text-spot-secondary">&copy; {{now.Format "2006"}} <a href="https://bsky.app/profile/julien.rbrt.fr" class="hover:text-spot-text transition">julien.rbrt.fr</a> &middot; Made in Europe &#127466;&#127482; &middot; <a href="/terms" class="hover:text-spot-text transition">Terms</a></span>
246246 </div>
@@ -276,35 +276,11 @@
276276 applyTheme();
277277 }
278278
279- function applyShape() {
280- var shapePref = localStorage.getItem('shape') || 'rounded';
281- if (shapePref === 'squared') {
282- document.documentElement.setAttribute('data-shape', 'squared');
283- } else {
284- document.documentElement.removeAttribute('data-shape');
285- }
286- document.querySelectorAll('.shape-text').forEach(function(el) {
287- el.textContent = shapePref === 'squared' ? 'Rounded' : 'Squared';
288- });
289- }
290-
291- function toggleShape() {
292- var current = localStorage.getItem('shape') || 'rounded';
293- var next = current === 'squared' ? 'rounded' : 'squared';
294- if (next === 'rounded') {
295- localStorage.removeItem('shape');
296- } else {
297- localStorage.setItem('shape', next);
298- }
299- applyShape();
300- }
301-
302279 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {
303280 if (themePref === 'system') applyTheme();
304281 });
305282
306283 applyTheme();
307- applyShape();
308284
309285 // reload page when page restored from bfcache.
310286 // useful for reloading article read/unread status.
@@ -6,7 +6,7 @@
6 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">6 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
7 <title>Glean</title>7 <title>Glean</title>
8 <script>8 <script>
9- (function(){var p=localStorage.getItem('theme')||'system';var r=p==='system'?(window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light'):p;document.documentElement.setAttribute('data-theme',r);var s=localStorage.getItem('shape');if(s)document.documentElement.setAttribute('data-shape',s)})();9+ (function(){var p=localStorage.getItem('theme')||'system';var r=p==='system'?(window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light'):p;document.documentElement.setAttribute('data-theme',r)})();
10 </script>10 </script>
11 <link rel="stylesheet" href="/static/output.css">11 <link rel="stylesheet" href="/static/output.css">
12 <script src="/static/htmx.min.js"></script>12 <script src="/static/htmx.min.js"></script>
@@ -46,7 +46,7 @@
46 <dialog id="confirm-dialog" class="bg-spot-surface rounded-xl p-6 max-w-sm shadow-spot-elevated border border-spot-divider backdrop:bg-black/50" onclick="if(event.target===this)this.close()">46 <dialog id="confirm-dialog" class="bg-spot-surface rounded-xl p-6 max-w-sm shadow-spot-elevated border border-spot-divider backdrop:bg-black/50" onclick="if(event.target===this)this.close()">
47 <p id="confirm-dialog-msg" class="text-spot-text text-sm mb-6"></p>47 <p id="confirm-dialog-msg" class="text-spot-text text-sm mb-6"></p>
48 <div class="flex justify-end gap-3">48 <div class="flex justify-end gap-3">
49- <button onclick="document.getElementById('confirm-dialog').close(false)" class="text-sm text-spot-secondary hover:text-spot-text px-4 py-2 rounded-pill border border-spot-outline transition">Cancel</button>49+ <button onclick="document.getElementById('confirm-dialog').close(false)" class="text-sm text-spot-text px-4 py-2 rounded-pill border border-spot-outline hover:border-spot-text transition">Cancel</button>
50 <button id="confirm-dialog-ok" class="text-sm text-white bg-spot-red hover:brightness-110 px-4 py-2 rounded-pill font-bold uppercase tracking-button transition">Confirm</button>50 <button id="confirm-dialog-ok" class="text-sm text-white bg-spot-red hover:brightness-110 px-4 py-2 rounded-pill font-bold uppercase tracking-button transition">Confirm</button>
51 </div>51 </div>
52 </dialog>52 </dialog>
@@ -69,7 +69,7 @@
69 <kbd class="text-spot-text bg-spot-hover rounded px-1.5 py-0.5 text-xs font-mono text-center min-w-[28px]">m</kbd><span class="text-spot-secondary">Toggle read</span>69 <kbd class="text-spot-text bg-spot-hover rounded px-1.5 py-0.5 text-xs font-mono text-center min-w-[28px]">m</kbd><span class="text-spot-secondary">Toggle read</span>
70 </div>70 </div>
71 </div>71 </div>
72- <button onclick="document.getElementById('shortcuts-dialog').close()" class="mt-4 w-full text-sm text-spot-secondary hover:text-spot-text px-4 py-2 rounded-pill border border-spot-outline transition">Close</button>72+ <button onclick="document.getElementById('shortcuts-dialog').close()" class="mt-4 w-full text-sm text-spot-text px-4 py-2 rounded-pill border border-spot-outline hover:border-spot-text transition">Close</button>
73 </dialog>73 </dialog>
74 {{if or .User (or (eq .ActivePath "/trending") (eq .ActivePath "/stats"))}}74 {{if or .User (or (eq .ActivePath "/trending") (eq .ActivePath "/stats"))}}
75 <aside class="hidden lg:flex flex-col w-60 bg-spot-bg h-screen fixed left-0 top-0 px-3 py-4 z-20">75 <aside class="hidden lg:flex flex-col w-60 bg-spot-bg h-screen fixed left-0 top-0 px-3 py-4 z-20">
@@ -120,7 +120,7 @@
120 </div>120 </div>
121 </aside>121 </aside>
122 122
123- <nav class="lg:hidden fixed bottom-0 left-0 right-0 bg-spot-surface border-t border-spot-divider z-30 px-2 py-2">123+ <nav id="mobile-nav" class="lg:hidden fixed bottom-0 left-0 right-0 bg-spot-surface/80 backdrop-blur-xl border-t border-spot-divider z-30 px-2 py-2">
124 <div class="flex items-center justify-around">124 <div class="flex items-center justify-around">
125 <a href="/dashboard" class="flex flex-col items-center gap-0.5 {{activeClass .ActivePath "/dashboard"}} text-[10px] px-2 py-1">125 <a href="/dashboard" class="flex flex-col items-center gap-0.5 {{activeClass .ActivePath "/dashboard"}} text-[10px] px-2 py-1">
126 <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-4 0a1 1 0 01-1-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 01-1 1"/></svg>126 <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-4 0a1 1 0 01-1-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 01-1 1"/></svg>
@@ -134,6 +134,14 @@
134 <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/></svg>134 <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/></svg>
135 Trending135 Trending
136 </a>136 </a>
137+ <a href="/feeds" class="flex flex-col items-center gap-0.5 {{activeClass .ActivePath "/feeds"}} text-[10px] px-2 py-1">
138+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 5c7.18 0 13 5.82 13 13M6 11a7 7 0 017 7m-7-1a1 1 0 11-2 0 1 1 0 012 0z"/></svg>
139+ Feeds
140+ </a>
141+ <a href="/library" class="flex flex-col items-center gap-0.5 {{activeClass .ActivePath "/library"}} text-[10px] px-2 py-1">
142+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"/></svg>
143+ Library
144+ </a>
137 </div>145 </div>
138 </nav>146 </nav>
139 {{end}}147 {{end}}
@@ -196,14 +204,10 @@
196 <span class="theme-text-light hidden">Light</span>204 <span class="theme-text-light hidden">Light</span>
197 <span class="theme-text-system hidden">System</span>205 <span class="theme-text-system hidden">System</span>
198 </button>206 </button>
199- <button onclick="toggleShape()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left">207+ <button onclick="document.getElementById('shortcuts-dialog').showModal()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left">
200- <svg class="w-3.5 h-3.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4h16v16H4z"/></svg>208+ <svg class="w-3.5 h-3.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0 0 21 18V6a2.25 2.25 0 0 0-2.25-2.25H5.25A2.25 2.25 0 0 0 3 6v12a2.25 2.25 0 0 0 2.25 2.25Z"/></svg>
201- <span class="shape-text">Squared</span>209+ Shortcuts
202- </button>210+ </button>
203- <button onclick="document.getElementById('shortcuts-dialog').showModal()" class="text-xs text-spot-secondary hover:text-spot-text hover:underline inline-flex gap-1.5 items-center transition text-left">
204- <svg class="w-3.5 h-3.5 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0 0 21 18V6a2.25 2.25 0 0 0-2.25-2.25H5.25A2.25 2.25 0 0 0 3 6v12a2.25 2.25 0 0 0 2.25 2.25Z"/></svg>
205- Shortcuts
206- </button>
207 </div>211 </div>
208 </div>212 </div>
209 <div class="text-right">213 <div class="text-right">
@@ -228,19 +232,15 @@
228 </div>232 </div>
229 <div class="border-t border-spot-divider pt-4">233 <div class="border-t border-spot-divider pt-4">
230 <div class="flex flex-wrap items-center gap-3">234 <div class="flex flex-wrap items-center gap-3">
231- <button onclick="toggleTheme()" class="text-xs text-spot-secondary hover:text-spot-text inline-flex gap-1.5 items-center transition">235+ <button onclick="toggleTheme()" class="text-xs text-spot-secondary hover:text-spot-text inline-flex gap-1.5 items-center transition">
232- <svg class="w-3.5 h-3.5 theme-icon-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg>236+ <svg class="w-3.5 h-3.5 theme-icon-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg>
233- <svg class="w-3.5 h-3.5 theme-icon-light hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg>237+ <svg class="w-3.5 h-3.5 theme-icon-light hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg>
234- <svg class="w-3.5 h-3.5 theme-icon-system hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25A2.25 2.25 0 0 1 5.25 3h13.5A2.25 2.25 0 0 1 21 5.25Z"/></svg>238+ <svg class="w-3.5 h-3.5 theme-icon-system hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25A2.25 2.25 0 0 1 5.25 3h13.5A2.25 2.25 0 0 1 21 5.25Z"/></svg>
235- <span class="theme-text-dark">Dark</span>239+ <span class="theme-text-dark">Dark</span>
236- <span class="theme-text-light hidden">Light</span>240+ <span class="theme-text-light hidden">Light</span>
237- <span class="theme-text-system hidden">System</span>241+ <span class="theme-text-system hidden">System</span>
238- </button>242+ </button>
239- <button onclick="toggleShape()" class="text-xs text-spot-secondary hover:text-spot-text inline-flex gap-1.5 items-center transition">243+ </div>
240- <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4h16v16H4z"/></svg>
241- <span class="shape-text">Squared</span>
242- </button>
243- </div>
244 <div class="border-t border-spot-divider mt-4 pt-3">244 <div class="border-t border-spot-divider mt-4 pt-3">
245 <span class="text-xs text-spot-secondary">&copy; {{now.Format "2006"}} <a href="https://bsky.app/profile/julien.rbrt.fr" class="hover:text-spot-text transition">julien.rbrt.fr</a> &middot; Made in Europe &#127466;&#127482; &middot; <a href="/terms" class="hover:text-spot-text transition">Terms</a></span>245 <span class="text-xs text-spot-secondary">&copy; {{now.Format "2006"}} <a href="https://bsky.app/profile/julien.rbrt.fr" class="hover:text-spot-text transition">julien.rbrt.fr</a> &middot; Made in Europe &#127466;&#127482; &middot; <a href="/terms" class="hover:text-spot-text transition">Terms</a></span>
246 </div>246 </div>
@@ -276,35 +276,11 @@
276 applyTheme();276 applyTheme();
277 }277 }
278 278
279- function applyShape() {
280- var shapePref = localStorage.getItem('shape') || 'rounded';
281- if (shapePref === 'squared') {
282- document.documentElement.setAttribute('data-shape', 'squared');
283- } else {
284- document.documentElement.removeAttribute('data-shape');
285- }
286- document.querySelectorAll('.shape-text').forEach(function(el) {
287- el.textContent = shapePref === 'squared' ? 'Rounded' : 'Squared';
288- });
289- }
290-
291- function toggleShape() {
292- var current = localStorage.getItem('shape') || 'rounded';
293- var next = current === 'squared' ? 'rounded' : 'squared';
294- if (next === 'rounded') {
295- localStorage.removeItem('shape');
296- } else {
297- localStorage.setItem('shape', next);
298- }
299- applyShape();
300- }
301-
302 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {279 window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {
303 if (themePref === 'system') applyTheme();280 if (themePref === 'system') applyTheme();
304 });281 });
305 282
306 applyTheme();283 applyTheme();
307- applyShape();
308 284
309 // reload page when page restored from bfcache.285 // reload page when page restored from bfcache.
310 // useful for reloading article read/unread status.286 // useful for reloading article read/unread status.
modified internal/tmpl/login.html +1 -1
@@ -34,7 +34,7 @@
3434 </div>
3535
3636 <a href="/auth/register"
37- class="w-full flex items-center justify-center gap-3 border border-spot-outline rounded-pill px-4 py-3.5 text-sm font-bold uppercase tracking-button hover:bg-spot-hover-50 transition">
37+ class="w-full flex items-center justify-center gap-3 border border-spot-outline text-spot-text rounded-pill px-4 py-3.5 text-sm font-bold uppercase tracking-button hover:bg-spot-hover-50 transition">
3838 <svg class="h-5 w-auto" fill="currentColor" viewBox="77.86 113.9 129.15 129.15" xmlns="http://www.w3.org/2000/svg"><path d="M148.846 144.562C148.846 159.75 161.158 172.062 176.346 172.062H207.012V185.865H176.346C161.158 185.865 148.846 198.177 148.846 213.365V243.045H136.029V213.365C136.029 198.177 123.717 185.865 108.529 185.865H77.8633V172.062H108.529C123.717 172.062 136.029 159.75 136.029 144.562V113.896H148.846V144.562Z"/></svg>
3939 Register with Eurosky
4040 </a>
@@ -34,7 +34,7 @@
34 </div>34 </div>
35 35
36 <a href="/auth/register"36 <a href="/auth/register"
37- class="w-full flex items-center justify-center gap-3 border border-spot-outline rounded-pill px-4 py-3.5 text-sm font-bold uppercase tracking-button hover:bg-spot-hover-50 transition">37+ class="w-full flex items-center justify-center gap-3 border border-spot-outline text-spot-text rounded-pill px-4 py-3.5 text-sm font-bold uppercase tracking-button hover:bg-spot-hover-50 transition">
38 <svg class="h-5 w-auto" fill="currentColor" viewBox="77.86 113.9 129.15 129.15" xmlns="http://www.w3.org/2000/svg"><path d="M148.846 144.562C148.846 159.75 161.158 172.062 176.346 172.062H207.012V185.865H176.346C161.158 185.865 148.846 198.177 148.846 213.365V243.045H136.029V213.365C136.029 198.177 123.717 185.865 108.529 185.865H77.8633V172.062H108.529C123.717 172.062 136.029 159.75 136.029 144.562V113.896H148.846V144.562Z"/></svg>38 <svg class="h-5 w-auto" fill="currentColor" viewBox="77.86 113.9 129.15 129.15" xmlns="http://www.w3.org/2000/svg"><path d="M148.846 144.562C148.846 159.75 161.158 172.062 176.346 172.062H207.012V185.865H176.346C161.158 185.865 148.846 198.177 148.846 213.365V243.045H136.029V213.365C136.029 198.177 123.717 185.865 108.529 185.865H77.8633V172.062H108.529C123.717 172.062 136.029 159.75 136.029 144.562V113.896H148.846V144.562Z"/></svg>
39 Register with Eurosky39 Register with Eurosky
40 </a>40 </a>
modified internal/tmpl/partials/article-card.html +25 -17
@@ -2,39 +2,47 @@
22 <article data-article-id="{{.ID}}" data-feed-url="{{.FeedURL}}" data-article-url="{{if .URL.Valid}}{{.URL.String}}{{end}}" class="bg-spot-surface rounded-xl px-5 py-4 hover:bg-spot-hover-50 transition shadow-spot relative {{if .IsRead.Bool}}opacity-60{{end}}">
33 <div class="flex items-start justify-between gap-4">
44 <div class="min-w-0 flex-1">
5- <div class="flex items-center gap-2">
6- {{if not .IsRead.Bool}}<span class="w-2 h-2 rounded-full bg-spot-green shrink-0"></span>{{end}}
7- <a href="/articles/{{.ID}}{{.NavSuffix}}" class="font-bold text-spot-text hover:text-spot-green transition text-lg leading-tight">{{.Title}}</a>
5+ <div class="flex items-start gap-2.5">
6+ {{if not .IsRead.Bool}}<span class="w-2.5 h-2.5 rounded-full bg-spot-green shrink-0 mt-1.5"></span>{{end}}
7+ <a href="/articles/{{.ID}}{{.NavSuffix}}" class="font-semibold text-spot-text hover:text-spot-green transition text-[17px] leading-snug">{{.Title}}</a>
88 </div>
9- <div class="text-sm text-spot-secondary mt-1 flex items-center gap-2">
10- {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-4 h-4"}}
11- {{if .Author.Valid}}{{if .Author.String}}<span>{{.Author.String}}</span>{{end}}{{end}}
12- {{if .Published.Valid}}<span>{{.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}
13- <span class="text-spot-muted"><a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-green transition">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a></span>
9+ <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap pl-5">
10+ {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-3.5 h-3.5"}}
11+ <a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-text transition font-medium">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a>
12+ {{if .Author.Valid}}{{if .Author.String}}<span class="text-spot-muted">&middot;</span><span>{{.Author.String}}</span>{{end}}{{end}}
13+ {{if .Published.Valid}}<span class="text-spot-muted">&middot;</span><span>{{.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}
1414 </div>
1515 {{if .Summary.Valid}}{{if .Summary.String}}
16- <p class="text-sm text-spot-secondary mt-2 line-clamp-2">{{plainText .Summary.String}}</p>
16+ <p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed pl-5">{{plainText .Summary.String}}</p>
1717 {{end}}{{end}}
1818 </div>
19- <div class="flex flex-col items-center gap-3 shrink-0 pt-1">
20- {{template "like-button.html" .}}
19+ <div class="grid gap-2 shrink-0 pt-1">
20+ <div class="flex justify-center">{{template "like-button.html" .}}</div>
2121 {{if .IsRead.Bool}}
22- <span id="read-btn-{{.ID}}" class="text-[10px] text-spot-green uppercase tracking-button">Read</span>
22+ <div class="flex justify-center">
23+ <span id="read-btn-{{.ID}}" title="Read" class="inline-flex items-center gap-1 text-[10px] text-spot-muted uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover">
24+ <svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"/></svg>
25+ </span>
26+ </div>
2327 {{else}}
24- <button hx-post="/articles/{{.ID}}/read" hx-target="#read-btn-{{.ID}}" hx-swap="outerHTML" id="read-btn-{{.ID}}" class="text-[10px] text-spot-secondary hover:text-spot-text uppercase tracking-button transition">Mark read</button>
28+ <div class="flex justify-center">
29+ <button hx-post="/articles/{{.ID}}/read" hx-target="#read-btn-{{.ID}}" hx-swap="outerHTML" id="read-btn-{{.ID}}" title="Mark as Read" class="group inline-flex items-center gap-1 text-[10px] text-spot-text uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover hover:text-spot-green hover:bg-spot-green/15 transition">
30+ <svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"/></svg>
31+ </button>
32+ </div>
2533 {{end}}
2634 </div>
2735 </div>
28- <div class="annotate-form hidden mt-3 pt-3 border-t border-spot-divider">
36+ <div class="annotate-form hidden mt-4 pt-4 border-t border-spot-divider">
2937 <form hx-post="/library/create" hx-swap="none" hx-on::after-request="closeAnnotate(this)" class="space-y-2">
3038 <input type="hidden" name="feed_url" value="{{.FeedURL}}">
3139 <input type="hidden" name="article_url" value="{{if .URL.Valid}}{{.URL.String}}{{end}}">
3240 <input type="text" name="quote" placeholder="Quote a passage..."
33- class="w-full bg-spot-hover text-spot-text rounded-pill px-4 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-placeholder">
41+ class="w-full bg-spot-hover text-spot-text rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-placeholder">
3442 <div class="flex gap-2">
3543 <input type="text" name="note" placeholder="Add a note..."
36- class="flex-1 bg-spot-hover text-spot-text rounded-pill px-4 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-placeholder">
37- <button type="submit" class="bg-spot-green text-white rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:brightness-110 transition">Annotate</button>
44+ class="flex-1 bg-spot-hover text-spot-text rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-placeholder">
45+ <button type="submit" class="bg-spot-green text-white rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:brightness-110 transition">Save</button>
3846 <button type="button" onclick="closeAnnotate(this)" class="text-spot-secondary hover:text-spot-text px-2 text-sm transition">&times;</button>
3947 </div>
4048 </form>
@@ -2,39 +2,47 @@
2 <article data-article-id="{{.ID}}" data-feed-url="{{.FeedURL}}" data-article-url="{{if .URL.Valid}}{{.URL.String}}{{end}}" class="bg-spot-surface rounded-xl px-5 py-4 hover:bg-spot-hover-50 transition shadow-spot relative {{if .IsRead.Bool}}opacity-60{{end}}">2 <article data-article-id="{{.ID}}" data-feed-url="{{.FeedURL}}" data-article-url="{{if .URL.Valid}}{{.URL.String}}{{end}}" class="bg-spot-surface rounded-xl px-5 py-4 hover:bg-spot-hover-50 transition shadow-spot relative {{if .IsRead.Bool}}opacity-60{{end}}">
3 <div class="flex items-start justify-between gap-4">3 <div class="flex items-start justify-between gap-4">
4 <div class="min-w-0 flex-1">4 <div class="min-w-0 flex-1">
5- <div class="flex items-center gap-2">5+ <div class="flex items-start gap-2.5">
6- {{if not .IsRead.Bool}}<span class="w-2 h-2 rounded-full bg-spot-green shrink-0"></span>{{end}}6+ {{if not .IsRead.Bool}}<span class="w-2.5 h-2.5 rounded-full bg-spot-green shrink-0 mt-1.5"></span>{{end}}
7- <a href="/articles/{{.ID}}{{.NavSuffix}}" class="font-bold text-spot-text hover:text-spot-green transition text-lg leading-tight">{{.Title}}</a>7+ <a href="/articles/{{.ID}}{{.NavSuffix}}" class="font-semibold text-spot-text hover:text-spot-green transition text-[17px] leading-snug">{{.Title}}</a>
8 </div>8 </div>
9- <div class="text-sm text-spot-secondary mt-1 flex items-center gap-2">9+ <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap pl-5">
10- {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-4 h-4"}}10+ {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-3.5 h-3.5"}}
11- {{if .Author.Valid}}{{if .Author.String}}<span>{{.Author.String}}</span>{{end}}{{end}}11+ <a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-text transition font-medium">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a>
12- {{if .Published.Valid}}<span>{{.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}12+ {{if .Author.Valid}}{{if .Author.String}}<span class="text-spot-muted">&middot;</span><span>{{.Author.String}}</span>{{end}}{{end}}
13- <span class="text-spot-muted"><a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-green transition">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a></span>13+ {{if .Published.Valid}}<span class="text-spot-muted">&middot;</span><span>{{.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}
14 </div>14 </div>
15 {{if .Summary.Valid}}{{if .Summary.String}}15 {{if .Summary.Valid}}{{if .Summary.String}}
16- <p class="text-sm text-spot-secondary mt-2 line-clamp-2">{{plainText .Summary.String}}</p>16+ <p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed pl-5">{{plainText .Summary.String}}</p>
17 {{end}}{{end}}17 {{end}}{{end}}
18 </div>18 </div>
19- <div class="flex flex-col items-center gap-3 shrink-0 pt-1">19+ <div class="grid gap-2 shrink-0 pt-1">
20- {{template "like-button.html" .}}20+ <div class="flex justify-center">{{template "like-button.html" .}}</div>
21 {{if .IsRead.Bool}}21 {{if .IsRead.Bool}}
22- <span id="read-btn-{{.ID}}" class="text-[10px] text-spot-green uppercase tracking-button">Read</span>22+ <div class="flex justify-center">
23+ <span id="read-btn-{{.ID}}" title="Read" class="inline-flex items-center gap-1 text-[10px] text-spot-muted uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover">
24+ <svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"/></svg>
25+ </span>
26+ </div>
23 {{else}}27 {{else}}
24- <button hx-post="/articles/{{.ID}}/read" hx-target="#read-btn-{{.ID}}" hx-swap="outerHTML" id="read-btn-{{.ID}}" class="text-[10px] text-spot-secondary hover:text-spot-text uppercase tracking-button transition">Mark read</button>28+ <div class="flex justify-center">
29+ <button hx-post="/articles/{{.ID}}/read" hx-target="#read-btn-{{.ID}}" hx-swap="outerHTML" id="read-btn-{{.ID}}" title="Mark as Read" class="group inline-flex items-center gap-1 text-[10px] text-spot-text uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover hover:text-spot-green hover:bg-spot-green/15 transition">
30+ <svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"/></svg>
31+ </button>
32+ </div>
25 {{end}}33 {{end}}
26 </div>34 </div>
27 </div>35 </div>
28- <div class="annotate-form hidden mt-3 pt-3 border-t border-spot-divider">36+ <div class="annotate-form hidden mt-4 pt-4 border-t border-spot-divider">
29 <form hx-post="/library/create" hx-swap="none" hx-on::after-request="closeAnnotate(this)" class="space-y-2">37 <form hx-post="/library/create" hx-swap="none" hx-on::after-request="closeAnnotate(this)" class="space-y-2">
30 <input type="hidden" name="feed_url" value="{{.FeedURL}}">38 <input type="hidden" name="feed_url" value="{{.FeedURL}}">
31 <input type="hidden" name="article_url" value="{{if .URL.Valid}}{{.URL.String}}{{end}}">39 <input type="hidden" name="article_url" value="{{if .URL.Valid}}{{.URL.String}}{{end}}">
32 <input type="text" name="quote" placeholder="Quote a passage..."40 <input type="text" name="quote" placeholder="Quote a passage..."
33- class="w-full bg-spot-hover text-spot-text rounded-pill px-4 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-placeholder">41+ class="w-full bg-spot-hover text-spot-text rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-placeholder">
34 <div class="flex gap-2">42 <div class="flex gap-2">
35 <input type="text" name="note" placeholder="Add a note..."43 <input type="text" name="note" placeholder="Add a note..."
36- class="flex-1 bg-spot-hover text-spot-text rounded-pill px-4 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-placeholder">44+ class="flex-1 bg-spot-hover text-spot-text rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-placeholder">
37- <button type="submit" class="bg-spot-green text-white rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:brightness-110 transition">Annotate</button>45+ <button type="submit" class="bg-spot-green text-white rounded-pill px-4 py-1.5 text-xs font-bold uppercase tracking-button hover:brightness-110 transition">Save</button>
38 <button type="button" onclick="closeAnnotate(this)" class="text-spot-secondary hover:text-spot-text px-2 text-sm transition">&times;</button>46 <button type="button" onclick="closeAnnotate(this)" class="text-spot-secondary hover:text-spot-text px-2 text-sm transition">&times;</button>
39 </div>47 </div>
40 </form>48 </form>
modified internal/tmpl/partials/like-button.html +3 -2
@@ -1,7 +1,8 @@
11 {{define "like-button.html"}}
22 <button hx-post="/articles/{{.ID}}/like" hx-target="this" hx-swap="outerHTML"
3- class="text-spot-text rounded-pill px-2 py-1 text-xs font-bold transition inline-flex items-center gap-1 hover:text-spot-green">
4- <svg class="w-4 h-4 {{if .HasLiked}}text-spot-red{{else}}text-spot-muted{{end}}" fill="{{if .HasLiked}}currentColor{{else}}none{{end}}" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">{{template "icon-heart"}}</svg>
3+ title="{{if .HasLiked}}Unlike{{else}}Like{{end}}"
4+ class="group inline-flex items-center gap-1 text-[10px] uppercase tracking-button px-2 py-0.5 rounded-pill transition {{if .HasLiked}}text-spot-red bg-spot-red/15 hover:bg-spot-red/25{{else}}text-spot-text bg-spot-hover hover:text-spot-red hover:bg-spot-red/15{{end}}">
5+ <svg class="w-3 h-3" fill="{{if .HasLiked}}currentColor{{else}}none{{end}}" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">{{template "icon-heart"}}</svg>
56 <span>{{.LikeCount}}</span>
67 </button>
78 {{end}}
@@ -1,7 +1,8 @@
1 {{define "like-button.html"}}1 {{define "like-button.html"}}
2 <button hx-post="/articles/{{.ID}}/like" hx-target="this" hx-swap="outerHTML"2 <button hx-post="/articles/{{.ID}}/like" hx-target="this" hx-swap="outerHTML"
3- class="text-spot-text rounded-pill px-2 py-1 text-xs font-bold transition inline-flex items-center gap-1 hover:text-spot-green">3+ title="{{if .HasLiked}}Unlike{{else}}Like{{end}}"
4- <svg class="w-4 h-4 {{if .HasLiked}}text-spot-red{{else}}text-spot-muted{{end}}" fill="{{if .HasLiked}}currentColor{{else}}none{{end}}" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">{{template "icon-heart"}}</svg>4+ class="group inline-flex items-center gap-1 text-[10px] uppercase tracking-button px-2 py-0.5 rounded-pill transition {{if .HasLiked}}text-spot-red bg-spot-red/15 hover:bg-spot-red/25{{else}}text-spot-text bg-spot-hover hover:text-spot-red hover:bg-spot-red/15{{end}}">
5+ <svg class="w-3 h-3" fill="{{if .HasLiked}}currentColor{{else}}none{{end}}" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">{{template "icon-heart"}}</svg>
5 <span>{{.LikeCount}}</span>6 <span>{{.LikeCount}}</span>
6 </button>7 </button>
7 {{end}}8 {{end}}
modified internal/tmpl/partials/recommendation-article-card.html +12 -11
@@ -2,21 +2,22 @@
22 <article data-article-url="{{.URL}}" class="bg-spot-surface rounded-xl px-5 py-4 hover:bg-spot-hover-50 transition shadow-spot relative">
33 <div class="flex items-start justify-between gap-4">
44 <div class="min-w-0 flex-1">
5- <div class="flex items-center gap-2">
6- {{if not .IsRead}}<span class="w-2 h-2 rounded-full bg-spot-green shrink-0"></span>{{end}}
7- <a href="/articles/{{.ArticleID}}" class="font-bold text-spot-text hover:text-spot-green transition text-lg leading-tight">{{.Title}}</a>
5+ <div class="flex items-start gap-2.5">
6+ {{if not .IsRead}}<span class="w-2.5 h-2.5 rounded-full bg-spot-green shrink-0 mt-1.5"></span>{{end}}
7+ <a href="/articles/{{.ArticleID}}" class="font-semibold text-spot-text hover:text-spot-green transition text-[17px] leading-snug">{{.Title}}</a>
88 </div>
9- <div class="text-sm text-spot-secondary mt-1 flex items-center gap-2">
10- {{if .FaviconURL}}{{template "favicon" dict "src" .FaviconURL "size" "w-4 h-4"}}{{end}}
11- {{if .Author}}<span>{{.Author}}</span>{{end}}
12- {{if .Published.Valid}}<span>{{.Published.Time.Format "Jan 2"}}</span>{{end}}
13- <span class="text-spot-muted"><a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-green transition">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a></span>
9+ <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap pl-5">
10+ {{if .FaviconURL}}{{template "favicon" dict "src" .FaviconURL "size" "w-3.5 h-3.5"}}{{end}}
11+ <a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-text transition font-medium">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a>
12+ {{if .Author}}<span class="text-spot-muted">&middot;</span><span>{{.Author}}</span>{{end}}
13+ {{if .Published.Valid}}<span class="text-spot-muted">&middot;</span><span>{{.Published.Time.Format "Jan 2"}}</span>{{end}}
1414 </div>
15- {{if .Summary}}<p class="text-sm text-spot-secondary mt-2 line-clamp-2">{{plainText .Summary}}</p>{{end}}
15+ {{if .Summary}}<p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed pl-5">{{plainText .Summary}}</p>{{end}}
1616 </div>
1717 <div class="shrink-0 pt-1">
1818 <button hx-post="/recs/dismiss-article" hx-target="closest article" hx-swap="delete" hx-include="#dismiss-{{.ArticleID}}"
19- class="text-[10px] text-spot-secondary hover:text-spot-text uppercase tracking-button transition flex items-center gap-1">
19+ class="text-[10px] text-spot-muted hover:text-spot-text uppercase tracking-button transition flex items-center gap-1"
20+ title="Not interested">
2021 <input type="hidden" name="article_url" value="{{.URL}}" id="dismiss-{{.ArticleID}}">
2122 <svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
2223 Dismiss
@@ -24,4 +25,4 @@
2425 </div>
2526 </div>
2627 </article>
27-{{end}}
\ No newline at end of file
28+{{end}}
@@ -2,21 +2,22 @@
2 <article data-article-url="{{.URL}}" class="bg-spot-surface rounded-xl px-5 py-4 hover:bg-spot-hover-50 transition shadow-spot relative">2 <article data-article-url="{{.URL}}" class="bg-spot-surface rounded-xl px-5 py-4 hover:bg-spot-hover-50 transition shadow-spot relative">
3 <div class="flex items-start justify-between gap-4">3 <div class="flex items-start justify-between gap-4">
4 <div class="min-w-0 flex-1">4 <div class="min-w-0 flex-1">
5- <div class="flex items-center gap-2">5+ <div class="flex items-start gap-2.5">
6- {{if not .IsRead}}<span class="w-2 h-2 rounded-full bg-spot-green shrink-0"></span>{{end}}6+ {{if not .IsRead}}<span class="w-2.5 h-2.5 rounded-full bg-spot-green shrink-0 mt-1.5"></span>{{end}}
7- <a href="/articles/{{.ArticleID}}" class="font-bold text-spot-text hover:text-spot-green transition text-lg leading-tight">{{.Title}}</a>7+ <a href="/articles/{{.ArticleID}}" class="font-semibold text-spot-text hover:text-spot-green transition text-[17px] leading-snug">{{.Title}}</a>
8 </div>8 </div>
9- <div class="text-sm text-spot-secondary mt-1 flex items-center gap-2">9+ <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap pl-5">
10- {{if .FaviconURL}}{{template "favicon" dict "src" .FaviconURL "size" "w-4 h-4"}}{{end}}10+ {{if .FaviconURL}}{{template "favicon" dict "src" .FaviconURL "size" "w-3.5 h-3.5"}}{{end}}
11- {{if .Author}}<span>{{.Author}}</span>{{end}}11+ <a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-text transition font-medium">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a>
12- {{if .Published.Valid}}<span>{{.Published.Time.Format "Jan 2"}}</span>{{end}}12+ {{if .Author}}<span class="text-spot-muted">&middot;</span><span>{{.Author}}</span>{{end}}
13- <span class="text-spot-muted"><a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-green transition">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a></span>13+ {{if .Published.Valid}}<span class="text-spot-muted">&middot;</span><span>{{.Published.Time.Format "Jan 2"}}</span>{{end}}
14 </div>14 </div>
15- {{if .Summary}}<p class="text-sm text-spot-secondary mt-2 line-clamp-2">{{plainText .Summary}}</p>{{end}}15+ {{if .Summary}}<p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed pl-5">{{plainText .Summary}}</p>{{end}}
16 </div>16 </div>
17 <div class="shrink-0 pt-1">17 <div class="shrink-0 pt-1">
18 <button hx-post="/recs/dismiss-article" hx-target="closest article" hx-swap="delete" hx-include="#dismiss-{{.ArticleID}}"18 <button hx-post="/recs/dismiss-article" hx-target="closest article" hx-swap="delete" hx-include="#dismiss-{{.ArticleID}}"
19- class="text-[10px] text-spot-secondary hover:text-spot-text uppercase tracking-button transition flex items-center gap-1">19+ class="text-[10px] text-spot-muted hover:text-spot-text uppercase tracking-button transition flex items-center gap-1"
20+ title="Not interested">
20 <input type="hidden" name="article_url" value="{{.URL}}" id="dismiss-{{.ArticleID}}">21 <input type="hidden" name="article_url" value="{{.URL}}" id="dismiss-{{.ArticleID}}">
21 <svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>22 <svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
22 Dismiss23 Dismiss
@@ -24,4 +25,4 @@
24 </div>25 </div>
25 </div>26 </div>
26 </article>27 </article>
27-{{end}}
\ No newline at end of file\ No newline at end of file
28+{{end}}
modified internal/tmpl/partials/recommendation-feed-card.html +6 -6
@@ -1,5 +1,5 @@
11 {{define "recommendation-feed-card.html"}}
2-<div class="recommendation-card bg-spot-surface rounded-xl p-3 hover:bg-spot-hover-50 transition">
2+<div class="recommendation-card bg-spot-surface rounded-xl p-3 hover:bg-spot-hover-50 transition shadow-spot">
33 <div class="flex items-center justify-between gap-2">
44 <a href="/articles?feed={{.feed_url}}" class="min-w-0 flex items-center gap-2 flex-1">
55 {{template "favicon" dict "src" .favicon_url "size" "w-4 h-4"}}
@@ -10,17 +10,17 @@
1010 </a>
1111 <div class="flex items-center gap-2 shrink-0">
1212 <span class="text-xs text-spot-secondary">{{.subscriber_count}} subs</span>
13- <form hx-post="/recs/dismiss-feed" hx-target="closest .recommendation-card" hx-swap="outerHTML" class="inline">
13+ <form hx-post="/recs/dismiss-feed" hx-target="closest .recommendation-card" hx-swap="outerHTML" class="inline-flex items-center">
1414 {{csrfInput .CSRFToken}}
1515 <input type="hidden" name="feed_url" value="{{.feed_url}}">
16- <button type="submit" title="Not interested" class="text-spot-muted hover:text-spot-red transition -m-1 p-1 rounded-full hover:bg-spot-hover-50 flex items-center">
17- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/></svg>
16+ <button type="submit" title="Not interested" class="text-spot-muted hover:text-spot-red transition p-0.5 rounded hover:bg-spot-hover inline-flex items-center">
17+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-3.5 h-3.5"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/></svg>
1818 </button>
1919 </form>
20- <form hx-post="/feeds/add" hx-target="closest .recommendation-card" hx-swap="outerHTML" class="inline">
20+ <form hx-post="/feeds/add" hx-target="closest .recommendation-card" hx-swap="outerHTML" class="inline-flex items-center">
2121 {{csrfInput .CSRFToken}}
2222 <input type="hidden" name="feed_url" value="{{.feed_url}}">
23- <button type="submit" class="text-xs font-bold uppercase tracking-button text-spot-green hover:brightness-110 transition">Subscribe</button>
23+ <button type="submit" title="Subscribe" class="text-xs font-bold uppercase tracking-button text-spot-green hover:brightness-110 transition">Subscribe</button>
2424 </form>
2525 </div>
2626 </div>
@@ -1,5 +1,5 @@
1 {{define "recommendation-feed-card.html"}}1 {{define "recommendation-feed-card.html"}}
2-<div class="recommendation-card bg-spot-surface rounded-xl p-3 hover:bg-spot-hover-50 transition">2+<div class="recommendation-card bg-spot-surface rounded-xl p-3 hover:bg-spot-hover-50 transition shadow-spot">
3 <div class="flex items-center justify-between gap-2">3 <div class="flex items-center justify-between gap-2">
4 <a href="/articles?feed={{.feed_url}}" class="min-w-0 flex items-center gap-2 flex-1">4 <a href="/articles?feed={{.feed_url}}" class="min-w-0 flex items-center gap-2 flex-1">
5 {{template "favicon" dict "src" .favicon_url "size" "w-4 h-4"}}5 {{template "favicon" dict "src" .favicon_url "size" "w-4 h-4"}}
@@ -10,17 +10,17 @@
10 </a>10 </a>
11 <div class="flex items-center gap-2 shrink-0">11 <div class="flex items-center gap-2 shrink-0">
12 <span class="text-xs text-spot-secondary">{{.subscriber_count}} subs</span>12 <span class="text-xs text-spot-secondary">{{.subscriber_count}} subs</span>
13- <form hx-post="/recs/dismiss-feed" hx-target="closest .recommendation-card" hx-swap="outerHTML" class="inline">13+ <form hx-post="/recs/dismiss-feed" hx-target="closest .recommendation-card" hx-swap="outerHTML" class="inline-flex items-center">
14 {{csrfInput .CSRFToken}}14 {{csrfInput .CSRFToken}}
15 <input type="hidden" name="feed_url" value="{{.feed_url}}">15 <input type="hidden" name="feed_url" value="{{.feed_url}}">
16- <button type="submit" title="Not interested" class="text-spot-muted hover:text-spot-red transition -m-1 p-1 rounded-full hover:bg-spot-hover-50 flex items-center">16+ <button type="submit" title="Not interested" class="text-spot-muted hover:text-spot-red transition p-0.5 rounded hover:bg-spot-hover inline-flex items-center">
17- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/></svg>17+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-3.5 h-3.5"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/></svg>
18 </button>18 </button>
19 </form>19 </form>
20- <form hx-post="/feeds/add" hx-target="closest .recommendation-card" hx-swap="outerHTML" class="inline">20+ <form hx-post="/feeds/add" hx-target="closest .recommendation-card" hx-swap="outerHTML" class="inline-flex items-center">
21 {{csrfInput .CSRFToken}}21 {{csrfInput .CSRFToken}}
22 <input type="hidden" name="feed_url" value="{{.feed_url}}">22 <input type="hidden" name="feed_url" value="{{.feed_url}}">
23- <button type="submit" class="text-xs font-bold uppercase tracking-button text-spot-green hover:brightness-110 transition">Subscribe</button>23+ <button type="submit" title="Subscribe" class="text-xs font-bold uppercase tracking-button text-spot-green hover:brightness-110 transition">Subscribe</button>
24 </form>24 </form>
25 </div>25 </div>
26 </div>26 </div>
modified static/input.css +9 -13
@@ -19,11 +19,6 @@
1919 --spot-placeholder: rgba(255,255,255,0.45);
2020 --spot-active-bg: #ffffff;
2121 --spot-active-text: #1E3932;
22- --radius-sm: 0.5rem;
23- --radius-md: 0.75rem;
24- --radius-lg: 1rem;
25- --radius-pill: 9999px;
26- --radius-full: 50%;
2722 --spot-shadow: 0 1px 2px rgba(0,0,0,0.40), 0 2px 4px rgba(0,0,0,0.20);
2823 --spot-shadow-heavy: 0 4px 8px rgba(0,0,0,0.35), 0 12px 24px rgba(0,0,0,0.25);
2924 --spot-shadow-elevated: 0 8px 16px rgba(0,0,0,0.40), 0 24px 48px rgba(0,0,0,0.30);
@@ -49,13 +44,6 @@
4944 --spot-shadow-heavy: 0 4px 12px rgba(0,0,0,0.08), 0 12px 28px rgba(0,0,0,0.06);
5045 --spot-shadow-elevated: 0 8px 24px rgba(0,0,0,0.10), 0 24px 48px rgba(0,0,0,0.08);
5146 }
52-
53- [data-shape="squared"] {
54- --radius-sm: 0;
55- --radius-md: 0;
56- --radius-lg: 0;
57- --radius-pill: 0;
58- }
5947 }
6048
6149 @layer components {
@@ -108,9 +96,17 @@ body {
10896 color: var(--spot-text);
10997 }
11098
99+#mobile-nav a.bg-spot-hover {
100+ background: transparent !important;
101+ color: #00754A !important;
102+}
103+#mobile-nav a {
104+ transition: color 0.15s ease;
105+}
106+
111107 ::-webkit-scrollbar { width: 8px; }
112108 ::-webkit-scrollbar-track { background: var(--spot-bg); }
113-::-webkit-scrollbar-thumb { background: var(--spot-muted); border-radius: var(--radius-md); }
109+::-webkit-scrollbar-thumb { background: var(--spot-muted); border-radius: 6px; }
114110 ::-webkit-scrollbar-thumb:hover { background: var(--spot-outline); }
115111
116112 .htmx-swapping {
@@ -19,11 +19,6 @@
19 --spot-placeholder: rgba(255,255,255,0.45);19 --spot-placeholder: rgba(255,255,255,0.45);
20 --spot-active-bg: #ffffff;20 --spot-active-bg: #ffffff;
21 --spot-active-text: #1E3932;21 --spot-active-text: #1E3932;
22- --radius-sm: 0.5rem;
23- --radius-md: 0.75rem;
24- --radius-lg: 1rem;
25- --radius-pill: 9999px;
26- --radius-full: 50%;
27 --spot-shadow: 0 1px 2px rgba(0,0,0,0.40), 0 2px 4px rgba(0,0,0,0.20);22 --spot-shadow: 0 1px 2px rgba(0,0,0,0.40), 0 2px 4px rgba(0,0,0,0.20);
28 --spot-shadow-heavy: 0 4px 8px rgba(0,0,0,0.35), 0 12px 24px rgba(0,0,0,0.25);23 --spot-shadow-heavy: 0 4px 8px rgba(0,0,0,0.35), 0 12px 24px rgba(0,0,0,0.25);
29 --spot-shadow-elevated: 0 8px 16px rgba(0,0,0,0.40), 0 24px 48px rgba(0,0,0,0.30);24 --spot-shadow-elevated: 0 8px 16px rgba(0,0,0,0.40), 0 24px 48px rgba(0,0,0,0.30);
@@ -49,13 +44,6 @@
49 --spot-shadow-heavy: 0 4px 12px rgba(0,0,0,0.08), 0 12px 28px rgba(0,0,0,0.06);44 --spot-shadow-heavy: 0 4px 12px rgba(0,0,0,0.08), 0 12px 28px rgba(0,0,0,0.06);
50 --spot-shadow-elevated: 0 8px 24px rgba(0,0,0,0.10), 0 24px 48px rgba(0,0,0,0.08);45 --spot-shadow-elevated: 0 8px 24px rgba(0,0,0,0.10), 0 24px 48px rgba(0,0,0,0.08);
51 }46 }
52-
53- [data-shape="squared"] {
54- --radius-sm: 0;
55- --radius-md: 0;
56- --radius-lg: 0;
57- --radius-pill: 0;
58- }
59 }47 }
60 48
61 @layer components {49 @layer components {
@@ -108,9 +96,17 @@ body {
108 color: var(--spot-text);96 color: var(--spot-text);
109 }97 }
110 98
99+#mobile-nav a.bg-spot-hover {
100+ background: transparent !important;
101+ color: #00754A !important;
102+}
103+#mobile-nav a {
104+ transition: color 0.15s ease;
105+}
106+
111 ::-webkit-scrollbar { width: 8px; }107 ::-webkit-scrollbar { width: 8px; }
112 ::-webkit-scrollbar-track { background: var(--spot-bg); }108 ::-webkit-scrollbar-track { background: var(--spot-bg); }
113-::-webkit-scrollbar-thumb { background: var(--spot-muted); border-radius: var(--radius-md); }109+::-webkit-scrollbar-thumb { background: var(--spot-muted); border-radius: 6px; }
114 ::-webkit-scrollbar-thumb:hover { background: var(--spot-outline); }110 ::-webkit-scrollbar-thumb:hover { background: var(--spot-outline); }
115 111
116 .htmx-swapping {112 .htmx-swapping {
modified tailwind.config.js +7 -8
@@ -30,14 +30,13 @@ module.exports = {
3030 }
3131 },
3232 borderRadius: {
33- DEFAULT: 'var(--radius-sm)',
34- pill: 'var(--radius-pill)',
35- 'pill-lg': 'var(--radius-pill)',
36- sm: 'var(--radius-sm)',
37- md: 'var(--radius-md)',
38- lg: 'var(--radius-md)',
39- xl: 'var(--radius-lg)',
40- full: 'var(--radius-full)',
33+ DEFAULT: '6px',
34+ sm: '6px',
35+ md: '8px',
36+ lg: '10px',
37+ xl: '12px',
38+ pill: '9999px',
39+ full: '50%',
4140 },
4241 boxShadow: {
4342 'spot': 'var(--spot-shadow)',
@@ -30,14 +30,13 @@ module.exports = {
30 }30 }
31 },31 },
32 borderRadius: {32 borderRadius: {
33- DEFAULT: 'var(--radius-sm)',33+ DEFAULT: '6px',
34- pill: 'var(--radius-pill)',34+ sm: '6px',
35- 'pill-lg': 'var(--radius-pill)',35+ md: '8px',
36- sm: 'var(--radius-sm)',36+ lg: '10px',
37- md: 'var(--radius-md)',37+ xl: '12px',
38- lg: 'var(--radius-md)',38+ pill: '9999px',
39- xl: 'var(--radius-lg)',39+ full: '50%',
40- full: 'var(--radius-full)',
41 },40 },
42 boxShadow: {41 boxShadow: {
43 'spot': 'var(--spot-shadow)',42 'spot': 'var(--spot-shadow)',