diff --git a/web-player/docs/frontend-refactor-plan.md b/web-player/docs/frontend-refactor-plan.md index 502a994..ec32700 100644 --- a/web-player/docs/frontend-refactor-plan.md +++ b/web-player/docs/frontend-refactor-plan.md @@ -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) | | P2 | ✅ | (pendiente) | `` no interpola en Svelte (se trata como CSS del componente); solución: `{@html \`\`}` | | 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 | ⬜ | | | | P6 | ⬜ | | | | P7 | ⬜ | | | diff --git a/web-player/src/lib/components/MobileHeader.svelte b/web-player/src/lib/components/MobileHeader.svelte index ae1c0c5..d232195 100644 --- a/web-player/src/lib/components/MobileHeader.svelte +++ b/web-player/src/lib/components/MobileHeader.svelte @@ -6,6 +6,7 @@ import MenuItem from './ui/MenuItem.svelte'; import AccountMenu from './ui/AccountMenu.svelte'; import Avatar from './ui/Avatar.svelte'; + import IconButton from './ui/IconButton.svelte'; interface Props { user: SessionUser | null; @@ -50,14 +51,9 @@ {/snippet} {:else} - - - + + + {/if} diff --git a/web-player/src/lib/components/Sidebar.svelte b/web-player/src/lib/components/Sidebar.svelte index 8824a7b..223f487 100644 --- a/web-player/src/lib/components/Sidebar.svelte +++ b/web-player/src/lib/components/Sidebar.svelte @@ -5,6 +5,7 @@ import { createPlaylistModal } from '$lib/playlists.svelte'; import type { SessionUser } from '$lib/types'; import Artwork from './ui/Artwork.svelte'; + import IconButton from './ui/IconButton.svelte'; import Home from '@lucide/svelte/icons/house'; import Compass from '@lucide/svelte/icons/compass'; import ListMusic from '@lucide/svelte/icons/list-music'; @@ -77,14 +78,14 @@
Tus playlists {#if playlists.length > 0} - + + {/if}
diff --git a/web-player/src/lib/components/TopBar.svelte b/web-player/src/lib/components/TopBar.svelte index 12566e6..b5241e7 100644 --- a/web-player/src/lib/components/TopBar.svelte +++ b/web-player/src/lib/components/TopBar.svelte @@ -6,9 +6,10 @@ import Search from '@lucide/svelte/icons/search'; import X from '@lucide/svelte/icons/x'; import ChevronLeft from '@lucide/svelte/icons/chevron-left'; - import ChevronRight from '@lucide/svelte/icons/chevron-right'; import AccountMenu from './ui/AccountMenu.svelte'; import Avatar from './ui/Avatar.svelte'; + import IconButton from './ui/IconButton.svelte'; + import Button from './ui/Button.svelte'; interface Props { user: SessionUser | null; @@ -56,24 +57,18 @@ diff --git a/web-player/src/lib/components/player/PlayerExtras.svelte b/web-player/src/lib/components/player/PlayerExtras.svelte index 800d3cb..e0d3731 100644 --- a/web-player/src/lib/components/player/PlayerExtras.svelte +++ b/web-player/src/lib/components/player/PlayerExtras.svelte @@ -1,22 +1,19 @@ - {#if !compact} - + + {/if} diff --git a/web-player/src/lib/components/player/TransportControls.svelte b/web-player/src/lib/components/player/TransportControls.svelte index 326078e..7d00594 100644 --- a/web-player/src/lib/components/player/TransportControls.svelte +++ b/web-player/src/lib/components/player/TransportControls.svelte @@ -1,5 +1,6 @@ diff --git a/web-player/src/lib/components/ui/IconButton.svelte b/web-player/src/lib/components/ui/IconButton.svelte index 8cc0555..ee60492 100644 --- a/web-player/src/lib/components/ui/IconButton.svelte +++ b/web-player/src/lib/components/ui/IconButton.svelte @@ -4,8 +4,14 @@ interface Props { label: string; type?: 'button' | 'submit'; - size?: 'sm' | 'md'; + size?: 'xs' | 'sm' | 'md' | 'lg'; + shape?: 'square' | 'round'; + tone?: 'muted' | 'subtle' | 'plain'; + pressed?: boolean; + surface?: boolean; revealOnHover?: boolean; + href?: string; + reload?: boolean; onclick?: (event: MouseEvent) => void; class?: string; children: Snippet; @@ -14,26 +20,55 @@ let { label, type = 'button', - size = 'md', + size = 'sm', + shape = 'square', + tone = 'muted', + pressed, + surface = false, revealOnHover = false, + href, + reload = false, onclick, class: klass = '', children }: 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}` + ); - +{#if href} + + {@render children()} + +{:else} + +{/if} diff --git a/web-player/src/lib/components/ui/MixTile.svelte b/web-player/src/lib/components/ui/MixTile.svelte index 591d6b7..e2c586d 100644 --- a/web-player/src/lib/components/ui/MixTile.svelte +++ b/web-player/src/lib/components/ui/MixTile.svelte @@ -1,6 +1,6 @@ + +{#snippet icon()} + {#if playing} + + + + + {:else} + + + + {/if} +{/snippet} + +{#if as === 'span'} + +{:else} + +{/if} diff --git a/web-player/src/routes/(app)/albums/[id]/components/AlbumTrackTable.svelte b/web-player/src/routes/(app)/albums/[id]/components/AlbumTrackTable.svelte index 12bc291..e9e5e4b 100644 --- a/web-player/src/routes/(app)/albums/[id]/components/AlbumTrackTable.svelte +++ b/web-player/src/routes/(app)/albums/[id]/components/AlbumTrackTable.svelte @@ -54,7 +54,7 @@ update()} > - + diff --git a/web-player/src/routes/(app)/albums/[id]/components/LibraryPicker.svelte b/web-player/src/routes/(app)/albums/[id]/components/LibraryPicker.svelte index 12994da..5281c8e 100644 --- a/web-player/src/routes/(app)/albums/[id]/components/LibraryPicker.svelte +++ b/web-player/src/routes/(app)/albums/[id]/components/LibraryPicker.svelte @@ -55,7 +55,7 @@ update()} > - + diff --git a/web-player/src/routes/(app)/explore/+page.svelte b/web-player/src/routes/(app)/explore/+page.svelte index 599a1e4..5329697 100644 --- a/web-player/src/routes/(app)/explore/+page.svelte +++ b/web-player/src/routes/(app)/explore/+page.svelte @@ -1,6 +1,5 @@