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 Folder from '@lucide/svelte/icons/folder';
|
||||
import LogIn from '@lucide/svelte/icons/log-in';
|
||||
import MenuItem from '../ui/overlay/MenuItem.svelte';
|
||||
import AccountMenu from '../ui/overlay/AccountMenu.svelte';
|
||||
import IconButton from '../ui/primitives/IconButton.svelte';
|
||||
import Logo from '../ui/primitives/Logo.svelte';
|
||||
import MenuItem from '$lib/components/ui/overlay/MenuItem.svelte';
|
||||
import AccountMenu from '$lib/components/ui/overlay/AccountMenu.svelte';
|
||||
import IconButton from '$lib/components/ui/primitives/IconButton.svelte';
|
||||
import Logo from '$lib/components/ui/primitives/Logo.svelte';
|
||||
|
||||
interface Props {
|
||||
user: SessionUser | null;
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
import { liked } from '$lib/player/liked.svelte';
|
||||
import { createPlaylistModal } from '$lib/state/panels.svelte';
|
||||
import type { SessionUser } from '$lib/types';
|
||||
import ListRow from '../ui/media/ListRow.svelte';
|
||||
import IconButton from '../ui/primitives/IconButton.svelte';
|
||||
import ListRow from '$lib/components/ui/media/ListRow.svelte';
|
||||
import IconButton from '$lib/components/ui/primitives/IconButton.svelte';
|
||||
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;
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
</script>
|
||||
|
||||
<aside
|
||||
class="hidden min-h-0 shrink-0 flex-col border-r border-hairline p-5 lg:flex"
|
||||
style="width:var(--mf-sidebar-w)"
|
||||
class="hidden min-h-0 w-(--mf-sidebar-w) shrink-0 flex-col border-r border-hairline p-5 lg:flex"
|
||||
>
|
||||
<a href="/" class="mb-4">
|
||||
<Logo size="sm" />
|
||||
@@ -75,7 +74,7 @@
|
||||
{/if}
|
||||
</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)}
|
||||
{@const active = page.url.pathname === `/playlists/${playlist.id}`}
|
||||
<ListRow
|
||||
@@ -93,8 +92,8 @@
|
||||
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"
|
||||
>
|
||||
<Plus class="size-3.5" />
|
||||
Crear tu primera lista
|
||||
<Plus class="size-icon-xs" />
|
||||
Crear tu primera playlist
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
? 'text-fg'
|
||||
: 'text-fg-2'}"
|
||||
>
|
||||
<link.icon class="size-4" />
|
||||
<link.icon class="size-icon-sm" />
|
||||
<span class="text-xs font-medium">{link.label}</span>
|
||||
</a>
|
||||
{/each}
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
import Search from '@lucide/svelte/icons/search';
|
||||
import X from '@lucide/svelte/icons/x';
|
||||
import ChevronLeft from '@lucide/svelte/icons/chevron-left';
|
||||
import AccountMenu from '../ui/overlay/AccountMenu.svelte';
|
||||
import IconButton from '../ui/primitives/IconButton.svelte';
|
||||
import Button from '../ui/primitives/Button.svelte';
|
||||
import AccountMenu from '$lib/components/ui/overlay/AccountMenu.svelte';
|
||||
import IconButton from '$lib/components/ui/primitives/IconButton.svelte';
|
||||
import Button from '$lib/components/ui/primitives/Button.svelte';
|
||||
|
||||
interface Props {
|
||||
user: SessionUser | null;
|
||||
@@ -61,7 +61,7 @@
|
||||
<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"
|
||||
>
|
||||
<Search class="size-4 shrink-0 text-fg-2" />
|
||||
<Search class="size-icon-sm shrink-0 text-fg-2" />
|
||||
<input
|
||||
type="text"
|
||||
bind:this={searchInput}
|
||||
@@ -77,7 +77,7 @@
|
||||
aria-label="Borrar búsqueda"
|
||||
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>
|
||||
{/if}
|
||||
</label>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</script>
|
||||
|
||||
<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">
|
||||
<TrackInfo compact />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
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 type { SessionUser } from '$lib/types';
|
||||
|
||||
|
||||
@@ -43,8 +43,7 @@
|
||||
inert={!queuePanel.open}
|
||||
>
|
||||
<aside
|
||||
class="flex min-h-0 shrink-0 flex-col border-l border-hairline px-4 pt-5 pb-5"
|
||||
style="width:var(--mf-queue-w)"
|
||||
class="flex min-h-0 w-(--mf-queue-w) shrink-0 flex-col border-l border-hairline px-4 pt-5 pb-5"
|
||||
>
|
||||
<div class="mb-5 flex items-center justify-between">
|
||||
<h2 class="font-display text-base font-medium tracking-tight text-fg">En cola</h2>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
aria-label="Aleatorio"
|
||||
class="transition-colors hover:text-fg {player.shuffle ? 'text-accent' : 'text-fg-2'}"
|
||||
>
|
||||
<Shuffle class="size-4" />
|
||||
<Shuffle class="size-icon-sm" />
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
aria-label="Repetir"
|
||||
class="transition-colors hover:text-fg {player.repeat ? 'text-accent' : 'text-fg-2'}"
|
||||
>
|
||||
<Repeat class="size-4" />
|
||||
<Repeat class="size-icon-sm" />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
import { untrack } from 'svelte';
|
||||
import Disc3 from '@lucide/svelte/icons/disc-3';
|
||||
import CoverForm from './CoverForm.svelte';
|
||||
import Field from '../primitives/Field.svelte';
|
||||
import Input from '../primitives/Input.svelte';
|
||||
import Textarea from '../primitives/Textarea.svelte';
|
||||
import Field from '$lib/components/ui/primitives/Field.svelte';
|
||||
import Input from '$lib/components/ui/primitives/Input.svelte';
|
||||
import Textarea from '$lib/components/ui/primitives/Textarea.svelte';
|
||||
import { ALBUM_EARLIEST_YEAR, LIMITS } from '$lib/validation';
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
import { enhance } from '$app/forms';
|
||||
import type { LucideIcon } from '@lucide/svelte';
|
||||
import ImageDropzone from './ImageDropzone.svelte';
|
||||
import Button from '../primitives/Button.svelte';
|
||||
import Field from '../primitives/Field.svelte';
|
||||
import Alert from '../primitives/Alert.svelte';
|
||||
import Button from '$lib/components/ui/primitives/Button.svelte';
|
||||
import Field from '$lib/components/ui/primitives/Field.svelte';
|
||||
import Alert from '$lib/components/ui/primitives/Alert.svelte';
|
||||
|
||||
interface Props {
|
||||
action: string;
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
import { untrack } from 'svelte';
|
||||
import Music from '@lucide/svelte/icons/music';
|
||||
import CoverForm from './CoverForm.svelte';
|
||||
import Field from '../primitives/Field.svelte';
|
||||
import Input from '../primitives/Input.svelte';
|
||||
import Textarea from '../primitives/Textarea.svelte';
|
||||
import SegmentedControl from '../primitives/SegmentedControl.svelte';
|
||||
import Field from '$lib/components/ui/primitives/Field.svelte';
|
||||
import Input from '$lib/components/ui/primitives/Input.svelte';
|
||||
import Textarea from '$lib/components/ui/primitives/Textarea.svelte';
|
||||
import SegmentedControl from '$lib/components/ui/primitives/SegmentedControl.svelte';
|
||||
|
||||
import { LIMITS } from '$lib/validation';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { untrack } from 'svelte';
|
||||
import { enhance } from '$app/forms';
|
||||
import Button from '../primitives/Button.svelte';
|
||||
import Button from '$lib/components/ui/primitives/Button.svelte';
|
||||
|
||||
interface Props {
|
||||
following: boolean;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { player } from '$lib/player/player.svelte';
|
||||
import { isQueueCurrent, playAllOrToggle } from '$lib/player/actions';
|
||||
import type { Track } from '$lib/types';
|
||||
import Button from '../primitives/Button.svelte';
|
||||
import Button from '$lib/components/ui/primitives/Button.svelte';
|
||||
|
||||
interface Props {
|
||||
items: Track[];
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
import { pressable } from '$lib/actions/pressable';
|
||||
import MediaIdentity from './MediaIdentity.svelte';
|
||||
import EqBars from './EqBars.svelte';
|
||||
import IconButton from '../primitives/IconButton.svelte';
|
||||
import IconButton from '$lib/components/ui/primitives/IconButton.svelte';
|
||||
|
||||
interface RowAction {
|
||||
action?: string;
|
||||
@@ -86,7 +86,7 @@
|
||||
style="--mf-track-cols:{gridColumns}; --mf-track-cols-mobile:{gridColumnsMobile}"
|
||||
>
|
||||
{#if index}
|
||||
<Hash size={16} />
|
||||
<Hash class="size-icon-sm" />
|
||||
{/if}
|
||||
<span>Título</span>
|
||||
{#each columns as column (column)}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
import { themeMode } from '$lib/theme/mode.svelte';
|
||||
import { clickOutside } from '$lib/actions/clickOutside';
|
||||
import { onEscape } from '$lib/actions/onEscape';
|
||||
import Avatar from '../media/Avatar.svelte';
|
||||
import Avatar from '$lib/components/ui/media/Avatar.svelte';
|
||||
|
||||
interface Props {
|
||||
user: SessionUser;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import Dialog from './Dialog.svelte';
|
||||
import Button from '../primitives/Button.svelte';
|
||||
import Button from '$lib/components/ui/primitives/Button.svelte';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { playlistCover } from '$lib/utils/hrefs';
|
||||
import type { LucideIcon } from '@lucide/svelte';
|
||||
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 MenuItem from './MenuItem.svelte';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
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';
|
||||
|
||||
// Keep the last dialog's content so the exit transition doesn't render an empty panel.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
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 { pop } from '$lib/utils/transitions';
|
||||
import { onEscape } from '$lib/actions/onEscape';
|
||||
@@ -96,7 +96,7 @@
|
||||
</h2>
|
||||
</div>
|
||||
<IconButton label="Cerrar" onclick={onClose} class="shrink-0">
|
||||
<X class="size-4" />
|
||||
<X class="size-icon-sm" />
|
||||
</IconButton>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
children
|
||||
}: Props = $props();
|
||||
|
||||
const sizes = {
|
||||
const SIZE = {
|
||||
sm: 'rounded-control px-4 py-2 text-xs',
|
||||
md: 'rounded-btn-sm px-4.5 py-2.5 text-control-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',
|
||||
secondary: 'bg-btn text-fg hover:bg-btn-hover',
|
||||
accent: 'surface-active text-accent-soft hover:surface-active-hover',
|
||||
@@ -42,7 +42,7 @@
|
||||
};
|
||||
|
||||
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>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
class={classes}
|
||||
>
|
||||
{#if loading && !href}
|
||||
<LoaderCircle class="size-4 animate-spin" />
|
||||
<LoaderCircle class="size-icon-sm animate-spin" />
|
||||
{/if}
|
||||
{@render children()}
|
||||
</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"
|
||||
/>
|
||||
<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 class="cursor-pointer">{@render children()}</span>
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
const classes = $derived(
|
||||
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'
|
||||
: `flex items-center gap-2 rounded-full px-3.5 py-2 text-xs font-medium transition ${
|
||||
? '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'
|
||||
: `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'
|
||||
} ${disabled ? 'cursor-not-allowed opacity-40' : ''}`
|
||||
);
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
);
|
||||
|
||||
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' : ''
|
||||
} ${klass}`
|
||||
);
|
||||
|
||||
@@ -5,8 +5,8 @@ const HISTORY_INDEX = 'sveltekit:history';
|
||||
const LABELS: [RegExp, string][] = [
|
||||
[/^\/$/, 'Volver al inicio'],
|
||||
[/^\/explore\/?$/, 'Volver a explorar'],
|
||||
[/^\/playlists\/[^/]+/, 'Volver a la lista'],
|
||||
[/^\/playlists\/?$/, 'Volver a tus listas'],
|
||||
[/^\/playlists\/[^/]+/, 'Volver a la playlist'],
|
||||
[/^\/playlists\/?$/, 'Volver a tus playlists'],
|
||||
[/^\/albums\/[^/]+/, 'Volver al álbum'],
|
||||
[/^\/albums\/?$/, 'Volver a tus álbumes'],
|
||||
[/^\/library\/?$/, 'Volver a tus canciones'],
|
||||
|
||||
Reference in New Issue
Block a user