nandi/gleanpublic Fork 0
4bd7c6a
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/unread button stylesUnverified

Julien Robert committed 2026-05-15T21:25:39+02:00 Browse files
4bd7c6a parent: 6ba2d25
modified internal/server/articles_handler.go +2 -2
@@ -292,7 +292,7 @@ func (s *Server) handleMarkRead(w http.ResponseWriter, r *http.Request) {
292292 return
293293 }
294294 w.Header().Set("Content-Type", "text/html")
295- 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)
295+ 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)
296296 }
297297
298298 func (s *Server) handleMarkUnread(w http.ResponseWriter, r *http.Request) {
@@ -307,7 +307,7 @@ func (s *Server) handleMarkUnread(w http.ResponseWriter, r *http.Request) {
307307 return
308308 }
309309 w.Header().Set("Content-Type", "text/html")
310- fmt.Fprintf(w, `<button id="read-btn-%[1]d" hx-post="/articles/%[1]d/read" hx-target="#read-btn-%[1]d" hx-swap="outerHTML" 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"><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>Read</span></button>`, id)
310+ fmt.Fprintf(w, `<button id="read-btn-%[1]d" hx-post="/articles/%[1]d/read" hx-target="#read-btn-%[1]d" hx-swap="outerHTML" 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"><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>Read</span></button>`, id)
311311 }
312312
313313 func (s *Server) handleLikeArticle(w http.ResponseWriter, r *http.Request) {
@@ -292,7 +292,7 @@ func (s *Server) handleMarkRead(w http.ResponseWriter, r *http.Request) {
292 return292 return
293 }293 }
294 w.Header().Set("Content-Type", "text/html")294 w.Header().Set("Content-Type", "text/html")
295- 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)295+ 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)
296 }296 }
297 297
298 func (s *Server) handleMarkUnread(w http.ResponseWriter, r *http.Request) {298 func (s *Server) handleMarkUnread(w http.ResponseWriter, r *http.Request) {
@@ -307,7 +307,7 @@ func (s *Server) handleMarkUnread(w http.ResponseWriter, r *http.Request) {
307 return307 return
308 }308 }
309 w.Header().Set("Content-Type", "text/html")309 w.Header().Set("Content-Type", "text/html")
310- fmt.Fprintf(w, `<button id="read-btn-%[1]d" hx-post="/articles/%[1]d/read" hx-target="#read-btn-%[1]d" hx-swap="outerHTML" 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"><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>Read</span></button>`, id)310+ fmt.Fprintf(w, `<button id="read-btn-%[1]d" hx-post="/articles/%[1]d/read" hx-target="#read-btn-%[1]d" hx-swap="outerHTML" 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"><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>Read</span></button>`, id)
311 }311 }
312 312
313 func (s *Server) handleLikeArticle(w http.ResponseWriter, r *http.Request) {313 func (s *Server) handleLikeArticle(w http.ResponseWriter, r *http.Request) {
modified internal/tmpl/article_detail.html +1 -1
@@ -43,7 +43,7 @@
4343 <button hx-post="/articles/{{.Article.ID}}/{{if .ReadState.IsRead}}unread{{else}}read{{end}}"
4444 hx-target="#read-btn-{{.Article.ID}}" hx-swap="outerHTML"
4545 id="read-btn-{{.Article.ID}}"
46- title="{{if .ReadState.IsRead}}Mark as Unread{{else}}Mark as Read{{end}}"
46+ title="{{if .ReadState.IsRead}}Mark as unread{{else}}Mark as read{{end}}"
4747 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}}">
4848 <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>
4949 <span>{{if .ReadState.IsRead}}Unread{{else}}Read{{end}}</span>
@@ -43,7 +43,7 @@
43 <button hx-post="/articles/{{.Article.ID}}/{{if .ReadState.IsRead}}unread{{else}}read{{end}}"43 <button hx-post="/articles/{{.Article.ID}}/{{if .ReadState.IsRead}}unread{{else}}read{{end}}"
44 hx-target="#read-btn-{{.Article.ID}}" hx-swap="outerHTML"44 hx-target="#read-btn-{{.Article.ID}}" hx-swap="outerHTML"
45 id="read-btn-{{.Article.ID}}"45 id="read-btn-{{.Article.ID}}"
46- title="{{if .ReadState.IsRead}}Mark as Unread{{else}}Mark as Read{{end}}"46+ title="{{if .ReadState.IsRead}}Mark as unread{{else}}Mark as read{{end}}"
47 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 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}}">
48 <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 <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>
49 <span>{{if .ReadState.IsRead}}Unread{{else}}Read{{end}}</span>49 <span>{{if .ReadState.IsRead}}Unread{{else}}Read{{end}}</span>
modified internal/tmpl/articles.html +1 -1
@@ -47,7 +47,7 @@
4747 <form method="GET" action="/articles" class="flex-1" id="search-form">
4848 <div class="relative">
4949 <input type="text" name="q" value="{{.SearchQuery}}" placeholder="Search articles..."
50- class="w-full bg-spot-hover text-spot-text rounded-pill pl-10 pr-4 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-placeholder"
50+ class="w-full bg-spot-hover text-spot-text rounded-pill pl-10 pr-4 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-secondary"
5151 hx-get="/articles" hx-trigger="keyup changed delay:300ms, search" hx-target="#article-list" hx-swap="innerHTML" hx-include="[name='q']">
5252 <svg class="w-4 h-4 text-spot-muted absolute left-3.5 top-1/2 -translate-y-1/2 pointer-events-none" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
5353 {{if .FeedURL}}<input type="hidden" name="feed" value="{{.FeedURL}}">{{end}}
@@ -47,7 +47,7 @@
47 <form method="GET" action="/articles" class="flex-1" id="search-form">47 <form method="GET" action="/articles" class="flex-1" id="search-form">
48 <div class="relative">48 <div class="relative">
49 <input type="text" name="q" value="{{.SearchQuery}}" placeholder="Search articles..."49 <input type="text" name="q" value="{{.SearchQuery}}" placeholder="Search articles..."
50- class="w-full bg-spot-hover text-spot-text rounded-pill pl-10 pr-4 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-placeholder"50+ class="w-full bg-spot-hover text-spot-text rounded-pill pl-10 pr-4 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-spot-green placeholder:text-spot-secondary"
51 hx-get="/articles" hx-trigger="keyup changed delay:300ms, search" hx-target="#article-list" hx-swap="innerHTML" hx-include="[name='q']">51 hx-get="/articles" hx-trigger="keyup changed delay:300ms, search" hx-target="#article-list" hx-swap="innerHTML" hx-include="[name='q']">
52 <svg class="w-4 h-4 text-spot-muted absolute left-3.5 top-1/2 -translate-y-1/2 pointer-events-none" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>52 <svg class="w-4 h-4 text-spot-muted absolute left-3.5 top-1/2 -translate-y-1/2 pointer-events-none" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
53 {{if .FeedURL}}<input type="hidden" name="feed" value="{{.FeedURL}}">{{end}}53 {{if .FeedURL}}<input type="hidden" name="feed" value="{{.FeedURL}}">{{end}}
modified internal/tmpl/partials/article-card.html +6 -8
@@ -15,14 +15,12 @@
1515 <p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed">{{plainText .Summary.String}}</p>
1616 {{end}}{{end}}
1717 </div>
18- <div class="grid gap-2 shrink-0 pt-0.5">
19- <div class="flex justify-center">{{template "like-button.html" .}}</div>
20- <div class="flex justify-center">
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">
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>
23- <span>{{if .IsRead.Bool}}Unread{{else}}Read{{end}}</span>
24- </button>
25- </div>
18+ <div class="grid grid-cols-1 gap-2 shrink-0 pt-0.5">
19+ {{template "like-button.html" .}}
20+ <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 justify-center gap-1 text-[10px] text-spot-text hover:text-spot-green hover:bg-spot-green/15 uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover transition w-full">
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="M4.5 12.75l6 6 9-13.5"/></svg>
22+ <span>{{if .IsRead.Bool}}Unread{{else}}Read{{end}}</span>
23+ </button>
2624 </div>
2725 </div>
2826 <div class="annotate-form hidden mt-4 pt-4 border-t border-spot-divider">
@@ -15,14 +15,12 @@
15 <p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed">{{plainText .Summary.String}}</p>15 <p class="text-sm text-spot-secondary mt-2.5 line-clamp-2 leading-relaxed">{{plainText .Summary.String}}</p>
16 {{end}}{{end}}16 {{end}}{{end}}
17 </div>17 </div>
18- <div class="grid gap-2 shrink-0 pt-0.5">18+ <div class="grid grid-cols-1 gap-2 shrink-0 pt-0.5">
19- <div class="flex justify-center">{{template "like-button.html" .}}</div>19+ {{template "like-button.html" .}}
20- <div class="flex justify-center">20+ <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 justify-center gap-1 text-[10px] text-spot-text hover:text-spot-green hover:bg-spot-green/15 uppercase tracking-button px-2 py-0.5 rounded-pill bg-spot-hover transition w-full">
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">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="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>22+ <span>{{if .IsRead.Bool}}Unread{{else}}Read{{end}}</span>
23- <span>{{if .IsRead.Bool}}Unread{{else}}Read{{end}}</span>23+ </button>
24- </button>
25- </div>
26 </div>24 </div>
27 </div>25 </div>
28 <div class="annotate-form hidden mt-4 pt-4 border-t border-spot-divider">26 <div class="annotate-form hidden mt-4 pt-4 border-t border-spot-divider">
modified internal/tmpl/partials/like-button.html +1 -1
@@ -1,7 +1,7 @@
11 {{define "like-button.html"}}
22 <button hx-post="/articles/{{.ID}}/like" hx-target="this" hx-swap="outerHTML"
33 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}}">
4+ class="group inline-flex items-center justify-center gap-1 text-[10px] uppercase tracking-button px-2 py-0.5 rounded-pill transition w-full {{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}}">
55 <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>
66 <span>{{.LikeCount}}</span>
77 </button>
@@ -1,7 +1,7 @@
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 title="{{if .HasLiked}}Unlike{{else}}Like{{end}}"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}}">4+ class="group inline-flex items-center justify-center gap-1 text-[10px] uppercase tracking-button px-2 py-0.5 rounded-pill transition w-full {{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 <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>
6 <span>{{.LikeCount}}</span>6 <span>{{.LikeCount}}</span>
7 </button>7 </button>