mirror of
https://github.com/remvze/moodist.git
synced 2025-12-17 08:54:13 +00:00
feat: add lofi radios
This commit is contained in:
parent
76fdc74710
commit
bb39b4ba98
6 changed files with 159 additions and 0 deletions
|
|
@ -5,3 +5,4 @@ export { Source as SourceItem } from './source';
|
||||||
export { Presets as PresetsItem } from './presets';
|
export { Presets as PresetsItem } from './presets';
|
||||||
export { Shortcuts as ShortcutsItem } from './shortcuts';
|
export { Shortcuts as ShortcutsItem } from './shortcuts';
|
||||||
export { SleepTimer as SleepTimerItem } from './sleep-timer';
|
export { SleepTimer as SleepTimerItem } from './sleep-timer';
|
||||||
|
export { Lofi as LofiItem } from './lofi';
|
||||||
|
|
|
||||||
18
src/components/menu/items/lofi.tsx
Normal file
18
src/components/menu/items/lofi.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { IoIosMusicalNotes } from 'react-icons/io/index';
|
||||||
|
|
||||||
|
import { Item } from '../item';
|
||||||
|
|
||||||
|
interface LofiProps {
|
||||||
|
open: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Lofi({ open }: LofiProps) {
|
||||||
|
return (
|
||||||
|
<Item
|
||||||
|
icon={<IoIosMusicalNotes />}
|
||||||
|
label="Lofi Radios"
|
||||||
|
shortcut="Shift + L"
|
||||||
|
onClick={open}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -12,12 +12,14 @@ import {
|
||||||
PresetsItem,
|
PresetsItem,
|
||||||
ShortcutsItem,
|
ShortcutsItem,
|
||||||
SleepTimerItem,
|
SleepTimerItem,
|
||||||
|
LofiItem,
|
||||||
} from './items';
|
} from './items';
|
||||||
import { Divider } from './divider';
|
import { Divider } from './divider';
|
||||||
import { ShareLinkModal } from '@/components/modals/share-link';
|
import { ShareLinkModal } from '@/components/modals/share-link';
|
||||||
import { PresetsModal } from '@/components/modals/presets';
|
import { PresetsModal } from '@/components/modals/presets';
|
||||||
import { ShortcutsModal } from '@/components/modals/shortcuts';
|
import { ShortcutsModal } from '@/components/modals/shortcuts';
|
||||||
import { SleepTimerModal } from '@/components/modals/sleep-timer';
|
import { SleepTimerModal } from '@/components/modals/sleep-timer';
|
||||||
|
import { LofiModal } from '../modals/lofi';
|
||||||
import { fade, mix, slideY } from '@/lib/motion';
|
import { fade, mix, slideY } from '@/lib/motion';
|
||||||
import { useSoundStore } from '@/stores/sound';
|
import { useSoundStore } from '@/stores/sound';
|
||||||
|
|
||||||
|
|
@ -32,6 +34,7 @@ export function Menu() {
|
||||||
|
|
||||||
const initial = useMemo(
|
const initial = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
lofi: false,
|
||||||
presets: false,
|
presets: false,
|
||||||
shareLink: false,
|
shareLink: false,
|
||||||
shortcuts: false,
|
shortcuts: false,
|
||||||
|
|
@ -63,6 +66,7 @@ export function Menu() {
|
||||||
useHotkeys('shift+h', () => open('shortcuts'));
|
useHotkeys('shift+h', () => open('shortcuts'));
|
||||||
useHotkeys('shift+s', () => open('shareLink'), { enabled: !noSelected });
|
useHotkeys('shift+s', () => open('shareLink'), { enabled: !noSelected });
|
||||||
useHotkeys('shift+t', () => open('sleepTimer'));
|
useHotkeys('shift+t', () => open('sleepTimer'));
|
||||||
|
useHotkeys('shift+l', () => open('lofi'));
|
||||||
|
|
||||||
useCloseListener(closeAll);
|
useCloseListener(closeAll);
|
||||||
|
|
||||||
|
|
@ -99,6 +103,7 @@ export function Menu() {
|
||||||
<ShareItem open={() => open('shareLink')} />
|
<ShareItem open={() => open('shareLink')} />
|
||||||
<ShuffleItem />
|
<ShuffleItem />
|
||||||
<SleepTimerItem open={() => open('sleepTimer')} />
|
<SleepTimerItem open={() => open('sleepTimer')} />
|
||||||
|
<LofiItem open={() => open('lofi')} />
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<ShortcutsItem open={() => open('shortcuts')} />
|
<ShortcutsItem open={() => open('shortcuts')} />
|
||||||
|
|
@ -122,6 +127,7 @@ export function Menu() {
|
||||||
show={modals.shortcuts}
|
show={modals.shortcuts}
|
||||||
onClose={() => close('shortcuts')}
|
onClose={() => close('shortcuts')}
|
||||||
/>
|
/>
|
||||||
|
<LofiModal show={modals.lofi} onClose={() => close('lofi')} />
|
||||||
<PresetsModal show={modals.presets} onClose={() => close('presets')} />
|
<PresetsModal show={modals.presets} onClose={() => close('presets')} />
|
||||||
<SleepTimerModal
|
<SleepTimerModal
|
||||||
show={modals.sleepTimer}
|
show={modals.sleepTimer}
|
||||||
|
|
|
||||||
1
src/components/modals/lofi/index.ts
Normal file
1
src/components/modals/lofi/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export { LofiModal } from './lofi';
|
||||||
88
src/components/modals/lofi/lofi.module.css
Normal file
88
src/components/modals/lofi/lofi.module.css
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
.title {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: var(--font-md);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
color: var(--color-foreground-subtle);
|
||||||
|
}
|
||||||
|
|
||||||
|
.radios {
|
||||||
|
margin-top: 28px;
|
||||||
|
|
||||||
|
& .radio {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
padding: 24px 12px 12px;
|
||||||
|
background-color: var(--color-neutral-50);
|
||||||
|
border: 1px solid var(--color-neutral-200);
|
||||||
|
border-radius: 12px;
|
||||||
|
|
||||||
|
&:not(:last-of-type) {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -1px;
|
||||||
|
left: 50%;
|
||||||
|
width: 80%;
|
||||||
|
height: 1px;
|
||||||
|
content: '';
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent,
|
||||||
|
var(--color-neutral-400),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
& .label {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 25px;
|
||||||
|
padding: 0 16px;
|
||||||
|
font-size: var(--font-2xsm);
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-foreground-subtle);
|
||||||
|
background: linear-gradient(
|
||||||
|
var(--color-neutral-50),
|
||||||
|
var(--color-neutral-100)
|
||||||
|
);
|
||||||
|
border: 1px solid var(--color-neutral-200);
|
||||||
|
border-radius: 100px;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -1px;
|
||||||
|
left: 50%;
|
||||||
|
width: 70%;
|
||||||
|
height: 1px;
|
||||||
|
content: '';
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
transparent,
|
||||||
|
var(--color-neutral-400),
|
||||||
|
transparent
|
||||||
|
);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& iframe {
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 560 / 315;
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/components/modals/lofi/lofi.tsx
Normal file
45
src/components/modals/lofi/lofi.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { Modal } from '@/components/modal';
|
||||||
|
|
||||||
|
import { padNumber } from '@/helpers/number';
|
||||||
|
|
||||||
|
import styles from './lofi.module.css';
|
||||||
|
|
||||||
|
interface LofiModalProps {
|
||||||
|
onClose: () => void;
|
||||||
|
show: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LofiModal({ onClose, show }: LofiModalProps) {
|
||||||
|
const radios = [
|
||||||
|
{
|
||||||
|
src: 'https://www.youtube.com/embed/jfKfPfyJRdk?si=UiaAY0C8Rk6iBIsd',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://www.youtube.com/embed/4xDzrJKXOOY?si=zyZlOXnoMKr_MWfW',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://www.youtube.com/embed/S_MOd40zlYU?si=rf1_S-MMiAEIKJoi',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal persist show={show} onClose={onClose}>
|
||||||
|
<h2 className={styles.title}>Lofi Radios</h2>
|
||||||
|
<p className={styles.desc}>A curated list of Lofi radios.</p>
|
||||||
|
|
||||||
|
<div className={styles.radios}>
|
||||||
|
{radios.map((radio, index) => (
|
||||||
|
<div className={styles.radio} key={radio.src}>
|
||||||
|
<div className={styles.label}>Radio {padNumber(index + 1)}</div>
|
||||||
|
<iframe
|
||||||
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||||
|
referrerPolicy="strict-origin-when-cross-origin"
|
||||||
|
src={radio.src}
|
||||||
|
title="YouTube video player"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue