use custom lyrics styling on search form instead of setting

This commit is contained in:
jeffvli
2026-07-19 16:27:49 -07:00
parent e4378d1bc9
commit dbd82d46cf
10 changed files with 152 additions and 100 deletions
@@ -11,3 +11,7 @@
padding-left: var(--lyric-padding-left, 0%) !important;
}
}
.preview {
padding: 0 !important;
}
@@ -10,6 +10,7 @@ export interface LyricsScrollContentProps {
gap?: number;
paddingLeft?: number;
paddingRight?: number;
preview?: boolean;
style?: React.CSSProperties;
}
@@ -20,25 +21,35 @@ export const LyricsScrollContent = ({
gap,
paddingLeft = 0,
paddingRight = 0,
preview = false,
style,
}: LyricsScrollContentProps) => {
const contentStyle = useMemo(
() =>
({
'--lyric-padding-left': `${paddingLeft}%`,
'--lyric-padding-right': `${paddingRight}%`,
const contentStyle = useMemo(() => {
if (preview) {
return {
gap: gap !== undefined ? `${gap}px` : undefined,
paddingBottom: bottomScrollPadding,
paddingLeft: `${paddingLeft}%`,
paddingRight: `${paddingRight}%`,
paddingTop: '10vh',
padding: 0,
...style,
}) as React.CSSProperties,
[bottomScrollPadding, gap, paddingLeft, paddingRight, style],
);
} as React.CSSProperties;
}
return {
'--lyric-padding-left': `${paddingLeft}%`,
'--lyric-padding-right': `${paddingRight}%`,
gap: gap !== undefined ? `${gap}px` : undefined,
paddingBottom: bottomScrollPadding,
paddingLeft: `${paddingLeft}%`,
paddingRight: `${paddingRight}%`,
paddingTop: '10vh',
...style,
} as React.CSSProperties;
}, [bottomScrollPadding, gap, paddingLeft, paddingRight, preview, style]);
return (
<div className={clsx(styles.content, className)} style={contentStyle}>
<div
className={clsx(styles.content, preview && styles.preview, className)}
style={contentStyle}
>
{children}
</div>
);
@@ -33,22 +33,3 @@
}
}
}
.lyrics-preview {
:global(.synchronized-lyrics) {
height: auto !important;
padding: 1rem 0 !important;
overflow: visible !important;
transform: none !important;
}
}
.lyrics-content-wrapper {
:global(> div) {
height: auto !important;
max-height: none !important;
padding: 1rem 0 !important;
overflow: visible !important;
transform: none !important;
}
}
@@ -246,7 +246,6 @@ export const LyricsSearchForm = ({ artist, name, onSearchOverride }: LyricSearch
{selectedResult && (
<Stack style={{ flex: 1, height: '100%', minHeight: 0, overflow: 'hidden' }}>
<ScrollArea
className={styles['lyrics-preview']}
style={{
height: '100%',
paddingRight: '1rem',
@@ -255,46 +254,42 @@ export const LyricsSearchForm = ({ artist, name, onSearchOverride }: LyricSearch
{isPreviewLoading ? (
<Spinner container />
) : previewData ? (
<div
className={styles['lyrics-content-wrapper']}
style={{ width: '100%' }}
>
{Array.isArray(previewData) ? (
lyricsHasWordCues(previewData) ? (
<SynchronizedKaraokeLyrics
style={{ padding: 0 }}
{...({
artist: selectedResult.artist,
lyrics: previewData,
name: selectedResult.name,
remote: true,
source: selectedResult.source,
} as SynchronizedLyricsProps)}
/>
) : (
<SynchronizedLyrics
style={{ padding: 0 }}
{...({
artist: selectedResult.artist,
lyrics: previewData,
name: selectedResult.name,
remote: true,
source: selectedResult.source,
} as SynchronizedLyricsProps)}
/>
)
) : (
<UnsynchronizedLyrics
Array.isArray(previewData) ? (
lyricsHasWordCues(previewData) ? (
<SynchronizedKaraokeLyrics
preview
{...({
artist: selectedResult.artist,
lyrics: previewData,
name: selectedResult.name,
remote: true,
source: selectedResult.source,
} as UnsynchronizedLyricsProps)}
} as SynchronizedLyricsProps)}
/>
)}
</div>
) : (
<SynchronizedLyrics
preview
{...({
artist: selectedResult.artist,
lyrics: previewData,
name: selectedResult.name,
remote: true,
source: selectedResult.source,
} as SynchronizedLyricsProps)}
/>
)
) : (
<UnsynchronizedLyrics
preview
{...({
artist: selectedResult.artist,
lyrics: previewData,
name: selectedResult.name,
remote: true,
source: selectedResult.source,
} as UnsynchronizedLyricsProps)}
/>
)
) : (
<Center>
<Text isMuted>{t('page.fullscreenPlayer.noLyrics')}</Text>
@@ -7,3 +7,11 @@
overflow: hidden auto;
word-break: break-all;
}
.preview {
height: auto;
max-height: none;
padding: 1rem 0;
overflow: visible;
transform: none;
}
@@ -34,6 +34,7 @@ export interface SynchronizedKaraokeLyricsProps extends Omit<FullLyricsMetadata,
extraOverlayLyrics?: SynchronizedLyricsData[];
lyrics: SynchronizedLyricsData;
offsetMs?: number;
preview?: boolean;
pronunciationLyrics?: null | SynchronizedLyricsData;
romajiLyrics?: null | SynchronizedLyricsData;
settingsKey?: string;
@@ -44,6 +45,8 @@ export interface SynchronizedKaraokeLyricsProps extends Omit<FullLyricsMetadata,
}
const SEEK_DETECT_THRESHOLD_MS = 500;
const PREVIEW_FONT_SIZE = 20;
const PREVIEW_GAP = 20;
export const SynchronizedKaraokeLyrics = ({
agents,
@@ -52,6 +55,7 @@ export const SynchronizedKaraokeLyrics = ({
lyrics,
name,
offsetMs,
preview = false,
pronunciationLyrics,
romajiLyrics,
settingsKey = 'default',
@@ -77,6 +81,11 @@ export const SynchronizedKaraokeLyrics = ({
showScrollbar,
} = useSynchronizedLyricsBase(settingsKey, offsetMs);
const effectiveFontSize = preview ? PREVIEW_FONT_SIZE : settings.fontSize;
const effectiveGap = preview ? PREVIEW_GAP : settings.gap;
const effectivePaddingLeft = preview ? 0 : settings.paddingLeft;
const effectivePaddingRight = preview ? 0 : settings.paddingRight;
const normalizedLyrics = useMemo(() => normalizeLyrics(lyrics), [lyrics]);
const rafRef = useRef<null | number>(null);
const statusRef = useRef(usePlayerStoreBase.getState().player.status);
@@ -97,13 +106,13 @@ export const SynchronizedKaraokeLyrics = ({
containerRef,
followRef,
followScrollAlignmentRef,
fontSize: settings.fontSize,
gap: settings.gap,
fontSize: effectiveFontSize,
gap: effectiveGap,
lineIdPrefix: 'karaoke-line',
lineLeadTimeMsRef,
lyrics: normalizedLyrics,
paddingLeft: settings.paddingLeft,
paddingRight: settings.paddingRight,
paddingLeft: effectivePaddingLeft,
paddingRight: effectivePaddingRight,
scrollContainerId: LYRICS_SCROLL_CONTAINER_ID,
});
@@ -328,7 +337,11 @@ export const SynchronizedKaraokeLyrics = ({
return (
<div
className={clsx(styles.container, 'synchronized-karaoke-lyrics overlay-scrollbar')}
className={clsx(
styles.container,
preview && styles.preview,
'synchronized-karaoke-lyrics overlay-scrollbar',
)}
id={LYRICS_SCROLL_CONTAINER_ID}
onClick={handleContainerClick}
onMouseEnter={showScrollbar}
@@ -337,15 +350,16 @@ export const SynchronizedKaraokeLyrics = ({
style={{ ...containerStyle, ...style }}
>
<LyricsScrollContent
gap={settings.gap}
paddingLeft={settings.paddingLeft}
paddingRight={settings.paddingRight}
gap={effectiveGap}
paddingLeft={effectivePaddingLeft}
paddingRight={effectivePaddingRight}
preview={preview}
>
{settings.showProvider && source && (
<LyricLine
alignment={settings.alignment}
className="lyric-credit"
fontSize={settings.fontSize}
fontSize={effectiveFontSize}
text={`${source}`}
/>
)}
@@ -353,7 +367,7 @@ export const SynchronizedKaraokeLyrics = ({
<LyricLine
alignment={settings.alignment}
className="lyric-credit"
fontSize={settings.fontSize}
fontSize={effectiveFontSize}
text={`${name}${artist}`}
/>
)}
@@ -396,7 +410,7 @@ export const SynchronizedKaraokeLyrics = ({
alignment={settings.alignment}
className="lyric-line synchronized"
data-lyric-time={lineStartMs}
fontSize={settings.fontSize}
fontSize={effectiveFontSize}
id={`karaoke-line-${idx}`}
key={idx}
romajiText={pronunciationText}
@@ -414,7 +428,7 @@ export const SynchronizedKaraokeLyrics = ({
cueLines={rawLine.cueLines}
data-lyric-time={lineStartMs}
extraOverlays={extraOverlays}
fontSize={settings.fontSize}
fontSize={effectiveFontSize}
id={`karaoke-line-${idx}`}
key={idx}
lineIndex={idx}
@@ -8,3 +8,11 @@
word-break: break-all;
transform: translateY(-2rem);
}
.preview {
height: auto;
max-height: none;
padding: 1rem 0;
overflow: visible;
transform: none;
}
@@ -29,6 +29,7 @@ export interface SynchronizedLyricsProps extends Omit<FullLyricsMetadata, 'lyric
extraOverlayLyrics?: SynchronizedLyricsData[];
lyrics: SynchronizedLyricsData;
offsetMs?: number;
preview?: boolean;
pronunciationLyrics?: null | SynchronizedLyricsData;
romajiLyrics?: null | SynchronizedLyricsData;
settingsKey?: string;
@@ -38,12 +39,15 @@ export interface SynchronizedLyricsProps extends Omit<FullLyricsMetadata, 'lyric
}
const SEEK_DETECT_THRESHOLD_MS = 500;
const PREVIEW_FONT_SIZE = 20;
const PREVIEW_GAP = 20;
export const SynchronizedLyrics = ({
artist,
lyrics,
name,
offsetMs,
preview = false,
pronunciationLyrics,
romajiLyrics,
settingsKey = 'default',
@@ -68,6 +72,11 @@ export const SynchronizedLyrics = ({
showScrollbar,
} = useSynchronizedLyricsBase(settingsKey, offsetMs);
const effectiveFontSize = preview ? PREVIEW_FONT_SIZE : settings.fontSize;
const effectiveGap = preview ? PREVIEW_GAP : settings.gap;
const effectivePaddingLeft = preview ? 0 : settings.paddingLeft;
const effectivePaddingRight = preview ? 0 : settings.paddingRight;
const normalizedLyrics = useMemo(() => normalizeLyrics(lyrics), [lyrics]);
const rafRef = useRef<null | number>(null);
const statusRef = useRef(usePlayerStoreBase.getState().player.status);
@@ -83,13 +92,13 @@ export const SynchronizedLyrics = ({
containerRef,
followRef,
followScrollAlignmentRef,
fontSize: settings.fontSize,
gap: settings.gap,
fontSize: effectiveFontSize,
gap: effectiveGap,
lineIdPrefix: 'lyric',
lineLeadTimeMsRef,
lyrics: normalizedLyrics,
paddingLeft: settings.paddingLeft,
paddingRight: settings.paddingRight,
paddingLeft: effectivePaddingLeft,
paddingRight: effectivePaddingRight,
scrollContainerId: LYRICS_SCROLL_CONTAINER_ID,
});
@@ -240,7 +249,11 @@ export const SynchronizedLyrics = ({
return (
<div
className={clsx(styles.container, 'synchronized-lyrics overlay-scrollbar')}
className={clsx(
styles.container,
preview && styles.preview,
'synchronized-lyrics overlay-scrollbar',
)}
id={LYRICS_SCROLL_CONTAINER_ID}
onClick={handleContainerClick}
onMouseEnter={showScrollbar}
@@ -249,15 +262,16 @@ export const SynchronizedLyrics = ({
style={{ ...containerStyle, ...style }}
>
<LyricsScrollContent
gap={settings.gap}
paddingLeft={settings.paddingLeft}
paddingRight={settings.paddingRight}
gap={effectiveGap}
paddingLeft={effectivePaddingLeft}
paddingRight={effectivePaddingRight}
preview={preview}
>
{settings.showProvider && source && (
<LyricLine
alignment={settings.alignment}
className="lyric-credit"
fontSize={settings.fontSize}
fontSize={effectiveFontSize}
text={`${source}`}
/>
)}
@@ -265,7 +279,7 @@ export const SynchronizedLyrics = ({
<LyricLine
alignment={settings.alignment}
className="lyric-credit"
fontSize={settings.fontSize}
fontSize={effectiveFontSize}
text={`${name}${artist}`}
/>
)}
@@ -290,7 +304,7 @@ export const SynchronizedLyrics = ({
alignment={settings.alignment}
className="lyric-line synchronized"
data-lyric-time={lineStartMs}
fontSize={settings.fontSize}
fontSize={effectiveFontSize}
id={`lyric-${idx}`}
key={idx}
romajiText={pronunciationText}
@@ -7,3 +7,11 @@
overflow: hidden auto;
transform: translateY(-2rem);
}
.preview {
height: auto;
max-height: none;
padding: 1rem 0;
overflow: visible;
transform: none;
}
@@ -1,3 +1,4 @@
import clsx from 'clsx';
import { useMemo } from 'react';
import styles from './unsynchronized-lyrics.module.css';
@@ -9,15 +10,20 @@ import { FullLyricsMetadata } from '/@/shared/types/domain-types';
export interface UnsynchronizedLyricsProps extends Omit<FullLyricsMetadata, 'lyrics'> {
lyrics: string;
preview?: boolean;
romajiLyrics?: null | string;
settingsKey?: string;
translatedLyrics?: null | string;
}
const PREVIEW_FONT_SIZE = 20;
const PREVIEW_GAP = 20;
export const UnsynchronizedLyrics = ({
artist,
lyrics,
name,
preview = false,
romajiLyrics,
settingsKey = 'default',
source,
@@ -27,14 +33,16 @@ export const UnsynchronizedLyrics = ({
const displaySettings = useLyricsDisplaySettings(settingsKey);
const settings = {
...lyricsSettings,
fontSizeUnsync:
displaySettings.fontSizeUnsync && displaySettings.fontSizeUnsync !== 0
? displaySettings.fontSizeUnsync
: 24,
gapUnsync:
displaySettings.gapUnsync && displaySettings.gapUnsync !== 0
? displaySettings.gapUnsync
: 24,
fontSizeUnsync: preview
? PREVIEW_FONT_SIZE
: displaySettings.fontSizeUnsync && displaySettings.fontSizeUnsync !== 0
? displaySettings.fontSizeUnsync
: 24,
gapUnsync: preview
? PREVIEW_GAP
: displaySettings.gapUnsync && displaySettings.gapUnsync !== 0
? displaySettings.gapUnsync
: 24,
};
const lines = useMemo(() => {
return lyrics.split('\n');
@@ -49,12 +57,13 @@ export const UnsynchronizedLyrics = ({
}, [romajiLyrics]);
return (
<div className={styles.container}>
<div className={clsx(styles.container, preview && styles.preview)}>
<LyricsScrollContent
bottomScrollPadding="6vh"
gap={settings.gapUnsync}
paddingLeft={displaySettings.paddingLeft ?? 0}
paddingRight={displaySettings.paddingRight ?? 0}
paddingLeft={preview ? 0 : (displaySettings.paddingLeft ?? 0)}
paddingRight={preview ? 0 : (displaySettings.paddingRight ?? 0)}
preview={preview}
>
{settings.showProvider && source && (
<LyricLine