commit d777cb1ba933b5e0965abfa0e19d8162c6ca5068
parent 1857a25cd8c345818b4c97deda2a0f500e3f2e70
Author: brookjeynes <me@brookjeynes.dev>
Date: Sat, 13 Jun 2026 11:53:41 +1000
ui: style song page
Signed-off-by: brookjeynes <me@brookjeynes.dev>
Diffstat:
6 files changed, 122 insertions(+), 66 deletions(-)
diff --git a/Makefile b/Makefile
@@ -18,7 +18,7 @@ generate:
go tool templ generate
assets:
- ./build-assets.sh
+ ./scripts/build-assets.sh
fmt:
go fmt ./...
diff --git a/build-assets.sh b/build-assets.sh
@@ -1,23 +0,0 @@
-#! /bin/bash
-set -e
-
-if [ ! -f static/vendor/htmx.min.js ] || [ ! -f static/vendor/alpine.min.js ] || [ ! -f static/vendor/lucide.min.js ]; then
- printf '%s\n' 'missing static vendor files; run make setup first' >&2
- exit 1
-fi
-
-rm -rf static/files
-mkdir -p static/files/js
-mkdir -p static/vendor
-
-cp static/vendor/*.min.js static/files/js/
-
-minify internal/server/ui/styles.css -o static/files/styles.css
-minify internal/server/toast/toast.css -o static/files/toast.css
-minify static/minimal.css -o static/files/minimal.css
-
-minify internal/server/ui/js/string-utils.js -o static/files/js/string-utils.js
-minify internal/server/ui/js/lucide-utils.js -o static/files/js/lucide-utils.js
-minify internal/server/ui/views/new-song/new-song.js -o static/files/js/new-song.js
-minify internal/server/ui/views/new-album/new-album.js -o static/files/js/new-album.js
-minify internal/server/toast/toast.js -o static/files/js/toast.js
diff --git a/internal/server/ui/layouts/base/base.templ b/internal/server/ui/layouts/base/base.templ
@@ -30,6 +30,7 @@ templ Base(params BaseParams) {
<script src="/static/js/toast.js" defer></script>
<script src="/static/js/string-utils.js" defer></script>
<link rel="stylesheet" href="/static/styles.css" type="text/css"/>
+ <link rel="stylesheet" href="/static/song.css" type="text/css"/>
<link rel="stylesheet" href="/static/minimal.css" type="text/css"/>
<link rel="stylesheet" href="/static/toast.css" type="text/css"/>
<title>{ params.Title }</title>
diff --git a/internal/server/ui/views/song/song.css b/internal/server/ui/views/song/song.css
@@ -0,0 +1,35 @@
+.song-layout {
+ display: flex;
+ gap: 2rem;
+ align-items: flex-start;
+}
+
+.song-content {
+ flex: 1;
+ min-width: 0;
+}
+
+.song-details {
+ flex: 0 0 18rem;
+
+ dl {
+ dd {
+ margin-bottom: 0.5rem;
+
+ ul {
+ padding-left: 0;
+ }
+ }
+ }
+}
+
+@media (max-width: 700px) {
+ .song-layout {
+ flex-direction: column;
+ }
+
+ .song-details {
+ width: 100%;
+ flex-basis: auto;
+ }
+}
diff --git a/internal/server/ui/views/song/song.templ b/internal/server/ui/views/song/song.templ
@@ -9,53 +9,72 @@ import (
templ Song(params SongParams) {
@base.Base(base.BaseParams{Title: params.Song.Title}) {
- <article>
- <header>
- <hgroup>
- <h1>
+ <article class="song-layout">
+ <section class="song-content">
+ <header>
+ <h1 id="song-title">
{ params.Song.Title }
if params.Song.LatinTitle != nil {
<span>({ *params.Song.LatinTitle })</span>
}
</h1>
- </hgroup>
- <ul>
- for _, artist := range params.Song.Artists {
- <li>
- <a href={ routes.Artist(artist.Artist) }>
- { artist.Artist.Name }
- if artist.Artist.LatinName != nil {
- <span>({ *artist.Artist.LatinName })</span>
- }
- if artist.Role == domain.RoleFeatured {
- [featured]
- }
- </a>
- </li>
- }
- </ul>
- <time datetime={ params.Song.ReleaseDate.Format(time.DateOnly) }>{ params.Song.ReleaseDate.Format("Jan 2, 2006") }</time>
- <ul>
- for _, genre := range params.Song.Genres {
- <li>
- { genre }
- </li>
- }
- </ul>
- <ul>
- for _, album := range params.Song.Albums {
- <li>
- <a href={ routes.Album(album.Album) }>
- { album.Album.Title }
- if album.Album.LatinTitle != nil {
- <span>({ *album.Album.LatinTitle })</span>
- }
- </a>
- </li>
- }
- </ul>
- </header>
- <pre>{ params.Song.Lyrics }</pre>
+ </header>
+ <section>
+ <h2 id="lyrics-heading">Lyrics</h2>
+ <pre>{ params.Song.Lyrics }</pre>
+ </section>
+ </section>
+ <aside class="song-details">
+ <dl>
+ <dt>Artist(s)</dt>
+ <dd>
+ <ul>
+ for _, artist := range params.Song.Artists {
+ <li>
+ <a href={ routes.Artist(artist.Artist) }>
+ { artist.Artist.Name }
+ if artist.Artist.LatinName != nil {
+ <span>({ *artist.Artist.LatinName })</span>
+ }
+ if artist.Role == domain.RoleFeatured {
+ <span>[featured]</span>
+ }
+ </a>
+ </li>
+ }
+ </ul>
+ </dd>
+ <dt>Released</dt>
+ <dd>
+ <time datetime={ params.Song.ReleaseDate.Format(time.DateOnly) }>
+ { params.Song.ReleaseDate.Format("Jan 2, 2006") }
+ </time>
+ </dd>
+ <dt>Genre(s)</dt>
+ <dd>
+ <ul>
+ for _, genre := range params.Song.Genres {
+ <li>{ genre }</li>
+ }
+ </ul>
+ </dd>
+ <dt>Album(s)</dt>
+ <dd>
+ <ul>
+ for _, album := range params.Song.Albums {
+ <li>
+ <a href={ routes.Album(album.Album) }>
+ { album.Album.Title }
+ if album.Album.LatinTitle != nil {
+ <span>({ *album.Album.LatinTitle })</span>
+ }
+ </a>
+ </li>
+ }
+ </ul>
+ </dd>
+ </dl>
+ </aside>
</article>
}
}
diff --git a/scripts/build-assets.sh b/scripts/build-assets.sh
@@ -0,0 +1,24 @@
+#! /bin/bash
+set -e
+
+if [ ! -f static/vendor/htmx.min.js ] || [ ! -f static/vendor/alpine.min.js ] || [ ! -f static/vendor/lucide.min.js ]; then
+ printf '%s\n' 'missing static vendor files; run make setup first' >&2
+ exit 1
+fi
+
+rm -rf static/files
+mkdir -p static/files/js
+mkdir -p static/vendor
+
+cp static/vendor/*.min.js static/files/js/
+
+minify internal/server/ui/styles.css -o static/files/styles.css
+minify internal/server/toast/toast.css -o static/files/toast.css
+minify internal/server/ui/views/song/song.css -o static/files/song.css
+minify static/minimal.css -o static/files/minimal.css
+
+minify internal/server/ui/js/string-utils.js -o static/files/js/string-utils.js
+minify internal/server/ui/js/lucide-utils.js -o static/files/js/lucide-utils.js
+minify internal/server/ui/views/new-song/new-song.js -o static/files/js/new-song.js
+minify internal/server/ui/views/new-album/new-album.js -o static/files/js/new-album.js
+minify internal/server/toast/toast.js -o static/files/js/toast.js