Files
Musify/web-player/src/lib/components/ui/EmptyState.svelte
T
AdminandClaude Sonnet 5 2cf3e9f02d web-player: P10 — cabeceras, diálogos y tipografía
PageHeader fusiona CollectionHeader (title/eyebrow/description/meta/
cover?/actions?/align?): sin cover se comporta como el antiguo
PageHeader simple (acciones en línea), con cover como el antiguo
CollectionHeader (acciones debajo). Fija su propio margen inferior
(mb-7/8); se quitan los mt-* que ponía cada página después. Migra los
9 sitios que usaban uno u otro (álbumes, biblioteca, listas, subir,
Explorar ×2, me gusta, mezcla, perfil). CollectionHeader se borra.

AlbumHeader y PlaylistHeader se inlinean en sus páginas y se borran.
Decisión (recomendada, sin bloquear): PlaylistHeader gana iconos en
Editar/Eliminar/Reproducir, igual que ya tenía AlbumHeader.

ConfirmDialog nuevo sustituye los dos diálogos de borrado (álbum y
playlist), que tenían tipografías distintas. Modal pasa a usar
.glass-panel (en vez de duplicar el style= inline) y z-(--z-modal); su
eyebrow y título usan las recetas text-eyebrow/text-display-3.

SectionHeading gana `count?` (línea "N resultados", sustituye 4 copias
en Explorar) y `href?`/`linkLabel?` ("Ver todas", sustituye la de
Inicio). Aplica recetas de tipografía (text-display-2/3,
text-eyebrow, text-body) y tokens de ancho (max-w-prose-sm, max-w-hero)
en EmptyState, +error, "Sin resultados", hero y stats de Inicio, Queue
y Sidebar. El estado vacío "Todavía no has escuchado nada" (repetido
2 veces en Inicio) pasa a un snippet local.

Verificado con npm run check/build; sin QA visual autenticada (Docker
no disponible en esta sesión).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 00:48:23 +02:00

32 lines
815 B
Svelte

<script lang="ts">
import type { Snippet } from 'svelte';
import type { LucideIcon } from '@lucide/svelte';
interface Props {
icon?: LucideIcon;
title?: string;
description?: string;
class?: string;
actions?: Snippet;
}
let { icon: Icon, title, description, class: klass = '', actions }: Props = $props();
</script>
<div class="flex flex-col items-center rounded-panel px-6 py-16 text-center {klass}">
{#if Icon}
<Icon class="size-icon-xl text-fg-2" strokeWidth={1.25} />
{/if}
{#if title}
<h3 class="mt-6 text-display-3 text-fg">
{title}
</h3>
{/if}
{#if description}
<p class="mt-2.5 max-w-sm text-sm leading-relaxed text-fg-2">{description}</p>
{/if}
{#if actions}
<div class="mt-6 flex flex-wrap items-center justify-center gap-2.5">{@render actions()}</div>
{/if}
</div>