Skip to content

Commit

Permalink
feat(synced-lyrics): Better-Lyrics Styling for Synced-Lyrics (#2554)
Browse files Browse the repository at this point in the history
Co-authored-by: JellyBrick <[email protected]>
  • Loading branch information
kimjammer and JellyBrick authored Dec 24, 2024
1 parent 2bf67b9 commit 51da259
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 61 deletions.
4 changes: 4 additions & 0 deletions src/i18n/resources/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,10 @@
"line-effect": {
"label": "Line effect",
"submenu": {
"fancy": {
"label": "Fancy",
"tooltip": "Use large, app-like effects on the current line"
},
"focus": {
"label": "Focus",
"tooltip": "Make only the current line white"
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/synced-lyrics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { SyncedLyricsPluginConfig } from './types';
export default createPlugin({
name: () => t('plugins.synced-lyrics.name'),
description: () => t('plugins.synced-lyrics.description'),
authors: ['Non0reo', 'ArjixWasTaken'],
authors: ['Non0reo', 'ArjixWasTaken', 'KimJammer'],
restartNeeded: true,
addedVersion: '3.5.X',
config: {
Expand All @@ -19,8 +19,8 @@ export default createPlugin({
showLyricsEvenIfInexact: true,
showTimeCodes: false,
defaultTextString: '♪',
lineEffect: 'scale',
} as SyncedLyricsPluginConfig,
lineEffect: 'fancy',
} satisfies SyncedLyricsPluginConfig,

menu,
renderer,
Expand Down
21 changes: 18 additions & 3 deletions src/plugins/synced-lyrics/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { t } from '@/i18n';
import type { MenuContext } from '@/types/contexts';
import type { SyncedLyricsPluginConfig } from './types';

export const menu = async (ctx: MenuContext<SyncedLyricsPluginConfig>): Promise<
MenuItemConstructorOptions[]
> => {
export const menu = async (
ctx: MenuContext<SyncedLyricsPluginConfig>,
): Promise<MenuItemConstructorOptions[]> => {
const config = await ctx.getConfig();

return [
Expand All @@ -27,6 +27,21 @@ export const menu = async (ctx: MenuContext<SyncedLyricsPluginConfig>): Promise<
toolTip: t('plugins.synced-lyrics.menu.line-effect.tooltip'),
type: 'submenu',
submenu: [
{
label: t(
'plugins.synced-lyrics.menu.line-effect.submenu.fancy.label',
),
toolTip: t(
'plugins.synced-lyrics.menu.line-effect.submenu.fancy.tooltip',
),
type: 'radio',
checked: config.lineEffect === 'fancy',
click() {
ctx.setConfig({
lineEffect: 'fancy',
});
},
},
{
label: t(
'plugins.synced-lyrics.menu.line-effect.submenu.scale.label',
Expand Down
48 changes: 38 additions & 10 deletions src/plugins/synced-lyrics/renderer/components/SyncedLine.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createEffect, createMemo } from 'solid-js';
import { createEffect, createMemo, For } from 'solid-js';

import { currentTime } from './LyricsContainer';

Expand Down Expand Up @@ -32,7 +32,16 @@ export const SyncedLine = ({ line }: SyncedLineProps) => {
return config()?.defaultTextString ?? '';
});

// prettier-ignore
if (!text()) {
return (
<yt-formatted-string
text={{
runs: [{ text: '' }],
}}
/>
);
}

return (
<div
ref={ref}
Expand All @@ -41,14 +50,33 @@ export const SyncedLine = ({ line }: SyncedLineProps) => {
_ytAPI?.seekTo(line.timeInMs / 1000);
}}
>
<yt-formatted-string
class="text-lyrics description ytmusic-description-shelf-renderer"
text={{
runs: [
{ text: config()?.showTimeCodes ? `[${line.time}]` : '' },
{ text: text() }],
}}
/>
<div class="text-lyrics description ytmusic-description-shelf-renderer">
<yt-formatted-string
text={{
runs: [{ text: config()?.showTimeCodes ? `[${line.time}] ` : '' }],
}}
/>

<For each={text().split(' ')}>
{(word, index) => {
return (
<span
style={{
'transition-delay': `${index() * 0.05}s`,
'animation-delay': `${index() * 0.05}s`,
'--lyrics-duration:': `${line.duration / 1000}s;`,
}}
>
<yt-formatted-string
text={{
runs: [{ text: `${word} ` }],
}}
/>
</span>
);
}}
</For>
</div>
</div>
);
};
86 changes: 68 additions & 18 deletions src/plugins/synced-lyrics/renderer/renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,85 @@ createEffect(() => {

// Set the line effect
switch (config()?.lineEffect) {
case 'fancy':
root.style.setProperty('--lyrics-font-size', '3rem');
root.style.setProperty('--lyrics-line-height', '1.333');
root.style.setProperty('--lyrics-width', '100%');
root.style.setProperty('--lyrics-padding', '2rem');
root.style.setProperty(
'--lyrics-animations',
'lyrics-glow var(--lyrics-glow-duration) forwards, lyrics-wobble var(--lyrics-wobble-duration) forwards',
);

root.style.setProperty('--lyrics-inactive-font-weight', '700');
root.style.setProperty('--lyrics-inactive-opacity', '0.33');
root.style.setProperty('--lyrics-inactive-scale', '0.95');
root.style.setProperty('--lyrics-inactive-offset', '0');

root.style.setProperty('--lyrics-active-font-weight', '700');
root.style.setProperty('--lyrics-active-opacity', '1');
root.style.setProperty('--lyrics-active-scale', '1');
root.style.setProperty('--lyrics-active-offset', '0');
break;
case 'scale':
root.style.setProperty('--lyrics-font-size', '1.4rem');
root.style.setProperty(
'--previous-lyrics',
'var(--ytmusic-text-primary)',
'--lyrics-line-height',
'var(--ytmusic-body-line-height)',
);
root.style.setProperty('--current-lyrics', 'var(--ytmusic-text-primary)');
root.style.setProperty('--size-lyrics', '1.2');
root.style.setProperty('--offset-lyrics', '0');
root.style.setProperty('--lyric-width', '83%');
root.style.setProperty('--lyrics-width', '83%');
root.style.setProperty('--lyrics-padding', '0');
root.style.setProperty('--lyrics-animations', 'none');

root.style.setProperty('--lyrics-inactive-font-weight', '400');
root.style.setProperty('--lyrics-inactive-opacity', '0.33');
root.style.setProperty('--lyrics-inactive-scale', '1');
root.style.setProperty('--lyrics-inactive-offset', '0');

root.style.setProperty('--lyrics-active-font-weight', '700');
root.style.setProperty('--lyrics-active-opacity', '1');
root.style.setProperty('--lyrics-active-scale', '1.2');
root.style.setProperty('--lyrics-active-offset', '0');
break;
case 'offset':
root.style.setProperty('--lyrics-font-size', '1.4rem');
root.style.setProperty(
'--previous-lyrics',
'var(--ytmusic-text-primary)',
'--lyrics-line-height',
'var(--ytmusic-body-line-height)',
);
root.style.setProperty('--current-lyrics', 'var(--ytmusic-text-primary)');
root.style.setProperty('--size-lyrics', '1');
root.style.setProperty('--offset-lyrics', '5%');
root.style.setProperty('--lyric-width', '100%');
root.style.setProperty('--lyrics-width', '100%');
root.style.setProperty('--lyrics-padding', '0');
root.style.setProperty('--lyrics-animations', 'none');

root.style.setProperty('--lyrics-inactive-font-weight', '400');
root.style.setProperty('--lyrics-inactive-opacity', '0.33');
root.style.setProperty('--lyrics-inactive-scale', '1');
root.style.setProperty('--lyrics-inactive-offset', '0');

root.style.setProperty('--lyrics-active-font-weight', '700');
root.style.setProperty('--lyrics-active-opacity', '1');
root.style.setProperty('--lyrics-active-scale', '1');
root.style.setProperty('--lyrics-active-offset', '5%');
break;
case 'focus':
root.style.setProperty('--lyrics-font-size', '1.4rem');
root.style.setProperty(
'--previous-lyrics',
'var(--ytmusic-text-secondary)',
'--lyrics-line-height',
'var(--ytmusic-body-line-height)',
);
root.style.setProperty('--current-lyrics', 'var(--ytmusic-text-primary)');
root.style.setProperty('--size-lyrics', '1');
root.style.setProperty('--offset-lyrics', '0');
root.style.setProperty('--lyric-width', '100%');
root.style.setProperty('--lyrics-width', '100%');
root.style.setProperty('--lyrics-padding', '0');
root.style.setProperty('--lyrics-animations', 'none');

root.style.setProperty('--lyrics-inactive-font-weight', '400');
root.style.setProperty('--lyrics-inactive-opacity', '0.33');
root.style.setProperty('--lyrics-inactive-scale', '1');
root.style.setProperty('--lyrics-inactive-offset', '0');

root.style.setProperty('--lyrics-active-font-weight', '700');
root.style.setProperty('--lyrics-active-opacity', '1');
root.style.setProperty('--lyrics-active-scale', '1');
root.style.setProperty('--lyrics-active-offset', '0');
break;
}
});
Expand Down
109 changes: 83 additions & 26 deletions src/plugins/synced-lyrics/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,40 @@
display: block !important;
}

/* :root {
--ytmusic-text-primary: #fff;
--ytmusic-text-secondary: #aaa;
} */

/* Variables are overridden by selected line effect */
:root {
/* Layout */
--global-margin: 0.7rem;
--previous-lyrics: var(--ytmusic-text-primary);
--current-lyrics: var(--ytmusic-text-primary);
--upcoming-lyrics: var(--ytmusic-text-secondary);
--size-lyrics: 1.2em;
--offset-lyrics: 1em;
--lyrics-padding: 0;

/* Typography */
--lyrics-font-family: Satoshi, Avenir, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell,
Open Sans, Helvetica Neue, sans-serif;
--lyrics-font-size: 1.4rem;
--lyrics-line-height: var(--ytmusic-body-line-height);
--lyrics-width: 100%;

/* Inactive Lyrics */
--lyrics-inactive-font-weight: 400;
--lyrics-inactive-opacity: 0.33;
--lyrics-inactive-scale: 1;
--lyrics-inactive-offset: 0;

/* Active Lyrics */
--lyrics-active-font-weight: 700;
--lyrics-active-opacity: 1;
--lyrics-active-scale: 1;
--lyrics-active-offset: 0;

/* Animations */
--lyrics-animations: lyrics-glow var(--lyrics-glow-duration) forwards, lyrics-wobble var(--lyrics-wobble-duration) forwards;
--lyrics-scale-duration: 0.166s;
--lyrics-opacity-transition: 0.33s;
--lyrics-glow-duration: var(--lyrics-duration, 2s);
--lyrics-wobble-duration: calc(var(--lyrics-duration, 2s) / 2);

/* Colors */
--glow-color: rgba(255, 255, 255, 0.5);
}

.lyric-container {
Expand All @@ -32,7 +54,7 @@
}

.synced-line {
width: var(--lyric-width, 100%);
width: var(--lyrics-width, 100%);

& > .text-lyrics {
cursor: pointer;
Expand All @@ -43,8 +65,7 @@
display: block;
justify-content: left;
text-align: left;
margin: 0.5rem 0;
margin-right: 20px;
margin: 0.5rem 20px 0.5rem 0;
transition: all 0.3s ease-in-out;
}

Expand All @@ -54,35 +75,46 @@
}

.text-lyrics {
font-family: var(--lyrics-font-family) !important;
font-size: var(--lyrics-font-size) !important;
font-weight: var(--lyrics-inactive-font-weight) !important;
line-height: var(--lyrics-line-height) !important;
padding-top: var(--lyrics-padding);
padding-bottom: var(--lyrics-padding);
scale: var(--lyrics-inactive-scale);
translate: var(--lyrics-inactive-offset);
transition:
scale var(--lyrics-scale-duration),
translate 0.3s ease-in-out;

display: block;
text-align: left;
margin: var(--global-margin) 0;
transition:
scale 0.3s ease-in-out,
translate 0.3s ease-in-out,
color 0.1s ease-in-out;
transform-origin: 0 50%;
}

.text-lyrics > span {
margin-inline: 0.1em;
display: inline-block;
white-space: pre-wrap;
opacity: var(--lyrics-inactive-opacity);
transition: opacity var(--lyrics-opacity-transition);
}

.previous > .text-lyrics {
color: var(--previous-lyrics);
font-weight: normal;
}

.current > .text-lyrics {
color: var(--current-lyrics);
font-weight: bold;
scale: var(--size-lyrics);
translate: var(--offset-lyrics) 0;
font-weight: var(--lyrics-active-font-weight) !important;
scale: var(--lyrics-active-scale);
translate: var(--lyrics-active-offset);
}

.current > .text-lyrics > span {
opacity: var(--lyrics-active-opacity);
animation: var(--lyrics-animations);
}

.upcoming > .text-lyrics {
color: var(--upcoming-lyrics);
font-weight: normal;
}

.lyrics-renderer {
Expand Down Expand Up @@ -162,3 +194,28 @@

transition: top 325ms ease-in-out;
}

/* Animations */
@keyframes lyrics-wobble {
from {
transform: translateY(0px);
}
33.33% {
transform: translateY(1.75px);
}
66.66% {
transform: translateY(-1.75px);
}
to {
transform: translateY(0px);
}
}

@keyframes lyrics-glow {
0% {
text-shadow: 0 0 1.5rem var(--glow-color);
}
to {
text-shadow: 0 0 0 var(--glow-color);
}
}
Loading

0 comments on commit 51da259

Please sign in to comment.