Accordion accessible y reutilizable solo con la etiqueta details y css
Tags: webdev, a11y, typescript, programming
Published: 2024-03-04 17:51:42

Bienvenides a una nueva entrada de mi sección dedicada a realizar componentes reutilizables y, sobre todo, **accesibles**. En esta ocasión vamos a aprender cómo utilizar la etiqueta HTML **details** para realizar un accordion o acordión.

**Repositorio:** https://github.com/micaavigliano/accordion
**Proyecto:** https://accordion-five-sandy.vercel.app/

Para que nuestro accordion sea accesible debemos tener en cuenta los siguientes puntos:

- cuando el foco esta en el header del accordion debe poder colapsarse y expandirse presionando las teclas `enter` o `space`
- al presionar `tab` el foco se mueve al siguiente accordion o al siguiente elemento interactivo dentro del accordion
- al presionar `shift + tab` el foco se mueve al elemente interactivo anterior
- el screen reader o lector de pantalla debe anunciar el estado del elemento, es decir, si esta colapsado o expandido. También debe anunciar su nombre accesible.

La etiqueta `details` nos ayudará a pasar todos estos puntos, ya que de por sí es accesible de manera nativa.

## ¿Cómo utilizamos la etiqueta `details`?

La etiqueta `details` es una etiqueta nativa de HTML de estructura que se utiliza para crear un elemento que puedo ser expandido o colapsado. Dentro de esta etiqueta vamos a encontrar la etiqueta `summary` que se utiliza como encabezado que actúa como el control para expandir o colapsar el contenido. Por último, el contenido a mostrar se coloca después de la etiqueta `summary` y podrá ser cualquier elemento válido de HTML.

```
<details>
  <summary>Mostrar más</summary>
  <p>contenido</p>
</details>
```

{% codesandbox 6q82x6 %}

Ahora que ya aprendimos cómo se conforma y para qué sirve la etiqueta `details` vamos a realizar nuestro componente reutilizable.

Primero, vamos a hablar sobre las propiedades que el componente va a recibir:

```
interface AccordionProps {
  title: string;
  children: ReactNode | string;
  icon: ReactNode | string;
  name?: string;
}
```

- `title` será nuestro encabezado dentro de la etiqueta `summary`.
- `children` será el contenido a mostrar. Puede recibir un string o un ReactNode.
- `icon` va a ser el ícono que va a suplantar el ícono nativo que contiene el elemento details.
- `name` es opcional y será el valor que va a contener el atributo `name` del cual hablaremos a continuación.

## Atributo `name`

La etiqueta `details` acepta el atributo `name` y se utiliza para, si hay más de una etiqueta `details`, que los elementos se comporten como un grupo. Es decir, si un accordion esta abierto y se abre otro, automáticamente el anterior se cierra.

{% codesandbox 5qppfp %}

## Cómo sacar la flecha nativa del componente

Para poder sacar la flecha nativa tenemos que tener dos reglas en cuenta primero con el selector summary vamos a colocar el `list-style: none` para eliminar la flecha en algunos navegadores.

```
details summary {
  cursor: pointer;
  position: relative;
  list-style: none;
}
```
Para eliminar la flecha en navegadores como Chrome y Safari vamos a utilizar la propiedad `-webkit-details-marker`

```
details summary::-webkit-details-marker {
  display: none;
}
```

## ¿Cómo anuncian los lectores de pantalla la etiqueta `details`?

1) cuando el elemento esta colapsado

![Imagen del lector de pantalla voice over que anuncia: Accordion 3, colapsado, grupo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ggnstke12vb3dqveancx.png)

2) cuando el elemento esta expandido

![Imagen del lector de pantalla voiceover que anuncia: Accordion 3, expandido, grupo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f8aecbelxo2divor98li.png)

y, ¡Listo! Ya con todos estos cambios y cero javascript tenemos un Accordion funcionando y 100% accesible.

Espero que esta información les sirva y comentenme si hay algo en particular que les gustaría aprender sobre accesibilidad o si hay algún componente en particular que les llama la atención para poder trabajar en esta sección.

Muchas gracias por leerme siempre <3