web-player: consistent imports, tokens, glossary and app route grouping
This commit is contained in:
@@ -3,10 +3,10 @@
|
|||||||
import Upload from '@lucide/svelte/icons/upload';
|
import Upload from '@lucide/svelte/icons/upload';
|
||||||
import Folder from '@lucide/svelte/icons/folder';
|
import Folder from '@lucide/svelte/icons/folder';
|
||||||
import LogIn from '@lucide/svelte/icons/log-in';
|
import LogIn from '@lucide/svelte/icons/log-in';
|
||||||
import MenuItem from '../ui/overlay/MenuItem.svelte';
|
import MenuItem from '$lib/components/ui/overlay/MenuItem.svelte';
|
||||||
import AccountMenu from '../ui/overlay/AccountMenu.svelte';
|
import AccountMenu from '$lib/components/ui/overlay/AccountMenu.svelte';
|
||||||
import IconButton from '../ui/primitives/IconButton.svelte';
|
import IconButton from '$lib/components/ui/primitives/IconButton.svelte';
|
||||||
import Logo from '../ui/primitives/Logo.svelte';
|
import Logo from '$lib/components/ui/primitives/Logo.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: SessionUser | null;
|
user: SessionUser | null;
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
import { liked } from '$lib/player/liked.svelte';
|
import { liked } from '$lib/player/liked.svelte';
|
||||||
import { createPlaylistModal } from '$lib/state/panels.svelte';
|
import { createPlaylistModal } from '$lib/state/panels.svelte';
|
||||||
import type { SessionUser } from '$lib/types';
|
import type { SessionUser } from '$lib/types';
|
||||||
import ListRow from '../ui/media/ListRow.svelte';
|
import ListRow from '$lib/components/ui/media/ListRow.svelte';
|
||||||
import IconButton from '../ui/primitives/IconButton.svelte';
|
import IconButton from '$lib/components/ui/primitives/IconButton.svelte';
|
||||||
import Plus from '@lucide/svelte/icons/plus';
|
import Plus from '@lucide/svelte/icons/plus';
|
||||||
import Logo from '../ui/primitives/Logo.svelte';
|
import Logo from '$lib/components/ui/primitives/Logo.svelte';
|
||||||
|
|
||||||
const SIDEBAR_PLAYLISTS_LIMIT = 8;
|
const SIDEBAR_PLAYLISTS_LIMIT = 8;
|
||||||
|
|
||||||
@@ -33,8 +33,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<aside
|
<aside
|
||||||
class="hidden min-h-0 shrink-0 flex-col border-r border-hairline p-5 lg:flex"
|
class="hidden min-h-0 w-(--mf-sidebar-w) shrink-0 flex-col border-r border-hairline p-5 lg:flex"
|
||||||
style="width:var(--mf-sidebar-w)"
|
|
||||||
>
|
>
|
||||||
<a href="/" class="mb-4">
|
<a href="/" class="mb-4">
|
||||||
<Logo size="sm" />
|
<Logo size="sm" />
|
||||||
@@ -75,7 +74,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex min-h-0 flex-1 flex-col gap-px overflow-y-auto pb-icon-md">
|
<div class="flex min-h-0 flex-1 flex-col gap-px overflow-y-auto pb-4.5">
|
||||||
{#each visiblePlaylists as playlist (playlist.id)}
|
{#each visiblePlaylists as playlist (playlist.id)}
|
||||||
{@const active = page.url.pathname === `/playlists/${playlist.id}`}
|
{@const active = page.url.pathname === `/playlists/${playlist.id}`}
|
||||||
<ListRow
|
<ListRow
|
||||||
@@ -93,8 +92,8 @@
|
|||||||
onclick={() => createPlaylistModal.show()}
|
onclick={() => createPlaylistModal.show()}
|
||||||
class="flex items-center gap-2 rounded-control px-3 py-2 text-xs text-fg-2 transition-colors hover:bg-hover"
|
class="flex items-center gap-2 rounded-control px-3 py-2 text-xs text-fg-2 transition-colors hover:bg-hover"
|
||||||
>
|
>
|
||||||
<Plus class="size-3.5" />
|
<Plus class="size-icon-xs" />
|
||||||
Crear tu primera lista
|
Crear tu primera playlist
|
||||||
</button>
|
</button>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
? 'text-fg'
|
? 'text-fg'
|
||||||
: 'text-fg-2'}"
|
: 'text-fg-2'}"
|
||||||
>
|
>
|
||||||
<link.icon class="size-4" />
|
<link.icon class="size-icon-sm" />
|
||||||
<span class="text-xs font-medium">{link.label}</span>
|
<span class="text-xs font-medium">{link.label}</span>
|
||||||
</a>
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
import Search from '@lucide/svelte/icons/search';
|
import Search from '@lucide/svelte/icons/search';
|
||||||
import X from '@lucide/svelte/icons/x';
|
import X from '@lucide/svelte/icons/x';
|
||||||
import ChevronLeft from '@lucide/svelte/icons/chevron-left';
|
import ChevronLeft from '@lucide/svelte/icons/chevron-left';
|
||||||
import AccountMenu from '../ui/overlay/AccountMenu.svelte';
|
import AccountMenu from '$lib/components/ui/overlay/AccountMenu.svelte';
|
||||||
import IconButton from '../ui/primitives/IconButton.svelte';
|
import IconButton from '$lib/components/ui/primitives/IconButton.svelte';
|
||||||
import Button from '../ui/primitives/Button.svelte';
|
import Button from '$lib/components/ui/primitives/Button.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: SessionUser | null;
|
user: SessionUser | null;
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
<label
|
<label
|
||||||
class="flex h-9.5 w-full items-center gap-2.5 rounded-control bg-surface-2 px-3.5 transition focus-within:bg-surface-hover"
|
class="flex h-9.5 w-full items-center gap-2.5 rounded-control bg-surface-2 px-3.5 transition focus-within:bg-surface-hover"
|
||||||
>
|
>
|
||||||
<Search class="size-4 shrink-0 text-fg-2" />
|
<Search class="size-icon-sm shrink-0 text-fg-2" />
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
bind:this={searchInput}
|
bind:this={searchInput}
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
aria-label="Borrar búsqueda"
|
aria-label="Borrar búsqueda"
|
||||||
class="grid size-5 shrink-0 place-items-center rounded-full text-fg-2 transition hover:text-fg"
|
class="grid size-5 shrink-0 place-items-center rounded-full text-fg-2 transition hover:text-fg"
|
||||||
>
|
>
|
||||||
<X class="size-3.5" />
|
<X class="size-icon-xs" />
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="animate-enter pointer-events-auto flex items-center gap-icon-md px-4 py-3 glass-bar sm:hidden"
|
class="animate-enter pointer-events-auto flex items-center gap-4.5 px-4 py-3 glass-bar sm:hidden"
|
||||||
>
|
>
|
||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<TrackInfo compact />
|
<TrackInfo compact />
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import PlayerBar from './PlayerBar.svelte';
|
import PlayerBar from './PlayerBar.svelte';
|
||||||
import TabsBar from '../layout/TabsBar.svelte';
|
import TabsBar from '$lib/components/layout/TabsBar.svelte';
|
||||||
import { player } from '$lib/player/player.svelte';
|
import { player } from '$lib/player/player.svelte';
|
||||||
import type { SessionUser } from '$lib/types';
|
import type { SessionUser } from '$lib/types';
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,7 @@
|
|||||||
inert={!queuePanel.open}
|
inert={!queuePanel.open}
|
||||||
>
|
>
|
||||||
<aside
|
<aside
|
||||||
class="flex min-h-0 shrink-0 flex-col border-l border-hairline px-4 pt-5 pb-5"
|
class="flex min-h-0 w-(--mf-queue-w) shrink-0 flex-col border-l border-hairline px-4 pt-5 pb-5"
|
||||||
style="width:var(--mf-queue-w)"
|
|
||||||
>
|
>
|
||||||
<div class="mb-5 flex items-center justify-between">
|
<div class="mb-5 flex items-center justify-between">
|
||||||
<h2 class="font-display text-base font-medium tracking-tight text-fg">En cola</h2>
|
<h2 class="font-display text-base font-medium tracking-tight text-fg">En cola</h2>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
aria-label="Aleatorio"
|
aria-label="Aleatorio"
|
||||||
class="transition-colors hover:text-fg {player.shuffle ? 'text-accent' : 'text-fg-2'}"
|
class="transition-colors hover:text-fg {player.shuffle ? 'text-accent' : 'text-fg-2'}"
|
||||||
>
|
>
|
||||||
<Shuffle class="size-4" />
|
<Shuffle class="size-icon-sm" />
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
aria-label="Repetir"
|
aria-label="Repetir"
|
||||||
class="transition-colors hover:text-fg {player.repeat ? 'text-accent' : 'text-fg-2'}"
|
class="transition-colors hover:text-fg {player.repeat ? 'text-accent' : 'text-fg-2'}"
|
||||||
>
|
>
|
||||||
<Repeat class="size-4" />
|
<Repeat class="size-icon-sm" />
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
import { untrack } from 'svelte';
|
import { untrack } from 'svelte';
|
||||||
import Disc3 from '@lucide/svelte/icons/disc-3';
|
import Disc3 from '@lucide/svelte/icons/disc-3';
|
||||||
import CoverForm from './CoverForm.svelte';
|
import CoverForm from './CoverForm.svelte';
|
||||||
import Field from '../primitives/Field.svelte';
|
import Field from '$lib/components/ui/primitives/Field.svelte';
|
||||||
import Input from '../primitives/Input.svelte';
|
import Input from '$lib/components/ui/primitives/Input.svelte';
|
||||||
import Textarea from '../primitives/Textarea.svelte';
|
import Textarea from '$lib/components/ui/primitives/Textarea.svelte';
|
||||||
import { ALBUM_EARLIEST_YEAR, LIMITS } from '$lib/validation';
|
import { ALBUM_EARLIEST_YEAR, LIMITS } from '$lib/validation';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
import { enhance } from '$app/forms';
|
import { enhance } from '$app/forms';
|
||||||
import type { LucideIcon } from '@lucide/svelte';
|
import type { LucideIcon } from '@lucide/svelte';
|
||||||
import ImageDropzone from './ImageDropzone.svelte';
|
import ImageDropzone from './ImageDropzone.svelte';
|
||||||
import Button from '../primitives/Button.svelte';
|
import Button from '$lib/components/ui/primitives/Button.svelte';
|
||||||
import Field from '../primitives/Field.svelte';
|
import Field from '$lib/components/ui/primitives/Field.svelte';
|
||||||
import Alert from '../primitives/Alert.svelte';
|
import Alert from '$lib/components/ui/primitives/Alert.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
action: string;
|
action: string;
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
import { untrack } from 'svelte';
|
import { untrack } from 'svelte';
|
||||||
import Music from '@lucide/svelte/icons/music';
|
import Music from '@lucide/svelte/icons/music';
|
||||||
import CoverForm from './CoverForm.svelte';
|
import CoverForm from './CoverForm.svelte';
|
||||||
import Field from '../primitives/Field.svelte';
|
import Field from '$lib/components/ui/primitives/Field.svelte';
|
||||||
import Input from '../primitives/Input.svelte';
|
import Input from '$lib/components/ui/primitives/Input.svelte';
|
||||||
import Textarea from '../primitives/Textarea.svelte';
|
import Textarea from '$lib/components/ui/primitives/Textarea.svelte';
|
||||||
import SegmentedControl from '../primitives/SegmentedControl.svelte';
|
import SegmentedControl from '$lib/components/ui/primitives/SegmentedControl.svelte';
|
||||||
|
|
||||||
import { LIMITS } from '$lib/validation';
|
import { LIMITS } from '$lib/validation';
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { untrack } from 'svelte';
|
import { untrack } from 'svelte';
|
||||||
import { enhance } from '$app/forms';
|
import { enhance } from '$app/forms';
|
||||||
import Button from '../primitives/Button.svelte';
|
import Button from '$lib/components/ui/primitives/Button.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
following: boolean;
|
following: boolean;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { player } from '$lib/player/player.svelte';
|
import { player } from '$lib/player/player.svelte';
|
||||||
import { isQueueCurrent, playAllOrToggle } from '$lib/player/actions';
|
import { isQueueCurrent, playAllOrToggle } from '$lib/player/actions';
|
||||||
import type { Track } from '$lib/types';
|
import type { Track } from '$lib/types';
|
||||||
import Button from '../primitives/Button.svelte';
|
import Button from '$lib/components/ui/primitives/Button.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
items: Track[];
|
items: Track[];
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
import { pressable } from '$lib/actions/pressable';
|
import { pressable } from '$lib/actions/pressable';
|
||||||
import MediaIdentity from './MediaIdentity.svelte';
|
import MediaIdentity from './MediaIdentity.svelte';
|
||||||
import EqBars from './EqBars.svelte';
|
import EqBars from './EqBars.svelte';
|
||||||
import IconButton from '../primitives/IconButton.svelte';
|
import IconButton from '$lib/components/ui/primitives/IconButton.svelte';
|
||||||
|
|
||||||
interface RowAction {
|
interface RowAction {
|
||||||
action?: string;
|
action?: string;
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
style="--mf-track-cols:{gridColumns}; --mf-track-cols-mobile:{gridColumnsMobile}"
|
style="--mf-track-cols:{gridColumns}; --mf-track-cols-mobile:{gridColumnsMobile}"
|
||||||
>
|
>
|
||||||
{#if index}
|
{#if index}
|
||||||
<Hash size={16} />
|
<Hash class="size-icon-sm" />
|
||||||
{/if}
|
{/if}
|
||||||
<span>Título</span>
|
<span>Título</span>
|
||||||
{#each columns as column (column)}
|
{#each columns as column (column)}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
import { themeMode } from '$lib/theme/mode.svelte';
|
import { themeMode } from '$lib/theme/mode.svelte';
|
||||||
import { clickOutside } from '$lib/actions/clickOutside';
|
import { clickOutside } from '$lib/actions/clickOutside';
|
||||||
import { onEscape } from '$lib/actions/onEscape';
|
import { onEscape } from '$lib/actions/onEscape';
|
||||||
import Avatar from '../media/Avatar.svelte';
|
import Avatar from '$lib/components/ui/media/Avatar.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: SessionUser;
|
user: SessionUser;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Dialog from './Dialog.svelte';
|
import Dialog from './Dialog.svelte';
|
||||||
import Button from '../primitives/Button.svelte';
|
import Button from '$lib/components/ui/primitives/Button.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import { playlistCover } from '$lib/utils/hrefs';
|
import { playlistCover } from '$lib/utils/hrefs';
|
||||||
import type { LucideIcon } from '@lucide/svelte';
|
import type { LucideIcon } from '@lucide/svelte';
|
||||||
import ChevronRight from '@lucide/svelte/icons/chevron-right';
|
import ChevronRight from '@lucide/svelte/icons/chevron-right';
|
||||||
import MediaIdentity from '../media/MediaIdentity.svelte';
|
import MediaIdentity from '$lib/components/ui/media/MediaIdentity.svelte';
|
||||||
import GlassMenu from './GlassMenu.svelte';
|
import GlassMenu from './GlassMenu.svelte';
|
||||||
import MenuItem from './MenuItem.svelte';
|
import MenuItem from './MenuItem.svelte';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Dialog from './Dialog.svelte';
|
import Dialog from './Dialog.svelte';
|
||||||
import Button from '../primitives/Button.svelte';
|
import Button from '$lib/components/ui/primitives/Button.svelte';
|
||||||
import { dialog, type DialogAction, type DialogOptions } from '$lib/state/dialog.svelte';
|
import { dialog, type DialogAction, type DialogOptions } from '$lib/state/dialog.svelte';
|
||||||
|
|
||||||
// Keep the last dialog's content so the exit transition doesn't render an empty panel.
|
// Keep the last dialog's content so the exit transition doesn't render an empty panel.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
import X from '@lucide/svelte/icons/x';
|
import X from '@lucide/svelte/icons/x';
|
||||||
import IconButton from '../primitives/IconButton.svelte';
|
import IconButton from '$lib/components/ui/primitives/IconButton.svelte';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
import { pop } from '$lib/utils/transitions';
|
import { pop } from '$lib/utils/transitions';
|
||||||
import { onEscape } from '$lib/actions/onEscape';
|
import { onEscape } from '$lib/actions/onEscape';
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<IconButton label="Cerrar" onclick={onClose} class="shrink-0">
|
<IconButton label="Cerrar" onclick={onClose} class="shrink-0">
|
||||||
<X class="size-4" />
|
<X class="size-icon-sm" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -28,13 +28,13 @@
|
|||||||
children
|
children
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
const sizes = {
|
const SIZE = {
|
||||||
sm: 'rounded-control px-4 py-2 text-xs',
|
sm: 'rounded-control px-4 py-2 text-xs',
|
||||||
md: 'rounded-btn-sm px-4.5 py-2.5 text-control-sm',
|
md: 'rounded-btn-sm px-4.5 py-2.5 text-control-sm',
|
||||||
lg: 'rounded-btn px-6 py-3.5 text-sm'
|
lg: 'rounded-btn px-6 py-3.5 text-sm'
|
||||||
};
|
};
|
||||||
|
|
||||||
const variants = {
|
const VARIANT = {
|
||||||
primary: 'bg-cta-strong text-ink hover:bg-cta-strong-hover',
|
primary: 'bg-cta-strong text-ink hover:bg-cta-strong-hover',
|
||||||
secondary: 'bg-btn text-fg hover:bg-btn-hover',
|
secondary: 'bg-btn text-fg hover:bg-btn-hover',
|
||||||
accent: 'surface-active text-accent-soft hover:surface-active-hover',
|
accent: 'surface-active text-accent-soft hover:surface-active-hover',
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const classes = $derived(
|
const classes = $derived(
|
||||||
`inline-flex items-center justify-center gap-2 font-medium btn-transition focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-bg focus-visible:outline-none disabled:opacity-40 ${sizes[size]} ${variants[variant]} ${klass}`
|
`inline-flex items-center justify-center gap-2 font-medium btn-transition focus-ring focus-visible:ring-offset-2 focus-visible:ring-offset-bg disabled:opacity-40 ${SIZE[size]} ${VARIANT[variant]} ${klass}`
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
class={classes}
|
class={classes}
|
||||||
>
|
>
|
||||||
{#if loading && !href}
|
{#if loading && !href}
|
||||||
<LoaderCircle class="size-4 animate-spin" />
|
<LoaderCircle class="size-icon-sm animate-spin" />
|
||||||
{/if}
|
{/if}
|
||||||
{@render children()}
|
{@render children()}
|
||||||
</svelte:element>
|
</svelte:element>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
class="peer size-5 cursor-pointer appearance-none rounded-tag border border-line bg-surface transition checked:border-accent-soft checked:bg-accent-soft focus-visible:border-accent/60 focus-visible:outline-none"
|
class="peer size-5 cursor-pointer appearance-none rounded-tag border border-line bg-surface transition checked:border-accent-soft checked:bg-accent-soft focus-visible:border-accent/60 focus-visible:outline-none"
|
||||||
/>
|
/>
|
||||||
<Check
|
<Check
|
||||||
class="pointer-events-none absolute size-3.5 text-ink opacity-0 transition peer-checked:opacity-100"
|
class="pointer-events-none absolute size-icon-xs text-ink opacity-0 transition peer-checked:opacity-100"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span class="cursor-pointer">{@render children()}</span>
|
<span class="cursor-pointer">{@render children()}</span>
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
|
|
||||||
const classes = $derived(
|
const classes = $derived(
|
||||||
href
|
href
|
||||||
? 'rounded-full border border-line-strong px-3.5 py-2 text-xs text-fg-2 transition-colors hover:bg-hover hover:text-fg'
|
? 'focus-ring rounded-full border border-line-strong px-3.5 py-2 text-xs text-fg-2 transition-colors hover:bg-hover hover:text-fg'
|
||||||
: `flex items-center gap-2 rounded-full px-3.5 py-2 text-xs font-medium transition ${
|
: `focus-ring flex items-center gap-2 rounded-full px-3.5 py-2 text-xs font-medium transition ${
|
||||||
selected ? 'bg-cta-strong text-ink' : 'bg-btn text-fg-2 hover:bg-btn-hover hover:text-fg'
|
selected ? 'bg-cta-strong text-ink' : 'bg-btn text-fg-2 hover:bg-btn-hover hover:text-fg'
|
||||||
} ${disabled ? 'cursor-not-allowed opacity-40' : ''}`
|
} ${disabled ? 'cursor-not-allowed opacity-40' : ''}`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
const classes = $derived(
|
const classes = $derived(
|
||||||
`grid place-items-center transition focus-visible:ring-2 focus-visible:ring-accent focus-visible:outline-none ${SIZE[size]} ${shape === 'round' ? 'rounded-full' : 'rounded-control'} ${pressed ? 'text-accent' : 'text-fg-2 hover:text-fg'} ${background} ${
|
`grid place-items-center transition focus-ring ${SIZE[size]} ${shape === 'round' ? 'rounded-full' : 'rounded-control'} ${pressed ? 'text-accent' : 'text-fg-2 hover:text-fg'} ${background} ${
|
||||||
revealOnHover ? 'sm:opacity-0 sm:group-hover:opacity-100 sm:focus-visible:opacity-100' : ''
|
revealOnHover ? 'sm:opacity-0 sm:group-hover:opacity-100 sm:focus-visible:opacity-100' : ''
|
||||||
} ${klass}`
|
} ${klass}`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ const HISTORY_INDEX = 'sveltekit:history';
|
|||||||
const LABELS: [RegExp, string][] = [
|
const LABELS: [RegExp, string][] = [
|
||||||
[/^\/$/, 'Volver al inicio'],
|
[/^\/$/, 'Volver al inicio'],
|
||||||
[/^\/explore\/?$/, 'Volver a explorar'],
|
[/^\/explore\/?$/, 'Volver a explorar'],
|
||||||
[/^\/playlists\/[^/]+/, 'Volver a la lista'],
|
[/^\/playlists\/[^/]+/, 'Volver a la playlist'],
|
||||||
[/^\/playlists\/?$/, 'Volver a tus listas'],
|
[/^\/playlists\/?$/, 'Volver a tus playlists'],
|
||||||
[/^\/albums\/[^/]+/, 'Volver al álbum'],
|
[/^\/albums\/[^/]+/, 'Volver al álbum'],
|
||||||
[/^\/albums\/?$/, 'Volver a tus álbumes'],
|
[/^\/albums\/?$/, 'Volver a tus álbumes'],
|
||||||
[/^\/library\/?$/, 'Volver a tus canciones'],
|
[/^\/library\/?$/, 'Volver a tus canciones'],
|
||||||
|
|||||||
@@ -205,7 +205,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<SectionHeading title="Mixes" subtitle="Generados a partir de lo que más repites" />
|
<SectionHeading title="Mezclas" subtitle="Generados a partir de lo que más repites" />
|
||||||
{#if data.mixes.length > 0}
|
{#if data.mixes.length > 0}
|
||||||
<div class="grid-tiles">
|
<div class="grid-tiles">
|
||||||
{#each data.mixes as mix, i (mix.id)}
|
{#each data.mixes as mix, i (mix.id)}
|
||||||
@@ -255,11 +255,11 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<EmptyState
|
<EmptyState
|
||||||
icon={ListMusic}
|
icon={ListMusic}
|
||||||
title="Todavía no tienes listas"
|
title="Todavía no tienes playlists"
|
||||||
description="Crea tu primera lista y añádele canciones de tu biblioteca."
|
description="Crea tu primera playlist y añádele canciones de tu biblioteca."
|
||||||
>
|
>
|
||||||
{#snippet actions()}
|
{#snippet actions()}
|
||||||
<Button href="/playlists">Crear lista</Button>
|
<Button href="/playlists">Crear playlist</Button>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
{#snippet actions()}
|
{#snippet actions()}
|
||||||
{#if items.length > 0}
|
{#if items.length > 0}
|
||||||
<Button onclick={() => (creating = true)}>
|
<Button onclick={() => (creating = true)}>
|
||||||
<Plus class="size-4" />
|
<Plus class="size-icon-sm" />
|
||||||
Nuevo álbum
|
Nuevo álbum
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
{#snippet actions()}
|
{#snippet actions()}
|
||||||
{#if items.length > 0}
|
{#if items.length > 0}
|
||||||
<Button href="/upload">
|
<Button href="/upload">
|
||||||
<Upload class="size-4" />
|
<Upload class="size-icon-sm" />
|
||||||
Subir canción
|
Subir canción
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
>
|
>
|
||||||
{#snippet actions()}
|
{#snippet actions()}
|
||||||
<Button href="/upload">
|
<Button href="/upload">
|
||||||
<Upload class="size-4" />
|
<Upload class="size-icon-sm" />
|
||||||
Sube la primera
|
Sube la primera
|
||||||
</Button>
|
</Button>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
onclick={() => playShuffled(tracks)}
|
onclick={() => playShuffled(tracks)}
|
||||||
disabled={tracks.length === 0}
|
disabled={tracks.length === 0}
|
||||||
>
|
>
|
||||||
<Shuffle class="size-4" />
|
<Shuffle class="size-icon-sm" />
|
||||||
Aleatorio
|
Aleatorio
|
||||||
</Button>
|
</Button>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|||||||
@@ -19,18 +19,18 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
<title>Mis listas</title>
|
<title>Mis playlists</title>
|
||||||
<meta name="description" content="Mis listas en Musify." />
|
<meta name="description" content="Mis playlists en Musify." />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<Page>
|
<Page>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title="Mis listas"
|
title="Mis playlists"
|
||||||
description={items.length > 0 ? summary : 'Crea y organiza tus colecciones.'}
|
description={items.length > 0 ? summary : 'Crea y organiza tus colecciones.'}
|
||||||
>
|
>
|
||||||
{#snippet actions()}
|
{#snippet actions()}
|
||||||
{#if items.length > 0}
|
{#if items.length > 0}
|
||||||
<Button onclick={() => createPlaylistModal.show()}>Crear nueva lista</Button>
|
<Button onclick={() => createPlaylistModal.show()}>Crear nueva playlist</Button>
|
||||||
{/if}
|
{/if}
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
@@ -51,11 +51,11 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<EmptyState
|
<EmptyState
|
||||||
icon={ListMusic}
|
icon={ListMusic}
|
||||||
title="Todavía no tienes listas"
|
title="Todavía no tienes playlists"
|
||||||
description="Crea la primera y añádele canciones de tu biblioteca."
|
description="Crea la primera y añádele canciones de tu biblioteca."
|
||||||
>
|
>
|
||||||
{#snippet actions()}
|
{#snippet actions()}
|
||||||
<Button onclick={() => createPlaylistModal.show()}>Crear nueva lista</Button>
|
<Button onclick={() => createPlaylistModal.show()}>Crear nueva playlist</Button>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</EmptyState>
|
</EmptyState>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -133,7 +133,7 @@
|
|||||||
: 'bg-accent-btn text-accent-soft'}"
|
: 'bg-accent-btn text-accent-soft'}"
|
||||||
>
|
>
|
||||||
{#if stepStates[i] === 'done'}
|
{#if stepStates[i] === 'done'}
|
||||||
<Check class="size-3.5" />
|
<Check class="size-icon-xs" />
|
||||||
{:else}
|
{:else}
|
||||||
{i + 1}
|
{i + 1}
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -82,6 +82,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@utility focus-ring {
|
||||||
|
@apply focus-visible:ring-2 focus-visible:ring-accent focus-visible:outline-none;
|
||||||
|
}
|
||||||
|
|
||||||
@utility track-grid {
|
@utility track-grid {
|
||||||
grid-template-columns: var(--mf-track-cols-mobile);
|
grid-template-columns: var(--mf-track-cols-mobile);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user