mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-08 02:17:25 +02:00
fix(ui): make playlist toggle switches visible in all themes (#6277)
* fix(ui): make playlist toggle switches visible in all themes The Public and Auto-import switches in the playlist list did not set a color, so Material-UI used the theme's secondary color. Many themes use secondary as a surface color close to the table background, which made checked switches nearly invisible (Catppuccin, Rosé Pine, Monokai, Moonbase and others). Set color="primary" on the playlist switch, like every other switch in the app, and make primary the default MuiSwitch color in useCurrentTheme so future switches cannot regress. Fixes #6272. * refactor(ui): drop secondary switch overrides from themes Dracula, Gruvbox Dark, Tokyo Night and Tokyo Night Light styled checked MuiSwitch colorSecondary to work around the same invisible-switch problem (Gruvbox in #5064). With primary as the default switch color and every switch in the app using it, no switch renders with colorSecondary anymore, so these overrides are dead code.
This commit is contained in:
parent
95f67d2c4e
commit
caa2f8a0c0
8 changed files with 57 additions and 40 deletions
|
|
@ -95,6 +95,7 @@ export const ToggleField = ({ resource, source }) => {
|
|||
return (
|
||||
<Switch
|
||||
checked={record[source]}
|
||||
color="primary"
|
||||
onClick={handleClick}
|
||||
disabled={!isWritable(record.ownerId)}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React from 'react'
|
|||
import { render, screen } from '@testing-library/react'
|
||||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { TestContext } from 'ra-test'
|
||||
import { RecordContextProvider } from 'react-admin'
|
||||
import { PlaylistLove, ToggleField, ToggleAutoImport } from './PlaylistList'
|
||||
|
||||
vi.mock('../config', () => ({
|
||||
|
|
@ -14,6 +15,7 @@ vi.mock('../common', () => ({
|
|||
{record?.starred ? 'starred' : 'not-starred'}
|
||||
</button>
|
||||
),
|
||||
isWritable: (ownerId) => ownerId === 'me',
|
||||
}))
|
||||
|
||||
describe('<PlaylistLove />', () => {
|
||||
|
|
@ -55,3 +57,28 @@ describe('playlist toggles without a record', () => {
|
|||
expect(container.innerHTML).toBe('')
|
||||
})
|
||||
})
|
||||
|
||||
// Secondary is a surface color in many themes, so these toggles must use primary
|
||||
describe('<ToggleField />', () => {
|
||||
const renderToggle = (record) =>
|
||||
render(
|
||||
<TestContext>
|
||||
<RecordContextProvider value={record}>
|
||||
<ToggleField resource="playlist" source="public" />
|
||||
</RecordContextProvider>
|
||||
</TestContext>,
|
||||
)
|
||||
|
||||
it.each([
|
||||
['owner', 'me', false],
|
||||
['non-owner', 'someone-else', true],
|
||||
])('renders a primary-colored switch for the %s', (_, ownerId, disabled) => {
|
||||
renderToggle({ id: 'pl-1', public: true, ownerId })
|
||||
const input = screen.getByRole('checkbox')
|
||||
const switchBase = input.closest('.MuiSwitch-switchBase')
|
||||
expect(input.checked).toBe(true)
|
||||
expect(input.disabled).toBe(disabled)
|
||||
expect(switchBase.classList).toContain('MuiSwitch-colorPrimary')
|
||||
expect(switchBase.classList).not.toContain('MuiSwitch-colorSecondary')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -185,16 +185,6 @@ export default {
|
|||
color: `${foreground} !important`,
|
||||
},
|
||||
},
|
||||
MuiSwitch: {
|
||||
colorSecondary: {
|
||||
'&$checked': {
|
||||
color: green,
|
||||
},
|
||||
'&$checked + $track': {
|
||||
backgroundColor: green,
|
||||
},
|
||||
},
|
||||
},
|
||||
NDAlbumGridView: {
|
||||
albumName: {
|
||||
marginTop: '0.5rem',
|
||||
|
|
|
|||
|
|
@ -121,16 +121,6 @@ export default {
|
|||
boxShadow: '3px 3px 5px #3c3836',
|
||||
},
|
||||
},
|
||||
MuiSwitch: {
|
||||
colorSecondary: {
|
||||
'&$checked': {
|
||||
color: '#458588',
|
||||
},
|
||||
'&$checked + $track': {
|
||||
backgroundColor: '#458588',
|
||||
},
|
||||
},
|
||||
},
|
||||
NDMobileArtistDetails: {
|
||||
bgContainer: {
|
||||
background:
|
||||
|
|
|
|||
|
|
@ -184,16 +184,6 @@ export default {
|
|||
color: `${foreground} !important`,
|
||||
},
|
||||
},
|
||||
MuiSwitch: {
|
||||
colorSecondary: {
|
||||
'&$checked': {
|
||||
color: blue,
|
||||
},
|
||||
'&$checked + $track': {
|
||||
backgroundColor: blue,
|
||||
},
|
||||
},
|
||||
},
|
||||
NDAlbumGridView: {
|
||||
albumName: {
|
||||
marginTop: '0.5rem',
|
||||
|
|
|
|||
|
|
@ -184,16 +184,6 @@ export default {
|
|||
color: `${foreground} !important`,
|
||||
},
|
||||
},
|
||||
MuiSwitch: {
|
||||
colorSecondary: {
|
||||
'&$checked': {
|
||||
color: blue,
|
||||
},
|
||||
'&$checked + $track': {
|
||||
backgroundColor: blue,
|
||||
},
|
||||
},
|
||||
},
|
||||
NDAlbumGridView: {
|
||||
albumName: {
|
||||
marginTop: '0.5rem',
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ const useCurrentTheme = () => {
|
|||
...theme.props,
|
||||
MuiUseMediaQuery: { noSsr: true },
|
||||
MuiPopover: { disableScrollLock: true },
|
||||
// MUI defaults to secondary, which many themes use as a surface color
|
||||
MuiSwitch: { color: 'primary' },
|
||||
},
|
||||
}),
|
||||
[theme],
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@ import { Provider } from 'react-redux'
|
|||
import { createStore } from 'redux'
|
||||
import mediaQuery from 'css-mediaquery'
|
||||
import { renderHook } from '@testing-library/react-hooks'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles'
|
||||
import Switch from '@material-ui/core/Switch'
|
||||
import themes from './index'
|
||||
import useCurrentTheme from './useCurrentTheme'
|
||||
import { themeReducer } from '../reducers/themeReducer'
|
||||
import { AUTO_THEME_ID } from '../consts'
|
||||
|
|
@ -161,4 +165,27 @@ describe('useCurrentTheme', () => {
|
|||
expect(document.body.style.backgroundColor).toBe('rgb(18, 18, 18)')
|
||||
})
|
||||
})
|
||||
describe('switch color', () => {
|
||||
it.each(Object.keys(themes))(
|
||||
'renders switches with the primary color in %s',
|
||||
(theme) => {
|
||||
const { result } = renderHook(() => useCurrentTheme(), {
|
||||
wrapper: ({ children }) => (
|
||||
<Provider store={createStore(themeReducer, { theme })}>
|
||||
{children}
|
||||
</Provider>
|
||||
),
|
||||
})
|
||||
render(
|
||||
<ThemeProvider theme={createMuiTheme(result.current)}>
|
||||
<Switch checked onChange={() => {}} />
|
||||
</ThemeProvider>,
|
||||
)
|
||||
const switchBase = screen
|
||||
.getByRole('checkbox')
|
||||
.closest('.MuiSwitch-switchBase')
|
||||
expect(switchBase.classList).toContain('MuiSwitch-colorPrimary')
|
||||
},
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue