You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.2 KiB
90 lines
2.2 KiB
<script lang="ts" module>
|
|
import type { ResolvedPathname } from '$app/types';
|
|
|
|
/** Un escalón de la ruta. Sin `href` es el último: donde se está. */
|
|
export interface Miga {
|
|
texto: string;
|
|
href?: ResolvedPathname;
|
|
}
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
/**
|
|
* La ruta hasta la página actual.
|
|
*
|
|
* Estaba copiada en seis páginas, con el mismo marcado y el mismo CSS. Aquí
|
|
* se escribe una vez y se pasa la lista.
|
|
*
|
|
* Un par de decisiones que conviene no deshacer:
|
|
*
|
|
* - **Es una lista ordenada**, no una fila de enlaces sueltos. Un lector de
|
|
* pantalla anuncia cuántos escalones hay y en cuál va, que es justo la
|
|
* información que unas migas dan de un vistazo.
|
|
* - **El último no es enlace** y lleva `aria-current="page"`: no se enlaza a
|
|
* donde ya estás.
|
|
* - Las barras van en un pseudoelemento y no en el texto, para que no se
|
|
* lean ni se copien al seleccionar la ruta.
|
|
*/
|
|
interface Props {
|
|
migas: Miga[];
|
|
}
|
|
|
|
let { migas }: Props = $props();
|
|
</script>
|
|
|
|
<nav class="migas" aria-label="Ruta">
|
|
<ol>
|
|
<!--
|
|
La clave es la posición y no el texto: un disco y un tema pueden llamarse
|
|
igual —«Como si nada» es las dos cosas— y con el texto por clave Svelte
|
|
encuentra dos iguales y tumba la página al hidratar. Aquí una miga es un
|
|
escalón de la ruta, y lo que la identifica es dónde está.
|
|
-->
|
|
{#each migas as miga, i (i)}
|
|
<li>
|
|
{#if miga.href && i < migas.length - 1}
|
|
<a href={miga.href}>{miga.texto}</a>
|
|
{:else}
|
|
<span aria-current="page">{miga.texto}</span>
|
|
{/if}
|
|
</li>
|
|
{/each}
|
|
</ol>
|
|
</nav>
|
|
|
|
<style>
|
|
.migas {
|
|
padding-block: var(--sp-5) var(--sp-4);
|
|
font-size: var(--fs-sm);
|
|
color: var(--c-text-muted);
|
|
}
|
|
|
|
ol {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: var(--sp-2);
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
/* La barra la pone el CSS: no es texto, es un separador. */
|
|
li + li::before {
|
|
content: '/';
|
|
margin-right: var(--sp-2);
|
|
color: var(--c-text-muted);
|
|
}
|
|
|
|
a {
|
|
/* Alto suficiente para acertarle con el dedo sin cambiar el aspecto. */
|
|
display: inline-block;
|
|
padding-block: var(--sp-1);
|
|
text-decoration: none;
|
|
}
|
|
|
|
a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
</style>
|