Show style and tags in song rows

codex/redisenio-dominio-musical
dev 4 weeks ago
parent 38fc78aa9a
commit 3789442b3d

@ -30,10 +30,28 @@ test.describe('Reproductor', () => {
await page.goto(album);
const fila = page.getByRole('row').filter({ hasText: 'Ton silence me libère' });
const titulo = fila.getByRole('link', { name: 'Ton silence me libère', exact: true });
const estilo = fila.getByRole('link', { name: 'Baladas románticas', exact: true });
const etiquetas = fila.getByRole('list', { name: 'Etiquetas de Ton silence me libère' });
await expect(estilo).toBeVisible();
await expect(etiquetas).toBeVisible();
const alturas = await fila.evaluate((elemento) => {
const caja = (selector: string) => elemento.querySelector(selector)!.getBoundingClientRect();
return {
titulo: caja('.titulo').top,
estilo: caja('.clasificacion').top,
etiquetas: caja('.senas').top
};
});
expect(alturas.estilo).toBeGreaterThan(alturas.titulo);
expect(alturas.etiquetas).toBeGreaterThan(alturas.estilo);
await fila.getByRole('button', { name: 'Reproducir Ton silence me libère' }).click();
const barra = page.getByRole('region', { name: 'Reproductor' });
await expect(barra).toBeVisible();
await expect(titulo).toBeVisible();
await expect(temaEnBarra(page, 'ton-silence-me-libere')).toBeVisible();
await expect(fila.getByRole('button', { name: 'Pausar' })).toBeVisible();
});

@ -324,34 +324,51 @@
{/if}
<th scope="row">
<a class="titulo" href={resolve('/(sitio)/canciones/[slug]', { slug: c.slug })}>{c.titulo}</a>
<a class="titulo" href={resolve('/(sitio)/canciones/[slug]', { slug: c.slug })}
>{c.titulo}</a
>
<!--
De qué está hecho el tema, no su primer verso: la letra está
entera en la ficha, y aquí lo que sirve para elegir es el género
y las etiquetas.
Primero la clasificación musical y, en otra línea, las etiquetas.
Si el tema aún no tiene un género concreto usamos su estilo: así
la fila nunca pierde ese dato y las etiquetas no parecen géneros.
-->
<div class="senas">
{#if c.instrumental}
<span class="marca">Instrumental</span>
{/if}
{#each c.generos as g (g.slug)}
<a class="genero" href={resolve('/(sitio)/generos/[slug]', { slug: g.slug })}>
{g.nombre}
</a>
{/each}
<Etiquetas
etiquetas={c.etiquetas.slice(0, CUANTAS_ETIQUETAS)}
titulo="Etiquetas de {c.titulo}"
menudas
/>
{#if c.etiquetas.length > CUANTAS_ETIQUETAS}
<span class="mas muted">+{c.etiquetas.length - CUANTAS_ETIQUETAS}</span>
{/if}
{#if c.generos.length === 0 && c.etiquetas.length === 0}
<span class="muted sin">{listaDeNombres(c.interpretes.map((i) => i.nombre))}</span
>
{/if}
</div>
{#if c.generos.length > 0 || fila.estilo || c.interpretes.length > 0}
<div class="clasificacion">
<span class="visually-hidden">
{c.generos.length > 0 ? 'Género:' : fila.estilo ? 'Estilo:' : 'Intérprete:'}
</span>
{#if c.generos.length > 0}
{#each c.generos as g, indice (g.slug)}
{#if indice > 0}<span aria-hidden="true">·</span>{/if}
<a href={resolve('/(sitio)/generos/[slug]', { slug: g.slug })}>
{g.nombre}
</a>
{/each}
{:else if fila.estilo}
<a href={resolve('/(sitio)/musica/[estilo]', { estilo: fila.estilo.slug })}>
{fila.estilo.nombre}
</a>
{:else}
<span>{listaDeNombres(c.interpretes.map((i) => i.nombre))}</span>
{/if}
</div>
{/if}
{#if c.instrumental || c.etiquetas.length > 0}
<div class="senas">
{#if c.instrumental}
<span class="marca">Instrumental</span>
{/if}
<Etiquetas
etiquetas={c.etiquetas.slice(0, CUANTAS_ETIQUETAS)}
titulo="Etiquetas de {c.titulo}"
menudas
/>
{#if c.etiquetas.length > CUANTAS_ETIQUETAS}
<span class="mas muted">+{c.etiquetas.length - CUANTAS_ETIQUETAS}</span>
{/if}
</div>
{/if}
</th>
{#each visibles as columna (columna.campo)}
@ -556,20 +573,31 @@
background: var(--c-bg-sunken);
}
/*
* En una línea y sin envolver: en una lista de diez temas, una fila que crece
* porque su canción tiene una etiqueta más rompe el ritmo de todas. Lo que no
* cabe se recorta con el degradado del final.
*/
/*
* En una línea: en una tabla de treinta temas, una fila que crece porque su
* canción tiene una etiqueta más rompe el ritmo de todas.
*/
.clasificacion {
display: flex;
align-items: center;
gap: 0.45em;
margin-top: 0.15rem;
font-size: var(--fs-xs);
line-height: 1.25;
color: var(--c-text-muted);
}
.clasificacion a {
color: inherit;
}
.clasificacion a:hover,
.clasificacion a:focus-visible {
color: var(--c-text);
}
/* En una línea: el número máximo impide que las etiquetas alteren la fila. */
.senas {
display: flex;
align-items: center;
gap: var(--sp-2);
margin-top: var(--sp-1);
margin-top: 0.3rem;
}
.mas {
@ -585,22 +613,6 @@
flex: none;
}
/* El género es del glosario, no del catálogo: se distingue con el oro. */
.genero {
padding: 0.1em 0.6em;
border: 1px solid var(--c-accent);
border-radius: var(--radius-boton);
font-size: 0.6875rem;
color: var(--c-accent);
white-space: nowrap;
}
.genero:hover,
.genero:focus-visible {
background: color-mix(in oklab, var(--c-accent) 14%, transparent);
}
.sin,
.marca {
font-size: 0.6875rem;
white-space: nowrap;

Loading…
Cancel
Save

Powered by TurnKey Linux.