web-player: consistent imports, tokens, glossary and app route grouping

This commit is contained in:
2026-09-24 11:52:57 +02:00
parent 1a2ae37f49
commit 975fa7e4fd
32 changed files with 71 additions and 69 deletions
@@ -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}`
); );
+2 -2
View File
@@ -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}
+4
View File
@@ -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);