Blog

Fran Acedo
15 Ene 2024

Material Design 3 - Web Components

Tiempo de lectura 3 minutos

Sumario Conoce los nuevos componentes web de Material Design 3.

Contexto

Google lanza la primera versión de Material Design en el año 2014 creando así su propio lenguaje visual con la intención de transformar las interfaces de usuario. En 2018 publican la segunda versión, probablemente mi sistema de diseño favorito hasta la fecha, una gran actualización focalizada en la definición de su sistema de diseño y en la personalización.

Y, por último, llega la tan esperada tercera versión en 2021: Material You. Siendo sus principales objetivos la accesibilidad y la adaptación. Acompañando este lanzamiento, recientemente ha visto la luz la versión 1.0 de Material Web Components, una librería de componentes web independientes de cualquier framework. Y no me he podido resistir a experimentar con ella, así que allá vamos.

Puesta en marcha

Creamos un nuevo proyecto de Node e instalamos el paquete @material/web. Para trabajar necesitaremos un servidor, por lo que instalamos @web/dev-server como dependencia de desarrollo y agregamos el siguiente script al package.json para arrancarlo:

"start": "web-dev-server --node-resolve --open --watch"

Generamos un fichero HTML y un fichero JavaScript que servirá de punto de entrada para los componentes web:

<script type="module" src="./index.js"></script>

A partir de ahora importaremos los componentes que vayamos a usar. Los componentes disponibles siguen la siguiente estructura:

JavaScript :

import "@material/web/button/outlined-button.js";

HTML:

<md-outlined-button></md-outlined-button>

Personalizando

Para que podamos darles a los componentes un estilo propio, ponen a nuestra disposición los tokens de diseño. Nos permiten modificar ciertos aspectos como: tipografías, esquema de colores y la estética de los componentes.

Cada componente soporta una lista de tokens de diseño. Por ejemplo, una lista soporta (entre otros muchos) los siguientes:

--md-list-container-color: color de fondo del contenedor de la lista.

--md-list-item-label-text-color: color del texto principal de los elementos.

Demostración

Para el ejemplo montaremos un pequeño formulario con dos inputs, un botón con icono, un checkbox y un par de botones; un hello world en toda regla.

<head>
  <script type="module" src="./index.js"></script>

  <link
    href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined"
    rel="stylesheet"
  />

  <style>
    :root {
      font-family: "Roboto", system-ui, sans-serif;
      /* Design tokens system: cambio en los colores */
      --md-sys-color-primary: #ff7548;
      --md-sys-color-surface: #fff5e4;
      /* Design tokens outlined-text-field: cambio en la forma */
      --md-outlined-text-field-container-shape: 16px;
    }

    label {
      display: flex;
      align-items: center;
      gap: 16px;
    }

    form {
      display: flex;
      flex-direction: column;
      padding: 16px;
      gap: 16px;
      max-width: 400px;
    }
  </style>
</head>

Incrustamos la fuente que contiene los iconos de Material Design de Google, usamos algunos tokens de diseño y damos un poco de formato al formulario.

<body>
  <form>
    <md-outlined-text-field
    label="Usuario"
    type="text"
    name="username"
    supporting-text="No se aceptan símbolos especiales"
    maxlength="20"
    required
  ></md-outlined-text-field>

  <md-outlined-text-field
    label="Contraseña"
    type="password"
    name="password"
    minlength="8"
    required
  >
    <md-icon-button
      toggle
      id="toggle-password"
      slot="trailing-icon"
      aria-label="Cambiar visibilidad contraseña"
    >
      <md-icon>visibility</md-icon>
      <md-icon slot="selected">visibility_off</md-icon>
    </md-icon-button>
  </md-outlined-text-field>
  
  <label>
    Subscribirse a la newsletter
    <md-checkbox name="subscribe"></md-checkbox>
  </label>
  
  <div class="form-actions">
    <md-elevated-button type="reset">Limpiar</md-elevated-button>
    <md-elevated-button>Enviar</md-elevated-button>
  </div>
  
  </form>
</body>

Creamos un par de inputs, uno para el usuario y otro para la contraseña. Incrustamos un botón con un icono que nos permitirá modificar la visibilidad de la contraseña. Y para terminar un checkbox y un par de botones.

Cada componente expone una serie de atributos con los que poder modificar su comportamiento como es el caso de toggle de <md-icon-button> que permite modificar el icono que se visualiza en función de su estado. Y de igual manera, exponen una serie de métodos para trabajar con ellos.

import "@material/web/textfield/outlined-text-field.js";
import "@material/web/button/elevated-button.js";
import "@material/web/checkbox/checkbox.js";
import "@material/web/icon/icon.js";
import "@material/web/iconbutton/icon-button.js";

document
  .querySelector("#toggle-password")
  .addEventListener("click", (event) => {
    event.preventDefault();
    const passwordInput = document.querySelector(
      "md-outlined-text-field[name='password']"
    );
    const passwordInputType = passwordInput.getAttribute("type");
    passwordInput.setAttribute(
      "type",
      passwordInputType === "password" ? "text" : "password"
    );
  });

En el fichero JavaScript se importan los componentes con los que vamos a trabajar. Y para el propósito del ejemplo se ha dotado de funcionalidad al botón del input de tipo contraseña que permite modificar la visibilidad.

¿Qué opino yo?

En cuanto a mí, me encanta la estética de estos componentes y creo firmemente que van a estar hasta en la sopa. Echando un ojo a su roadmap queda claro que tienen trabajo para rato y que lo que podemos usar hoy es sólo la punta del iceberg. Sobre todo, espero que mimen un poco la parte de la personalización porque tod@s sabemos lo tedioso que es estar sobreescribiendo CSS… Tiene un gran futuro y su integración con las view-transitions suena muy prometedora.

Autor

Fran Acedo
Fran Acedo

Desarrollador en dev&del

Tiró de un hilo suelto y descosió el sofá

¿Estás interesado?

Déjanos tus datos y contactaremos contigo lo antes posible