diff --git a/app/assets/stylesheets/components/_list.scss b/app/assets/stylesheets/components/_list.scss
index 34ea63c6..2b1f86c0 100644
--- a/app/assets/stylesheets/components/_list.scss
+++ b/app/assets/stylesheets/components/_list.scss
@@ -35,8 +35,7 @@
color: transparent;
}
-.c-list__item.is-active *,
-.c-list__item:hover button[type="submit"] * {
+.c-list__item.is-active * {
color: var(--list-active-color);
}
diff --git a/app/assets/stylesheets/components/_search.scss b/app/assets/stylesheets/components/_search.scss
index 3f68f6da..bb361927 100644
--- a/app/assets/stylesheets/components/_search.scss
+++ b/app/assets/stylesheets/components/_search.scss
@@ -1,3 +1,11 @@
+@use "../tools/functions" as *;
+
+.c-search {
+ max-width: 380px;
+ width: 100%;
+ margin: 0 spacing("small");
+}
+
.c-search .c-loader {
display: none;
}
diff --git a/app/assets/stylesheets/components/_table.scss b/app/assets/stylesheets/components/_table.scss
index 0aaeb340..5411f821 100644
--- a/app/assets/stylesheets/components/_table.scss
+++ b/app/assets/stylesheets/components/_table.scss
@@ -1,16 +1,37 @@
+@use "../tools/responsive";
@use "../tools/functions" as *;
.c-table {
+ display: table;
width: 100%;
- table-layout: fixed;
+ table-layout: auto;
text-align: left;
}
-.c-table tr,
+.c-table[role="table"] {
+ display: grid;
+ grid-template-columns: var(--grid-tc);
+ --grid-tc: repeat(5, auto);
+}
+
+.c-table [role="rowgroup"] {
+ display: contents;
+}
+
.c-table [role="row"] {
+ display: contents;
+}
+
+.c-table tr,
+.c-table [role="columnheader"],
+.c-table [role="cell"] {
border-bottom: 1px solid var(--table-border-color);
}
+.c-table [role="columnheader"] {
+ font-weight: bold;
+}
+
.c-table th,
.c-table td,
.c-table [role="columnheader"],
@@ -20,16 +41,16 @@
color: var(--table-color);
}
-.c-table th:first-child,
-.c-table td:first-child,
-.c-table [role="columnheader"]:first-child,
-.c-table [role="cell"]:first-child {
- padding-left: 0;
+.c-table [role="cell"][span="row"] {
+ grid-column: 1 / -1;
}
-.c-table tbody tr:hover *,
-.c-table tbody tr.is-active *,
-.c-table [role="row"]:hover [role="cell"],
-.c-table [role="row"].is-active [role="cell"] {
- color: var(--table-active-color);
+@include responsive.media-query using ($breakpoint) {
+ @if $breakpoint == "medium" {
+ .c-table[role="table"][cols\@medium="3"] { --grid-tc: repeat(3, auto); }
+ }
+
+ @if $breakpoint == "small" {
+ .c-table[role="table"][cols\@small="2"] { --grid-tc: repeat(2, auto); }
+ }
}
diff --git a/app/assets/stylesheets/elements/_content.scss b/app/assets/stylesheets/elements/_content.scss
index dac4ce50..2ec065ab 100644
--- a/app/assets/stylesheets/elements/_content.scss
+++ b/app/assets/stylesheets/elements/_content.scss
@@ -50,3 +50,12 @@ hr {
border-bottom: 0;
margin: spacing("large") 0;
}
+
+button[type="submit"] {
+ cursor: pointer;
+
+ &:hover,
+ &:hover * {
+ color: var(--link-active-color);
+ }
+}
diff --git a/app/assets/stylesheets/objects/_flex.scss b/app/assets/stylesheets/objects/_flex.scss
index ef960348..31d307dc 100644
--- a/app/assets/stylesheets/objects/_flex.scss
+++ b/app/assets/stylesheets/objects/_flex.scss
@@ -97,3 +97,7 @@
.o-flex__item--grow-1 {
flex-grow: 1;
}
+
+.o-flex__item--basic-0 {
+ flex-basis: 0;
+}
diff --git a/app/assets/stylesheets/objects/_grid.scss b/app/assets/stylesheets/objects/_grid.scss
index cfa5473d..6ccc6f7c 100644
--- a/app/assets/stylesheets/objects/_grid.scss
+++ b/app/assets/stylesheets/objects/_grid.scss
@@ -2,100 +2,7 @@
@use "../settings/variables";
@use "../tools/responsive";
-@use "../tools/functions";
-
-@mixin grid($breakpoint-postfix) {
- .o-grid[cols#{$breakpoint-postfix}="1"] { --grid-tc: repeat(1, 1fr); }
- .o-grid[cols#{$breakpoint-postfix}="2"] { --grid-tc: repeat(2, 1fr); }
- .o-grid[cols#{$breakpoint-postfix}="3"] { --grid-tc: repeat(3, 1fr); }
- .o-grid[cols#{$breakpoint-postfix}="4"] { --grid-tc: repeat(4, 1fr); }
- .o-grid[cols#{$breakpoint-postfix}="5"] { --grid-tc: repeat(5, 1fr); }
- .o-grid[cols#{$breakpoint-postfix}="6"] { --grid-tc: repeat(6, 1fr); }
- .o-grid[cols#{$breakpoint-postfix}="7"] { --grid-tc: repeat(7, 1fr); }
- .o-grid[cols#{$breakpoint-postfix}="8"] { --grid-tc: repeat(8, 1fr); }
-
- /* span=start... */
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}^="1"] { --grid-cs: 1; }
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}^="2"] { --grid-cs: 2; }
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}^="3"] { --grid-cs: 3; }
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}^="4"] { --grid-cs: 4; }
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}^="5"] { --grid-cs: 5; }
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}^="6"] { --grid-cs: 6; }
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}^="7"] { --grid-cs: 7; }
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}^="8"] { --grid-cs: 8; }
-
- /* span=...+width, span=...-end */
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="+1"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}="1"] {
- --grid-ce: 1;
- }
-
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="+2"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="-1"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}="2"] {
- --grid-ce: 2;
- }
-
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="+3"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="-2"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}="3"] {
- --grid-ce: 3;
- }
-
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="+4"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="-3"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}="4"] {
- --grid-ce: 4;
- }
-
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="+5"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="-4"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}="5"] {
- --grid-ce: 5;
- }
-
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="+6"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="-5"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}="6"] {
- --grid-ce: 6;
- }
-
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="+7"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="-6"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}="7"] {
- --grid-ce: 7;
- }
-
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="+8"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="-7"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}="8"] {
- --grid-ce: 8;
- }
-
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}$="-8"] {
- --grid-ce: 9;
- }
-
- /* connect vars */
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}] {
- grid-column-end: span var(--grid-ce);
- }
-
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}*="+"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}*="-"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}*=".."] {
- grid-column-start: var(--grid-cs);
- }
-
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}*="-"],
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}*=".."] {
- grid-column-end: var(--grid-ce);
- }
-
- .o-grid > .o-grid__item[span#{$breakpoint-postfix}="row"] {
- grid-column: 1 / -1;
- }
-}
+@use "../tools/functions" as *;
.o-grid {
display: grid !important;
@@ -105,30 +12,78 @@
--grid-ce: -1; /* column end */
}
-/* o-cell -- cell or column */
.o-grid > .o-grid__item {
display: block;
appearance: none;
}
-.o-grid--justify-items-center {
- justify-items: center;
+.o-grid--shelf {
+ grid-gap: spacing("medium");
}
-.o-grid--align-items-center {
- align-items: center;
+.o-grid--list {
+ grid-gap: spacing("small");
+ --grid-tc: repeat(3, 1fr);
}
-.o-grid__item--justify-end {
- justify-self: end;
+.o-grid > .o-grid__item--row {
+ grid-column: 1 / -1;
}
-@each $name, $value in variables.$spacing {
- .o-grid--gap-#{$name} {
- grid-gap: $value;
+@include responsive.media-query using ($breakpoint) {
+ @if $breakpoint == "extra-wide" {
+ .o-grid--shelf {
+ --grid-tc: repeat(7, 1fr);
+ }
}
-}
-@include responsive.media-query using ($breakpoint) {
- @include grid(functions.breakpoint-postfix($breakpoint));
+ @if $breakpoint == "wide" {
+ .o-grid--shelf {
+ --grid-tc: repeat(6, 1fr);
+ }
+ }
+
+ @if $breakpoint == "extra-large" {
+ .o-grid--shelf {
+ --grid-tc: repeat(5, 1fr);
+ }
+ }
+
+ @if $breakpoint == "large" {
+ .o-grid--shelf {
+ --grid-tc: repeat(4, 1fr);
+ }
+ }
+
+ @if $breakpoint == "medium" {
+ .o-grid--shelf {
+ --grid-tc: repeat(3, 1fr);
+ }
+
+ .o-grid--list {
+ --grid-tc: repeat(2, 1fr);
+ }
+ }
+
+ @if $breakpoint == "small" {
+ .o-grid--shelf {
+ --grid-tc: repeat(2, 1fr);
+ }
+ }
+
+ @if $breakpoint == "extra-small" {
+ .o-grid--shelf {
+ --grid-tc: repeat(3, 1fr);
+ }
+ }
+
+ @if $breakpoint == "narrow" {
+ .o-grid--shelf {
+ --grid-tc: repeat(2, 1fr);
+ }
+
+ .o-grid--list {
+ --grid-tc: repeat(1, 1fr);
+ }
+ }
}
diff --git a/app/assets/stylesheets/utilities/_border.scss b/app/assets/stylesheets/utilities/_border.scss
index 0fdcb0ec..387ca6b3 100644
--- a/app/assets/stylesheets/utilities/_border.scss
+++ b/app/assets/stylesheets/utilities/_border.scss
@@ -4,6 +4,10 @@
box-shadow: 0 8px 16px -4px rgba(9, 30, 66, 0.25), 0 0 1px rgba(9, 30, 66, 0.31) !important;
}
+.u-border-none {
+ border: none !important;
+}
+
@each $name, $value in variables.$border-radius {
.u-border-radius-#{$name} {
border-radius: $value !important;
diff --git a/app/assets/stylesheets/utilities/_sizing.scss b/app/assets/stylesheets/utilities/_sizing.scss
index c9fbb513..493e0162 100644
--- a/app/assets/stylesheets/utilities/_sizing.scss
+++ b/app/assets/stylesheets/utilities/_sizing.scss
@@ -1,48 +1,25 @@
-@use "../tools/responsive";
@use "../tools/functions";
-@mixin sizing($breakpoint-postfix) {
- .u-vw-100#{$breakpoint-postfix} {
- width: 100vw !important;
- }
-
- .u-vh-100#{$breakpoint-postfix} {
- height: 100vh !important;
- }
-
- .u-w-100#{$breakpoint-postfix} {
- width: 100% !important;
- }
-
- .u-h-100#{$breakpoint-postfix} {
- height: 100% !important;
- }
-
- .u-h-0#{$breakpoint-postfix} {
- height: 0 !important;
- }
-
- .u-w-0#{$breakpoint-postfix} {
- width: 0 !important;
- }
+.u-vw-100 {
+ width: 100vw !important;
+}
- .u-w-15#{$breakpoint-postfix} {
- width: 15% !important;
- }
+.u-vh-100 {
+ height: 100vh !important;
+}
- .u-w-25#{$breakpoint-postfix} {
- width: 25% !important;
- }
+.u-w-100 {
+ width: 100% !important;
+}
- .u-w-50#{$breakpoint-postfix} {
- width: 50% !important;
- }
+.u-h-100 {
+ height: 100% !important;
+}
- .u-w-75#{$breakpoint-postfix} {
- width: 75% !important;
- }
+.u-h-0 {
+ height: 0 !important;
}
-@include responsive.media-query using ($breakpoint) {
- @include sizing(functions.breakpoint-postfix($breakpoint));
+.u-w-0 {
+ width: 0 !important;
}
diff --git a/app/controllers/albums_controller.rb b/app/controllers/albums_controller.rb
index 715db1a4..24563d5a 100644
--- a/app/controllers/albums_controller.rb
+++ b/app/controllers/albums_controller.rb
@@ -12,11 +12,6 @@ class AlbumsController < ApplicationController
def index
records = Album.includes(:artist).order(:name)
@pagy, @albums = pagy(records)
-
- respond_to do |format|
- format.turbo_stream if params[:page].to_i > 1
- format.html
- end
end
def show
diff --git a/app/controllers/playlists/songs_controller.rb b/app/controllers/playlists/songs_controller.rb
index f08fc398..63ccc046 100644
--- a/app/controllers/playlists/songs_controller.rb
+++ b/app/controllers/playlists/songs_controller.rb
@@ -9,11 +9,6 @@ class Playlists::SongsController < ApplicationController
def show
@pagy, @songs = pagy(@playlist.songs.includes(:artist))
-
- respond_to do |format|
- format.turbo_stream if params[:page].to_i > 1
- format.html
- end
end
def create
diff --git a/app/controllers/playlists_controller.rb b/app/controllers/playlists_controller.rb
index d793830a..1cfbd350 100644
--- a/app/controllers/playlists_controller.rb
+++ b/app/controllers/playlists_controller.rb
@@ -8,11 +8,6 @@ class PlaylistsController < ApplicationController
def index
@pagy, @playlists = pagy(Current.user.all_playlists.order(created_at: :desc))
-
- respond_to do |format|
- format.turbo_stream if params[:page].to_i > 1
- format.html
- end
end
def new
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index e4726379..c3d7e84e 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -62,35 +62,6 @@ def playlist_songs_path(playlist, options = {})
super(playlist, options)
end
- def shelf_grid_tag(**options, &block)
- class_option = "o-grid o-grid--gap-medium #{options[:class]}"
- tag_options = options.merge(
- :class => class_option,
- "cols@narrow" => 2,
- "cols@extra-small" => 3,
- "cols@small" => 2,
- "cols@medium" => 3,
- "cols@large" => 4,
- "cols@extra-large" => 5,
- "cols@wide" => 6,
- "cols@extra-wide" => 7
- )
-
- tag.div(**tag_options, escape: false, &block)
- end
-
- def list_grid_tag(**options, &block)
- class_option = "o-grid o-grid--gap-small #{options[:class]}"
- tag_options = options.merge(
- :class => class_option,
- "cols" => 3,
- "cols@narrow" => 1,
- "cols@medium" => 2
- )
-
- tag.div(**tag_options, escape: false, &block)
- end
-
def page_title_tag(title)
content_for :title, title
end
diff --git a/app/javascript/controllers/element_controller.js b/app/javascript/controllers/element_controller.js
new file mode 100644
index 00000000..7a5e812f
--- /dev/null
+++ b/app/javascript/controllers/element_controller.js
@@ -0,0 +1,7 @@
+import { Controller } from '@hotwired/stimulus'
+
+export default class extends Controller {
+ replaceWithChildren ({ target }) {
+ this.element.replaceWith(...target.children)
+ }
+}
diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js
index 5734dc74..2c9c0c09 100644
--- a/app/javascript/controllers/index.js
+++ b/app/javascript/controllers/index.js
@@ -6,12 +6,12 @@ import { application } from './application'
import DialogController from './dialog_controller.js'
+import ElementController from './element_controller'
+
import FlashController from './flash_controller.js'
import FormController from './form_controller.js'
-import InfiniteScrollController from './infinite_scroll_controller.js'
-
import LoaderController from './loader_controller.js'
import MediaSessionController from './media_session_controller.js'
@@ -30,12 +30,12 @@ import ThemeController from './theme_controller.js'
application.register('dialog', DialogController)
+application.register('element', ElementController)
+
application.register('flash', FlashController)
application.register('form', FormController)
-application.register('infinite-scroll', InfiniteScrollController)
-
application.register('loader', LoaderController)
application.register('media-session', MediaSessionController)
diff --git a/app/javascript/controllers/infinite_scroll_controller.js b/app/javascript/controllers/infinite_scroll_controller.js
deleted file mode 100644
index e62189c8..00000000
--- a/app/javascript/controllers/infinite_scroll_controller.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import { Controller } from '@hotwired/stimulus'
-import { fetchTurboStream } from '../helper'
-
-export default class extends Controller {
- static targets = ['trigger']
-
- static values = {
- container: String,
- url: String,
- totalPages: Number
- }
-
- initialize () {
- this.page = 2
- }
-
- connect () {
- if (!this.hasNextPage) { return }
-
- this.observer = new IntersectionObserver(this._handleNextPageLoad.bind(this), {
- root: this.hasContainerValue ? document.querySelector(this.containerValue) : document,
- rootMargin: '0px',
- threshold: 1.0
- })
-
- this.observer.observe(this.triggerTarget)
- }
-
- disconnect () {
- if (this.observer) {
- this.observer.disconnect()
- }
- }
-
- _handleNextPageLoad (entries) {
- entries.forEach((entry) => {
- if (entry.intersectionRatio !== 1) { return }
-
- if (!this.hasNextPage) {
- this.triggerTarget.classList.add('u-display-none')
- return
- }
-
- if (this.abortController) {
- // Abort previous fetch request.
- this.abortController.abort()
- }
-
- this.abortController = new AbortController()
-
- const nextUrl = `${this.urlValue}?page=${this.page}`
-
- fetchTurboStream(nextUrl, { signal: this.abortController.signal }, () => {
- this.page += 1
- })
- })
- }
-
- get hasNextPage () {
- return this.page <= this.totalPagesValue
- }
-}
diff --git a/app/javascript/helper.js b/app/javascript/helper.js
index 35b52f66..ba34cd74 100644
--- a/app/javascript/helper.js
+++ b/app/javascript/helper.js
@@ -1,5 +1,3 @@
-import { Turbo } from '@hotwired/turbo-rails'
-
function formatDuration (secs) {
const date = new Date(null)
date.setSeconds(secs)
@@ -38,27 +36,6 @@ async function fetchRequest (url, options = {}) {
return fetch(request, options)
}
-async function fetchTurboStream (url, options = {}, successCallback = () => {}) {
- const turboStreamHeader = {
- Accept: 'text/vnd.turbo-stream.html'
- }
-
- options.headers = ('headers' in options)
- ? { ...options.headers, ...turboStreamHeader }
- : turboStreamHeader
-
- try {
- const response = await fetchRequest(url, options)
-
- if (response.ok) {
- const streamMessage = await response.text()
-
- Turbo.renderStreamMessage(streamMessage)
- successCallback()
- }
- } catch (_) { /* ignore error */ }
-}
-
function dispatchEvent (element, type, data = null) {
if (typeof element === 'string') { element = document.querySelector(element) }
element.dispatchEvent(new CustomEvent(type, { detail: data }))
@@ -69,6 +46,5 @@ export {
shuffle,
randomIndex,
fetchRequest,
- fetchTurboStream,
dispatchEvent
}
diff --git a/app/views/albums/index.html.erb b/app/views/albums/index.html.erb
index 1b6fd560..331cb157 100644
--- a/app/views/albums/index.html.erb
+++ b/app/views/albums/index.html.erb
@@ -5,15 +5,18 @@
<%= empty_alert_tag has_icon: true, has_overlay: false %>
<% else %>
-
<%= t('label.albums') %>
-
- <%= shelf_grid_tag class: 'o-container o-container--large', id: 'turbo-albums-content' do %>
+
+
<%= t('label.albums') %>
+ <%= turbo_frame_tag "turbo-albums-page-#{@pagy.page}", class: 'o-grid o-grid--shelf', target: '_top' do %>
<%= render partial: 'albums/album', collection: @albums, cached: true %>
- <% end %>
-
+
<% if @pagy.next %>
- <%= loader_tag %>
+ <%= turbo_frame_tag "turbo-albums-page-#{@pagy.next}", src: pagy_url_for(@pagy, @pagy.next), loading: 'lazy', class: 'o-grid__item o-grid__item--row u-my-small', data: { controller: 'element', action: 'turbo:frame-render->element#replaceWithChildren' } do %>
+
+ <%= loader_tag %>
+
+ <% end %>
<% end %>
-
+ <% end %>
<% end %>
diff --git a/app/views/albums/index.turbo_stream.erb b/app/views/albums/index.turbo_stream.erb
deleted file mode 100644
index d403f690..00000000
--- a/app/views/albums/index.turbo_stream.erb
+++ /dev/null
@@ -1 +0,0 @@
-<%= turbo_stream.append 'turbo-albums-content', partial: 'albums/album', collection: @albums, cached: true %>
diff --git a/app/views/albums/show.html.erb b/app/views/albums/show.html.erb
index 4cbe04a1..e75622f6 100644
--- a/app/views/albums/show.html.erb
+++ b/app/views/albums/show.html.erb
@@ -22,7 +22,7 @@
<% @songs.each do |song| %>
- <%= button_to current_playlist_songs_path(song_id: song.id), class: 'u-w-100 o-flex o-flex--justify-between o-flex--align-center u-cursor-pointer', form_class: 'o-flex__item--grow-1', form: { 'data-submit-start-action' => 'check_before_playing', 'data-submit-end-action' => 'play', 'data-turbo-frame' => 'turbo-playlist' } do %>
+ <%= button_to current_playlist_songs_path(song_id: song.id), class: 'u-w-100 o-flex o-flex--justify-between o-flex--align-center', form_class: 'o-flex__item--grow-1', form: { 'data-submit-start-action' => 'check_before_playing', 'data-submit-end-action' => 'play', 'data-turbo-frame' => 'turbo-playlist' } do %>
<%= song.name %>
<% if @album.artist.is_various? %>
diff --git a/app/views/artists/_albums.html.erb b/app/views/artists/_albums.html.erb
index e83e16a7..90281521 100644
--- a/app/views/artists/_albums.html.erb
+++ b/app/views/artists/_albums.html.erb
@@ -1,6 +1,6 @@
<% if albums.present? %>
<%= title %>
- <%= shelf_grid_tag class: 'u-mb-large' do %>
+
<%= render partial: 'artists/album', collection: albums, cached: true %>
- <% end %>
+
<% end %>
diff --git a/app/views/artists/index.html.erb b/app/views/artists/index.html.erb
index a05de624..28685d4d 100644
--- a/app/views/artists/index.html.erb
+++ b/app/views/artists/index.html.erb
@@ -5,15 +5,18 @@
<%= empty_alert_tag has_icon: true, has_overlay: false %>
<% else %>
-
<%= t('label.artists') %>
-
- <%= shelf_grid_tag class: 'o-container o-container--large', id: 'turbo-artists-content' do %>
+
+
<%= t('label.artists') %>
+ <%= turbo_frame_tag "turbo-artists-page-#{@pagy.page}", class: 'o-grid o-grid--shelf', target: '_top' do %>
<%= render partial: 'artists/artist', collection: @artists, cached: true %>
- <% end %>
-
+
<% if @pagy.next %>
- <%= loader_tag %>
+ <%= turbo_frame_tag "turbo-artists-page-#{@pagy.next}", src: pagy_url_for(@pagy, @pagy.next), loading: 'lazy', class: 'o-grid__item o-grid__item--row u-my-small', data: { controller: 'element', action: 'turbo:frame-render->element#replaceWithChildren' } do %>
+
+ <%= loader_tag %>
+
+ <% end %>
<% end %>
-
+ <% end %>
<% end %>
diff --git a/app/views/artists/index.turbo_stream.erb b/app/views/artists/index.turbo_stream.erb
deleted file mode 100644
index 2a108d26..00000000
--- a/app/views/artists/index.turbo_stream.erb
+++ /dev/null
@@ -1 +0,0 @@
-<%= turbo_stream.append 'turbo-artists-content', partial: 'artists/artist', collection: @artists, cached: true %>
diff --git a/app/views/artists/show.html.erb b/app/views/artists/show.html.erb
index d0f93a84..b2445d5f 100644
--- a/app/views/artists/show.html.erb
+++ b/app/views/artists/show.html.erb
@@ -1,6 +1,6 @@
<% cache @artist do %>
- <%= shelf_grid_tag class: 'u-pb-wide' do %>
+
<%= image_tag image_url_for(@artist), class: 'u-image-fluid c-card__image', data: { test_id: 'artist_image' } %>
@@ -15,7 +15,7 @@
<%= link_to t('label.edit'), edit_artist_path(@artist), data: { turbo_frame: 'turbo-dialog' }, class: 'c-button c-button--secondary u-mt-large' %>
<% end %>
- <% end %>
+
<% end %>
<%= render partial: 'artists/albums', locals: { title: t('label.albums'), albums: @albums } %>
<%= render partial: 'artists/albums', locals: { title: t('label.appears_on'), albums: @appears_on_albums } %>
diff --git a/app/views/current_playlist/songs/show.html.erb b/app/views/current_playlist/songs/show.html.erb
index 317d8464..3d373fea 100644
--- a/app/views/current_playlist/songs/show.html.erb
+++ b/app/views/current_playlist/songs/show.html.erb
@@ -10,7 +10,7 @@
<%= icon_tag 'more-vertical', title: t('label.more') %>
- <%= button_to t('label.clear'), current_playlist_songs_path(clear_all: true), method: :delete, form_class: 'c-dropdown__item u-cursor-pointer', form: { data: { action: 'turbo:submit-end->playlist-songs#clear' } } %>
+ <%= button_to t('label.clear'), current_playlist_songs_path(clear_all: true), method: :delete, form_class: 'c-dropdown__item', form: { data: { action: 'turbo:submit-end->playlist-songs#clear' } } %>
diff --git a/app/views/dialog/playlists/_playlist.html.erb b/app/views/dialog/playlists/_playlist.html.erb
index b95550ef..7ae71aea 100644
--- a/app/views/dialog/playlists/_playlist.html.erb
+++ b/app/views/dialog/playlists/_playlist.html.erb
@@ -1,3 +1,3 @@
-