nandi/gleanpublic Fork 0
e4922e2
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 read article visualsUnverified

Julien Robert committed 2026-05-15T00:22:29+02:00 Browse files
e4922e2 parent: 75afa72
modified internal/server/articles_handler.go +1 -1
@@ -293,7 +293,7 @@ func (s *Server) handleMarkRead(w http.ResponseWriter, r *http.Request) {
293293 return
294294 }
295295 w.Header().Set("Content-Type", "text/html")
296- fmt.Fprintf(w, `<button id="read-btn-%[1]d" hx-post="/articles/%[1]d/unread" hx-target="#read-btn-%[1]d" hx-swap="outerHTML" title="Mark as Unread" 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"><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><span>Unread</span></button>`, id)
296+ fmt.Fprintf(w, `<button id="read-btn-%[1]d" hx-post="/articles/%[1]d/unread" hx-target="#read-btn-%[1]d" hx-swap="outerHTML" title="Mark as Unread" class="group inline-flex items-center gap-1 text-[10px] text-spot-secondary uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover hover:text-spot-green hover:bg-spot-green/15 transition"><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><span>Unread</span></button>`, id)
297297 }
298298
299299 func (s *Server) handleMarkUnread(w http.ResponseWriter, r *http.Request) {
@@ -293,7 +293,7 @@ func (s *Server) handleMarkRead(w http.ResponseWriter, r *http.Request) {
293 return293 return
294 }294 }
295 w.Header().Set("Content-Type", "text/html")295 w.Header().Set("Content-Type", "text/html")
296- fmt.Fprintf(w, `<button id="read-btn-%[1]d" hx-post="/articles/%[1]d/unread" hx-target="#read-btn-%[1]d" hx-swap="outerHTML" title="Mark as Unread" 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"><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><span>Unread</span></button>`, id)296+ fmt.Fprintf(w, `<button id="read-btn-%[1]d" hx-post="/articles/%[1]d/unread" hx-target="#read-btn-%[1]d" hx-swap="outerHTML" title="Mark as Unread" class="group inline-flex items-center gap-1 text-[10px] text-spot-secondary uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover hover:text-spot-green hover:bg-spot-green/15 transition"><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><span>Unread</span></button>`, id)
297 }297 }
298 298
299 func (s *Server) handleMarkUnread(w http.ResponseWriter, r *http.Request) {299 func (s *Server) handleMarkUnread(w http.ResponseWriter, r *http.Request) {
modified internal/tmpl/articles.html +3 -2
@@ -130,8 +130,9 @@
130130 method: 'POST',
131131 headers: {'X-CSRF-Token': document.querySelector('input[name="csrf_token"]') ? document.querySelector('input[name="csrf_token"]').value : ''}
132132 }).then(function() {
133- var dot = el.querySelector('.bg-spot-green.rounded-full');
134- if (dot) { dot.classList.remove('bg-spot-green'); dot.classList.add('bg-spot-muted'); }
133+ el.classList.remove('border-l', 'border-spot-green/80');
134+ var title = el.querySelector('a[href^="/articles/"]');
135+ if (title) { title.classList.remove('font-bold', 'text-[17px]'); title.classList.add('font-semibold', 'text-[15px]'); }
135136 }).catch(function() {});
136137 }
137138 var readTimers = {};
@@ -130,8 +130,9 @@
130 method: 'POST',130 method: 'POST',
131 headers: {'X-CSRF-Token': document.querySelector('input[name="csrf_token"]') ? document.querySelector('input[name="csrf_token"]').value : ''}131 headers: {'X-CSRF-Token': document.querySelector('input[name="csrf_token"]') ? document.querySelector('input[name="csrf_token"]').value : ''}
132 }).then(function() {132 }).then(function() {
133- var dot = el.querySelector('.bg-spot-green.rounded-full');133+ el.classList.remove('border-l', 'border-spot-green/80');
134- if (dot) { dot.classList.remove('bg-spot-green'); dot.classList.add('bg-spot-muted'); }134+ var title = el.querySelector('a[href^="/articles/"]');
135+ if (title) { title.classList.remove('font-bold', 'text-[17px]'); title.classList.add('font-semibold', 'text-[15px]'); }
135 }).catch(function() {});136 }).catch(function() {});
136 }137 }
137 var readTimers = {};138 var readTimers = {};
modified internal/tmpl/partials/article-card-expanded.html +9 -7
@@ -1,12 +1,11 @@
11 {{define "article-card-expanded.html"}}
2-<article data-article-id="{{.ID}}" data-feed-url="{{.FeedURL}}" data-article-url="{{if .URL.Valid}}{{.URL.String}}{{end}}" data-expanded="true" class="bg-spot-surface rounded-xl px-5 py-4 shadow-spot relative">
2+<article data-article-id="{{.ID}}" data-feed-url="{{.FeedURL}}" data-article-url="{{if .URL.Valid}}{{.URL.String}}{{end}}" data-expanded="true" class="bg-spot-surface rounded-xl px-5 py-4 shadow-spot relative {{if not .IsRead.Bool}}border-l border-spot-green/80{{end}}">
33 <div class="flex items-start justify-between gap-4">
44 <div class="min-w-0 flex-1">
55 <div class="flex items-start gap-2.5">
6- <span class="w-2 h-2 rounded-full shrink-0 mt-2 {{if .IsRead.Bool}}bg-spot-muted{{else}}bg-spot-green{{end}}"></span>
7- <a href="/articles/{{.ID}}{{.NavSuffix}}" class="font-semibold text-spot-text hover:text-spot-green transition leading-snug {{if .IsRead.Bool}}text-[15px]{{else}}text-[17px]{{end}}">{{.Title}}</a>
6+ <a href="/articles/{{.ID}}{{.NavSuffix}}" class="{{if .IsRead.Bool}}font-semibold text-[15px]{{else}}font-bold text-[17px]{{end}} text-spot-text hover:text-spot-green transition leading-snug">{{.Title}}</a>
87 </div>
9- <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap pl-[18px]">
8+ <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap">
109 {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-3.5 h-3.5"}}
1110 <a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-text transition font-medium">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a>
1211 {{if .Author.Valid}}{{if .Author.String}}<span class="text-spot-muted">&middot;</span><span>{{.Author.String}}</span>{{end}}{{end}}
@@ -35,12 +34,15 @@
3534 </div>
3635 </div>
3736 {{else}}
38- <div class="mt-4 pt-4 border-t border-spot-divider">
39- <a href="/articles/{{.ID}}{{.NavSuffix}}" class="text-spot-green hover:underline text-sm">Read full article &rarr;</a>
37+ <div class="mt-3 pt-3 border-t border-spot-divider">
38+ <a href="/articles/{{.ID}}{{.NavSuffix}}" class="inline-flex items-center gap-1.5 text-[10px] text-spot-secondary hover:text-spot-green uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover hover:bg-spot-green/15 transition">
39+ Read full article
40+ <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="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"/></svg>
41+ </a>
4042 </div>
4143 {{end}}
4244
43- <div class="mt-4 pt-4 border-t border-spot-divider flex items-center justify-end gap-1.5">
45+ <div class="mt-2 pt-2 border-t border-spot-divider flex items-center justify-end gap-1.5">
4446 <div>{{template "like-button.html" .}}</div>
4547 </div>
4648 </article>
@@ -1,12 +1,11 @@
1 {{define "article-card-expanded.html"}}1 {{define "article-card-expanded.html"}}
2-<article data-article-id="{{.ID}}" data-feed-url="{{.FeedURL}}" data-article-url="{{if .URL.Valid}}{{.URL.String}}{{end}}" data-expanded="true" class="bg-spot-surface rounded-xl px-5 py-4 shadow-spot relative">2+<article data-article-id="{{.ID}}" data-feed-url="{{.FeedURL}}" data-article-url="{{if .URL.Valid}}{{.URL.String}}{{end}}" data-expanded="true" class="bg-spot-surface rounded-xl px-5 py-4 shadow-spot relative {{if not .IsRead.Bool}}border-l border-spot-green/80{{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-start gap-2.5">5 <div class="flex items-start gap-2.5">
6- <span class="w-2 h-2 rounded-full shrink-0 mt-2 {{if .IsRead.Bool}}bg-spot-muted{{else}}bg-spot-green{{end}}"></span>6+ <a href="/articles/{{.ID}}{{.NavSuffix}}" class="{{if .IsRead.Bool}}font-semibold text-[15px]{{else}}font-bold text-[17px]{{end}} text-spot-text hover:text-spot-green transition leading-snug">{{.Title}}</a>
7- <a href="/articles/{{.ID}}{{.NavSuffix}}" class="font-semibold text-spot-text hover:text-spot-green transition leading-snug {{if .IsRead.Bool}}text-[15px]{{else}}text-[17px]{{end}}">{{.Title}}</a>
8 </div>7 </div>
9- <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap pl-[18px]">8+ <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap">
10 {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-3.5 h-3.5"}}9 {{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>10 <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}}11 {{if .Author.Valid}}{{if .Author.String}}<span class="text-spot-muted">&middot;</span><span>{{.Author.String}}</span>{{end}}{{end}}
@@ -35,12 +34,15 @@
35 </div>34 </div>
36 </div>35 </div>
37 {{else}}36 {{else}}
38- <div class="mt-4 pt-4 border-t border-spot-divider">37+ <div class="mt-3 pt-3 border-t border-spot-divider">
39- <a href="/articles/{{.ID}}{{.NavSuffix}}" class="text-spot-green hover:underline text-sm">Read full article &rarr;</a>38+ <a href="/articles/{{.ID}}{{.NavSuffix}}" class="inline-flex items-center gap-1.5 text-[10px] text-spot-secondary hover:text-spot-green uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover hover:bg-spot-green/15 transition">
39+ Read full article
40+ <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="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"/></svg>
41+ </a>
40 </div>42 </div>
41 {{end}}43 {{end}}
42 44
43- <div class="mt-4 pt-4 border-t border-spot-divider flex items-center justify-end gap-1.5">45+ <div class="mt-2 pt-2 border-t border-spot-divider flex items-center justify-end gap-1.5">
44 <div>{{template "like-button.html" .}}</div>46 <div>{{template "like-button.html" .}}</div>
45 </div>47 </div>
46 </article>48 </article>
modified internal/tmpl/partials/article-card.html +5 -6
@@ -1,25 +1,24 @@
11 {{define "article-card.html"}}
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 group {{if .IsRead.Bool}}opacity-55{{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 group {{if not .IsRead.Bool}}border-l border-spot-green/80{{end}}">
33 <div class="flex items-start justify-between gap-4">
44 <div class="min-w-0 flex-1">
55 <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 mt-2"></span>{{end}}
7- <a href="/articles/{{.ID}}{{.NavSuffix}}" class="font-semibold text-spot-text hover:text-spot-green transition leading-snug {{if .IsRead.Bool}}text-[15px]{{else}}text-[17px]{{end}}">{{.Title}}</a>
6+ <a href="/articles/{{.ID}}{{.NavSuffix}}" class="{{if .IsRead.Bool}}font-semibold text-[15px]{{else}}font-bold text-[17px]{{end}} text-spot-text hover:text-spot-green transition leading-snug">{{.Title}}</a>
87 </div>
9- <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap {{if not .IsRead.Bool}}pl-[18px]{{end}}">
8+ <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap">
109 {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-3.5 h-3.5"}}
1110 <a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-text transition font-medium">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a>
1211 {{if .Author.Valid}}{{if .Author.String}}<span class="text-spot-muted">&middot;</span><span>{{.Author.String}}</span>{{end}}{{end}}
1312 {{if .Published.Valid}}<span class="text-spot-muted">&middot;</span><span>{{.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}
1413 </div>
1514 {{if .Summary.Valid}}{{if .Summary.String}}
16- <p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed {{if not .IsRead.Bool}}pl-[18px]{{else}}pl-0{{end}}">{{plainText .Summary.String}}</p>
15+ <p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed">{{plainText .Summary.String}}</p>
1716 {{end}}{{end}}
1817 </div>
1918 <div class="grid gap-2 shrink-0 pt-0.5">
2019 <div class="flex justify-center">{{template "like-button.html" .}}</div>
2120 <div class="flex justify-center">
22- <button id="read-btn-{{.ID}}" hx-post="/articles/{{.ID}}/{{if .IsRead.Bool}}unread{{else}}read{{end}}" hx-target="#read-btn-{{.ID}}" hx-swap="outerHTML" title="{{if .IsRead.Bool}}Mark as Unread{{else}}Mark as Read{{end}}" class="group inline-flex items-center gap-1 text-[10px] {{if .IsRead.Bool}}text-spot-muted{{else}}text-spot-text hover:text-spot-green hover:bg-spot-green/15{{end}} uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover transition">
21+ <button id="read-btn-{{.ID}}" hx-post="/articles/{{.ID}}/{{if .IsRead.Bool}}unread{{else}}read{{end}}" hx-target="#read-btn-{{.ID}}" hx-swap="outerHTML" title="{{if .IsRead.Bool}}Mark as Unread{{else}}Mark as Read{{end}}" class="group inline-flex items-center gap-1 text-[10px] {{if .IsRead.Bool}}text-spot-secondary hover:text-spot-green hover:bg-spot-green/15{{else}}text-spot-text hover:text-spot-green hover:bg-spot-green/15{{end}} uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover transition">
2322 <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>
2423 <span>{{if .IsRead.Bool}}Unread{{else}}Read{{end}}</span>
2524 </button>
@@ -1,25 +1,24 @@
1 {{define "article-card.html"}}1 {{define "article-card.html"}}
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 group {{if .IsRead.Bool}}opacity-55{{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 group {{if not .IsRead.Bool}}border-l border-spot-green/80{{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-start gap-2.5">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 mt-2"></span>{{end}}6+ <a href="/articles/{{.ID}}{{.NavSuffix}}" class="{{if .IsRead.Bool}}font-semibold text-[15px]{{else}}font-bold text-[17px]{{end}} text-spot-text hover:text-spot-green transition leading-snug">{{.Title}}</a>
7- <a href="/articles/{{.ID}}{{.NavSuffix}}" class="font-semibold text-spot-text hover:text-spot-green transition leading-snug {{if .IsRead.Bool}}text-[15px]{{else}}text-[17px]{{end}}">{{.Title}}</a>
8 </div>7 </div>
9- <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap {{if not .IsRead.Bool}}pl-[18px]{{end}}">8+ <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap">
10 {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-3.5 h-3.5"}}9 {{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>10 <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}}11 {{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}}12 {{if .Published.Valid}}<span class="text-spot-muted">&middot;</span><span>{{.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}}
14 </div>13 </div>
15 {{if .Summary.Valid}}{{if .Summary.String}}14 {{if .Summary.Valid}}{{if .Summary.String}}
16- <p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed {{if not .IsRead.Bool}}pl-[18px]{{else}}pl-0{{end}}">{{plainText .Summary.String}}</p>15+ <p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed">{{plainText .Summary.String}}</p>
17 {{end}}{{end}}16 {{end}}{{end}}
18 </div>17 </div>
19 <div class="grid gap-2 shrink-0 pt-0.5">18 <div class="grid gap-2 shrink-0 pt-0.5">
20 <div class="flex justify-center">{{template "like-button.html" .}}</div>19 <div class="flex justify-center">{{template "like-button.html" .}}</div>
21 <div class="flex justify-center">20 <div class="flex justify-center">
22- <button id="read-btn-{{.ID}}" hx-post="/articles/{{.ID}}/{{if .IsRead.Bool}}unread{{else}}read{{end}}" hx-target="#read-btn-{{.ID}}" hx-swap="outerHTML" title="{{if .IsRead.Bool}}Mark as Unread{{else}}Mark as Read{{end}}" class="group inline-flex items-center gap-1 text-[10px] {{if .IsRead.Bool}}text-spot-muted{{else}}text-spot-text hover:text-spot-green hover:bg-spot-green/15{{end}} uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover transition">21+ <button id="read-btn-{{.ID}}" hx-post="/articles/{{.ID}}/{{if .IsRead.Bool}}unread{{else}}read{{end}}" hx-target="#read-btn-{{.ID}}" hx-swap="outerHTML" title="{{if .IsRead.Bool}}Mark as Unread{{else}}Mark as Read{{end}}" class="group inline-flex items-center gap-1 text-[10px] {{if .IsRead.Bool}}text-spot-secondary hover:text-spot-green hover:bg-spot-green/15{{else}}text-spot-text hover:text-spot-green hover:bg-spot-green/15{{end}} uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover transition">
23 <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>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="M4.5 12.75l6 6 9-13.5"/></svg>
24 <span>{{if .IsRead.Bool}}Unread{{else}}Read{{end}}</span>23 <span>{{if .IsRead.Bool}}Unread{{else}}Read{{end}}</span>
25 </button>24 </button>
modified internal/tmpl/partials/recommendation-article-card.html +4 -5
@@ -1,18 +1,17 @@
11 {{define "recommendation-article-card.html"}}
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 {{if not .IsRead}}border-l border-spot-green/80{{end}}">
33 <div class="flex items-start justify-between gap-4">
44 <div class="min-w-0 flex-1">
55 <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 mt-2"></span>{{end}}
7- <a href="/articles/{{.ArticleID}}" class="font-semibold text-spot-text hover:text-spot-green transition text-[17px] leading-snug">{{.Title}}</a>
6+ <a href="/articles/{{.ArticleID}}" class="{{if .IsRead}}font-semibold text-[15px]{{else}}font-bold text-[17px]{{end}} text-spot-text hover:text-spot-green transition leading-snug">{{.Title}}</a>
87 </div>
9- <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap {{if not .IsRead}}pl-[18px]{{end}}">
8+ <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap">
109 {{if .FaviconURL}}{{template "favicon" dict "src" .FaviconURL "size" "w-3.5 h-3.5"}}{{end}}
1110 <a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-text transition font-medium">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a>
1211 {{if .Author}}<span class="text-spot-muted">&middot;</span><span>{{.Author}}</span>{{end}}
1312 {{if .Published.Valid}}<span class="text-spot-muted">&middot;</span><span>{{.Published.Time.Format "Jan 2"}}</span>{{end}}
1413 </div>
15- {{if .Summary}}<p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed {{if not .IsRead}}pl-[18px]{{end}}">{{plainText .Summary}}</p>{{end}}
14+ {{if .Summary}}<p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed">{{plainText .Summary}}</p>{{end}}
1615 </div>
1716 <div class="shrink-0 pt-0.5">
1817 <button hx-post="/recs/dismiss-article" hx-target="closest article" hx-swap="delete" hx-include="#dismiss-{{.ArticleID}}"
@@ -1,18 +1,17 @@
1 {{define "recommendation-article-card.html"}}1 {{define "recommendation-article-card.html"}}
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 {{if not .IsRead}}border-l border-spot-green/80{{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-start gap-2.5">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 mt-2"></span>{{end}}6+ <a href="/articles/{{.ArticleID}}" class="{{if .IsRead}}font-semibold text-[15px]{{else}}font-bold text-[17px]{{end}} text-spot-text hover:text-spot-green transition leading-snug">{{.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>7 </div>
9- <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap {{if not .IsRead}}pl-[18px]{{end}}">8+ <div class="text-xs text-spot-secondary mt-2 flex items-center gap-1.5 flex-wrap">
10 {{if .FaviconURL}}{{template "favicon" dict "src" .FaviconURL "size" "w-3.5 h-3.5"}}{{end}}9 {{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>10 <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}}11 {{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}}12 {{if .Published.Valid}}<span class="text-spot-muted">&middot;</span><span>{{.Published.Time.Format "Jan 2"}}</span>{{end}}
14 </div>13 </div>
15- {{if .Summary}}<p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed {{if not .IsRead}}pl-[18px]{{end}}">{{plainText .Summary}}</p>{{end}}14+ {{if .Summary}}<p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed">{{plainText .Summary}}</p>{{end}}
16 </div>15 </div>
17 <div class="shrink-0 pt-0.5">16 <div class="shrink-0 pt-0.5">
18 <button hx-post="/recs/dismiss-article" hx-target="closest article" hx-swap="delete" hx-include="#dismiss-{{.ArticleID}}"17 <button hx-post="/recs/dismiss-article" hx-target="closest article" hx-swap="delete" hx-include="#dismiss-{{.ArticleID}}"