From ece7fecc76e44479ef16d19d5817ba1fd8f3cde6 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Tue, 18 Jul 2023 18:39:39 -0700 Subject: [PATCH] Highlight currently playing song on all song tables (#178) --- .../cells/combined-title-cell.tsx | 1 + .../virtual-table/cells/generic-cell.tsx | 12 +- .../virtual-table/cells/title-cell.tsx | 29 ++ .../hooks/use-current-song-row-styles.ts | 57 +++ .../components/virtual-table/index.tsx | 4 +- .../components/album-detail-content.tsx | 4 + ...m-artist-detail-top-songs-list-content.tsx | 4 + .../hooks/use-handle-context-menu.ts | 2 - .../components/playlist-detail-content.tsx | 4 + .../playlist-detail-song-list-content.tsx | 4 + .../songs/components/song-list-table-view.tsx | 4 + src/renderer/styles/ag-grid.scss | 34 +- src/renderer/themes/default.scss | 334 +++++++++--------- 13 files changed, 299 insertions(+), 194 deletions(-) create mode 100644 src/renderer/components/virtual-table/cells/title-cell.tsx create mode 100644 src/renderer/components/virtual-table/hooks/use-current-song-row-styles.ts diff --git a/src/renderer/components/virtual-table/cells/combined-title-cell.tsx b/src/renderer/components/virtual-table/cells/combined-title-cell.tsx index 63d86068..a8977e2d 100644 --- a/src/renderer/components/virtual-table/cells/combined-title-cell.tsx +++ b/src/renderer/components/virtual-table/cells/combined-title-cell.tsx @@ -102,6 +102,7 @@ export const CombinedTitleCell = ({ value, rowIndex, node }: ICellRendererParams diff --git a/src/renderer/components/virtual-table/cells/generic-cell.tsx b/src/renderer/components/virtual-table/cells/generic-cell.tsx index e61e9e01..bdb25384 100644 --- a/src/renderer/components/virtual-table/cells/generic-cell.tsx +++ b/src/renderer/components/virtual-table/cells/generic-cell.tsx @@ -1,20 +1,10 @@ import type { ICellRendererParams } from '@ag-grid-community/core'; -import { motion, Variants } from 'framer-motion'; import { Link } from 'react-router-dom'; import styled from 'styled-components'; import { Skeleton } from '/@/renderer/components/skeleton'; import { Text } from '/@/renderer/components/text'; -export const CELL_VARIANTS: Variants = { - animate: { - opacity: 1, - }, - initial: { - opacity: 0, - }, -}; - -export const CellContainer = styled(motion.div)<{ position?: 'left' | 'center' | 'right' }>` +export const CellContainer = styled.div<{ position?: 'left' | 'center' | 'right' }>` display: flex; align-items: center; justify-content: ${(props) => diff --git a/src/renderer/components/virtual-table/cells/title-cell.tsx b/src/renderer/components/virtual-table/cells/title-cell.tsx new file mode 100644 index 00000000..54fedbe1 --- /dev/null +++ b/src/renderer/components/virtual-table/cells/title-cell.tsx @@ -0,0 +1,29 @@ +import type { ICellRendererParams } from '@ag-grid-community/core'; +import { Skeleton } from '/@/renderer/components/skeleton'; +import { Text } from '/@/renderer/components/text'; +import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell'; + +export const TitleCell = ({ value }: ICellRendererParams) => { + if (value === undefined) { + return ( + + + + ); + } + + return ( + + + {value} + + + ); +}; diff --git a/src/renderer/components/virtual-table/hooks/use-current-song-row-styles.ts b/src/renderer/components/virtual-table/hooks/use-current-song-row-styles.ts new file mode 100644 index 00000000..1ad467f2 --- /dev/null +++ b/src/renderer/components/virtual-table/hooks/use-current-song-row-styles.ts @@ -0,0 +1,57 @@ +import { RowClassRules, RowNode } from '@ag-grid-community/core'; +import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; +import { MutableRefObject, useEffect, useMemo } from 'react'; +import { Song } from '/@/renderer/api/types'; +import { useCurrentSong, usePlayerStore } from '/@/renderer/store'; + +interface UseCurrentSongRowStylesProps { + tableRef: MutableRefObject; +} + +export const useCurrentSongRowStyles = ({ tableRef }: UseCurrentSongRowStylesProps) => { + const currentSong = useCurrentSong(); + + const rowClassRules = useMemo | undefined>(() => { + return { + 'current-song': (params) => { + return params?.data?.id === currentSong?.id; + }, + }; + }, [currentSong?.id]); + + // Redraw song rows when current song changes + useEffect(() => { + const unsubSongChange = usePlayerStore.subscribe( + (state) => state.current.song, + (song, previousSong) => { + if (tableRef?.current) { + const { api, columnApi } = tableRef?.current || {}; + if (api == null || columnApi == null) { + return; + } + + const currentNode = song?.id ? api.getRowNode(song.id) : undefined; + + const previousNode = previousSong?.id + ? api.getRowNode(previousSong?.id) + : undefined; + + const rowNodes = [currentNode, previousNode].filter( + (e) => e !== undefined, + ) as RowNode[]; + + api.redrawRows({ rowNodes }); + } + }, + { equalityFn: (a, b) => a?.id === b?.id }, + ); + + return () => { + unsubSongChange(); + }; + }, [tableRef]); + + return { + rowClassRules, + }; +}; diff --git a/src/renderer/components/virtual-table/index.tsx b/src/renderer/components/virtual-table/index.tsx index 6f07d8bf..238cbcb8 100644 --- a/src/renderer/components/virtual-table/index.tsx +++ b/src/renderer/components/virtual-table/index.tsx @@ -34,6 +34,7 @@ import { FavoriteCell } from '/@/renderer/components/virtual-table/cells/favorit import { RatingCell } from '/@/renderer/components/virtual-table/cells/rating-cell'; import { TablePagination } from '/@/renderer/components/virtual-table/table-pagination'; import { ActionsCell } from '/@/renderer/components/virtual-table/cells/actions-cell'; +import { TitleCell } from '/@/renderer/components/virtual-table/cells/title-cell'; export * from './table-config-dropdown'; export * from './table-pagination'; @@ -274,8 +275,7 @@ const tableColumns: { [key: string]: ColDef } = { width: 80, }, title: { - cellRenderer: (params: ICellRendererParams) => - GenericCell(params, { position: 'left', primary: true }), + cellRenderer: TitleCell, colId: TableColumn.TITLE, field: 'name', headerName: 'Title', diff --git a/src/renderer/features/albums/components/album-detail-content.tsx b/src/renderer/features/albums/components/album-detail-content.tsx index 1697a5a4..df2d67d7 100644 --- a/src/renderer/features/albums/components/album-detail-content.tsx +++ b/src/renderer/features/albums/components/album-detail-content.tsx @@ -33,6 +33,7 @@ import { } from '/@/renderer/components/virtual-table'; import { SwiperGridCarousel } from '/@/renderer/components/grid-carousel'; import { FullWidthDiscCell } from '/@/renderer/components/virtual-table/cells/full-width-disc-cell'; +import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles'; const isFullWidthRow = (node: RowNode) => { return node.id?.startsWith('disc-'); @@ -266,6 +267,8 @@ export const AlbumDetailContent = ({ tableRef }: AlbumDetailContentProps) => { ALBUM_CONTEXT_MENU_ITEMS, ); + const { rowClassRules } = useCurrentSongRowStyles({ tableRef }); + return ( @@ -356,6 +359,7 @@ export const AlbumDetailContent = ({ tableRef }: AlbumDetailContentProps) => { if (isFullWidthRow(data.data)) return false; return true; }} + rowClassRules={rowClassRules} rowData={songsRowData} rowSelection="multiple" onCellContextMenu={handleContextMenu} diff --git a/src/renderer/features/artists/components/album-artist-detail-top-songs-list-content.tsx b/src/renderer/features/artists/components/album-artist-detail-top-songs-list-content.tsx index ee063185..7b54ec04 100644 --- a/src/renderer/features/artists/components/album-artist-detail-top-songs-list-content.tsx +++ b/src/renderer/features/artists/components/album-artist-detail-top-songs-list-content.tsx @@ -9,6 +9,7 @@ import { LibraryItem, QueueSong } from '/@/renderer/api/types'; import { usePlayQueueAdd } from '/@/renderer/features/player'; import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid'; import { getColumnDefs, VirtualTable } from '/@/renderer/components/virtual-table'; +import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles'; interface AlbumArtistSongListContentProps { data: QueueSong[]; @@ -48,6 +49,8 @@ export const AlbumArtistDetailTopSongsListContent = ({ }); }; + const { rowClassRules } = useCurrentSongRowStyles({ tableRef }); + return ( <> @@ -69,6 +72,7 @@ export const AlbumArtistDetailTopSongsListContent = ({ enableCellChangeFlash={false} getRowId={(data) => data.data.uniqueId} rowBuffer={20} + rowClassRules={rowClassRules} rowData={data} rowHeight={page.table.rowHeight || 40} rowModelType="clientSide" diff --git a/src/renderer/features/context-menu/hooks/use-handle-context-menu.ts b/src/renderer/features/context-menu/hooks/use-handle-context-menu.ts index ff1d8c80..e4ae1d95 100644 --- a/src/renderer/features/context-menu/hooks/use-handle-context-menu.ts +++ b/src/renderer/features/context-menu/hooks/use-handle-context-menu.ts @@ -22,8 +22,6 @@ export const useHandleTableContextMenu = ( const api = gridApi || e?.api; - console.log('api :>> ', api); - if (!api) return; let selectedNodes = sortBy(api.getSelectedNodes(), ['rowIndex']); diff --git a/src/renderer/features/playlists/components/playlist-detail-content.tsx b/src/renderer/features/playlists/components/playlist-detail-content.tsx index 9bcb73d8..a84df4f3 100644 --- a/src/renderer/features/playlists/components/playlist-detail-content.tsx +++ b/src/renderer/features/playlists/components/playlist-detail-content.tsx @@ -14,6 +14,7 @@ import { useFixedTableHeader, VirtualTable, } from '/@/renderer/components/virtual-table'; +import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles'; import { useHandleTableContextMenu } from '/@/renderer/features/context-menu'; import { PLAYLIST_SONG_CONTEXT_MENU_ITEMS, @@ -163,6 +164,8 @@ export const PlaylistDetailContent = ({ tableRef }: PlaylistDetailContentProps) }); }; + const { rowClassRules } = useCurrentSongRowStyles({ tableRef }); + const loadMoreRef = useRef(null); return ( @@ -234,6 +237,7 @@ export const PlaylistDetailContent = ({ tableRef }: PlaylistDetailContentProps) // It's possible that there are duplicate song ids in a playlist return `${data.data.id}-${data.data.pageIndex}`; }} + rowClassRules={rowClassRules} rowData={playlistSongData} rowHeight={60} rowSelection="multiple" diff --git a/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx b/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx index c6351ce9..b948657f 100644 --- a/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx +++ b/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx @@ -40,6 +40,7 @@ import { queryKeys } from '/@/renderer/api/query-keys'; import { usePlaylistDetail } from '/@/renderer/features/playlists/queries/playlist-detail-query'; import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid'; import { getColumnDefs, VirtualTable, TablePagination } from '/@/renderer/components/virtual-table'; +import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles'; interface PlaylistDetailContentProps { tableRef: MutableRefObject; @@ -224,6 +225,8 @@ export const PlaylistDetailSongListContent = ({ tableRef }: PlaylistDetailConten }); }; + const { rowClassRules } = useCurrentSongRowStyles({ tableRef }); + return ( <> @@ -240,6 +243,7 @@ export const PlaylistDetailSongListContent = ({ tableRef }: PlaylistDetailConten pagination={isPaginationEnabled} paginationAutoPageSize={isPaginationEnabled} paginationPageSize={pagination.itemsPerPage || 100} + rowClassRules={rowClassRules} rowHeight={page.table.rowHeight || 40} rowModelType="infinite" onBodyScrollEnd={handleScroll} diff --git a/src/renderer/features/songs/components/song-list-table-view.tsx b/src/renderer/features/songs/components/song-list-table-view.tsx index d3e624ed..ffd292ca 100644 --- a/src/renderer/features/songs/components/song-list-table-view.tsx +++ b/src/renderer/features/songs/components/song-list-table-view.tsx @@ -6,6 +6,7 @@ import { queryKeys } from '/@/renderer/api/query-keys'; import { LibraryItem, QueueSong, SongListQuery, SongListResponse } from '/@/renderer/api/types'; import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid'; import { VirtualTable } from '/@/renderer/components/virtual-table'; +import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles'; import { AgGridFetchFn, useVirtualTable, @@ -54,6 +55,8 @@ export const SongListTableView = ({ tableRef, itemCount }: SongListTableViewProp [server], ); + const { rowClassRules } = useCurrentSongRowStyles({ tableRef }); + const tableProps = useVirtualTable>({ contextMenu: SONG_CONTEXT_MENU_ITEMS, fetch: { @@ -86,6 +89,7 @@ export const SongListTableView = ({ tableRef, itemCount }: SongListTableViewProp key={`table-${listProperties.display}-${listProperties.table.rowHeight}-${server?.id}`} ref={tableRef} {...tableProps} + rowClassRules={rowClassRules} onRowDoubleClicked={handleRowDoubleClick} /> diff --git a/src/renderer/styles/ag-grid.scss b/src/renderer/styles/ag-grid.scss index 4d1d6ec2..5063ee5f 100644 --- a/src/renderer/styles/ag-grid.scss +++ b/src/renderer/styles/ag-grid.scss @@ -1,41 +1,41 @@ .ag-header-fixed { - position: fixed !important; - top: 65px; - z-index: 15; - background: var(--table-header-bg) !important; - margin: 0 -2rem; - padding: 0 2rem; - border-bottom: 1px solid var(--table-border-color); - box-shadow: 0 -1px 0 0 #181818; - transition: position 0.2s ease-in-out; + position: fixed !important; + top: 65px; + z-index: 15; + background: var(--table-header-bg) !important; + margin: 0 -2rem; + padding: 0 2rem; + border-bottom: 1px solid var(--table-border-color); + box-shadow: 0 -1px 0 0 #181818; + transition: position 0.2s ease-in-out; } .ag-header { - z-index: 5; + z-index: 5; } .window-frame { - top: 95px; + top: 95px; } .ag-header-transparent { - --ag-header-background-color: rgba(0, 0, 0, 0%) !important; + --ag-header-background-color: rgba(0, 0, 0, 0%) !important; } .ag-header-fixed-margin { - margin-top: 43px !important; + margin-top: 43px !important; } .ag-header-cell-comp-wrapper { - margin: 0.5rem 0.5rem; + margin: 0.5rem 0.5rem; } .ag-header-cell, .ag-header-group-cell { - padding-left: 0.5rem; - padding-right: 0.5rem; + padding-left: 0.5rem; + padding-right: 0.5rem; } .ag-header-cell-resize { - background-color: transparent; + background-color: transparent; } diff --git a/src/renderer/themes/default.scss b/src/renderer/themes/default.scss index d63fc030..eb2e398c 100644 --- a/src/renderer/themes/default.scss +++ b/src/renderer/themes/default.scss @@ -1,204 +1,214 @@ :root { - --root-font-size: 13px; - --icon-color: rgb(255, 255, 255); + --root-font-size: 13px; + --icon-color: rgb(255, 255, 255); - --primary-color: rgb(53, 116, 252); - --secondary-color: rgb(255, 120, 120); - --success-color: green; - --warning-color: orange; - --danger-color: rgb(204, 50, 50); - --generic-border-color: rgba(50, 50, 50, 0.3); + --primary-color: rgb(53, 116, 252); + --secondary-color: rgb(255, 120, 120); + --success-color: green; + --warning-color: orange; + --danger-color: rgb(204, 50, 50); + --generic-border-color: rgba(50, 50, 50, 0.3); - --main-bg: rgb(18, 18, 18); - --main-fg: rgb(225, 225, 225); - --main-fg-secondary: rgb(150, 150, 150); + --main-bg: rgb(18, 18, 18); + --main-fg: rgb(225, 225, 225); + --main-fg-secondary: rgb(150, 150, 150); - --window-bar-bg: rgb(24, 24, 24); - --window-bar-fg: rgb(255, 255, 255); + --window-bar-bg: rgb(24, 24, 24); + --window-bar-fg: rgb(255, 255, 255); - --titlebar-fg: rgb(255, 255, 255); - --titlebar-bg: rgb(12, 12, 12); - --titlebar-controls-bg: rgba(0, 0, 0, 0); + --titlebar-fg: rgb(255, 255, 255); + --titlebar-bg: rgb(12, 12, 12); + --titlebar-controls-bg: rgba(0, 0, 0, 0); - --sidebar-bg: rgb(0, 0, 0); - --sidebar-bg-hover: rgb(50, 50, 50); - --sidebar-fg: rgb(190, 190, 190); - --sidebar-fg-hover: rgb(255, 255, 255); - --sidebar-handle-bg: #4d4d4d; - --sidebar-border: 2px rgba(18, 18, 18, 0.7) solid; + --sidebar-bg: rgb(0, 0, 0); + --sidebar-bg-hover: rgb(50, 50, 50); + --sidebar-fg: rgb(190, 190, 190); + --sidebar-fg-hover: rgb(255, 255, 255); + --sidebar-handle-bg: #4d4d4d; + --sidebar-border: 2px rgba(18, 18, 18, 0.7) solid; - --playerbar-bg: rgb(24, 24, 24); - --playerbar-btn-main-fg: rgb(0, 0, 0); - --playerbar-btn-main-fg-hover: rgb(0, 0, 0); - --playerbar-btn-main-bg: rgb(230, 230, 230); - --playerbar-btn-main-bg-hover: rgb(255, 255, 255); - --playerbar-btn-fg: rgba(200, 200, 200, 0.8); - --playerbar-btn-fg-hover: rgba(255, 255, 255, 1); - --playerbar-btn-bg: #c5c5c5; - --playerbar-btn-bg-hover: transparent; - --playerbar-border-top: 1px rgba(50, 50, 50, 0.7) solid; - --playerbar-slider-track-bg: #3c3f43; - --playerbar-slider-track-progress-bg: #cccccc; + --playerbar-bg: rgb(24, 24, 24); + --playerbar-btn-main-fg: rgb(0, 0, 0); + --playerbar-btn-main-fg-hover: rgb(0, 0, 0); + --playerbar-btn-main-bg: rgb(230, 230, 230); + --playerbar-btn-main-bg-hover: rgb(255, 255, 255); + --playerbar-btn-fg: rgba(200, 200, 200, 0.8); + --playerbar-btn-fg-hover: rgba(255, 255, 255, 1); + --playerbar-btn-bg: #c5c5c5; + --playerbar-btn-bg-hover: transparent; + --playerbar-border-top: 1px rgba(50, 50, 50, 0.7) solid; + --playerbar-slider-track-bg: #3c3f43; + --playerbar-slider-track-progress-bg: #cccccc; - --tooltip-bg: #ffffff; - --tooltip-fg: #000000; + --tooltip-bg: #ffffff; + --tooltip-fg: #000000; - --scrollbar-track-bg: transparent; - --scrollbar-thumb-bg: rgba(160, 160, 160, 0.3); - --scrollbar-thumb-bg-hover: rgba(160, 160, 160, 0.6); + --scrollbar-track-bg: transparent; + --scrollbar-thumb-bg: rgba(160, 160, 160, 0.3); + --scrollbar-thumb-bg-hover: rgba(160, 160, 160, 0.6); - --btn-filled-bg: var(--primary-color); - --btn-filled-bg-hover: rgb(34, 96, 255); - --btn-filled-fg: #ffffff; - --btn-filled-fg-hover: #ffffff; - --btn-filled-border: none; - --btn-filled-radius: 4px; + --btn-filled-bg: var(--primary-color); + --btn-filled-bg-hover: rgb(34, 96, 255); + --btn-filled-fg: #ffffff; + --btn-filled-fg-hover: #ffffff; + --btn-filled-border: none; + --btn-filled-radius: 4px; - --btn-default-bg: rgb(31, 31, 32); - --btn-default-bg-hover: rgb(63, 63, 63); - --btn-default-fg: rgb(193, 193, 193); - --btn-default-fg-hover: rgb(193, 193, 193); - --btn-default-border: none; - --btn-default-radius: 2px; + --btn-default-bg: rgb(31, 31, 32); + --btn-default-bg-hover: rgb(63, 63, 63); + --btn-default-fg: rgb(193, 193, 193); + --btn-default-fg-hover: rgb(193, 193, 193); + --btn-default-border: none; + --btn-default-radius: 2px; - --btn-subtle-bg: transparent; - --btn-subtle-bg-hover: transparent; - --btn-subtle-fg: rgb(220, 220, 220); - --btn-subtle-fg-hover: rgb(255, 255, 255); - --btn-subtle-border: none; - --btn-subtle-radius: 4px; + --btn-subtle-bg: transparent; + --btn-subtle-bg-hover: transparent; + --btn-subtle-fg: rgb(220, 220, 220); + --btn-subtle-fg-hover: rgb(255, 255, 255); + --btn-subtle-border: none; + --btn-subtle-radius: 4px; - --btn-outline-bg: transparent; - --btn-outline-bg-hover: transparent; - --btn-outline-fg: rgb(220, 220, 220); - --btn-outline-fg-hover: rgb(255, 255, 255); - --btn-outline-border: 1px rgba(140, 140, 140, 0.5) solid; - --btn-outline-border-hover: 1px rgba(255, 255, 255, 0.5) solid; - --btn-outline-radius: 5rem; + --btn-outline-bg: transparent; + --btn-outline-bg-hover: transparent; + --btn-outline-fg: rgb(220, 220, 220); + --btn-outline-fg-hover: rgb(255, 255, 255); + --btn-outline-border: 1px rgba(140, 140, 140, 0.5) solid; + --btn-outline-border-hover: 1px rgba(255, 255, 255, 0.5) solid; + --btn-outline-radius: 5rem; - --input-bg: rgb(35, 35, 35); - --input-fg: rgb(193, 193, 193); - --input-placeholder-fg: rgb(107, 108, 109); - --input-active-fg: rgb(193, 193, 193); - --input-active-bg: rgba(255, 255, 255, 0.1); + --input-bg: rgb(35, 35, 35); + --input-fg: rgb(193, 193, 193); + --input-placeholder-fg: rgb(107, 108, 109); + --input-active-fg: rgb(193, 193, 193); + --input-active-bg: rgba(255, 255, 255, 0.1); - --dropdown-menu-bg: rgb(32, 32, 32); - --dropdown-menu-fg: rgb(235, 235, 235); - --dropdown-menu-item-padding: 0.8rem; - --dropdown-menu-item-font-size: 1rem; - --dropdown-menu-bg-hover: rgb(62, 62, 62); - --dropdown-menu-border: 1px var(--generic-border-color) solid; - --dropdown-menu-border-radius: 4px; + --dropdown-menu-bg: rgb(32, 32, 32); + --dropdown-menu-fg: rgb(235, 235, 235); + --dropdown-menu-item-padding: 0.8rem; + --dropdown-menu-item-font-size: 1rem; + --dropdown-menu-bg-hover: rgb(62, 62, 62); + --dropdown-menu-border: 1px var(--generic-border-color) solid; + --dropdown-menu-border-radius: 4px; - --switch-track-bg: rgb(50, 50, 50); - --switch-track-enabled-bg: var(--primary-color); - --switch-thumb-bg: rgb(255, 255, 255); + --switch-track-bg: rgb(50, 50, 50); + --switch-track-enabled-bg: var(--primary-color); + --switch-thumb-bg: rgb(255, 255, 255); - --slider-track-bg: rgb(50, 50, 50); - --slider-thumb-bg: rgb(255, 255, 255); + --slider-track-bg: rgb(50, 50, 50); + --slider-thumb-bg: rgb(255, 255, 255); - --skeleton-bg: rgba(255, 255, 255, 8%); + --skeleton-bg: rgba(255, 255, 255, 8%); - --toast-title-fg: rgb(255, 255, 255); - --toast-description-fg: rgb(193, 194, 197); - --toast-bg: rgb(16, 16, 16); + --toast-title-fg: rgb(255, 255, 255); + --toast-description-fg: rgb(193, 194, 197); + --toast-bg: rgb(16, 16, 16); - --modal-bg: var(--main-bg); - --modal-header-bg: var(--paper-bg); + --modal-bg: var(--main-bg); + --modal-header-bg: var(--paper-bg); - --badge-bg: rgb(80, 80, 80); - --badge-fg: rgb(255, 255, 255); - --badge-radius: 12px; + --badge-bg: rgb(80, 80, 80); + --badge-fg: rgb(255, 255, 255); + --badge-radius: 12px; - --paper-bg: rgb(20, 20, 20); + --paper-bg: rgb(20, 20, 20); - --placeholder-bg: rgba(53, 53, 53, 1); - --placeholder-fg: rgba(126, 126, 126); + --placeholder-bg: rgba(53, 53, 53, 1); + --placeholder-fg: rgba(126, 126, 126); - --card-default-bg: rgb(32, 32, 32); - --card-default-bg-hover: rgb(44, 44, 44); - --card-default-radius: 5px; - --card-poster-bg: transparent; - --card-poster-bg-hover: transparent; - --card-poster-radius: 3px; + --card-default-bg: rgb(32, 32, 32); + --card-default-bg-hover: rgb(44, 44, 44); + --card-default-radius: 5px; + --card-poster-bg: transparent; + --card-poster-bg-hover: transparent; + --card-poster-radius: 3px; - --background-noise: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMDAiIGhlaWdodD0iMzAwIj48ZmlsdGVyIGlkPSJhIiB4PSIwIiB5PSIwIj48ZmVUdXJidWxlbmNlIHR5cGU9ImZyYWN0YWxOb2lzZSIgYmFzZUZyZXF1ZW5jeT0iLjc1IiBzdGl0Y2hUaWxlcz0ic3RpdGNoIi8+PGZlQ29sb3JNYXRyaXggdHlwZT0ic2F0dXJhdGUiIHZhbHVlcz0iMCIvPjwvZmlsdGVyPjxwYXRoIGZpbHRlcj0idXJsKCNhKSIgb3BhY2l0eT0iLjA1IiBkPSJNMCAwaDMwMHYzMDBIMHoiLz48L3N2Zz4='); + --background-noise: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMDAiIGhlaWdodD0iMzAwIj48ZmlsdGVyIGlkPSJhIiB4PSIwIiB5PSIwIj48ZmVUdXJidWxlbmNlIHR5cGU9ImZyYWN0YWxOb2lzZSIgYmFzZUZyZXF1ZW5jeT0iLjc1IiBzdGl0Y2hUaWxlcz0ic3RpdGNoIi8+PGZlQ29sb3JNYXRyaXggdHlwZT0ic2F0dXJhdGUiIHZhbHVlcz0iMCIvPjwvZmlsdGVyPjxwYXRoIGZpbHRlcj0idXJsKCNhKSIgb3BhY2l0eT0iLjA1IiBkPSJNMCAwaDMwMHYzMDBIMHoiLz48L3N2Zz4='); - --table-header-bg: rgb(24, 24, 24); - --table-header-fg: rgb(179, 179, 179); - --table-border: none; - --table-border-color: hsla(0, 0%, 100%, 0.1); - --table-bg: var(--main-bg); - --table-alt-bg: var(--main-bg); - --table-fg: rgb(179, 179, 179); - --table-row-hover-bg: rgba(100, 100, 100, 0.2); - --table-row-selected-bg: rgba(100, 100, 100, 0.4); + --table-header-bg: rgb(24, 24, 24); + --table-header-fg: rgb(179, 179, 179); + --table-border: none; + --table-border-color: hsla(0, 0%, 100%, 0.1); + --table-bg: var(--main-bg); + --table-alt-bg: var(--main-bg); + --table-fg: rgb(179, 179, 179); + --table-row-hover-bg: rgba(100, 100, 100, 0.2); + --table-row-selected-bg: rgba(100, 100, 100, 0.4); - .ag-theme-alpine-dark { - --ag-font-family: var(--content-font-family); + .ag-theme-alpine-dark { + --ag-font-family: var(--content-font-family); - --ag-borders: var(--table-border); - --ag-border-color: var(--table-border-color); + --ag-borders: var(--table-border); + --ag-border-color: var(--table-border-color); - --ag-header-background-color: var(--table-header-bg); - --ag-header-foreground-color: var(--table-header-fg); + --ag-header-background-color: var(--table-header-bg); + --ag-header-foreground-color: var(--table-header-fg); - --ag-background-color: var(--table-bg); - --ag-odd-row-background-color: var(--table-alt-bg); - --ag-foreground-color: var(--table-fg); + --ag-background-color: var(--table-bg); + --ag-odd-row-background-color: var(--table-alt-bg); + --ag-foreground-color: var(--table-fg); - --ag-row-hover-color: var(--table-row-hover-bg); - --ag-selected-row-background-color: var(--table-row-selected-bg); + --ag-row-hover-color: var(--table-row-hover-bg); + --ag-selected-row-background-color: var(--table-row-selected-bg); - --ag-cell-horizontal-padding: 0.5rem; - } + --ag-cell-horizontal-padding: 0.5rem; + } - .ag-header { - border-bottom: 2px solid var(--table-border-color); - } + .ag-header { + border-bottom: 2px solid var(--table-border-color); + } - .ag-ltr .ag-header-cell-resize { - right: 0px; - } + .ag-ltr .ag-header-cell-resize { + right: 0px; + } - .ag-header:hover .ag-header-cell-resize { - position: absolute; - top: 25%; - border: 1px var(--table-border-color) solid; - height: 50%; - width: 0.2em; - } + .ag-header:hover .ag-header-cell-resize { + position: absolute; + top: 25%; + border: 1px var(--table-border-color) solid; + height: 50%; + width: 0.2em; + } - .ag-header-cell-label { - font-family: var(--content-font-family); - font-weight: 500; - text-transform: uppercase; - } + .ag-header-cell-label { + font-family: var(--content-font-family); + font-weight: 500; + text-transform: uppercase; + } - .ag-cell-rating, - .ag-cell-favorite { - display: none; - } - - .ag-cell-rating.visible { - display: block; - } - - .ag-cell-favorite.visible { - display: block; - } - - .ag-row-hover { .ag-cell-rating, .ag-cell-favorite { - display: block; + display: none; } - } - .ag-cell-focus { - border: 1px var(--table-border-color) solid !important; - } - .current-song { - background: rgba(96, 144, 240, 0.3) !important; - } + .ag-cell-transparent { + opacity: 0; + } + + .ag-cell-rating.visible { + display: block; + } + + .ag-cell-favorite.visible { + display: block; + } + + .ag-row-hover { + .ag-cell-transparent { + opacity: 1; + } + + .ag-cell-rating, + .ag-cell-favorite { + display: block; + } + } + .ag-cell-focus { + border: 1px var(--table-border-color) solid !important; + } + + .current-song { + .current-song-child { + color: var(--primary-color) !important; + } + } }