91 Commits

Author SHA1 Message Date
York
2aa7a5c466
fix(ui): prevent Safari album grid resize when top menus open (#6125)
* fix(ui): prevent Safari album grid resize when top menus open

* fix(ui): disable scroll lock for all popovers

---------

Co-authored-by: Deluan Quintão <deluan@navidrome.org>
2026-09-10 20:48:33 -04:00
Deluan Quintão
fe1c87c190
fix(ui): round the album grid hover overlay in the Nautiline theme (#6115)
The theme rounded the cover image directly and set a border radius on
albumContainer, which has no background or clipping, so it rounded
nothing. The hover overlay is a sibling of the image inside the same
link, so it kept square corners that poked out over the rounded cover.

Move the radius to that link and clip it, so both the image and the
overlay follow the same rounded box. This also covers the mobile bar,
which is always visible.

Fixes #6110
2026-09-09 10:52:15 -04:00
jaxi
1ceb25c6c1
feat(ui): added Catppuccin Mocha and Frappé themes, updated Macchiato theme to better reflect the official palette (#5835)
* added catppuccin mocha theme

* added catppuccin mocha theme to index.js

* fix syntax

* add catppuccin frappé theme

* made frappe and mocha themes more consistant with official color palette and added comments for easy verification

* same for macchiato, seperate commit in case original is preferred

* added comments to .js files

---------

Co-authored-by: Deluan Quintão <deluan@navidrome.org>
2026-09-06 23:28:25 -04:00
Deluan Quintão
50633f839d
fix(ui): restore each page's scroll position when navigating back (#5892)
* fix(ui): anchor detail pages to the top when opened from a list

React Router keeps the previous page's scroll offset, so opening an album from
a scrolled list started the detail page mid-song-list. Artist pages had the
same bug; it just shows less because the artist list is rarely long enough to
scroll far.

Keyed on the record id rather than mount, so detail-to-detail navigation (an
album's artist link) resets too, and so the scroll waits for the record instead
of firing against an empty page.

* feat(ui): remember each route's scroll offset

A hook that saves window.scrollY per history entry and, on navigation, tops a
pushed route or returns a popped one to where it was. Keyed on location.key so
back and forward each restore their own offset, and bounded because history
entries are not.

Callers pass their own readiness: restoring before the rows render leaves the
document too short, so the browser clamps to the top and the offset is lost with
no error to show for it.

* refactor(ui): fold scroll-to-top into route scroll restoration

useScrollToTop only ever forced the top, so it fixed opening a detail page from a
scrolled list and did nothing for the return trip: coming back to the list landed
wherever it happened to be. The new hook covers both, and its readiness argument
carries over the reason the old one keyed on the record id - waiting for the
record rather than firing against an empty page.

* feat(ui): restore the album list's position when returning to it

The list is the page worth remembering: scrolling a long way to find an album and
landing back at the top is the annoyance the detail-page scroll fix could not
reach.

Mounted as a pass-through around the List's child rather than beside it, because
React Admin calls Children.only on List children and clones that one child with
the list props - which is also how this reads loaded/total to wait for rows.

* fix(ui): key scroll restoration on the route, not location.key

Hash history never assigns location.key - history.js calls createLocation with an
undefined key and warns that it cannot carry state - so every route collapsed
into one slot. The detail page's own scroll listener then overwrote the list's
saved offset with 0, and going back restored that 0. Only the scroll-to-top half
worked, which is what made it look fine.

Keyed on pathname+search instead. The spec that would have caught this asserts
two routes keep separate offsets; the previous ones mocked the router and so
only ever confirmed the assumption.

* refactor(ui): tidy up scroll restoration after review

Four cleanups, none changing behaviour:

ScrollRestorer read loaded/total off whatever props React Admin happened to clone
in. useListContext is the contract for those values and is already used three
times elsewhere, including further down this same file; the clone payload is an
implementation detail that would fail silently if it ever changed.

The restore runs in a layout effect now. A passive effect is flushed after paint,
so an image-heavy grid was painted at the old offset and then jumped.

MAX_ENTRIES matches the naming every other module-level cap in common/ uses.

The per-instance guard against re-restoring was deletable with a green suite, so
it now has a spec: readiness flickering on one route must not scroll twice.

* fix(ui): resolve media queries on the first render

MUI defaults useMediaQuery and withWidth to SSR-safe two-pass rendering: the first
render reports the wrong breakpoint and a layout effect corrects it. Navidrome is
client-only, so every mount paints a layout it immediately reflows. Album tiles
render without their artist line and grow 14px when it arrives, and react-admin's
own buttons paint labelled before collapsing to icons, which together grew the
album list 79px right after a scroll restore and dragged the position with it.

Setting noSsr on the theme reaches react-admin's internals too. withWidth needs its
own option because it gates on a mount flag rather than on the media query.

* fix(ui): keep restoring the scroll offset until it sticks

A single scrollTo assumes the page is already at its final height. It often is not:
the artist page reports ready as soon as its cached header record renders, while the
albums below are still loading, so the browser clamps the offset to the top of a
viewport-tall document and it is lost with no error.

The restore now retries until the offset lands, yielding as soon as the position moves
somewhere we did not put it. Keying that on input events instead breaks the trackpad
back-swipe, whose wheel momentum keeps firing through the restore window.

Offsets are also committed when leaving the page rather than on every scroll. Tearing
the page down collapses the document and snaps to the top, and a live listener recorded
that clamp over the offset being left behind.

* refactor(ui): tidy up scroll restoration after review

Folds the offset commit into the scroll tracker's own cleanup now that the tracker
ignores the collapse snap, so one effect does what two did. Skips scheduling the retry
loop when the first scrollTo already landed, and only pays for the scrollHeight read on
scroll events that reach the top, since that is the only case the guard can fire.

The theme hook's own prefers-color-scheme query runs above the ThemeProvider carrying
the new prop, so it needs noSsr passed directly or the auto theme still renders dark
first and flips.

Also lifts the repeated fake-timer fixture in the specs into one helper and restores
real timers from afterEach, so a failing assertion no longer leaves them installed for
every later spec.

* fix(ui): bank the scroll offset before the next page tops itself

Committing the offset from the scroll listener's passive cleanup ran too late. The
incoming page scrolls to the top in its own layout effect, and the outgoing page's
listener is still attached at that moment, so it recorded that 0 over the offset being
left behind. Whether it did depended on when the browser dispatched the scroll event
relative to React's passive flush, which made returning to a detail page lose its
position intermittently.

Moving the commit back into a layout cleanup makes it deterministic: React runs those
in the mutation phase, before the incoming page's layout effects. The scrollHeight
guard in the listener went with it, since it only covered the case where the incoming
page was shorter than the viewport and the ordering covers all of them.
2026-08-04 22:07:16 -04:00
Patrick
89aa58a713
feat(ui): add rose pine themes (#5664)
* feat(theme): add rose pine themes

fix checkboxes

* feat(theme): apply review suggestions

* feat(theme): fix toolbar background in mobile view

* feat(theme): small css improvements
2026-07-03 17:53:57 -04:00
Jan Mrzygłód
37e5a1d248
fix(ui): Fix Nautiline theme font and width on mobile devices (#5590)
Signed-off-by: devBoi76 <mrzyglodjan@protonmail.com>
2026-06-10 16:47:54 -04:00
Metalhearf
cc18bf7329
feat(ui): add Tokyo Night theme (#5497)
* feat(themes): add Tokyo Night theme

Signed-off-by: Metalhearf <6446231+Metalhearf@users.noreply.github.com>

* fix(themes): address review feedback on Tokyo Night

Signed-off-by: Metalhearf <6446231+Metalhearf@users.noreply.github.com>

---------

Signed-off-by: Metalhearf <6446231+Metalhearf@users.noreply.github.com>
Co-authored-by: Deluan <deluan@navidrome.org>
2026-06-05 21:04:48 -04:00
Love
e15896bf32 feat(ui): Add Catppuccin Latte (#5250)
Add Catppuccin Latte (the light version) theme based on the existing Catppuccin Macchiato theme.
The palette and player styling are adapted for light mode while staying as close as practical
to the existing Macchiato theme behavior. I've opted to use gray for the
color for controls.

The dark version appears to mix a few control/accent colors,
so for Latte I standardized those choices. This might be worth looking
into in a separate PR. It uses gray and blue.

Signed-off-by: Love Billenius <lovebillenius@disroot.org>
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
Signed-off-by: Deluan <deluan@navidrome.org>
2026-06-05 20:42:53 -04:00
craiglush
29c123854c
feat(ui): Add Moonbase themes (Alpha light + Bravo dark) (#5243)
* Add Moonbase theme

A warm dark theme with gold (#d4a039) accents on deep charcoal
backgrounds (#0a0a09/#141413). Features muted cream text (#e5ddd3),
copper error states (#c45c3c), and subtle earthy secondary tones.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix review comments on Moonbase theme

- Fix CSS selector: use :not(.player-delete) instead of :not([class=".player-delete"])
- Fix MuiFormHelperText override structure: target error key directly
- Remove empty icon: {} and avatar: {} from NDLogin overrides
- Use comma-separated rgba syntax and hex for linear-gradient

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add Moonbase Alpha (light) and rename dark to Moonbase Bravo

Split the Moonbase theme into a complementary pair:
- Moonbase Alpha: warm cream/stone light theme with deep gold accents
- Moonbase Bravo: the original deep charcoal dark theme

Both share the same gold (#d4a039) brand accent, copper error states,
and earthy neutral palette. Alpha uses darkened gold (#9a7420) for
better contrast on light backgrounds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
2026-06-05 20:35:56 -04:00
Tales Costa
dad4203f9a
fix(ui): Gruvbox Dark colors (#5553)
* Add Gruvbox Dark theme

Add Gruvbox Dark color theme including:
- gruvboxDark.js with full palette and component overrides
- gruvboxDark.css.js with custom player styles

* Fix: move error state to MuiFormHelperText
2026-06-02 08:38:57 -04:00
VirtualWolf
23252e0638
fix(ui): updated the AMusic theme to use the correct text colour for primary confirmation buttons (#5509) 2026-05-19 11:01:41 -03:00
Deluan
4570dec675 fix(ui): refine image filters for playing and paused states in SquiddiesGlass
Signed-off-by: Deluan <deluan@navidrome.org>
2026-04-08 13:13:56 -04:00
cafecitopuro
0a0f1779cb
feat(ui): add Nutball theme (#4544)
* add nutball theme

* fix album grid outline

* cleanup

* Pagination fix + accent color update

* Fix animation on Activity icon

* style: fix prettier formatting in nutball theme

---------

Co-authored-by: Deluan <deluan@navidrome.org>
2026-03-24 19:39:02 -04:00
Deluan
51c48bcacd fix(ui): enforce consistent delete button contrast for delete in AMusic theme
Signed-off-by: Deluan <deluan@navidrome.org>
2026-03-10 18:12:57 -04:00
Deluan Quintão
08a71320ea
fix(ui): make toggle switches visible in Gruvbox Dark theme (#5063) (#5064)
The secondary color (#3c3836) matches the panel/table cell background,
making checked MuiSwitch thumbs invisible. Add MuiSwitch override using
Gruvbox cyan (#458588), consistent with existing interactive elements.
2026-02-18 15:38:20 -05:00
Paul Becker
f00af7f983
feat(ui): add Dracula theme (#5023)
Signed-off-by: Paul Becker <p@becker.kiwi>
2026-02-12 16:42:34 -05:00
Boris Rorsvort
4f3845bbe3
fix(ui): Nautiline theme font path (#4983)
* fix: Nautiline theme font path

* refactor font path
2026-02-04 17:24:30 -05:00
Boris Rorsvort
37aa54fe06
feat(ui): Add Nautiline like theme (#4909)
* wip

* add main file

* fixes

* linting

* refactor

* fix player

* fix lint

* fix pr comments

* Add font locally

* fix: quickfix
2026-01-20 12:11:47 -05:00
Deluan
ebbe62bbbd fix(ui): update delete button color in AMusic theme
Signed-off-by: Deluan <deluan@navidrome.org>
2025-12-14 13:51:01 -05:00
dragonish
42c85a18e2
fix(ui) Improve player buttons in AMusic theme (#4797)
* fix(ui): improve the lyric button of the AMusic theme

* fix(amusic): update styles for music player panel SVG and disabled button states

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
2025-12-13 13:04:29 -05:00
Deluan
9f0d3f3cf4 fix(ui): sync body background color with theme
Set document.body.style.backgroundColor to match the current theme's background
color whenever the theme changes. This fixes the white background that appeared
during pull-to-refresh gestures on mobile or overscroll on desktop, where the
browser reveals the area behind the app content.

The background color is determined by the theme's palette.background.default
value if defined, otherwise falls back to Material-UI defaults (#303030 for
dark themes, #fafafa for light themes).

Signed-off-by: Deluan <deluan@navidrome.org>
2025-12-02 16:14:32 -05:00
Stephan Wahlen
2b30ed1520
fix(ui): Amusic theme improvements (#4731)
* fix low contrast in "delete missing files" button

* make login screen a bit nicer

* style modal similar to rest of ui

* Add custom styles for Ra Pagination

* Refactor styles in amusic.js

Removed albumSubtitle color and updated styles for albumPlayButton and albumArtistName

* Add NDDeleteLibraryButton and NDDeleteUserButton styles

low contrast

* low contrast text on delete buttons

* playbutton color back to pink without background
2025-11-28 08:52:26 -05:00
Xavier Araque
ee51bd9281
feat(ui): add SquiddiesGlass Theme (#4632)
* feat: Add SquiddiesGlass Theme

* feat: fix commnets by gemini-code-assist in PR

* feat: fix Prettier format

* feat: fix play button, and text mobile

* feat: fix play button, and text mobile, prettier

* feat: fix chip, title artist

* fix: loading albbun, play button color

* prettier

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Xavier Araque <francisco.araque@toolfactory.net>
Co-authored-by: Deluan <deluan@navidrome.org>
2025-11-22 13:41:59 -05:00
Stephan Wahlen
2451e9e7ae
feat(ui): add AMusic (Apple Music inspired) theme (#4723)
* first show at AMuisc Theme

* prettier

* fix Duplicate key 'MuiButton'

* fix file name

* Update amusic.js

* Add styles for NDAlbumGridView in amusic.js

* Fix MuiToolbar background property in amusic.js

* Fix syntax error in amusic.js background property

* run prettier

* fix banded table styling and more

* more styling to player

- fix some appearances of green in queue
- match queue styling to rest of theme
- round albumart in player and prevent rotation

* fix queue panel background and border

to make it stand out more against the background

* fix stray comma

and lint+prettier

* queue hover still green

and player preview image not rounded properly

* Update amusic.css.js

* more mobile color fixes

* artist page

* prettier

* rounded art in albumgridview

* small tweaks to colors and radiuses

* artist and album heading

* external links colors

* unify font colors + albumgrid corner radius

* get rid of queue hover green

* unify colors in player

same red shades as primary

* mobile player floating panel background shade of green

* unify border colors

and attempt to get album cover corner radius working

* final touches

* Update amusic.css.js

* fix invisible button color fir muibutton

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* fix css syntax on player queue color overrides

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

* remove unused MuiTableHead

* sort theme list in index.js alphabetically

* remove unused properties

* Revert "fix css syntax on player queue color overrides"

This reverts commit 503bba321d958aed5251667c58214822ceb70f59.

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-11-22 11:23:02 -05:00
Deluan
9b3bdc8a8b fix(ui): adjust margins for bulk actions buttons in Spotify-ish and Ligera
Signed-off-by: Deluan <deluan@navidrome.org>
2025-11-13 18:30:44 -05:00
Deluan
f939ad84f3 fix(ui): increase contrast of button text in the Dark theme
Signed-off-by: Deluan <deluan@navidrome.org>
2025-11-12 16:17:41 -05:00
Deluan Quintão
69527085db
fix(ui): resolve transparent dropdown background in Ligera theme (#4665)
Fixed the multi-library selector dropdown background in the Ligera theme by changing the palette.background.paper value from 'inherit' to bLight['500'] ('#ffffff'). This ensures the dropdown has a solid white background that properly overlays content, making the library selection options clearly readable.

Closes #4502
2025-11-08 12:47:02 -05:00
deluan
0bdd3e6f8b fix(ui): fix Ligera theme's RaPaginationActions contrast 2025-10-30 16:34:31 -04:00
Konstantin Morenko
465846c1bc
fix(ui): fix color of MuiIconButton in Gruvbox Dark theme (#4585)
* Fixed color of MuiIconButton in gruvboxDark.js

* Update ui/src/themes/gruvboxDark.js

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-29 09:14:40 -04:00
Deluan
aee2a1f8be fix(ui): artist buttons in spotify-ish
Signed-off-by: Deluan <deluan@navidrome.org>
2025-06-09 17:56:59 -04:00
Deluan Quintão
7d1f5ddf06
fix(ui): playlist details overflow in spotify-based themes (#4184)
* test: ensure playlist details width

* fix(test): simplify expectation for minWidth in NDPlaylistDetails

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(test): test all themes

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2025-06-08 14:21:40 -04:00
Deluan Quintão
fcdd30ba8f
build(ui): migrate from CRA/Jest to Vite/Vitest (#3311)
* feat: create vite project

* feat: it's alive!

* feat: `make dev` working!

* feat: replace custom serviceWorker with vite plugin

* test: replace Jest with Vitest

* fix: run prettier

* fix: skip eslint for now.

* chore: remove ui.old folder

* refactor: replace lodash.pick with simple destructuring

* fix: eslint errors (wip)

* fix: eslint errors (wip)

* fix: display-name eslint errors (wip)

* fix: no-console eslint errors (wip)

* fix: react-refresh/only-export-components eslint errors (wip)

* fix: react-refresh/only-export-components eslint errors (wip)

* fix: react-refresh/only-export-components eslint errors (wip)

* fix: react-refresh/only-export-components eslint errors (wip)

* fix: build

* fix: pwa manifest

* refactor: pwa manifest

* refactor: simplify PORT configuration

* refactor: rename simple JS files

* test: cover playlistUtils

* fix: react-image-lightbox

* feat(ui): add sourcemaps to help debug issues
2024-09-28 11:54:36 -04:00
gruneforth
b0e7941abe
fix(ui): fix Nuclear Theme (#3291)
* Add Nuclear Theme

* Fix login screen color & Softened "link" coloring

---------

Co-authored-by: grune <grune@grunk.me>
2024-09-19 17:13:44 -04:00
Kendall Garner
3e1fa20413
fix background color for nord theme (#3124) 2024-06-29 18:50:33 -04:00
gruneforth
1802015737
Add Nuclear Theme (#3098) 2024-06-29 17:04:30 -04:00
edthu
2fdc1677f7
Add Catppuccin Macchiato Theme (#3014)
* Added Catppuccin Macchiato theme

* fixed index.js formatting
2024-05-11 13:08:51 -04:00
Tim
8f9ed1b994
Handling long playlist comments (#2973)
Closes #1737

* wrapping playlist comment in a <Collapse> element

* Extract common collapsible logic into a component

---------

Co-authored-by: Deluan <deluan@navidrome.org>
2024-04-25 20:28:25 -04:00
Caio Cotts
86757663d6 Reformat code with Prettier's new rules. 2023-12-18 15:12:24 -05:00
Lukas H
ac7f94e620
Fix text being unreadable with Ligera theme (#2517)
Change MuiFormGroup color to make it readable.
2023-09-10 12:28:21 -04:00
Deluan
a3d78e95f2 Fix Monokai theme. Closes #2353 2023-05-17 15:36:30 -04:00
Kendall Garner
f8dfb3ad86
Clearer lyrics in Nord theme (#2146) 2023-02-04 13:02:15 -05:00
vlfldr
a1a5b2fc30
Fix invisible checkboxes in Gruvbox theme (#2135)
* Added Gruvbox Dark color theme

* Correct formatting by running prettier

* Fixed invisible checkboxes and tweaked colors in Gruvbox theme
2023-02-01 13:33:55 -05:00
Deluan
230f2fdc02 Reduce spacing between album buttons, to avoid breaking the toolbar in two 2023-01-24 18:36:47 -05:00
vlfldr
8ae0bcb459
Add Gruvbox Dark color theme (#2092)
* Added Gruvbox Dark color theme

* Correct formatting by running prettier
2023-01-18 13:23:36 -05:00
Deluan Quintão
334ccac643
Spotify-ish Improvement (#2012)
* spotify-improvement

* fixing the issue of applying styles to filter fields too

* Remove scrollbar styling.

Maybe we should simulate macOS's scrollbar behaviour, with something like this: https://gist.github.com/spemer/a0e218bbb45433bd611e68446523a00b

Co-authored-by: Rishabh Malhotra <rishabhmalhotraa01@gmail.com>
2022-11-27 12:13:00 -05:00
Renere
6a6fa3e3b5
Nord Theme - Make links have a different colour (#1900) 2022-10-01 22:23:33 -04:00
Renere
22507c9789
Add Nord Theme. Closes #1158 and supersedes #1159 (#1899).
* Re-add tpbnick's Nord theme

* Run Prettier formatter on Nord theme

* Update themes index

* Fix button margins

* Modernise the look of switches

* Adjust margins and padding

* Fix sidebar's background colour not applying to all of sidebar when scrolling down

* Adjust App Bar box shadow

* Adjust roundedness

* Adjust shadows

* Adjust outlined inputs

* Add transitions to items in sidebar when hovered / losing hover

* Adjust border radiuses

* Adjust pagination buttons

* Add big play button from Spotify theme

* Remove playlist background gradient

* Adjust colour of MuiChip elelments

* Adjust table borders

* Remove duplicate MuiTableRow key

* Attempt to make switches in both the playlist section and settings section visable against background & the toggle. Not ideal.

* Style the player

* Format CSS to Prettier standards

* Fix mobile player style

* Make play button in album grid view blue

* Make main view background lighter
2022-10-01 12:01:21 -04:00
William Lohan
4209e14208
Add theme Electric Purple (#1889)
* add theme file

add theme file electricPurple.js

* import theme file 

import theme file  electricPurple

* add electricPurple.css.js
2022-09-30 19:54:00 -04:00
Matt Doyle
5987cd0c08
Fixes a coloring glitch with the Monokai theme "unauthorized" popup (#1670)
* Fixes the coloring on the Monokai theme auth popup

* Indentation fix
2022-03-26 22:41:29 -04:00
Matt Doyle
e7cf74d863
Adds a Monokai theme (#1669)
* Adds a new Monokai theme

* Deletes a commented-out line
2022-03-26 21:14:13 -04:00