Design Prot Merge #1

Merged
NotS1mp merged 217 commits from design-prot into master 2026-09-21 15:48:16 +00:00
20 changed files with 191 additions and 138 deletions
Showing only changes of commit aa20e70671 - Show all commits
+1 -1
View File
@@ -776,7 +776,7 @@ Tareas:
| P1 | ✅ | (pendiente) | Verificado con `build` (Tailwind compila `@apply sm:` dentro de `@utility`); sin QA visual autenticada (Docker no disponible en esta sesión) | | P1 | ✅ | (pendiente) | Verificado con `build` (Tailwind compila `@apply sm:` dentro de `@utility`); sin QA visual autenticada (Docker no disponible en esta sesión) |
| P2 | ✅ | (pendiente) | `<style>{expr}</style>` no interpola en Svelte (se trata como CSS del componente); solución: `{@html \`<style>${css}</style>\`}` | | P2 | ✅ | (pendiente) | `<style>{expr}</style>` no interpola en Svelte (se trata como CSS del componente); solución: `{@html \`<style>${css}</style>\`}` |
| P3 | ✅ | (pendiente) | Se quitó el nombre bajo el avatar de perfil (decisión tomada: redundante con el título de CollectionHeader). Se añadió `size="fill"` a Artwork (no está en la spec) para las tarjetas de grid fluidas (AlbumCard/PlaylistCard/MixTile), ya que P9 (MediaCard) aún no existe. SearchResultRow perdió su prop `kind`/radio-por-tipo (ahora el radio lo decide Artwork/Avatar). Sin QA visual autenticada (Docker no disponible) | | P3 | ✅ | (pendiente) | Se quitó el nombre bajo el avatar de perfil (decisión tomada: redundante con el título de CollectionHeader). Se añadió `size="fill"` a Artwork (no está en la spec) para las tarjetas de grid fluidas (AlbumCard/PlaylistCard/MixTile), ya que P9 (MediaCard) aún no existe. SearchResultRow perdió su prop `kind`/radio-por-tipo (ahora el radio lo decide Artwork/Avatar). Sin QA visual autenticada (Docker no disponible) |
| P4 | ⬜ | | | | P4 | ✅ | (pendiente) | Decisión tomada sin bloquear: se elimina el botón "adelante" decorativo (TopBar) y el icono `AlignJustify` decorativo (PlayerExtras) por ser código muerto visual. `TransportControls` (shuffle/prev/next/repeat) se deja sin migrar a IconButton a propósito: son iconos sin chrome (sin fondo/hit-box), migrarlos habría añadido una píldora de hover no presente hoy — riesgo visual no verificable sin Docker |
| P5 | ⬜ | | | | P5 | ⬜ | | |
| P6 | ⬜ | | | | P6 | ⬜ | | |
| P7 | ⬜ | | | | P7 | ⬜ | | |
@@ -6,6 +6,7 @@
import MenuItem from './ui/MenuItem.svelte'; import MenuItem from './ui/MenuItem.svelte';
import AccountMenu from './ui/AccountMenu.svelte'; import AccountMenu from './ui/AccountMenu.svelte';
import Avatar from './ui/Avatar.svelte'; import Avatar from './ui/Avatar.svelte';
import IconButton from './ui/IconButton.svelte';
interface Props { interface Props {
user: SessionUser | null; user: SessionUser | null;
@@ -50,14 +51,9 @@
{/snippet} {/snippet}
</AccountMenu> </AccountMenu>
{:else} {:else}
<a <IconButton href="/auth/login" reload label="Iniciar sesión" shape="round" size="md">
href="/auth/login" <LogIn class="size-icon-lg" strokeWidth={2} />
data-sveltekit-reload </IconButton>
aria-label="Iniciar sesión"
class="flex items-center rounded-full p-1.5 text-fg-3 transition hover:bg-hover hover:text-fg"
>
<LogIn class="h-6 w-6" strokeWidth={2} />
</a>
{/if} {/if}
</div> </div>
</header> </header>
+7 -6
View File
@@ -5,6 +5,7 @@
import { createPlaylistModal } from '$lib/playlists.svelte'; import { createPlaylistModal } from '$lib/playlists.svelte';
import type { SessionUser } from '$lib/types'; import type { SessionUser } from '$lib/types';
import Artwork from './ui/Artwork.svelte'; import Artwork from './ui/Artwork.svelte';
import IconButton from './ui/IconButton.svelte';
import Home from '@lucide/svelte/icons/house'; import Home from '@lucide/svelte/icons/house';
import Compass from '@lucide/svelte/icons/compass'; import Compass from '@lucide/svelte/icons/compass';
import ListMusic from '@lucide/svelte/icons/list-music'; import ListMusic from '@lucide/svelte/icons/list-music';
@@ -77,14 +78,14 @@
<div class="flex items-center justify-between px-3 pb-1.5"> <div class="flex items-center justify-between px-3 pb-1.5">
<span class="text-xs font-medium tracking-widest text-muted uppercase">Tus playlists</span> <span class="text-xs font-medium tracking-widest text-muted uppercase">Tus playlists</span>
{#if playlists.length > 0} {#if playlists.length > 0}
<button <IconButton
type="button" label="Crear playlist"
tone="plain"
size="xs"
onclick={() => createPlaylistModal.show()} onclick={() => createPlaylistModal.show()}
aria-label="Crear playlist"
class="text-muted transition-colors hover:text-fg"
> >
<Plus class="h-3.5 w-3.5" strokeWidth={1.25} /> <Plus class="size-icon-sm" strokeWidth={1.25} />
</button> </IconButton>
{/if} {/if}
</div> </div>
+13 -22
View File
@@ -6,9 +6,10 @@
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 ChevronRight from '@lucide/svelte/icons/chevron-right';
import AccountMenu from './ui/AccountMenu.svelte'; import AccountMenu from './ui/AccountMenu.svelte';
import Avatar from './ui/Avatar.svelte'; import Avatar from './ui/Avatar.svelte';
import IconButton from './ui/IconButton.svelte';
import Button from './ui/Button.svelte';
interface Props { interface Props {
user: SessionUser | null; user: SessionUser | null;
@@ -56,24 +57,18 @@
</script> </script>
<header class="hidden items-center gap-3.5 px-6.5 pt-4 pb-3 sm:flex"> <header class="hidden items-center gap-3.5 px-6.5 pt-4 pb-3 sm:flex">
<div class="flex shrink-0 gap-1.5"> <IconButton
<button label="Atrás"
type="button" shape="round"
tone="subtle"
surface
size="xs"
onclick={() => history.back()} onclick={() => history.back()}
aria-label="Atrás"
class="grid h-7.5 w-7.5 place-items-center rounded-full bg-surface-2 text-fg-2 transition-colors hover:bg-surface-hover hover:text-fg"
> >
<ChevronLeft class="h-3.75 w-3.75" strokeWidth={1.9} /> <ChevronLeft class="size-icon-sm" strokeWidth={1.9} />
</button> </IconButton>
<span
aria-hidden="true"
class="grid h-7.5 w-7.5 place-items-center rounded-full bg-surface-2 text-muted"
>
<ChevronRight class="h-3.75 w-3.75" strokeWidth={1.9} />
</span>
</div>
<form onsubmit={onSubmit} class="max-w-120 min-w-0 flex-1"> <form onsubmit={onSubmit} class="max-w-search min-w-0 flex-1">
<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"
> >
@@ -126,13 +121,9 @@
{/snippet} {/snippet}
</AccountMenu> </AccountMenu>
{:else} {:else}
<a <Button href="/auth/login" reload variant="accent" size="sm" class="shrink-0"
href="/auth/login" >Iniciar sesión</Button
data-sveltekit-reload
class="shrink-0 rounded-full bg-accent-soft px-4 py-2 text-sm font-semibold text-ink transition hover:brightness-110"
> >
Iniciar sesión
</a>
{/if} {/if}
</div> </div>
</header> </header>
@@ -1,22 +1,19 @@
<script lang="ts"> <script lang="ts">
import VolumeControl from './VolumeControl.svelte'; import VolumeControl from './VolumeControl.svelte';
import IconButton from '$lib/components/ui/IconButton.svelte';
import { queuePanel } from '$lib/player/queuePanel.svelte'; import { queuePanel } from '$lib/player/queuePanel.svelte';
import AlignJustify from '@lucide/svelte/icons/align-justify';
import ListMusic from '@lucide/svelte/icons/list-music'; import ListMusic from '@lucide/svelte/icons/list-music';
</script> </script>
<div class="hidden w-64 shrink-0 items-center justify-end gap-3.5 sm:flex"> <div class="hidden w-(--mf-player-side-w) shrink-0 items-center justify-end gap-3.5 sm:flex">
<span aria-hidden="true" class="text-fg-3">
<AlignJustify class="h-3.75 w-3.75" strokeWidth={1.8} />
</span>
<VolumeControl /> <VolumeControl />
<button <IconButton
type="button" label="Cola de reproducción"
tone="plain"
size="xs"
pressed={queuePanel.open}
onclick={() => queuePanel.toggle()} onclick={() => queuePanel.toggle()}
aria-pressed={queuePanel.open}
aria-label="Cola de reproducción"
class="transition-colors hover:text-fg {queuePanel.open ? 'text-fg' : 'text-fg-2'}"
> >
<ListMusic class="h-4 w-4" strokeWidth={1.8} /> <ListMusic class="size-icon-sm" strokeWidth={1.8} />
</button> </IconButton>
</div> </div>
@@ -3,6 +3,7 @@
import { queuePanel } from '$lib/player/queuePanel.svelte'; import { queuePanel } from '$lib/player/queuePanel.svelte';
import Artwork from '$lib/components/ui/Artwork.svelte'; import Artwork from '$lib/components/ui/Artwork.svelte';
import ArtistLink from '$lib/components/ui/ArtistLink.svelte'; import ArtistLink from '$lib/components/ui/ArtistLink.svelte';
import IconButton from '$lib/components/ui/IconButton.svelte';
import { fmtTime } from '$lib/format'; import { fmtTime } from '$lib/format';
import X from '@lucide/svelte/icons/x'; import X from '@lucide/svelte/icons/x';
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
@@ -22,14 +23,9 @@
> >
<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>
<button <IconButton label="Cerrar cola" tone="plain" size="xs" onclick={() => queuePanel.close()}>
type="button" <X class="size-icon-md" />
onclick={() => queuePanel.close()} </IconButton>
aria-label="Cerrar cola"
class="text-fg-3 transition-colors hover:text-fg"
>
<X class="h-4 w-4" />
</button>
</div> </div>
{#if player.current.id} {#if player.current.id}
@@ -4,6 +4,7 @@
import Artwork from '$lib/components/ui/Artwork.svelte'; import Artwork from '$lib/components/ui/Artwork.svelte';
import ExplicitBadge from '$lib/components/ui/ExplicitBadge.svelte'; import ExplicitBadge from '$lib/components/ui/ExplicitBadge.svelte';
import ArtistLink from '$lib/components/ui/ArtistLink.svelte'; import ArtistLink from '$lib/components/ui/ArtistLink.svelte';
import IconButton from '$lib/components/ui/IconButton.svelte';
import Heart from '@lucide/svelte/icons/heart'; import Heart from '@lucide/svelte/icons/heart';
interface Props { interface Props {
@@ -52,14 +53,14 @@
/> />
</div> </div>
{#if !compact} {#if !compact}
<button <IconButton
type="button" label={isLiked ? 'Quitar de Me gusta' : 'Añadir a Me gusta'}
tone="plain"
size="xs"
pressed={isLiked}
onclick={toggleLike} onclick={toggleLike}
aria-label={isLiked ? 'Quitar de Me gusta' : 'Añadir a Me gusta'}
aria-pressed={isLiked}
class="shrink-0 transition hover:opacity-80 {isLiked ? 'text-accent' : 'text-fg-3'}"
> >
<Heart class="h-4 w-4" fill={isLiked ? 'currentColor' : 'none'} strokeWidth={1.7} /> <Heart class="size-icon-md" fill={isLiked ? 'currentColor' : 'none'} strokeWidth={1.7} />
</button> </IconButton>
{/if} {/if}
</div> </div>
@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { player } from '$lib/player/player.svelte'; import { player } from '$lib/player/player.svelte';
import PlayButton from '$lib/components/ui/PlayButton.svelte';
import Shuffle from '@lucide/svelte/icons/shuffle'; import Shuffle from '@lucide/svelte/icons/shuffle';
import Repeat from '@lucide/svelte/icons/repeat'; import Repeat from '@lucide/svelte/icons/repeat';
@@ -36,23 +37,11 @@
</svg> </svg>
</button> </button>
<button <PlayButton
type="button" playing={player.playing}
onclick={() => player.toggle()} onclick={() => player.toggle()}
aria-label={player.playing ? 'Pausar' : 'Reproducir'} label={player.playing ? 'Pausar' : 'Reproducir'}
class="grid h-10 w-10 shrink-0 place-items-center rounded-full bg-cta-strong text-ink transition duration-150 hover:brightness-95" />
>
{#if player.playing}
<svg width="15" height="15" viewBox="0 0 15 15" fill="currentColor">
<rect x="3" y="1" width="3" height="13" rx="1" />
<rect x="9" y="1" width="3" height="13" rx="1" />
</svg>
{:else}
<svg width="15" height="15" viewBox="0 0 15 15" fill="currentColor">
<path d="M3 1.5v12l10-6z" />
</svg>
{/if}
</button>
<button type="button" onclick={() => player.next()} aria-label="Siguiente" class={sideClass}> <button type="button" onclick={() => player.next()} aria-label="Siguiente" class={sideClass}>
<svg width="16" height="14" viewBox="0 0 16 14" fill="currentColor"> <svg width="16" height="14" viewBox="0 0 16 14" fill="currentColor">
@@ -24,10 +24,10 @@
<a <a
href={target.url} href={target.url}
{onclick} {onclick}
class="group inline-flex items-center text-fg-3 transition-colors hover:text-accent-soft" class="inline-flex items-center text-fg-3 transition-colors hover:text-accent-soft"
> >
<span class="grid h-8 w-8 place-items-center transition-colors group-hover:text-accent-soft"> <span class="grid size-8 place-items-center">
<ArrowLeft class="h-4 w-4" /> <ArrowLeft class="size-icon-sm" />
</span> </span>
{target.label} {target.label}
</a> </a>
@@ -3,7 +3,7 @@
import LoaderCircle from '@lucide/svelte/icons/loader-circle'; import LoaderCircle from '@lucide/svelte/icons/loader-circle';
interface Props { interface Props {
variant?: 'primary' | 'secondary' | 'secondaryOnGlow' | 'accent' | 'danger'; variant?: 'primary' | 'secondary' | 'glass' | 'accent' | 'strong' | 'danger';
size?: 'sm' | 'md' | 'lg'; size?: 'sm' | 'md' | 'lg';
type?: 'button' | 'submit'; type?: 'button' | 'submit';
href?: string; href?: string;
@@ -34,21 +34,20 @@
lg: 'px-6 py-3.5 text-sm' lg: 'px-6 py-3.5 text-sm'
}; };
const subtleButton = const subtle = 'bg-btn text-fg-2 hover:bg-btn-hover hover:text-fg';
'bg-[var(--mf-btn-bg)] text-fg-2 hover:bg-[var(--mf-btn-bg-hover)] hover:text-fg'; const glass = 'font-normal bg-btn-glass text-fg-2 hover:bg-btn-glass-hover hover:text-fg';
const subtleButtonOnGlow =
'bg-[var(--mf-btn-secondary-bg)] text-fg-2 hover:bg-[var(--mf-btn-secondary-bg-hover)] hover:text-fg';
const variants = { const variants = {
primary: subtleButton, primary: subtle,
secondary: subtleButton, secondary: subtle,
secondaryOnGlow: subtleButtonOnGlow, glass,
accent: 'bg-accent-btn text-accent-soft hover:bg-accent-btn-hover', accent: 'bg-accent-btn text-accent-soft hover:bg-accent-btn-hover',
strong: 'bg-cta-strong text-ink hover:brightness-95',
danger: 'bg-danger text-on-art hover:brightness-110' danger: 'bg-danger text-on-art hover:brightness-110'
}; };
const classes = $derived( const classes = $derived(
`inline-flex items-center justify-center gap-2 rounded-xl 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 rounded-control 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}`
); );
</script> </script>
@@ -4,8 +4,14 @@
interface Props { interface Props {
label: string; label: string;
type?: 'button' | 'submit'; type?: 'button' | 'submit';
size?: 'sm' | 'md'; size?: 'xs' | 'sm' | 'md' | 'lg';
shape?: 'square' | 'round';
tone?: 'muted' | 'subtle' | 'plain';
pressed?: boolean;
surface?: boolean;
revealOnHover?: boolean; revealOnHover?: boolean;
href?: string;
reload?: boolean;
onclick?: (event: MouseEvent) => void; onclick?: (event: MouseEvent) => void;
class?: string; class?: string;
children: Snippet; children: Snippet;
@@ -14,26 +20,55 @@
let { let {
label, label,
type = 'button', type = 'button',
size = 'md', size = 'sm',
shape = 'square',
tone = 'muted',
pressed,
surface = false,
revealOnHover = false, revealOnHover = false,
href,
reload = false,
onclick, onclick,
class: klass = '', class: klass = '',
children children
}: Props = $props(); }: Props = $props();
const sizes = { sm: 'h-7 w-7', md: 'h-8 w-8' }; const SIZE: Record<'xs' | 'sm' | 'md' | 'lg', string> = {
xs: 'size-7',
sm: 'size-8',
md: 'size-9',
lg: 'size-10'
};
const TEXT: Record<'muted' | 'subtle' | 'plain', string> = {
muted: 'text-muted hover:text-fg',
subtle: 'text-fg-2 hover:text-fg',
plain: 'text-fg-2 hover:text-fg'
};
const background = $derived(
surface ? 'bg-surface-2 hover:bg-surface-hover' : tone === 'plain' ? '' : 'hover:bg-hover'
);
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[tone]} ${background} ${
revealOnHover ? 'sm:opacity-0 sm:group-hover:opacity-100 sm:focus-visible:opacity-100' : ''
} ${klass}`
);
</script> </script>
<button {#if href}
{type} <a
{onclick} {href}
data-sveltekit-reload={reload ? '' : undefined}
aria-label={label} aria-label={label}
title={label} title={label}
class="grid place-items-center rounded-control text-muted transition hover:bg-hover hover:text-fg focus-visible:bg-hover focus-visible:text-fg focus-visible:ring-2 focus-visible:ring-accent focus-visible:outline-none {sizes[ class={classes}
size >
]} {revealOnHover
? 'sm:opacity-0 sm:group-hover:opacity-100 sm:focus-visible:opacity-100'
: ''} {klass}"
>
{@render children()} {@render children()}
</button> </a>
{:else}
<button {type} {onclick} aria-label={label} title={label} aria-pressed={pressed} class={classes}>
{@render children()}
</button>
{/if}
@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import Play from '@lucide/svelte/icons/play';
import Artwork from './Artwork.svelte'; import Artwork from './Artwork.svelte';
import PlayButton from './PlayButton.svelte';
import { player } from '$lib/player/player.svelte'; import { player } from '$lib/player/player.svelte';
import { queueItemForTarget } from '$lib/tracks'; import { queueItemForTarget } from '$lib/tracks';
import { mixItemTarget, type Mix } from '$lib/mixes'; import { mixItemTarget, type Mix } from '$lib/mixes';
@@ -36,14 +36,13 @@
<div <div
class="pointer-events-none absolute inset-0 bg-linear-to-b from-transparent from-45% to-scrim/40" class="pointer-events-none absolute inset-0 bg-linear-to-b from-transparent from-45% to-scrim/40"
></div> ></div>
<button <PlayButton
type="button" variant="glass"
size="sm"
onclick={play} onclick={play}
aria-label="Reproducir {mix.title}" label="Reproducir {mix.title}"
class="absolute right-2.5 bottom-2.5 grid h-9.5 w-9.5 place-items-center rounded-full border border-on-art/12 bg-ink/76 text-fg opacity-0 backdrop-blur transition-opacity duration-150 group-hover/tile:opacity-100" class="absolute right-2.5 bottom-2.5 opacity-0 transition-opacity duration-150 group-hover/tile:opacity-100"
> />
<Play class="h-3.5 w-3.5" fill="currentColor" />
</button>
</Artwork> </Artwork>
<div class="mt-3.25 truncate text-sm font-semibold text-fg"> <div class="mt-3.25 truncate text-sm font-semibold text-fg">
{mix.title} {mix.title}
@@ -0,0 +1,59 @@
<script lang="ts">
interface Props {
playing?: boolean;
size?: 'sm' | 'md' | 'lg';
variant?: 'strong' | 'glass';
label: string;
onclick?: (event: MouseEvent) => void;
as?: 'button' | 'span';
class?: string;
}
let {
playing = false,
size = 'md',
variant = 'strong',
label,
onclick,
as = 'button',
class: klass = ''
}: Props = $props();
const SIZE: Record<'sm' | 'md' | 'lg', string> = {
sm: 'size-9.5',
md: 'size-10',
lg: 'size-11.5'
};
const VARIANT: Record<'strong' | 'glass', string> = {
strong: 'bg-cta-strong text-ink hover:brightness-95',
glass: 'border border-on-art/12 bg-ink/76 text-fg backdrop-blur'
};
const classes = $derived(
`grid shrink-0 place-items-center rounded-full transition duration-150 ${SIZE[size]} ${VARIANT[variant]} ${klass}`
);
</script>
{#snippet icon()}
{#if playing}
<svg width="15" height="15" viewBox="0 0 15 15" fill="currentColor">
<rect x="3" y="1" width="3" height="13" rx="1" />
<rect x="9" y="1" width="3" height="13" rx="1" />
</svg>
{:else}
<svg width="15" height="15" viewBox="0 0 15 15" fill="currentColor">
<path d="M3 1.5v12l10-6z" />
</svg>
{/if}
{/snippet}
{#if as === 'span'}
<span aria-hidden="true" class={classes}>
{@render icon()}
</span>
{:else}
<button type="button" {onclick} aria-label={label} class={classes}>
{@render icon()}
</button>
{/if}
@@ -54,7 +54,7 @@
update()} update()}
> >
<input type="hidden" name="trackId" value={track.id} /> <input type="hidden" name="trackId" value={track.id} />
<IconButton type="submit" label="Quitar del álbum" size="sm" revealOnHover> <IconButton type="submit" label="Quitar del álbum" size="xs" revealOnHover>
<X class="h-3.5 w-3.5" /> <X class="h-3.5 w-3.5" />
</IconButton> </IconButton>
</form> </form>
@@ -55,7 +55,7 @@
update()} update()}
> >
<input type="hidden" name="trackId" value={track.id} /> <input type="hidden" name="trackId" value={track.id} />
<IconButton type="submit" label="Añadir al álbum" size="sm" revealOnHover> <IconButton type="submit" label="Añadir al álbum" size="xs" revealOnHover>
<Plus class="h-3.5 w-3.5" /> <Plus class="h-3.5 w-3.5" />
</IconButton> </IconButton>
</form> </form>
@@ -1,6 +1,5 @@
<script lang="ts"> <script lang="ts">
import Music from '@lucide/svelte/icons/music'; import Music from '@lucide/svelte/icons/music';
import Play from '@lucide/svelte/icons/play';
import { player } from '$lib/player/player.svelte'; import { player } from '$lib/player/player.svelte';
import { fetchAlbumQueueItems } from '$lib/albums'; import { fetchAlbumQueueItems } from '$lib/albums';
import { fmtTime, fmtPlays } from '$lib/format'; import { fmtTime, fmtPlays } from '$lib/format';
@@ -11,6 +10,7 @@
import InfiniteScroll from '$lib/components/ui/InfiniteScroll.svelte'; import InfiniteScroll from '$lib/components/ui/InfiniteScroll.svelte';
import Artwork from '$lib/components/ui/Artwork.svelte'; import Artwork from '$lib/components/ui/Artwork.svelte';
import Avatar from '$lib/components/ui/Avatar.svelte'; import Avatar from '$lib/components/ui/Avatar.svelte';
import PlayButton from '$lib/components/ui/PlayButton.svelte';
import NowPlaying from '$lib/components/ui/NowPlaying.svelte'; import NowPlaying from '$lib/components/ui/NowPlaying.svelte';
import SearchResultRow from '$lib/components/ui/SearchResultRow.svelte'; import SearchResultRow from '$lib/components/ui/SearchResultRow.svelte';
import SectionHeading from '$lib/components/ui/SectionHeading.svelte'; import SectionHeading from '$lib/components/ui/SectionHeading.svelte';
@@ -339,11 +339,7 @@
{/if} {/if}
</div> </div>
<span <PlayButton as="span" size="lg" label="Reproducir" class="group-hover/top:brightness-110" />
class="grid h-11.5 w-11.5 shrink-0 place-items-center rounded-full bg-cta-strong text-ink transition group-hover/top:brightness-110"
>
<Play class="h-4 w-4" fill="currentColor" strokeWidth={0} />
</span>
{/snippet} {/snippet}
{#if topResult.kind === 'track'} {#if topResult.kind === 'track'}
@@ -84,7 +84,7 @@
update()} update()}
> >
<input type="hidden" name="trackId" value={track.id} /> <input type="hidden" name="trackId" value={track.id} />
<IconButton type="submit" label="Borrar canción" size="sm" revealOnHover> <IconButton type="submit" label="Borrar canción" size="xs" revealOnHover>
<X class="h-3.5 w-3.5" /> <X class="h-3.5 w-3.5" />
</IconButton> </IconButton>
</form> </form>
@@ -98,7 +98,7 @@
<TrackMeta>{fmtTime(Number(track.duration))}</TrackMeta> <TrackMeta>{fmtTime(Number(track.duration))}</TrackMeta>
<IconButton <IconButton
label="Quitar de Me gusta" label="Quitar de Me gusta"
size="sm" size="xs"
revealOnHover revealOnHover
onclick={() => liked.toggle(track)} onclick={() => liked.toggle(track)}
> >
@@ -62,7 +62,7 @@
update()} update()}
> >
<input type="hidden" name="trackId" value={track.id} /> <input type="hidden" name="trackId" value={track.id} />
<IconButton type="submit" label="Quitar de la playlist" size="sm" revealOnHover> <IconButton type="submit" label="Quitar de la playlist" size="xs" revealOnHover>
<X class="h-3.5 w-3.5" /> <X class="h-3.5 w-3.5" />
</IconButton> </IconButton>
</form> </form>
+3 -9
View File
@@ -150,18 +150,12 @@
</p> </p>
<div class="mt-6.5 flex flex-wrap items-center gap-2.5"> <div class="mt-6.5 flex flex-wrap items-center gap-2.5">
{#if spotlight} {#if spotlight}
<Button <Button variant="strong" onclick={playSpotlight}>
variant="accent"
class="!bg-cta-strong !text-ink hover:!brightness-95"
onclick={playSpotlight}
>
{heroPlaying ? 'Pausar' : 'Reanudar'} {heroPlaying ? 'Pausar' : 'Reanudar'}
{spotlight.name} {spotlight.name}
</Button> </Button>
{/if} {/if}
<Button href="/explore" variant="secondaryOnGlow" class="!font-normal" <Button href="/explore" variant="glass">Explorar música</Button>
>Explorar música</Button
>
</div> </div>
</div> </div>
@@ -274,7 +268,7 @@
</p> </p>
<div class="mt-5 flex gap-2.5"> <div class="mt-5 flex gap-2.5">
<Button variant="accent" onclick={playSpotlight}>Reproducir</Button> <Button variant="accent" onclick={playSpotlight}>Reproducir</Button>
<Button variant="secondaryOnGlow" onclick={shuffleSpotlight}>Aleatorio</Button> <Button variant="glass" onclick={shuffleSpotlight}>Aleatorio</Button>
</div> </div>
</div> </div>
<div class="flex flex-col gap-0.5 p-5.5 sm:p-6"> <div class="flex flex-col gap-0.5 p-5.5 sm:p-6">