Align song details typography and cards

codex/redisenio-dominio-musical
dev 4 weeks ago
parent ac0119a16d
commit 94dcf2eea5

@ -166,6 +166,50 @@ test.describe('Página de música', () => {
await expect(favorito.locator('svg')).toHaveAttribute('width', '28');
await expect(lista.locator('svg')).toHaveAttribute('width', '28');
});
test('la letra y las tarjetas de la ficha comparten retícula y tipografía de interfaz', async ({
page
}) => {
await page.goto('/canciones/ton-silence-me-libere');
const filaPestanas = page.getByRole('tablist', { name: 'Contenido del tema' });
const ficha = page.locator('aside.lateral');
const tituloFicha = ficha.getByRole('heading', { name: 'Ficha' });
const cajaPestanas = await filaPestanas.boundingBox();
const cajaFicha = await tituloFicha.boundingBox();
expect(cajaPestanas).not.toBeNull();
expect(cajaFicha).not.toBeNull();
expect(
Math.abs(
(cajaPestanas?.y ?? 0) +
(cajaPestanas?.height ?? 0) -
((cajaFicha?.y ?? 0) + (cajaFicha?.height ?? 0))
)
).toBeLessThan(2);
const familiaPestana = await filaPestanas
.getByRole('tab', { name: 'Letra' })
.evaluate((elemento) => getComputedStyle(elemento).fontFamily);
const familiaFicha = await tituloFicha.evaluate(
(elemento) => getComputedStyle(elemento).fontFamily
);
const familiaLetra = await page
.locator('.texto.versos')
.evaluate((elemento) => getComputedStyle(elemento).fontFamily);
expect(familiaFicha).toBe(familiaPestana);
expect(familiaLetra).not.toBe(familiaFicha);
await expect(filaPestanas.getByRole('tab', { name: 'Letra' })).toHaveCSS('font-size', '15px');
await expect(tituloFicha).toHaveCSS('font-size', '15px');
await expect(ficha.locator('dl').first()).toHaveCSS('font-size', '15px');
const tarjetas = ficha.locator('section.bloque');
expect(await tarjetas.count()).toBeGreaterThanOrEqual(2);
for (const tarjeta of await tarjetas.all()) {
await expect(tarjeta).toHaveCSS('border-top-style', 'solid');
await expect(tarjeta).toHaveCSS('overflow', 'hidden');
}
});
});
test.describe('Etiquetas', () => {

@ -1,8 +1,8 @@
<script lang="ts">
/**
* La columna de datos de un tema: valoración, ficha, créditos y registro.
* La columna de datos de un tema: ficha, créditos y registro.
*
* Vive aparte porque son cuatro bloques de información y ninguno tiene que
* Vive aparte porque son bloques de información y ninguno tiene que
* ver con lo que hace la página —presentar la letra y dejarla sonar—. Con
* ellos dentro, la ficha pasaba de las setecientas líneas y había que
* recorrerla entera para tocar cualquier cosa.
@ -54,93 +54,97 @@
-->
<section class="bloque">
<h2>Ficha</h2>
<dl>
{#if album}
<dt>{album.sintetico ? 'Publicación' : 'Álbum'}</dt>
<dd>
<a href={resolve('/(sitio)/albumes/[slug]', { slug: album.slug })}>
{album.sintetico ? 'Single suelto' : album.titulo}
</a>
</dd>
{#if !album.sintetico && cancion.numero !== null}
<dt>Pista</dt>
<dd>{cancion.numero} de {album.canciones.length}</dd>
<div class="contenido-bloque">
<dl>
{#if album}
<dt>{album.sintetico ? 'Publicación' : 'Álbum'}</dt>
<dd>
<a href={resolve('/(sitio)/albumes/[slug]', { slug: album.slug })}>
{album.sintetico ? 'Single suelto' : album.titulo}
</a>
</dd>
{#if !album.sintetico && cancion.numero !== null}
<dt>Pista</dt>
<dd>{cancion.numero} de {album.canciones.length}</dd>
{/if}
{/if}
{#if cancion.ano}
<dt>Año</dt>
<dd>{cancion.ano}</dd>
{/if}
{#if cancion.duracion}
<dt>Duración</dt>
<dd>{segundosADuracion(cancion.duracion)}</dd>
{/if}
{#if cancion.tieneLetra}
<dt>Idioma</dt>
<dd title={cancion.idioma}>{nombreDeIdioma(cancion.idioma)}</dd>
{/if}
{#if cancion.formacionVocal}
<dt>Voces</dt>
<dd>{NOMBRES_FORMACION_VOCAL[cancion.formacionVocal]}</dd>
{/if}
<dt>Acceso de escucha</dt>
<dd>{NOMBRES_ACCESO_CANCION[cancion.acceso]}</dd>
{#if cancion.versiones.length > 0}
<dt>Versiones</dt>
<dd>{cancion.versiones.length + 1}</dd>
{/if}
{#if estilo}
<dt>Estilo</dt>
<dd>
<a href={resolve('/(sitio)/musica/[estilo]', { estilo: estilo.slug })}>
{estilo.nombre}
</a>
</dd>
{/if}
<!-- Las etiquetas van arriba, junto al titulo: ver `canciones/[slug]`. -->
{#if album?.sello}
<dt>Sello</dt>
<dd>{album.sello}</dd>
{/if}
{/if}
{#if cancion.ano}
<dt>Año</dt>
<dd>{cancion.ano}</dd>
{/if}
{#if cancion.duracion}
<dt>Duración</dt>
<dd>{segundosADuracion(cancion.duracion)}</dd>
{/if}
{#if cancion.tieneLetra}
<dt>Idioma</dt>
<dd title={cancion.idioma}>{nombreDeIdioma(cancion.idioma)}</dd>
{/if}
{#if cancion.formacionVocal}
<dt>Voces</dt>
<dd>{NOMBRES_FORMACION_VOCAL[cancion.formacionVocal]}</dd>
{/if}
<dt>Acceso de escucha</dt>
<dd>{NOMBRES_ACCESO_CANCION[cancion.acceso]}</dd>
{#if cancion.versiones.length > 0}
<dt>Versiones</dt>
<dd>{cancion.versiones.length + 1}</dd>
{/if}
{#if estilo}
<dt>Estilo</dt>
<dd>
<a href={resolve('/(sitio)/musica/[estilo]', { estilo: estilo.slug })}>
{estilo.nombre}
</a>
</dd>
{/if}
<!-- Las etiquetas van arriba, junto al titulo: ver `canciones/[slug]`. -->
{#if album?.sello}
<dt>Sello</dt>
<dd>{album.sello}</dd>
{/if}
</dl>
</dl>
</div>
</section>
<section class="bloque">
<h2>Créditos</h2>
<dl>
{#if cancion.tieneLetra}
<dt>Letra</dt>
<dd>{listaDeNombres(cancion.letra)}</dd>
{/if}
<dt>Música</dt>
<dd>{listaDeNombres(cancion.musica)}</dd>
{#if cancion.interpretes.length > 0}
<dt>Interpretación</dt>
<dd>
{#each cancion.interpretes as interprete, i (interprete.id + interprete.rol)}
{#if i > 0},
{/if}
{#if interprete.slug}
<a href={resolve('/(sitio)/interpretes/[slug]', { slug: interprete.slug })}
>{interprete.nombre}</a
>
{:else}
{interprete.nombre}
{/if}
{/each}
</dd>
{/if}
</dl>
<div class="contenido-bloque">
<dl>
{#if cancion.tieneLetra}
<dt>Letra</dt>
<dd>{listaDeNombres(cancion.letra)}</dd>
{/if}
<dt>Música</dt>
<dd>{listaDeNombres(cancion.musica)}</dd>
{#if cancion.interpretes.length > 0}
<dt>Interpretación</dt>
<dd>
{#each cancion.interpretes as interprete, i (interprete.id + interprete.rol)}
{#if i > 0},
{/if}
{#if interprete.slug}
<a href={resolve('/(sitio)/interpretes/[slug]', { slug: interprete.slug })}
>{interprete.nombre}</a
>
{:else}
{interprete.nombre}
{/if}
{/each}
</dd>
{/if}
</dl>
</div>
</section>
{#if hayRegistro}
@ -152,41 +156,43 @@
-->
<section class="bloque">
<h2>Registro</h2>
<dl>
{#if registro.iswc}
<dt title="Identifica la obra, la misma en todas sus versiones">ISWC</dt>
<dd class="codigo">{registro.iswc}</dd>
{/if}
{#if registro.isrc}
<dt title="Identifica esta grabación en concreto">ISRC</dt>
<dd class="codigo">{registro.isrc}</dd>
{/if}
{#if registro.entidad}
<dt>Entidad</dt>
<dd>
{registro.entidad}{#if registro.numero}<span class="muted"
>&nbsp;·&nbsp;{registro.numero}</span
>{/if}
</dd>
{/if}
{#if registro.editorial}
<dt>Editorial</dt>
<dd>{registro.editorial}</dd>
{/if}
</dl>
<div class="contenido-bloque">
<dl>
{#if registro.iswc}
<dt title="Identifica la obra, la misma en todas sus versiones">ISWC</dt>
<dd class="codigo">{registro.iswc}</dd>
{/if}
{#if registro.isrc}
<dt title="Identifica esta grabación en concreto">ISRC</dt>
<dd class="codigo">{registro.isrc}</dd>
{/if}
{#if registro.entidad}
<dt>Entidad</dt>
<dd>
{registro.entidad}{#if registro.numero}<span class="muted"
>&nbsp;·&nbsp;{registro.numero}</span
>{/if}
</dd>
{/if}
{#if registro.editorial}
<dt>Editorial</dt>
<dd>{registro.editorial}</dd>
{/if}
</dl>
{#if registro.reparto.length > 0}
<p class="subtitulo">Reparto de autoría</p>
<ul class="reparto">
{#each registro.reparto as parte (parte.nombre + parte.rol)}
<li>
<span class="quien">{parte.nombre}</span>
<span class="rol muted">{etiquetasRol[parte.rol] ?? parte.rol}</span>
<span class="parte">{parte.porcentaje} %</span>
</li>
{/each}
</ul>
{/if}
{#if registro.reparto.length > 0}
<p class="subtitulo">Reparto de autoría</p>
<ul class="reparto">
{#each registro.reparto as parte (parte.nombre + parte.rol)}
<li>
<span class="quien">{parte.nombre}</span>
<span class="rol muted">{etiquetasRol[parte.rol] ?? parte.rol}</span>
<span class="parte">{parte.porcentaje} %</span>
</li>
{/each}
</ul>
{/if}
</div>
</section>
{/if}
</aside>
@ -195,19 +201,34 @@
.lateral {
display: flex;
flex-direction: column;
gap: var(--sp-5);
gap: var(--sp-4);
}
.bloque {
overflow: hidden;
border: 1px solid var(--c-border);
border-radius: var(--radius-tarjeta);
background: var(--c-bg-raised);
}
h2 {
font-size: var(--fs-lg);
margin-bottom: var(--sp-2);
padding-bottom: var(--sp-2);
margin: 0;
padding: var(--sp-2) var(--sp-3);
border-bottom: 1px solid var(--c-border);
font-family: var(--font-body);
font-size: var(--boton-texto);
font-weight: 600;
line-height: 1.2;
letter-spacing: 0;
}
.contenido-bloque {
padding: var(--sp-3);
}
dl {
margin: 0;
font-size: var(--fs-sm);
font-size: var(--boton-texto);
}
dt {

@ -176,7 +176,8 @@
padding: var(--sp-2) var(--sp-3);
border: none;
background: none;
font-size: var(--fs-sm);
font-size: var(--boton-texto);
line-height: 1.2;
color: var(--c-text-muted);
cursor: pointer;
white-space: nowrap;

@ -107,7 +107,8 @@
.media {
margin: 0;
font-size: var(--fs-lg);
font-family: var(--font-display);
font-family: var(--font-body);
font-variant-numeric: tabular-nums;
color: var(--c-accent);
}

Loading…
Cancel
Save

Powered by TurnKey Linux.