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 @@ - diff --git a/app/views/dialog/playlists/index.html.erb b/app/views/dialog/playlists/index.html.erb index ecfb769b..90b8710f 100644 --- a/app/views/dialog/playlists/index.html.erb +++ b/app/views/dialog/playlists/index.html.erb @@ -5,18 +5,17 @@ <% if @playlists.present? %> <%= form_tag nil, 'data-turbo-frame': '_top' do %> <%= hidden_field_tag :song_id, params[:song_id] %> -
    -
    - <%= render partial: 'dialog/playlists/playlist', collection: @playlists, cached: true %> -
    -
    - <% if @pagy.next %> - <%= loader_tag %> + <%= turbo_frame_tag "turbo-dialog-playlists-page-#{@pagy.page}", class: 'c-list', data: { action: 'click->dialog#hide' }, target: '_top' do %> + <%= render partial: 'dialog/playlists/playlist', collection: @playlists, cached: true %> + + <% if @pagy.next %> + <%= turbo_frame_tag "turbo-dialog-playlists-page-#{@pagy.next}", src: pagy_url_for(@pagy, @pagy.next), loading: 'lazy', class: 'u-my-small', data: { controller: 'element', action: 'turbo:frame-render->element#replaceWithChildren' } do %> +
    + <%= loader_tag %> +
    <% end %> -
    -
    + <% end %> + <% end %> <% end %> <% else %> <%= empty_alert_tag %> diff --git a/app/views/dialog/playlists/index.turbo_stream.erb b/app/views/dialog/playlists/index.turbo_stream.erb deleted file mode 100644 index abd70043..00000000 --- a/app/views/dialog/playlists/index.turbo_stream.erb +++ /dev/null @@ -1 +0,0 @@ -<%= turbo_stream.append 'turbo-dialog-playlists', partial: 'dialog/playlists/playlist', collection: @playlists, cached: true %> diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb index 9679d727..df2d518c 100644 --- a/app/views/home/index.html.erb +++ b/app/views/home/index.html.erb @@ -3,16 +3,16 @@ <% if [@recently_added_albums, @recently_played_albums].any?(&:present?) %> <% if @recently_played_albums.present? %>

    <%= t('label.recently_played') %>

    - <%= shelf_grid_tag class: 'u-mb-large' do %> +
    <%= render partial: 'albums/album', collection: @recently_played_albums, cached: true %> - <% end %> +
    <% end %> <% if @recently_added_albums.present? %>

    <%= t('label.recently_added') %>

    - <%= shelf_grid_tag class: 'u-mb-large' do %> +
    <%= render partial: 'albums/album', collection: @recently_added_albums, cached: true %> - <% end %> +
    <% end %> <% else %>
    diff --git a/app/views/layouts/dialog.html.erb b/app/views/layouts/dialog.html.erb index 37d374ea..f5f916d8 100644 --- a/app/views/layouts/dialog.html.erb +++ b/app/views/layouts/dialog.html.erb @@ -6,7 +6,7 @@ <%= icon_tag 'close', title: t('label.close') %> -
    +
    <%= yield %>
    diff --git a/app/views/layouts/plain.html.erb b/app/views/layouts/plain.html.erb index 1b637bc1..326a11db 100644 --- a/app/views/layouts/plain.html.erb +++ b/app/views/layouts/plain.html.erb @@ -3,7 +3,7 @@ <%= render 'shared/flash' %>
    -
    +
    diff --git a/app/views/playlists/index.html.erb b/app/views/playlists/index.html.erb index 20e483a6..e2072410 100644 --- a/app/views/playlists/index.html.erb +++ b/app/views/playlists/index.html.erb @@ -3,16 +3,17 @@

    <%= t('lable.playlists') %>

    <%= link_to t('label.add'), new_playlist_path, data: { turbo_frame: 'turbo-dialog' }, class: 'c-button c-button--primary' %>
    -
    - <%= list_grid_tag id: 'turbo-playlist-list' do %> - <% if @playlists.present? %> - <%= render partial: 'playlists/playlist', collection: @playlists, cached: true %> - <% end %> + <%= turbo_frame_tag "turbo-playlists-page-#{@pagy.page}", class: 'o-grid o-grid--list', target: '_top' do %> + <% if @playlists.present? %> + <%= render partial: 'playlists/playlist', collection: @playlists, cached: true %> <% end %> -
    - <% if @pagy.next %> - <%= loader_tag %> + + <% if @pagy.next %> + <%= turbo_frame_tag "turbo-playlists-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 %>
    diff --git a/app/views/playlists/index.turbo_stream.erb b/app/views/playlists/index.turbo_stream.erb deleted file mode 100644 index b833755e..00000000 --- a/app/views/playlists/index.turbo_stream.erb +++ /dev/null @@ -1 +0,0 @@ -<%= turbo_stream.append 'turbo-playlist-list', partial: 'playlists/playlist', collection: @playlists, cached: true %> diff --git a/app/views/playlists/songs/_list.html.erb b/app/views/playlists/songs/_list.html.erb index 3c89be75..9f368a1c 100644 --- a/app/views/playlists/songs/_list.html.erb +++ b/app/views/playlists/songs/_list.html.erb @@ -1,10 +1,11 @@ -
    -
      - <%= render partial: 'playlists/songs/song', collection: songs, locals: { playlist: playlist }, cached: true %> -
    -
    - <% if pagy.next %> - <%= loader_tag %> +<%= turbo_frame_tag "#{dom_id(playlist)}-page-#{@pagy.page}", class: 'c-list', target: '_top', data: { controller: 'playlist-sortable', action: 'turbo:submit-end->playlist-songs#submitEndHandle turbo:submit-start->playlist-songs#submitStartHandle', playlist_sortable_url_value: 'playlist_songs_path(playlist)'} do %> + <%= render partial: 'playlists/songs/song', collection: songs, locals: { playlist: playlist }, cached: true %> + + <% if @pagy.next %> + <%= turbo_frame_tag "#{dom_id(playlist)}-page-#{@pagy.next}", src: pagy_url_for(@pagy, @pagy.next), loading: 'lazy', class: 'u-my-small', data: { controller: 'element', action: 'turbo:frame-render->element#replaceWithChildren' } do %> +
    + <%= loader_tag %> +
    <% end %> -
    -
    + <% end %> +<% end %> diff --git a/app/views/playlists/songs/_song.html.erb b/app/views/playlists/songs/_song.html.erb index e484b1bc..5d090565 100644 --- a/app/views/playlists/songs/_song.html.erb +++ b/app/views/playlists/songs/_song.html.erb @@ -1,7 +1,7 @@
  • <%= icon_tag 'drag-indicator', size: 'small' %>
    - <%= 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 %>

    <%= song.artist.title %> diff --git a/app/views/playlists/songs/show.turbo_stream.erb b/app/views/playlists/songs/show.turbo_stream.erb deleted file mode 100644 index adb0324b..00000000 --- a/app/views/playlists/songs/show.turbo_stream.erb +++ /dev/null @@ -1 +0,0 @@ -<%= turbo_stream.append dom_id(@playlist), partial: 'playlists/songs/song', collection: @songs, locals: { playlist: @playlist }, cached: true %> diff --git a/app/views/search/albums/index.html.erb b/app/views/search/albums/index.html.erb index 80449ce8..00ae22e3 100644 --- a/app/views/search/albums/index.html.erb +++ b/app/views/search/albums/index.html.erb @@ -1,5 +1,5 @@

    <%= t('text.search_results', query: params[:query]) %>

    <%= t('label.albums') %>

    -<%= shelf_grid_tag class: 'u-mb-large' do %> +
    <%= render partial: 'albums/album', collection: @albums, cached: true %> -<% end %> +
    diff --git a/app/views/search/artists/index.html.erb b/app/views/search/artists/index.html.erb index 873516f2..31433930 100644 --- a/app/views/search/artists/index.html.erb +++ b/app/views/search/artists/index.html.erb @@ -1,5 +1,5 @@

    <%= t('text.search_results', query: params[:query]) %>

    <%= t('label.artists') %>

    -<%= shelf_grid_tag class: 'u-mb-large' do %> +
    <%= render partial: 'artists/artist', collection: @artists, cached: true %> -<% end %> +
    diff --git a/app/views/search/index.html.erb b/app/views/search/index.html.erb index 5b135704..c4d41fcf 100644 --- a/app/views/search/index.html.erb +++ b/app/views/search/index.html.erb @@ -9,9 +9,9 @@ <%= link_to t('text.see_all'), search_albums_path(query: params[:query]), class: 'is-active' %> <% end %>
    - <%= shelf_grid_tag class: 'u-mb-large' do %> +
    <%= render partial: 'albums/album', collection: @albums, cached: true %> - <% end %> +
    <% end %> <% if @artists.present? %> @@ -22,9 +22,9 @@ <%= link_to t('text.see_all'), search_artists_path(query: params[:query]), class: 'is-active' %> <% end %>
    - <%= shelf_grid_tag class: 'u-mb-large' do %> +
    <%= render partial: 'artists/artist', collection: @artists, cached: true %> - <% end %> +
    <% end %> <% if @playlists.present? %> @@ -35,9 +35,9 @@ <%= link_to t('text.see_all'), search_playlists_path(query: params[:query]), class: 'is-active' %> <% end %>
  • - <%= list_grid_tag class: 'u-mb-wide' do %> +
    <%= render partial: 'playlists/playlist', collection: @playlists, cached: true %> - <% end %> +
    <% end %> <% if @songs.present? %> @@ -48,7 +48,7 @@ <%= link_to t('text.see_all'), search_songs_path(query: params[:query]), class: 'is-active' %> <% end %> - <%= render partial: 'songs/table', locals: { songs: @songs } %> + <%= render partial: 'search/songs/table', locals: { songs: @songs } %> <% end %> <% else %>

    <%= t('text.no_search_results', query: params[:query]) %>

    diff --git a/app/views/search/playlists/index.html.erb b/app/views/search/playlists/index.html.erb index 6faa7cf1..418333a5 100644 --- a/app/views/search/playlists/index.html.erb +++ b/app/views/search/playlists/index.html.erb @@ -1,6 +1,6 @@

    <%= t('text.search_results', query: params[:query]) %>

    <%= t('label.playlists') %>

    -<%= list_grid_tag do %> +
    <%= render partial: 'playlists/playlist', collection: @playlists, cached: true %> -<% end %> +
    diff --git a/app/views/search/songs/_table.html.erb b/app/views/search/songs/_table.html.erb new file mode 100644 index 00000000..83c49d29 --- /dev/null +++ b/app/views/search/songs/_table.html.erb @@ -0,0 +1,14 @@ +
    +
    +
    +
    <%= t('label.name') %>
    +
    <%= t('label.artist') %>
    +
    <%= t('label.album') %>
    +
    <%= t('label.duration') %>
    +
    <%= t('label.actions') %>
    +
    +
    +
    + <%= render partial: 'songs/song', collection: songs, cached: true %> +
    +
    diff --git a/app/views/search/songs/index.html.erb b/app/views/search/songs/index.html.erb index 7554aa35..8ef58ca1 100644 --- a/app/views/search/songs/index.html.erb +++ b/app/views/search/songs/index.html.erb @@ -1,3 +1,3 @@

    <%= t('text.search_results', query: params[:query]) %>

    <%= t('label.songs') %>

    -<%= render partial: 'songs/table', locals: { songs: @songs } %> +<%= render partial: 'search/songs/table', locals: { songs: @songs } %> diff --git a/app/views/shared/_search_bar.html.erb b/app/views/shared/_search_bar.html.erb index 15debdd4..c8bc2c5f 100644 --- a/app/views/shared/_search_bar.html.erb +++ b/app/views/shared/_search_bar.html.erb @@ -1,7 +1,7 @@ -
    - <%= form_tag search_path, method: :get, class: 'c-search c-input-group o-grid__item', - 'span@medium': '2-6', span: '3-5', - data: { action: 'search#submit', controller: 'search' } do %> +
    +
    +
    + <%= form_tag search_path, method: :get, class: 'c-search c-input-group o-flex__item', data: { action: 'search#submit', controller: 'search' } do %>
    <%= icon_tag 'search', size: 'large' %>
    @@ -12,8 +12,8 @@
    <% end %> -
    -
    +
    +
    <%= avatar_tag Current.user %>
    <%= link_to t('label.settings'), setting_path, class: 'c-dropdown__item' %> diff --git a/app/views/songs/_song.html.erb b/app/views/songs/_song.html.erb index fc29e411..b28bb1e4 100644 --- a/app/views/songs/_song.html.erb +++ b/app/views/songs/_song.html.erb @@ -1,15 +1,19 @@ -
    - <%= button_to current_playlist_songs_path(song_id: song.id), form_class: 'o-grid__item', class: 'u-w-100 u-cursor-pointer', form: { 'span' => '1-7', 'span@medium' => '1-5', 'span@small' => '1-4', 'span@narrow' => '1-3', 'data-submit-start-action' => 'check_before_playing', 'data-submit-end-action' => 'play', 'data-turbo-frame' => 'turbo-playlist' } do %> -
    - <%= song.name %> - <%= song.artist.title %> - <%= song.album.title %> - <%= format_duration(song.duration) %> -
    - <% end %> - +
    +
    + <%= button_to current_playlist_songs_path(song_id: song.id), data: { test_id: 'song_item'}, form: { 'data-submit-start-action' => 'check_before_playing', 'data-submit-end-action' => 'play', 'data-turbo-frame' => 'turbo-playlist' } do %> + <%= song.name %> + <% end %> +
    +
    + <%= link_to song.artist.title, artist_path(song.artist) %> +
    +
    + <%= link_to song.album.title, album_path(song.album) %> +
    +
    <%= format_duration(song.duration) %>
    +
    <%= link_to dialog_playlists_path(song_id: song.id), data: { test_id: 'song_add_playlist', turbo_frame: 'turbo-dialog' } do %> <%= icon_tag 'playlist-add', size: 'small', title: t('text.add_to_playlist') %> <% end %> - +
    diff --git a/app/views/songs/_table.html.erb b/app/views/songs/_table.html.erb index 11ba9573..624ee40a 100644 --- a/app/views/songs/_table.html.erb +++ b/app/views/songs/_table.html.erb @@ -1,14 +1,24 @@ -
    +<%# Because turbo frame doesn't support add on others built-in elements like tbody yet, %> +<%# So I can't use table element here to implement infinite scroll. %> +<%# If turbo frame support built-in elements later https://github.com/hotwired/turbo/pull/131,%> +<%# this view can use table element to refactor. %> +
    -
    - <%= t('label.name') %> - <%= t('label.artist') %> - <%= t('label.album') %> - <%= t('label.duration') %> - <%= t('label.actions') %> +
    +
    <%= t('label.name') %>
    +
    <%= t('label.artist') %>
    +
    <%= t('label.album') %>
    +
    <%= t('label.duration') %>
    +
    <%= t('label.actions') %>
    -
    + <%= turbo_frame_tag "turbo-songs-page-#{pagy.page}", role: 'rowgroup', target: '_top', data: { action: 'turbo:submit-end->playlist-songs#submitEndHandle turbo:submit-start->playlist-songs#submitStartHandle' } do %> <%= render partial: 'songs/song', collection: songs, cached: true %> -
    + + <% if pagy.next %> + <%= turbo_frame_tag "turbo-songs-page-#{pagy.next}", src: pagy_url_for(pagy, pagy.next), loading: 'lazy', role: 'cell', span: 'row', class: 'o-flex o-flex--justify-center u-my-small u-border-none', data: { controller: 'element', action: 'turbo:frame-render->element#replaceWithChildren' } do %> + <%= loader_tag %> + <% end %> + <% end %> + <% end %>
    diff --git a/app/views/songs/index.html.erb b/app/views/songs/index.html.erb index 63c334c7..8ae6709c 100644 --- a/app/views/songs/index.html.erb +++ b/app/views/songs/index.html.erb @@ -5,13 +5,8 @@ <%= empty_alert_tag has_icon: true, has_overlay: false %>
    <% else %> -
    -

    <%= t('label.songs') %>

    - <%= render partial: 'songs/table', locals: { songs: @songs } %> -
    - <% if @pagy.next %> - <%= loader_tag %> - <% end %> -
    -
    +
    +

    <%= t('label.songs') %>

    + <%= render partial: 'songs/table', locals: { songs: @songs, pagy: @pagy } %> +
    <% end %> diff --git a/app/views/songs/index.turbo_stream.erb b/app/views/songs/index.turbo_stream.erb deleted file mode 100644 index d6dad8de..00000000 --- a/app/views/songs/index.turbo_stream.erb +++ /dev/null @@ -1 +0,0 @@ -<%= turbo_stream.append 'turbo-songs-content', partial: 'songs/song', collection: @songs, cached: true %> diff --git a/test/helpers/application_helper_test.rb b/test/helpers/application_helper_test.rb index 62a78c3d..97a56d93 100644 --- a/test/helpers/application_helper_test.rb +++ b/test/helpers/application_helper_test.rb @@ -9,24 +9,4 @@ class ApplicationHelperTest < ActionView::TestCase assert_equal "15:00", format_duration(900) assert_equal "02:30:00", format_duration(9000) end - - test "shelf grid tag with class option" do - tag_content = '
    ' - - assert_equal tag_content, shelf_grid_tag(class: "test") - end - - test "shelf grid tag with block content" do - tag_content = '

    test

    ' - - shelf_tag = shelf_grid_tag do - tag.p "test" - end - - assert_equal tag_content, shelf_tag - end end