diff --git a/ui/src/audioplayer/LyricsLayerControls.jsx b/ui/src/audioplayer/LyricsLayerControls.jsx
index bcb396e44..449a704d9 100644
--- a/ui/src/audioplayer/LyricsLayerControls.jsx
+++ b/ui/src/audioplayer/LyricsLayerControls.jsx
@@ -176,13 +176,14 @@ const LyricsLayerControls = ({
onToggleTranslation,
onTogglePronunciation,
source,
+ active = true,
labels = {},
testId = 'lyrics-layer-controls',
}) => {
const classes = useStyles()
const [sourceAnchor, setSourceAnchor] = useState(null)
const sourcePopoverId = `${testId}-source-popover`
- const sourceOpen = Boolean(source && sourceAnchor)
+ const sourceOpen = Boolean(active && source && sourceAnchor)
const sourceDetails = [
{
label: labels.provider || 'Provider',
@@ -195,8 +196,8 @@ const LyricsLayerControls = ({
].filter((detail) => detail.value)
useEffect(() => {
- if (!source) setSourceAnchor(null)
- }, [source])
+ if (!active || !source) setSourceAnchor(null)
+ }, [active, source])
return (
diff --git a/ui/src/audioplayer/LyricsSidebar.test.jsx b/ui/src/audioplayer/LyricsSidebar.test.jsx
index b5023ca4a..0bafd3bcc 100644
--- a/ui/src/audioplayer/LyricsSidebar.test.jsx
+++ b/ui/src/audioplayer/LyricsSidebar.test.jsx
@@ -31,6 +31,12 @@ const lyric = {
synced: true,
line: [{ start: 0, end: 1000, value: 'Main line' }],
}
+const source = {
+ type: 'plugin',
+ name: 'Better Lyrics',
+ provider: 'ttml',
+ format: 'ttml',
+}
const originalPointerEvent = window.PointerEvent
const ControlledLyricsSidebar = ({
@@ -184,6 +190,21 @@ describe('', () => {
expect(sidebar).not.toHaveAttribute('inert')
})
+ it('closes the source popover when the queue obscures the sidebar', async () => {
+ const { rerender } = renderSidebar({ source })
+
+ fireEvent.click(screen.getByRole('button', { name: 'View lyrics source' }))
+ expect(screen.getByRole('dialog', { name: 'Lyrics source' })).toBeVisible()
+
+ rerender(sidebarView({ source, obscuredByQueue: true }))
+
+ await waitFor(() =>
+ expect(
+ screen.queryByRole('dialog', { name: 'Lyrics source' }),
+ ).not.toBeInTheDocument(),
+ )
+ })
+
it('clamps controlled keyboard resizing to the available width', () => {
const onWidthChange = vi.fn()
renderSidebar({ initialWidth: 999, maxWidth: 435, onWidthChange })
diff --git a/ui/src/audioplayer/MobileKaraokeLyricsPortal.test.jsx b/ui/src/audioplayer/MobileKaraokeLyricsPortal.test.jsx
index 2676db7f5..eb2748684 100644
--- a/ui/src/audioplayer/MobileKaraokeLyricsPortal.test.jsx
+++ b/ui/src/audioplayer/MobileKaraokeLyricsPortal.test.jsx
@@ -38,6 +38,22 @@ const { defaultLyricsResponse, useEnhancedLyricsMock } = vi.hoisted(() => {
}
})
+const sourcedLyricsResponse = {
+ ...defaultLyricsResponse,
+ layers: {
+ ...defaultLyricsResponse.layers,
+ main: {
+ ...defaultLyricsResponse.layers.main,
+ source: {
+ type: 'plugin',
+ name: 'Better Lyrics',
+ provider: 'ttml',
+ format: 'ttml',
+ },
+ },
+ },
+}
+
vi.mock('./useEnhancedLyrics', () => ({
default: useEnhancedLyricsMock,
}))
@@ -198,6 +214,23 @@ describe('', () => {
expect(layer).toHaveStyle({ pointerEvents: 'auto' })
})
+ it('closes the source popover when the queue obscures mobile lyrics', async () => {
+ useEnhancedLyricsMock.mockImplementation(() => sourcedLyricsResponse)
+ const host = createHost()
+ const { rerender } = render()
+
+ fireEvent.click(screen.getByRole('button', { name: 'Toggle lyrics' }))
+ const sourceButton = await within(host).findByTestId('lyrics-source-button')
+ fireEvent.click(sourceButton)
+ expect(screen.getByRole('dialog')).toBeVisible()
+
+ rerender()
+
+ await waitFor(() =>
+ expect(screen.queryByRole('dialog')).not.toBeInTheDocument(),
+ )
+ })
+
it('attaches when the mobile cover host appears after activation', async () => {
vi.useFakeTimers()
diff --git a/ui/src/audioplayer/usePlayerLyrics.jsx b/ui/src/audioplayer/usePlayerLyrics.jsx
index 32669facf..de8f2114c 100644
--- a/ui/src/audioplayer/usePlayerLyrics.jsx
+++ b/ui/src/audioplayer/usePlayerLyrics.jsx
@@ -195,6 +195,7 @@ const usePlayerLyrics = ({
onToggleTranslation={toggleTranslation}
onTogglePronunciation={togglePronunciation}
source={lyricsSource}
+ active={useInlineMobileLyrics && !obscuredByQueue}
labels={labels}
testId="lyrics-mobile-layer-controls"
/>