Improve read article visualsUnverified
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) { | ||
| 293 | 293 | return |
| 294 | 294 | } |
| 295 | 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 | 299 | 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 | return | 293 | 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 @@ | ||
| 130 | 130 | method: 'POST', |
| 131 | 131 | headers: {'X-CSRF-Token': document.querySelector('input[name="csrf_token"]') ? document.querySelector('input[name="csrf_token"]').value : ''} |
| 132 | 132 | }).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]'); } | |
| 135 | 136 | }).catch(function() {}); |
| 136 | 137 | } |
| 137 | 138 | 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 @@ | ||
| 1 | 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 | 3 | <div class="flex items-start justify-between gap-4"> |
| 4 | 4 | <div class="min-w-0 flex-1"> |
| 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> | |
| 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> | |
| 8 | 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 | 9 | {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-3.5 h-3.5"}} |
| 11 | 10 | <a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-text transition font-medium">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a> |
| 12 | 11 | {{if .Author.Valid}}{{if .Author.String}}<span class="text-spot-muted">·</span><span>{{.Author.String}}</span>{{end}}{{end}} |
| @@ -35,12 +34,15 @@ | ||
| 35 | 34 | </div> |
| 36 | 35 | </div> |
| 37 | 36 | {{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 →</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> | |
| 40 | 42 | </div> |
| 41 | 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 | 46 | <div>{{template "like-button.html" .}}</div> |
| 45 | 47 | </div> |
| 46 | 48 | </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">·</span><span>{{.Author.String}}</span>{{end}}{{end}} | 11 | {{if .Author.Valid}}{{if .Author.String}}<span class="text-spot-muted">·</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 →</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 @@ | ||
| 1 | 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 | 3 | <div class="flex items-start justify-between gap-4"> |
| 4 | 4 | <div class="min-w-0 flex-1"> |
| 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}} | |
| 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> | |
| 8 | 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 | 9 | {{template "favicon" dict "src" .FeedFaviconURL.String "size" "w-3.5 h-3.5"}} |
| 11 | 10 | <a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-text transition font-medium">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a> |
| 12 | 11 | {{if .Author.Valid}}{{if .Author.String}}<span class="text-spot-muted">·</span><span>{{.Author.String}}</span>{{end}}{{end}} |
| 13 | 12 | {{if .Published.Valid}}<span class="text-spot-muted">·</span><span>{{.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}} |
| 14 | 13 | </div> |
| 15 | 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 | 16 | {{end}}{{end}} |
| 18 | 17 | </div> |
| 19 | 18 | <div class="grid gap-2 shrink-0 pt-0.5"> |
| 20 | 19 | <div class="flex justify-center">{{template "like-button.html" .}}</div> |
| 21 | 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 | 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 | 23 | <span>{{if .IsRead.Bool}}Unread{{else}}Read{{end}}</span> |
| 25 | 24 | </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">·</span><span>{{.Author.String}}</span>{{end}}{{end}} | 11 | {{if .Author.Valid}}{{if .Author.String}}<span class="text-spot-muted">·</span><span>{{.Author.String}}</span>{{end}}{{end}} |
| 13 | {{if .Published.Valid}}<span class="text-spot-muted">·</span><span>{{.Published.Time.Format "Jan 2, 2006 15:04"}}</span>{{end}} | 12 | {{if .Published.Valid}}<span class="text-spot-muted">·</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 @@ | ||
| 1 | 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 | 3 | <div class="flex items-start justify-between gap-4"> |
| 4 | 4 | <div class="min-w-0 flex-1"> |
| 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}} | |
| 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> | |
| 8 | 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 | 9 | {{if .FaviconURL}}{{template "favicon" dict "src" .FaviconURL "size" "w-3.5 h-3.5"}}{{end}} |
| 11 | 10 | <a href="/articles?feed={{.FeedURL}}" class="hover:text-spot-text transition font-medium">{{if .FeedTitle}}{{.FeedTitle}}{{else}}{{.FeedURL}}{{end}}</a> |
| 12 | 11 | {{if .Author}}<span class="text-spot-muted">·</span><span>{{.Author}}</span>{{end}} |
| 13 | 12 | {{if .Published.Valid}}<span class="text-spot-muted">·</span><span>{{.Published.Time.Format "Jan 2"}}</span>{{end}} |
| 14 | 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 | 15 | </div> |
| 17 | 16 | <div class="shrink-0 pt-0.5"> |
| 18 | 17 | <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">·</span><span>{{.Author}}</span>{{end}} | 11 | {{if .Author}}<span class="text-spot-muted">·</span><span>{{.Author}}</span>{{end}} |
| 13 | {{if .Published.Valid}}<span class="text-spot-muted">·</span><span>{{.Published.Time.Format "Jan 2"}}</span>{{end}} | 12 | {{if .Published.Valid}}<span class="text-spot-muted">·</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}}" |