feat: enhance book detail star rating display with visual half-stars

Improve star rating display on book detail page to show always-visible
5-star rating scale with theme-aware colors and visual half-star rendering.

Changes:

Enhanced renderStars() function:
- Always displays 5 stars (0/5 now shows 5 grey stars instead of empty)
- Filled stars use var(--accent) color (theme-aware highlight)
- Empty stars use var(--text-secondary) (theme-aware grey, adapts to light/dark themes)
- Half-stars use CSS linear-gradient (90deg) to split star vertically:
  - Left half: var(--accent) (filled, color)
  - Right half: var(--text-secondary) (empty, grey)
- Uses webkit-background-clip and text-fill-color transparent for gradient effect

Added getBookRating() helper function:
- Returns rating value or 0 if book.Rating is nil
- Allows unrated books to display 0/5 (5 grey stars)
- Makes rating section always visible instead of hiding when nil

Template changes:
- Updated rating display to always show (no conditionals)
- Removed text-yellow-400 class (colors now inline with theme vars)
- Added templ.Raw() wrapper for HTML rendering (prevents escaping)
- Simplified rating display logic

Benefits:
- Users can now see rating scale even when book isn't rated
- Visual half-star is much more intuitive than ½ text character
- Theme-aware colors adapt to light/dark mode automatically
- Follows existing patterns ( UnsafeHTML, CSS variables, etc.)

This makes the rating section more discoverable and user-friendly.
This commit is contained in:
2026-03-29 00:26:50 -04:00
parent a157c546fd
commit e89ed4dbc6
3 changed files with 246 additions and 243 deletions
+8 -10
View File
@@ -93,16 +93,14 @@ templ BookDetail(user User, book handlers.MediaDetail, errorMessage string) {
</button>
</div>
<!-- Rating Display -->
if book.Rating != nil {
<div class="mb-6">
<span class="text-yellow-400 text-2xl">
{ renderStars(book.Rating.Rating) }
</span>
<span class="ml-2 text-sm" style="color: var(--text-secondary);">
({ fmt.Sprintf("%.1f", float64(book.Rating.Rating)/2.0) } / 5)
</span>
</div>
}
<div class="mb-6">
<span class="text-2xl">
@templ.Raw(renderStars(getBookRating(book.Rating)))
</span>
<span class="ml-2 text-sm" style="color: var(--text-secondary);">
({ fmt.Sprintf("%.1f", float64(getBookRating(book.Rating))/2.0) } / 5)
</span>
</div>
<!-- Series Badge -->
if book.Series.Valid && book.Series.String != "" {
<div class="mb-4">