6. PWA con Material Design

Versión para imprimir.

1. Introduccion

2. Referencias

Sitios de Material Design
Material.io

Material Design es una guía de diseño para aplicaciones multiplataforma. La encuentras en https://m3.material.io/.

Herramienta para selección de colores
Material Theme Builder

https://m3.material.io/theme-builder/

Adaptación multiplataforma

La forma de adaptar Material Design en distintas plataformas está en https://material.io/design/platform-guidance/cross-platform-adaptation.html

3. Hazlo funcionar

  1. Prueba e instala, de preferencia con Chrome, el sitio https://pwamd.rf.gd/ y en https://gilpgpwamd.github.io/.

  2. Descarga el archivo /src/pwamd.zip y descompáctalo.

  3. Crea tu proyecto en GitHub pages:

    1. Crea una cuenta de email con el nombre de tu sitio, por ejemplo, miapp@google.com

    2. Crea una cuenta de GitHub usando el email anterior y selecciona el nombre de usuario unsando la parte inicial del correo electrónico, por ejemplo miapp.

    3. Crea un repositorio nuevo. En la página principal de GitHub cliquea 📘 New.

    4. En la página Create a new repository introduce los siguientes datos:

      • Proporciona el nombre de tu repositorio debajo de donde dice Repository name *. Debes usar el nombre de tu cuenta seguido por .github.io; por ejemplo miapp.github.io

      • Mantén la selección Public.

      • Verifica la casilla Add a README file. En este archivo se muestra información sobre tu proyecto.

      • Cliquea License: None. y selecciona la licencia que consideres más adecuada para tu proyecto.

      • Cliquea Create repository.

    5. Entra al repositorio y selecciona ⚙ Settings, luego selecciona 📁 Pages y en la sección Branches selecciona la carpeta donde se ubicará la carpeta. De preferencia selecciona / (root) para que coloques la página en la raíz del proyecto.

  4. Importa el proyecto en GitHub:

    1. En la página principal de tu proyecto en GitHub, en la pestaña < > Code, cliquea < > Code y en la sección Branches y copia la dirección que está en HTTPS, debajo de Clone.

    2. En Visual Studio Code, usa el botón de la izquierda para Source Control.

      Imagen de Source Control
    3. Cliquea el botón Clone Repository.

    4. Pega la url que copiaste anteriormente hasta arriba, donde dice algo como Provide repository URL y presiona la teclea Intro.

    5. Selecciona la carpeta donde se guardará la carpeta del proyecto.

    6. Abre la carpeta del proyecto importado.

    7. Añade el contenido de la carpeta descompactada que contiene el código del ejemplo, excepto el archivo .htaccess.

  5. Edita los archivos que desees.

  6. Crea los íconos del proyecto con https://www.photopea.com/. Este paso se hizo com Microsoft Edge (versión Chromium), pero no funcionó con Google Chrome.

  7. Crea los íconos enmascarables con https://maskable.app/ a partir del archivo «icono2048.png».

  8. Coloca el archivo favicon.ico en la raíz del proyecto.

  9. Coloca los otros íconos en la carpeta img y asegúrate de que estén declarados en el archivo site.webmanifest.

  10. Para cambiar los colores, entra al sitio https://material-foundation.github.io/material-theme-builder/, selecciona los colores de tu aplicación, haz clic en Pick your fonts →. Elige font Roboto, haz clic en Export theme →. Haz clic en Export y selecciona Web (CSS) para descargar el zip que contiene los estilos que generan los colores. Descompacta el zip y copia los archivos de la carpeta css a la carpeta css del proyecto, sobreescribiendo los archivos del ejemplo.

  11. El archivo sw.js tiene una lista de los archivos que se instalan. El archivo instruccionesListadoSw.txt te indica como generarla usando Visual Studio Code.

  12. Cada vez que modifiques los archivos, debes modificar el valor de VERSION en el archivo sw.js para poder ver los cambios en el navegador.

  13. Si tu proyecto no usa backend, haz clic derecho en index.html, selecciona Open with Live Server y se abre el navegador para que puedas probar localmente el ejemplo.

  14. Si tu proyecto usa PHP, haz clic derecho en index.html, selecciona PHP Server: serve project y se abre el navegador para que puedas probar localmente el ejemplo.

  15. Haz al menos una captura de la ventana de tu aplicación con orientación vertical y otra con orientación horizontal, todas ellas de 320 px como mínimo y 3,840 px como máximo.

  16. Coloca las capturas en la carpeta img y asegúrate de que estén declaradas en el archivo site.webmanifest.

  17. Cuando desarrolles, es incómodo modificar la versión cada que realizas cambios; en ves de ello desinstala la app:

    1. Abre las herramientas de depuración haciendo clic derecho en la página y selecciona Inspeccionar (o Inspect si aparece en inglés).

    2. En la Pestaña Aplicación (o Application en inglés) selecciona Almacenamoento (o Storage en inglés). Cliquea Borrar datos del sitio.

    3. Recarga la app, de preferencia haciendo clic derecho en el ícono de volver a cargar la página Ïmagen del ícono de recarga y seleccionando vaciar caché y volver a cargar de manera forzada (o algo parecido). Si no aparece un menú emergente, simplemente cliquea volver a cargar la página Ïmagen del ícono de recarga. Revisa que no aparezca ningún error ni en la pestañas Consola, ni en Red.

    4. Tanbién puedes usar la combinación de teclas Ctrl+Mayúsculas+r para forzar que se actualice temporalmente el navegador en caso de que no se vean los cambios.

    5. En la Pestaña Aplicación (o Application en inglés) selecciona Archivo de manifiesto (o Manifest file en inglés). Esta herramienta analiza la estructura del archivo de manifiesto y te indica si hay un error. InfinityFree bloquea el análisis de las imágenes.

    6. En la Pestaña Aplicación (o Application en inglés) selecciona Almacenamiento en caché (o Cache storage en inglés). Aquí puedes revisar si el caché de la aplicación se llenó correctamente. En caso de que esté vacío, es que hubo algún error durante la carga y la app se ejecuta más lenta.

  18. Para depurar paso a paso haz lo siguiente:

    1. En el navegador, haz clic derecho en la página que deseas depurar y selecciona inspeccionar.

    2. Selecciona la pestaña Fuentes (o Sources si tu navegador está en Inglés).

    3. Selecciona el archivo donde vas a empezar a depurar.

    4. Haz clic en el número de la línea donde vas a empezar a depurar.

    5. Recarga la página de manera normal.

    6. Empieza a usar tu sitio.

    7. Si se ejecuta alguna de las líneas de código seleccionadas, aparece resaltada en la pestaña de fuentes. Usa los controles de depuración para avanzar, como se muestra en este video.

  19. Cuando usas GitHub pages, antes de subir los archivos, no debes modificar el valor de VERSION en el archivo sw.js.

  20. Para subir el código a GitHub, en la sección de SOURCE CONTROL, en Message introduce un mensaje sobre los cambios que hiciste, por ejemplo index.html corregido, selecciona v y luego Commit & Push.

    Imagen de Commit & Push
  21. Si usas GitHub pages:

    1. Entra a la página de tu repositorio y abajo a la derecha, selecciona el enlace github-pages.

    2. Se muestran los despliegues realizados. Recarga la página hasta que apareca el mensaje de tu último push con una palomita dentro de un círculo verde.

    3. A partir de este momento, espera al menos 11 minutos para modificar el valor de VERSION en el archivo sw.js y volver a subir el proyecto.

  22. Si no usas GitHub pages:

    1. Sube el proyecto al hosting que elijas sin incluir el archivo .htaccess. En algunos casos puedes usar filezilla (https://filezilla-project.org/)

    2. En algunos host como InfinityFree, tienes que configurar el certificado SSL.

    3. En algunos host, como InfinityFree, debes subir el archivo .htaccess cuando el certificado SSL se ha creado e instalado. Sirve para forzar el uso de https, para eliminar el control de cache, pues ahora lo lleva el service worker y para asignar el mime type correcto para el archivo de manifest.

    4. Abre un navegador y prueba el proyecto en tu hosting.

    5. En el hosting InfinityFree, la primera ves que corres la página, puede marcar un mensaje de error, pero al recargar funciona correctamente. Puedes evitar este problema usando un dominio propio.

  23. Instala y usa tu PWA en Windows. Aunque en este video se recomienda usar Edge, al momento de actualizar el contenido, la opción más recomendada es Chrome para que te muestre las descripciones y las capturas de pantalla.

  24. Instala y usa tu PWA en Android. Al momento de actualizar las notas, tal vez no te aparezca el botón para instalar y tengas que seleccionar la acción de instalar que aparece en el menú de extensión de Chrome.

  25. Instala y usa tu PWA en iOS (iPhone y iPad).

4. Archivos

Haz clic en los triángulos para expandir las carpetas

5. index.html - Página principal

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>PWA con MD</title>
8
9 <!-- Resumen para los motores de búsqueda. -->
10 <meta name="description" content="Ejemplo de PWA con Material Design">
11
12 <script src="js/registraServiceWorker.js"></script>
13
14 <meta name="viewport" content="width=device-width">
15
16 <!-- Color de la barra de navegación de Chrome en dispositivos móviles. -->
17 <meta name="theme-color" content="#fffbfe">
18
19 <!-- Ícono para la página web, que normalmente se pone en la raíz del sitio.
20 Puede ser diferente para cada página. -->
21 <link rel="icon" sizes="32x32" href="favicon.ico">
22
23 <!-- Configuración de la PWA para Chrome, Edge y Safari.
24 Debe ponerse en todas las páginas. -->
25 <link rel="manifest" href="site.webmanifest">
26
27 <!-- Permite a los navegadores, que como Safari no soportan el estándar
28 completo de custom elementsm, lo cumplan totalmente. Debe ponerse en todas
29 las páginas. -->
30 <script src="ungap/custom-elements.js"></script>
31
32 <!-- Configuración de todas las páginas con JavaSript. -->
33 <script type="module" src="js/configura.js"></script>
34 <link rel="stylesheet" href="css/estilos.css">
35 <link rel="stylesheet" href="css/transicion_completa.css">
36
37</head>
38
39<body>
40
41 <md-top-app-bar class="center-aligned">
42
43 <h1>PWA con MD</h1>
44
45 <button is="md-menu-button" slot="navigation"></button>
46
47 <button type="button" class="md-standard-icon-button avatar" title="Perfil"
48 slot="action">
49 <span class="material-symbols-outlined">account_circle</span>
50 </button>
51
52 </md-top-app-bar>
53
54 <main>
55 <p>
56 Esta es la página principal de la app. Las X que siguen son para que veas
57 como se comporta cuando se hace scroll.
58 </p>
59 <p>x</p>
60 <p>x</p>
61 <p>x</p>
62 <p>x</p>
63 <p>x</p>
64 <p>x</p>
65 <p>x</p>
66 <p>x</p>
67 <p>x</p>
68 <p>x</p>
69 <p>x</p>
70 <p>x</p>
71 <p>x</p>
72 <p>x</p>
73 <p>x</p>
74 <p>x</p>
75 <p>x</p>
76 <p>x</p>
77 <p>x</p>
78 <p>x</p>
79 <p>x</p>
80 <p>x</p>
81 <p>x</p>
82 </main>
83
84 <nav-drw></nav-drw>
85
86</body>
87
88</html>

Solo para los más rudos

6. secundaria.html - Vista secundaria

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Vista secundaria - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar class="medium" headline="h1Headline">
26
27 <h1>Secundaria</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 <button type="button" class="md-standard-icon-button" title="Agregar"
32 slot="action">
33 <span class="material-symbols-outlined">add</span>
34 </button>
35
36 <button type="button" class="md-standard-icon-button" title="Editar"
37 slot="action">
38 <span class="material-symbols-outlined">edit</span>
39 </button>
40
41 <button is="md-overflow-button" slot="action"
42 onclick="overflow.alterna(this)"></button>
43
44 </md-top-app-bar>
45
46 <h1 id="h1Headline">Página secundaria</h1>
47
48 <main>
49 <p>
50 Esta es una página secundaria de la app. Las X que siguen son para que veas
51 como se comporta cuando se hace scroll.
52 </p>
53 <p>x</p>
54 <p>x</p>
55 <p>x</p>
56 <p>x</p>
57 <p>x</p>
58 <p>x</p>
59 <p>x</p>
60 <p>x</p>
61 <p>x</p>
62 <p>x</p>
63 <p>x</p>
64 <p>x</p>
65 <p>x</p>
66 <p>x</p>
67 <p>x</p>
68 <p>x</p>
69 <p>x</p>
70 <p>x</p>
71 <p>x</p>
72 <p>x</p>
73 <p>x</p>
74 <p>x</p>
75 <p>x</p>
76 </main>
77
78 <md-overflow-menu id="overflow">
79
80 <button type="button">
81 <span class="material-symbols-outlined">star</span>
82 Marcar favorito
83 </button>
84
85 <button type="button">
86 <span class="material-symbols-outlined"> delete</span>
87 Eliminar
88 </button>
89
90 </md-overflow-menu>
91
92 <nav-drw></nav-drw>
93
94</body>
95
96</html>

Solo para los más rudos

7. iconos.html - Íconos oficiales

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Íconos - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar>
26
27 <h1>Íconos</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 </md-top-app-bar>
32
33 <main>
34
35 <button type="button" class="md-standard-icon-button">
36 <span class="material-symbols-outlined">favorite</span>
37 </button>
38
39 <button type="button" class="md-standard-icon-button" disabled>
40 <span class="material-symbols-outlined">bolt</span>
41 </button>
42
43 <a class="md-standard-icon-button" target="_blank" rel="noreferrer"
44 href="https://google.com">
45 <span class="material-symbols-outlined">star</span></a>
46
47 <span class="material-symbols-outlined">thumb_up</span>
48
49 <button type="button" class="md-fab-primary"
50 style="position: fixed; bottom: 1rem; right: 1rem;">
51 <span class="material-symbols-outlined">add</span>
52 </button>
53
54 </main>
55
56 <nav-drw></nav-drw>
57
58</body>
59
60</html>

Solo para los más rudos

8. botones.html - Botones

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Botones - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar>
26
27 <h1>Botones</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 </md-top-app-bar>
32
33 <main>
34
35 <p>
36
37 <button class="md-filled-button">
38 Primario
39 </button>
40
41 <button class="md-outline-button">
42 Secundario
43 </button>
44
45 </p>
46
47 </main>
48
49 <nav-drw></nav-drw>
50
51</body>
52
53</html>

Solo para los más rudos

9. campos.html - Campos de texto

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Campos de texto - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar headline="headline">
26
27 <h1>Texto</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 </md-top-app-bar>
32
33 <h1 id="headline">Campos de texto</h1>
34
35 <main>
36
37 <!-- Usa
38 class="float"
39 cuando quieras que la etiqueta esté arriba todo el tiempo. -->
40 <p>
41 <label class="md-filled-text-field float">
42 <output>Saludo</output>
43 <span>Saludo</span>
44 </label>
45 </p>
46
47 <p>
48 <label class="md-filled-text-field">
49 <input required placeholder="Nombre*">
50 <span>Nombre *</span>
51 <small>Obligatorio</small>
52 </label>
53 </p>
54
55 <p>
56 <label class="md-filled-text-field">
57 <input type="email" placeholder="Email">
58 <span accesskey="M">Email</span>
59 </label>
60 </p>
61
62 <p>
63 <label class="md-filled-text-field float">
64 <input type="date" placeholder="Fecha">
65 <span>Fecha</span>
66 </label>
67 </p>
68
69 <p>
70 <label class="md-filled-text-field">
71 <textarea rows="3" placeholder="Dirección"></textarea>
72 <span>Dirección</span>
73 </label>
74 </p>
75
76 </main>
77
78 <nav-drw></nav-drw>
79
80</body>
81
82</html>

Solo para los más rudos

10. select.html - Selects

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Select - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <form>
26
27 <md-top-app-bar>
28
29 <h1>Select</h1>
30
31 <button is="md-menu-button" slot="navigation"></button>
32
33 </md-top-app-bar>
34
35 <main>
36
37 <p>
38 <span id="etiquetaGrupo" class="md-filled-text-field" accesskey="G">
39 <md-select-menu name="grupo" required value="IC21"
40 aria-labelledby="etiquetaGrupo"
41 options="opcionesDeGrupo"></md-select-menu>
42 <span>Grupo *</span>
43 <small>Obligatorio</small>
44 </span>
45 </p>
46
47 <p>
48 <button class="md-filled-button" style="width: 100%;">Enviar</button>
49 </p>
50
51 </main>
52
53 <md-options-menu id="opcionesDeGrupo" aria-label="Opciones de grupo">
54 <span data-value="" title="Selecciona opción"></span>
55 <span data-value="IC21">IC-21</span>
56 <span data-value="IC22">IC-22</span>
57 <span data-value="IC23">IC-23</span>
58 </md-options-menu>
59
60 <nav-drw></nav-drw>
61
62 </form>
63
64</body>
65
66</html>

Solo para los más rudos

11. interruptor.html - Interruptores

Salida

Ábrelo en otra pestaña.

Interruptor en Android
Interruptor en Android
Interruptor en iOS
Interruptor en iOS
1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Interruptores - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar>
26
27 <h1>Interruptores</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 </md-top-app-bar>
32
33 <main>
34 <p>
35 <label accesskey="R">
36 Muestra resultados
37 <input type="checkbox" class="md-switch">
38 </label>
39 </p>
40 </main>
41
42 <nav-drw></nav-drw>
43
44</body>
45
46</html>

Solo para los más rudos

12. slider.html

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Sliders - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar>
26
27 <h1>Sliders</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 </md-top-app-bar>
32
33 <main>
34
35 <md-slider-field>
36 <label>Rango</label>
37 <input type="range" slot="slider" min="1" max="10">
38 <small slot="supporting">Calcúlalo bien</small>
39 </md-slider-field>
40
41 </main>
42
43 <nav-drw></nav-drw>
44
45</body>
46
47</html>

Solo para los más rudos

13. segmentado.html - Botones segmentados

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Botón segmentado - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar headline="headline">
26
27 <h1>Segmentado</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 </md-top-app-bar>
32
33 <h1 id="headline">Botón segmentado</h1>
34
35 <main>
36
37 <p class="md-segmented-button">
38
39 <input id="bueno" type="radio" name="estado" checked value="2">
40 <label for="bueno">
41 <span class="material-symbols-outlined">done</span>
42 Bueno
43 </label>
44
45 <input id="intermedio" type="radio" name="estado" value="1">
46 <label for="intermedio">
47 <span class="material-symbols-outlined">done</span>
48 Intermedio
49 </label>
50
51 <input id="malo" type="radio" name="estado" value="0">
52 <label for="malo">
53 <span class="material-symbols-outlined">done</span>
54 Malo
55 </label>
56
57 </p>
58
59 </main>
60
61 <nav-drw></nav-drw>
62
63</body>
64
65</html>

Solo para los más rudos

14. one-line.html - Listas con elementos one-line

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Listas one-line - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar headline="headline">
26
27 <h1>one-line</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 </md-top-app-bar>
32
33 <h1 id="headline">Listas one-line</h1>
34
35 <main>
36
37 <ul class="md-list">
38
39 <li class="md-one-line">
40 <span class="headline">
41 Ciudad de México
42 </span>
43 </li>
44
45 <li class="md-one-line">
46 <span class="headline">
47 Lorem ipsum dolor sit amet consectetur adipisicing elit.
48 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
49 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
50 alias!
51 </span>
52 </li>
53
54 <li class="md-one-line icon">
55 <span class="material-symbols-outlined">account_balance</span>
56 <span class="headline">
57 Atenas
58 </span>
59 </li>
60
61 <li class="md-one-line avatar">
62 <img alt="Avatar de Ana" src="img/pexels-moises-patrício-10961948.jpg">
63 <span class="headline">
64 Ana
65 </span>
66 </li>
67
68 <li class="md-one-line image">
69 <img alt="Coyote de Neza" src="img/Escultura_de_coyote.jpeg">
70 <span class="headline">
71 Neza
72 </span>
73 </li>
74
75 <li class="md-one-line video">
76 <img alt="Ciudad de San Francisco"
77 src="img/pexels-craig-dennis-3701822.jpg">
78 <span class="headline">
79 San Francisco
80 </span>
81 </li>
82
83 <li class="md-one-line video">
84 <img alt="Ciudad de San Francisco"
85 src="img/pexels-craig-dennis-3701822.jpg">
86 <span class="headline">
87 Lorem ipsum dolor sit amet consectetur adipisicing elit.
88 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
89 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
90 </span>
91 </li>
92
93 <li>
94 <a class="md-one-line image" target="_blank" rel=”noreferrer”
95 href="https://culturacolectiva.com/historia/ciudad-neza-su-historia-en-fotografias/">
96 <img alt="Coyote de Neza" src="img/Escultura_de_coyote.jpeg">
97 <span class="headline">
98 Neza Link
99 </span>
100 </a>
101 </li>
102
103 </ul>
104
105 <footer>
106 <ul>
107 <li>
108 <p>
109 <small>
110 <a target="_blank" rel=”noreferrer”
111 href="https://www.pexels.com/es-es/foto/nina-mono-cara-sonriente-10961948/">
112 La foto de la niña es de Moises Patrício, publicada en el sitio Pexels.
113 Haz clic en este hipervínculo para más información.
114 </a>
115 </small>
116 </p>
117 </li>
118 <li>
119 <p>
120 <small>
121 <a target="_blank" rel=”noreferrer”
122 href="https://www.pinterest.com.mx/ludresi/">
123 La foto del Coyote de Neza es de Ludres Isan, publicada en el sitio
124 Pinterest. Haz clic en este hipervínculo para más información.
125 </a>
126 </small>
127 </p>
128 </li>
129 <li>
130 <p>
131 <small>
132 <a target="_blank" rel=”noreferrer”
133 href="https://www.pexels.com/es-es/foto/puente-golden-gate-san-francisco-california-3701822/">
134 La foto del puente de San Francisco es de Craig Dennis, publicada en el
135 sitio Pexels. Haz clic en este hipervínculo para más información.
136 </a>
137 </small>
138 </p>
139 </li>
140 </ul>
141 </footer>
142
143 </main>
144
145 <nav-drw></nav-drw>
146
147</body>
148
149</html>

Solo para los más rudos

15. two-line.html - Listas con elementos two-line

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Listas two-line - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar headline="headline">
26
27 <h1>two-line</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 </md-top-app-bar>
32
33 <h1 id="headline">Listas two-line</h1>
34
35 <main>
36
37 <ul class="md-list">
38
39 <li class="md-two-line">
40 <span class="headline">
41 Ciudad de México 2
42 </span>
43 <span class="supporting">
44 Lorem ipsum dolor sit amet consectetur adipisicing elit.
45 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
46 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
47 alias!
48 </span>
49 </li>
50
51 <li class="md-two-line icon">
52 <span class="material-symbols-outlined">account_balance</span>
53 <span class="headline">
54 Atenas 2
55 </span>
56 <span class="supporting">
57 Lorem ipsum dolor sit amet consectetur adipisicing elit.
58 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
59 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
60 alias!
61 </span>
62 </li>
63
64 <li class="md-two-line avatar">
65 <img alt="Avatar de Ana" src="img/pexels-moises-patrício-10961948.jpg">
66 <span class="headline">
67 Ana 2
68 </span>
69 <span class="supporting">
70 Lorem ipsum dolor sit amet consectetur adipisicing elit.
71 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
72 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
73 alias!
74 </span>
75 </li>
76
77 <li class="md-two-line image">
78 <img alt="Coyote de Neza" src="img/Escultura_de_coyote.jpeg">
79 <span class="headline">
80 Neza 2
81 </span>
82 <span class="supporting">
83 Lorem ipsum dolor sit amet consectetur adipisicing elit.
84 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
85 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
86 alias!
87 </span>
88 </li>
89
90 <li class="md-two-line video">
91 <img alt="Ciudad de San Francisco"
92 src="img/pexels-craig-dennis-3701822.jpg">
93 <span class="headline">
94 San Francisco 2
95 </span>
96 <span class="supporting">
97 Lorem ipsum dolor sit amet consectetur adipisicing elit.
98 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
99 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
100 alias!
101 </span>
102 </li>
103
104 <li>
105 <a class="md-two-line image" target="_blank" rel="noreferrer"
106 href="https://culturacolectiva.com/historia/ciudad-neza-su-historia-en-fotografias/">
107 <img alt="Coyote de Neza" src="img/Escultura_de_coyote.jpeg">
108 <span class="headline">
109 Neza Link 2
110 </span>
111 <span class="supporting">
112 Lorem ipsum dolor sit amet consectetur adipisicing elit.
113 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
114 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
115 alias!
116 </span>
117 </a>
118 </li>
119
120 </ul>
121
122 <footer>
123 <ul>
124 <li>
125 <p>
126 <small>
127 <a target="_blank" rel="noreferrer"
128 href="https://www.pexels.com/es-es/foto/nina-mono-cara-sonriente-10961948/">
129 La foto de la niña es de Moises Patrício, publicada en el sitio Pexels.
130 Haz clic en este hipervínculo para más información.
131 </a>
132 </small>
133 </p>
134 </li>
135 <li>
136 <p>
137 <small>
138 <a target="_blank" rel=”noreferrer”
139 href="https://www.pinterest.com.mx/ludresi/">
140 La foto del Coyote de Neza es de Ludres Isan, publicada en el sitio
141 Pinterest. Haz clic en este hipervínculo para más información.
142 </a>
143 </small>
144 </p>
145 </li>
146 <li>
147 <p>
148 <small>
149 <a target="_blank" rel=”noreferrer”
150 href="https://www.pexels.com/es-es/foto/puente-golden-gate-san-francisco-california-3701822/">
151 La foto del puente de San Francisco es de Craig Dennis, publicada en el
152 sitio Pexels. Haz clic en este hipervínculo para más información.
153 </a>
154 </small>
155 </p>
156 </li>
157 </ul>
158 </footer>
159
160 </main>
161
162 <nav-drw></nav-drw>
163
164</body>
165
166</html>

Solo para los más rudos

16. three-line.html - Listas con elementos three-line

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Listas tree-line - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar headline="headline">
26
27 <h1>tree-line</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 </md-top-app-bar>
32
33 <h1 id="headline">Listas tree-line</h1>
34
35 <main>
36
37 <ul class="md-list">
38
39 <li class="md-three-line">
40 <span class="headline">
41 Ciudad de México 3
42 </span>
43 <span class="supporting">
44 Lorem ipsum dolor sit amet consectetur adipisicing elit.
45 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
46 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
47 alias!
48 </span>
49 </li>
50
51 <li class="md-three-line icon">
52 <span class="material-symbols-outlined">account_balance</span>
53 <span class="headline">
54 Atenas 3
55 </span>
56 <span class="supporting">
57 Lorem ipsum dolor sit amet consectetur adipisicing elit.
58 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
59 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
60 alias!
61 </span>
62 </li>
63
64 <li class="md-three-line avatar">
65 <img alt="Avatar de Ana" src="img/pexels-moises-patrício-10961948.jpg">
66 <span class="headline">
67 Ana 3
68 </span>
69 <span class="supporting">
70 Lorem ipsum dolor sit amet consectetur adipisicing elit.
71 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
72 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
73 alias!
74 </span>
75 </li>
76
77 <li class="md-three-line image">
78 <img alt="Coyote de Neza" src="img/Escultura_de_coyote.jpeg">
79 <span class="headline">
80 Neza 3
81 </span>
82 <span class="supporting">
83 Lorem ipsum dolor sit amet consectetur adipisicing elit.
84 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
85 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
86 alias!
87 </span>
88 </li>
89
90 <li class="md-three-line video">
91 <img alt="Ciudad de San Francisco"
92 src="img/pexels-craig-dennis-3701822.jpg">
93 <span class="headline">
94 San Francisco 3
95 </span>
96 <span class="supporting">
97 Lorem ipsum dolor sit amet consectetur adipisicing elit.
98 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
99 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
100 alias!
101 </span>
102 </li>
103
104 <li>
105 <a class="md-three-line image" target="_blank" rel=”noreferrer”
106 href="https://culturacolectiva.com/historia/ciudad-neza-su-historia-en-fotografias/">
107 <img alt="Coyote de Neza" src="img/Escultura_de_coyote.jpeg">
108 <span class="headline">
109 Neza Link 3
110 </span>
111 <span class="supporting">
112 Lorem ipsum dolor sit amet consectetur adipisicing elit.
113 Laboriosam eaque unde voluptates tempore ad suscipit libero, saepe neque
114 illo amet, eos ea similique quia, maiores tenetur modi nobis expedita
115 alias!
116 </span>
117 </a>
118 </li>
119
120 </ul>
121
122 <footer>
123 <ul>
124 <li>
125 <p>
126 <small>
127 <a target="_blank" rel=”noreferrer”
128 href="https://www.pexels.com/es-es/foto/nina-mono-cara-sonriente-10961948/">
129 La foto de la niña es de Moises Patrício, publicada en el sitio Pexels.
130 Haz clic en este hipervínculo para más información.
131 </a>
132 </small>
133 </p>
134 </li>
135 <li>
136 <p>
137 <small>
138 <a target="_blank" rel=”noreferrer”
139 href="https://www.pinterest.com.mx/ludresi/">
140 La foto del Coyote de Neza es de Ludres Isan, publicada en el sitio
141 Pinterest. Haz clic en este hipervínculo para más información.
142 </a>
143 </small>
144 </p>
145 </li>
146 <li>
147 <p>
148 <small>
149 <a target="_blank" rel=”noreferrer”
150 href="https://www.pexels.com/es-es/foto/puente-golden-gate-san-francisco-california-3701822/">
151 La foto del puente de San Francisco es de Craig Dennis, publicada en el
152 sitio Pexels. Haz clic en este hipervínculo para más información.
153 </a>
154 </small>
155 </p>
156 </li>
157 </ul>
158 </footer>
159
160 </main>
161
162 <nav-drw></nav-drw>
163
164</body>
165
166</html>

Solo para los más rudos

17. tarjetas.html - Tarjetas

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Tarjetas - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar>
26 <h1>Tarjetas</h1>
27
28 <button is="md-menu-button" slot="navigation"></button>
29
30 </md-top-app-bar>
31
32 <div class="md-cards">
33
34 <a target="_blank" rel=”noreferrer”
35 href="https://www.pexels.com/es-es/foto/lobo-blanco-y-negro-397857/">
36 <figure>
37 <img alt="Lobo" src="img/pexels-steve-397857.jpg">
38 </figure>
39 <span class="headline">
40 Lobo
41 </span>
42 <span class="supporting">
43 Foto de Steve en Pexels.
44 </span>
45 </a>
46
47 <a target="_blank" rel=”noreferrer”
48 href="https://www.pexels.com/es-es/foto/foto-de-buho-ural-3732453/">
49 <figure>
50 <img alt="Buho" src="img/pexels-erik-karits-3732453.jpg">
51 </figure>
52 <span class="headline">
53 Buho
54 </span>
55 <span class="supporting">
56 Foto de Erik Karits en Pexels
57 </span>
58 </a>
59
60 <a target="_blank" rel=”noreferrer”
61 href="https://www.pexels.com/es-es/foto/perro-de-pelo-corto-marron-y-blanco-acostado-3978352/">
62 <figure>
63 <img alt="Perro" src="img/pexels-creative-workshop-3978352.jpg">
64 </figure>
65 <span class="headline">
66 Perro
67 </span>
68 <span class="supporting">
69 Foto de Creative Workshop en Pexels
70 </span>
71 </a>
72
73 <a target="_blank" rel=”noreferrer”
74 href="https://www.pexels.com/es-es/foto/gatito-gris-en-bolsa-de-papel-plateada-141496/">
75 <figure>
76 <img alt="Gato" src="img/pexels-vadim-b-141496.jpg">
77 </figure>
78 <span class="headline">
79 Gato
80 </span>
81 <span class="supporting">
82 Foto de Vadim B en Pexels
83 </span>
84 </a>
85
86 <a target="_blank" rel=”noreferrer”
87 href="https://www.pexels.com/es-es/foto/leon-marron-2270848/">
88 <figure>
89 <img alt="León" src="img/pexels-ralph-2270848.jpg">
90 </figure>
91 <span class="headline">
92 León
93 </span>
94 <span class="supporting">
95 Foto de Ralph en Pexels
96 </span>
97 </a>
98
99 <a target="_blank" rel=”noreferrer”
100 href="https://www.pexels.com/es-es/foto/oso-cafe-35435/">
101 <figure>
102 <img alt="Oso" src="img/pexels-rasmus-svinding-35435.jpg">
103 </figure>
104 <span class="headline">
105 Oso
106 </span>
107 <span class="supporting">
108 Foto de Rasmus Svinding en Pexels
109 </span>
110 </a>
111
112 <a target="_blank" rel=”noreferrer”
113 href="https://www.pexels.com/es-es/foto/animal-perro-mono-hierba-10226903/">
114 <figure>
115 <img alt="Coyote" src="img/pexels-esteban-arango-10226903.jpg">
116 </figure>
117 <span class="headline">
118 Coyote
119 </span>
120 <span class="supporting">
121 Foto de Esteban Arango en Pexels
122 </span>
123 </a>
124
125 </div>
126
127 <nav-drw></nav-drw>
128
129</body>
130
131</html>

Solo para los más rudos

18. Cajón de navegación

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Vista secundaria - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar class="medium" headline="h1Headline">
26
27 <h1>Secundaria</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 <button type="button" class="md-standard-icon-button" title="Agregar"
32 slot="action">
33 <span class="material-symbols-outlined">add</span>
34 </button>
35
36 <button type="button" class="md-standard-icon-button" title="Editar"
37 slot="action">
38 <span class="material-symbols-outlined">edit</span>
39 </button>
40
41 <button is="md-overflow-button" slot="action"
42 onclick="overflow.alterna(this)"></button>
43
44 </md-top-app-bar>
45
46 <h1 id="h1Headline">Página secundaria</h1>
47
48 <main>
49 <p>
50 Esta es una página secundaria de la app. Las X que siguen son para que veas
51 como se comporta cuando se hace scroll.
52 </p>
53 <p>x</p>
54 <p>x</p>
55 <p>x</p>
56 <p>x</p>
57 <p>x</p>
58 <p>x</p>
59 <p>x</p>
60 <p>x</p>
61 <p>x</p>
62 <p>x</p>
63 <p>x</p>
64 <p>x</p>
65 <p>x</p>
66 <p>x</p>
67 <p>x</p>
68 <p>x</p>
69 <p>x</p>
70 <p>x</p>
71 <p>x</p>
72 <p>x</p>
73 <p>x</p>
74 <p>x</p>
75 <p>x</p>
76 </main>
77
78 <md-overflow-menu id="overflow">
79
80 <button type="button">
81 <span class="material-symbols-outlined">star</span>
82 Marcar favorito
83 </button>
84
85 <button type="button">
86 <span class="material-symbols-outlined"> delete</span>
87 Eliminar
88 </button>
89
90 </md-overflow-menu>
91
92 <nav-drw></nav-drw>
93
94</body>
95
96</html>

Solo para los más rudos

19. navtab.html - Navegación con pestañas scrollable

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Pestañas scrollable - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_pestanas.css">
20 <link rel="expect" blocking="render" href="#navtab">
21
22</head>
23
24<body>
25
26 <md-top-app-bar adicional="tab" headline="headline">
27
28 <h1>scrollable</h1>
29
30 <button type="button" class="md-standard-icon-button" title="Agregar"
31 slot="action">
32 <span class="material-symbols-outlined">add</span>
33 </button>
34 <button type="button" class="md-standard-icon-button" title="Editar"
35 slot="action">
36 <span class="material-symbols-outlined">edit</span>
37 </button>
38
39 </md-top-app-bar>
40
41 <h1 id="headline">Pestañas scrollable</h1>
42
43 <nav-tab-scrollable id="tab"></nav-tab-scrollable>
44
45 <main>
46 <p>
47 Esta página usa navegación por pestañas fijas. Las X que siguen son para que
48 veas como se comporta cuando se hace scroll.
49 </p>
50 <p>x</p>
51 <p>x</p>
52 <p>x</p>
53 <p>x</p>
54 <p>x</p>
55 <p>x</p>
56 <p>x</p>
57 <p>x</p>
58 <p>x</p>
59 <p>x</p>
60 <p>x</p>
61 <p>x</p>
62 <p>x</p>
63 <p>x</p>
64 <p>x</p>
65 <p>x</p>
66 <p>x</p>
67 <p>x</p>
68 <p>x</p>
69 <p>x</p>
70 <p>x</p>
71 <p>x</p>
72 <p>x</p>
73 </main>
74
75</body>
76
77</html>

Solo para los más rudos

20. navTabFixed.html - Navegación con pestañas fijas

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Pestañas fijas - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_pestanas.css">
20 <link rel="expect" blocking="render" href="#navtabfixed">
21
22</head>
23
24<body>
25
26 <md-top-app-bar adicional="tab" headline="headline">
27
28 <h1>fijas</h1>
29
30 <button type="button" class="md-standard-icon-button" title="Agregar"
31 slot="action">
32 <span class="material-symbols-outlined">add</span>
33 </button>
34 <button type="button" class="md-standard-icon-button" title="Editar"
35 slot="action">
36 <span class="material-symbols-outlined">edit</span>
37 </button>
38
39 </md-top-app-bar>
40
41 <h1 id="headline">Pestañas fijas</h1>
42
43 <nav-tab-fixed id="tab"></nav-tab-fixed>
44
45 <main>
46 <p>
47 Esta página usa navegación por pestañas filas. Las X que siguen son para que
48 veas como se comporta cuando se hace scroll.
49 </p>
50 <p>x</p>
51 <p>x</p>
52 <p>x</p>
53 <p>x</p>
54 <p>x</p>
55 <p>x</p>
56 <p>x</p>
57 <p>x</p>
58 <p>x</p>
59 <p>x</p>
60 <p>x</p>
61 <p>x</p>
62 <p>x</p>
63 <p>x</p>
64 <p>x</p>
65 <p>x</p>
66 <p>x</p>
67 <p>x</p>
68 <p>x</p>
69 <p>x</p>
70 <p>x</p>
71 <p>x</p>
72 <p>x</p>
73 </main>
74
75</body>
76
77</html>

21. navbar.html - Barra de navegación

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Barra de Navegación - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_pestanas.css">
20 <link rel="expect" blocking="render" href="#navbar">
21
22</head>
23
24<body
25 style="padding-bottom: 5rem;">
26
27 <md-top-app-bar headline="headline">
28
29 <h1>navegación</h1>
30
31 <button type="button" class="md-standard-icon-button" title="Agregar"
32 slot="action">
33 <span class="material-symbols-outlined">add</span>
34 </button>
35 <button type="button" class="md-standard-icon-button" title="Editar"
36 slot="action">
37 <span class="material-symbols-outlined">edit</span>
38 </button>
39
40 </md-top-app-bar>
41
42 <h1 id="headline">Barra de navegación</h1>
43
44 <main>
45 <p>
46 Esta página usa barra de navegación. Las X que siguen son para que veas como
47 se comporta cuando se hace scroll.
48 </p>
49 <p>x</p>
50 <p>x</p>
51 <p>x</p>
52 <p>x</p>
53 <p>x</p>
54 <p>x</p>
55 <p>x</p>
56 <p>x</p>
57 <p>x</p>
58 <p>x</p>
59 <p>x</p>
60 <p>x</p>
61 <p>x</p>
62 <p>x</p>
63 <p>x</p>
64 <p>x</p>
65 <p>x</p>
66 <p>x</p>
67 <p>x</p>
68 <p>x</p>
69 <p>x</p>
70 <p>x</p>
71 <p>x</p>
72 </main>
73
74 <nav-bar></nav-bar>
75
76</body>
77
78</html>

Solo para los más rudos

22. formulario.html - Formulario típico

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Formulario - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <form id="form" novalidate onsubmit="procesa(event)">
26
27 <md-top-app-bar>
28
29 <h1>Formulario</h1>
30
31 <button is="md-menu-button" slot="navigation"></button>
32
33 </md-top-app-bar>
34
35 <main>
36
37 <p>
38 <span class="md-filled-text-field" accesskey="G">
39 <md-select-menu id="selectGenero" required options="opcionesDeGenero"
40 oninput="copiaMensajes()"></md-select-menu>
41 <span>Género *</span>
42 <small id="supportingGenero">Obligatorio</small>
43 </span>
44 </p>
45
46 <p>
47 <button class="md-filled-button" style="width: 100%;">Recomendar</button>
48 </p>
49
50 </main>
51
52 <md-options-menu id="opcionesDeGenero" aria-label="Opciones de género">
53 <span data-value="" title="Selecciona género"></span>
54 <span data-value="pop">Pop</span>
55 <span data-value="reg">Reguetón</span>
56 </md-options-menu>
57
58 <nav-drw></nav-drw>
59
60 </form>
61
62 <script type="module">
63 import { muestraTextoDeAyuda } from "./lib/js/muestraTextoDeAyuda.js"
64 import { exportaAHtml } from "./lib/js/exportaAHtml.js"
65 import { muestraError } from "./lib/js/muestraError.js"
66
67 function copiaMensajes() {
68 muestraTextoDeAyuda(selectGenero, supportingGenero, "Obligatorio")
69 }
70 exportaAHtml(copiaMensajes)
71
72 /**
73 * @param {SubmitEvent} evt
74 */
75 function procesa(evt) {
76 evt.preventDefault()
77 try {
78 copiaMensajes()
79 if (
80 selectGenero.validity.valid) {
81 const genero = selectGenero.value
82 const resultado = recomienda(genero)
83 alert(resultado)
84 }
85 } catch (e) {
86 muestraError(e)
87 }
88 }
89 exportaAHtml(procesa)
90
91 /** @param {string} genero */
92 function recomienda(genero) {
93 if (genero === "pop") {
94 return "Para el pop te recomiendo a Dua Lipa."
95 } else if (genero === "reg") {
96 return "Para el reguetón te recomiendo a Bad Bunny."
97 }
98 }
99 </script>
100
101</body>
102
103</html>

23. ayuda.html - Vista de ayuda

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es" class="light dark">
3
4<head>
5
6 <meta charset="UTF-8">
7 <title>Ayuda - PWA con MD</title>
8
9 <script src="js/registraServiceWorker.js"></script>
10
11 <meta name="viewport" content="width=device-width">
12 <meta name="theme-color" content="#fffbfe">
13 <link rel="icon" sizes="32x32" href="favicon.ico">
14 <link rel="manifest" href="site.webmanifest">
15 <script src="ungap/custom-elements.js"></script>
16
17 <script type="module" src="js/configura.js"></script>
18 <link rel="stylesheet" href="css/estilos.css">
19 <link rel="stylesheet" href="css/transicion_completa.css">
20
21</head>
22
23<body>
24
25 <md-top-app-bar>
26
27 <h1>Ayuda</h1>
28
29 <button is="md-menu-button" slot="navigation"></button>
30
31 </md-top-app-bar>
32
33 <main>
34
35 <ul class="md-list">
36 <li class="md-two-line">
37 <span class="headline">
38 Título
39 </span>
40 <span class="supporting">
41 PWA con Material Design
42 </span>
43 </li>
44 <li class="md-two-line">
45 <span class="headline">
46 Descripción
47 </span>
48 <span class="supporting">
49 Ejemplos de vistas móviles.
50 </span>
51 </li>
52 <li class="md-two-line">
53 <span class="headline">
54 Autor
55 </span>
56 <span class="supporting">
57 Gilberto Pacheco Gallegos
58 </span>
59 </li>
60 <li class="md-two-line">
61 <span class="headline">
62 Derechos de autor
63 </span>
64 <span class="supporting">
65 © 2024 Gilberto Pacheco Gallegos
66 </span>
67 </li>
68 <li class="md-three-line">
69 <span class="headline">
70 Este software usa la librería para PWA
71 </span>
72 <span class="supporting">
73 Esta obra de Gilberto Pacheco Gallegos está bajo una
74 <a target="_blank" rel="license noreferrer"
75 href="http://creativecommons.org/licenses/by/4.0/">
76 Licencia Creative Commons Atribución 4.0 Internacional</a></span>
77 </li>
78 <li>
79 <a class="md-three-line" target="_blank" rel=”noreferrer”
80 href="https://fonts.google.com/icons">
81 <span class="headline">
82 También usa Material Symbols
83 </span>
84 <span class="supporting">
85 Desarrollada por Google bajo licencia Apache 2.0
86 </span>
87 </a>
88 </li>
89 </ul>
90
91 </main>
92
93 <nav-drw></nav-drw>
94
95</body>
96
97</html>

24. Carpeta « js »

Versión para imprimir.

A. js / configura.js

1/** Barra de navegación. */
2import "./nav-drw.js"
3import "./nav-tab-scrollable.js"
4import "./nav-tab-fixed.js"
5import "./nav-bar.js"
6/** Elementos utilizados */
7import "../lib/js/custom/md-menu-button.js"
8import "../lib/js/custom/md-options-menu.js"
9import "../lib/js/custom/md-overflow-button.js"
10import "../lib/js/custom/md-overflow-menu.js"
11import "../lib/js/custom/md-select-menu.js"
12import "../lib/js/custom/md-top-app-bar.js"
13import "../lib/js/custom/md-slider-field.js"

B. js / nav-bar.js

1import { resaltaSiEstasEn } from "../lib/js/resaltaSiEstasEn.js"
2
3export class NavBar extends HTMLElement {
4
5 connectedCallback() {
6 this.classList.add("md-navigation-bar")
7
8 this.innerHTML = /* HTML */`
9 <a ${resaltaSiEstasEn(["/index.html", "", "/"])} href="index.html">
10 <span class="material-symbols-outlined">home</span>
11 Inicio
12 </a>
13
14 <a ${resaltaSiEstasEn(["/navTabFixed.html"])} href="navTabFixed.html">
15 <span class="material-symbols-outlined">tabs</span>
16 Pestañas
17 </a>
18
19 <a id="navbar" ${resaltaSiEstasEn(["/navbar.html"])} href="navbar.html">
20 <span class="material-symbols-outlined">bottom_navigation</span>
21 Barra
22 </a>
23
24 <a ${resaltaSiEstasEn(["/formulario.html"])} href="formulario.html">
25 <span class="material-symbols-outlined">newspaper</span>
26 Forma
27 </a>`
28
29 }
30
31}
32
33customElements.define("nav-bar", NavBar)

C. js / nav-drw.js

1import { resaltaSiEstasEn } from "../lib/js/resaltaSiEstasEn.js"
2import { MdNavigationDrawer } from "../lib/js/custom/MdNavigationDrawer.js"
3
4export class NavDrw extends MdNavigationDrawer {
5
6 /**
7 * @override
8 */
9 getHipervinculos() {
10 return /* HTML */`
11 <h1>PWA con MD</h1>
12
13 <a ${resaltaSiEstasEn(["/index.html", "", "/"])} href="index.html">
14 <span class="material-symbols-outlined">home</span>
15 Inicio
16 </a>
17
18 <a ${resaltaSiEstasEn(["/secundaria.html"])} href="secundaria.html">
19 <span class="material-symbols-outlined">scrollable_header</span>
20 Página secundaria
21 </a>
22
23 <a ${resaltaSiEstasEn(["/iconos.html"])} href="iconos.html">
24 <span class="material-symbols-outlined">sentiment_satisfied</span>
25 Íconos
26 </a>
27
28 <a ${resaltaSiEstasEn(["/botones.html"])} href="botones.html">
29 <span class="material-symbols-outlined">right_click</span>
30 Botones
31 </a>
32
33 <a ${resaltaSiEstasEn(["/campos.html"])} href="campos.html">
34 <span class="material-symbols-outlined">password</span>
35 Campos de texto
36 </a>
37
38 <a ${resaltaSiEstasEn(["/select.html"])} href="select.html">
39 <span class="material-symbols-outlined">bottom_panel_close</span>
40 Select
41 </a>
42
43 <a ${resaltaSiEstasEn(["/interruptor.html"])} href="interruptor.html">
44 <span class="material-symbols-outlined">toggle_on</span>
45 Interruptores
46 </a>
47
48 <a ${resaltaSiEstasEn(["/slider.html"])} href="slider.html">
49 <span class="material-symbols-outlined">linear_scale</span>
50 Sliders
51 </a>
52
53 <a ${resaltaSiEstasEn(["/segmentado.html"])} href="segmentado.html">
54 <span class="material-symbols-outlined">splitscreen_left</span>
55 Botón segmentado
56 </a>
57
58 <a ${resaltaSiEstasEn(["/one-line.html"])} href="one-line.html">
59 <span class="material-symbols-outlined">list</span>
60 Listas one-line
61 </a>
62
63 <a ${resaltaSiEstasEn(["/two-line.html"])} href="two-line.html">
64 <span class="material-symbols-outlined">lists</span>
65 Listas two-line
66 </a>
67
68 <a ${resaltaSiEstasEn(["/three-line.html"])} href="three-line.html">
69 <span class="material-symbols-outlined">receipt_long</span>
70 Listas three-line
71 </a>
72
73 <a ${resaltaSiEstasEn(["/tarjetas.html"])} href="tarjetas.html">
74 <span class="material-symbols-outlined">cards</span>
75 Tarjetas
76 </a>
77
78 <a ${resaltaSiEstasEn(["/navtab.html"])} href="navtab.html">
79 <span class="material-symbols-outlined">swipe_left</span>
80 Pestañas scrollable
81 </a>
82
83 <a ${resaltaSiEstasEn(["/navTabFixed.html"])} href="navTabFixed.html">
84 <span class="material-symbols-outlined">tabs</span>
85 Pestañas fijas
86 </a>
87
88 <a ${resaltaSiEstasEn(["/navbar.html"])} href="navbar.html">
89 <span class="material-symbols-outlined">bottom_navigation</span>
90 Barra de navegación
91 </a>
92
93 <a ${resaltaSiEstasEn(["/formulario.html"])} href="formulario.html">
94 <span class="material-symbols-outlined">newspaper</span>
95 Formulario
96 </a>
97
98 <a ${resaltaSiEstasEn(["/ayuda.html"])} href="ayuda.html">
99 <span class="material-symbols-outlined">help</span>
100 Ayuda
101 </a>`
102 }
103
104}
105
106customElements.define("nav-drw", NavDrw)

D. js / nav-tab-fixed.js

1import { resaltaSiEstasEn } from "../lib/js/resaltaSiEstasEn.js"
2
3export class NavTabFixed extends HTMLElement {
4
5 connectedCallback() {
6 this.classList.add("md-tab", "fixed")
7
8 this.innerHTML = /* HTML */`
9 <a ${resaltaSiEstasEn(["/index.html", "", "/"])} href="index.html">
10 <span class="material-symbols-outlined">home</span>
11 Inicio
12 </a>
13
14 <a ${resaltaSiEstasEn(["/navtab.html"])} href="navtab.html">
15 <span class="material-symbols-outlined">swipe_left</span>
16 Pestañas scrollable
17 </a>
18
19 <a id="navtabfixed" ${resaltaSiEstasEn(["/navTabFixed.html"])}
20 href="navTabFixed.html">
21 <span class="material-symbols-outlined">tabs</span>
22 Pestañas fijas
23 </a>
24
25 <a ${resaltaSiEstasEn(["/navbar.html"])} href="navbar.html">
26 <span class="material-symbols-outlined">bottom_navigation</span>
27 Barra de navegación
28 </a>`
29 }
30
31}
32
33customElements.define("nav-tab-fixed", NavTabFixed)

E. js / nav-tab-scrollable.js

1import { querySelector } from "../lib/js/querySelector.js"
2import { resaltaSiEstasEn } from "../lib/js/resaltaSiEstasEn.js"
3
4export class NavTabScrollable extends HTMLElement {
5
6 connectedCallback() {
7 this.classList.add("md-tab", "scrollable")
8
9 this.innerHTML = /* HTML */`
10 <a ${resaltaSiEstasEn(["/index.html", "", "/"])} href="index.html">
11 <span class="material-symbols-outlined">home</span>
12 Inicio
13 </a>
14
15 <a ${resaltaSiEstasEn(["/secundaria.html"])} href="secundaria.html">
16 <span class="material-symbols-outlined">scrollable_header</span>
17 Página secundaria
18 </a>
19
20 <a ${resaltaSiEstasEn(["/iconos.html"])} href="iconos.html">
21 <span class="material-symbols-outlined">sentiment_satisfied</span>
22 Íconos
23 </a>
24
25 <a ${resaltaSiEstasEn(["/botones.html"])} href="botones.html">
26 <span class="material-symbols-outlined">right_click</span>
27 Botones
28 </a>
29
30 <a ${resaltaSiEstasEn(["/campos.html"])} href="campos.html">
31 <span class="material-symbols-outlined">password</span>
32 Campos de texto
33 </a>
34
35 <a ${resaltaSiEstasEn(["/select.html"])} href="select.html">
36 <span class="material-symbols-outlined">bottom_panel_close</span>
37 Select
38 </a>
39
40 <a ${resaltaSiEstasEn(["/interruptor.html"])} href="interruptor.html">
41 <span class="material-symbols-outlined">toggle_on</span>
42 Interruptores
43 </a>
44
45 <a ${resaltaSiEstasEn(["/slider.html"])} href="slider.html">
46 <span class="material-symbols-outlined">linear_scale</span>
47 Sliders
48 </a>
49
50 <a ${resaltaSiEstasEn(["/segmentado.html"])} href="segmentado.html">
51 <span class="material-symbols-outlined">splitscreen_left</span>
52 Botón segmentado
53 </a>
54
55 <a ${resaltaSiEstasEn(["/one-line.html"])} href="one-line.html">
56 <span class="material-symbols-outlined">list</span>
57 Listas one-line
58 </a>
59
60 <a ${resaltaSiEstasEn(["/two-line.html"])} href="two-line.html">
61 <span class="material-symbols-outlined">lists</span>
62 Listas two-line
63 </a>
64
65 <a ${resaltaSiEstasEn(["/three-line.html"])} href="three-line.html">
66 <span class="material-symbols-outlined">receipt_long</span>
67 Listas three-line
68 </a>
69
70 <a ${resaltaSiEstasEn(["/tarjetas.html"])} href="tarjetas.html">
71 <span class="material-symbols-outlined">cards</span>
72 Tarjetas
73 </a>
74
75 <a id="navtab" ${resaltaSiEstasEn(["/navtab.html"])} href="navtab.html">
76 <span class="material-symbols-outlined">swipe_left</span>
77 Pestañas scrollable
78 </a>
79
80 <a ${resaltaSiEstasEn(["/navTabFixed.html"])} href="navTabFixed.html">
81 <span class="material-symbols-outlined">tabs</span>
82 Pestañas fijas
83 </a>
84
85 <a ${resaltaSiEstasEn(["/navbar.html"])} href="navbar.html">
86 <span class="material-symbols-outlined">bottom_navigation</span>
87 Barra de navegación
88 </a>
89
90 <a ${resaltaSiEstasEn(["/formulario.html"])} href="formulario.html">
91 <span class="material-symbols-outlined">newspaper</span>
92 Formulario
93 </a>
94
95 <a ${resaltaSiEstasEn(["/ayuda.html"])} href="ayuda.html">
96 <span class="material-symbols-outlined">help</span>
97 Ayuda
98 </a>`
99
100 }
101
102}
103
104customElements.define("nav-tab-scrollable", NavTabScrollable)

F. js / registraServiceWorker.js

1"use strict" // usa JavaScript en modo estricto.
2
3const nombreDeServiceWorker = "sw.js"
4
5try {
6 navigator.serviceWorker.register(nombreDeServiceWorker)
7 .then(registro => {
8 console.log(nombreDeServiceWorker, "registrado.")
9 console.log(registro)
10 })
11 .catch(error => console.log(error))
12} catch (error) {
13 console.log(error)
14}

25. site.webmanifest

  • Este archivo sirve para configurar los instaladores de la aplicación.

Explicación de las propiedades

short_name

Nombre corto. Normalmente se despliega en dispositivos móviles. Máximo 20 caracteres.

name

Nombre largo. Normalmente se despliega en computadoras de escritorio. Máximo 30 caracteres.

id

Identificador del archivo de instalación. Normalmente es la ruta del archivo inicial de la app.

start_url

Ruta del archivo inicial de la app.

display

Forma de mostrar la app. El término standalone significa que no se muestra la barra de navegación del navegador web.

theme_color

Color de la barra de estado (en dispositivos móviles) o de título (en computadoras de escritorio) de la app.

background_color

Color de fondo de la pantalla desplah en dispositivos móviles.

description

Describe el propósito de la aplicación. Aparece en el cuadro de diálogo que muestra el navegador al instalar la app.

screenshots

Listado de máximo 8 capturas de pantalla. Aparecen en el cuadro de diálogo que muestra el navegador al instalar la app. Debes incluir al menos una con "form_factor": "wide" y otra con "form_factor": "narrow".

icons

Listado de íconos en distintas resoluciones para los instaladores de la app. Se selecciona el que se vea mejor según las característocas del dispositivo.

src

Url de la imagen dentro de la app.

sizes

Dimensiones en pixeles de la imagen, anchoxalto.

type

Tipo mime de la imagen.

purpose

Forma en que se usa la imagen.

maskable

La imagen puede recortarse de forma segura para tomar distintas formas, como círculos, gotas, cuadrados con esquinas redondeadas, etc. Normalmente se usa para dispositivos móviles.

any

No se puede asegurar nada sobre la imagen. Normalmente se usa para dispositivos de escritorio.

Normalmente debe proporcionarse un juego de íconos con purpose any y otro juego de íconos con purpose maskable.

form_factor

Orientación de una screenshot.

wide

La screenshot tiene una orientación horizontal. Normalmente la creenshot se usa para dispositivos de escritorio.

narrow

La screenshot tiene una orientación vertical. Normalmente la creenshot se usa para dispositivos móviles.

Debes incluir al menos una screenshot con "form_factor": "wide" y otra con "form_factor": "narrow".

label

Descripción de una screenshot. Aparece en el cuadro de diálogo que muestra el navegador al instalar la app.

1{
2 "short_name": "PWA con MD",
3 "name": "PWA con Material Design",
4 "id": "/index.html",
5 "start_url": "/index.html",
6 "display": "standalone",
7 "theme_color": "#fffbfe",
8 "background_color": "#fffbfe",
9 "display_override": [
10 "window-controls-overlay"
11 ],
12 "description": "PWA con componentes de Material Design.",
13 "screenshots": [
14 {
15 "src": "/img/screenshot_horizontal.png",
16 "sizes": "1257x646",
17 "type": "image/png",
18 "form_factor": "wide",
19 "label": "PWA con Material Design"
20 },
21 {
22 "src": "/img/screenshot_vertical.png",
23 "sizes": "595x644",
24 "type": "image/png",
25 "form_factor": "narrow",
26 "label": "PWA con Material Design (2)"
27 }
28 ],
29 "icons": [
30 {
31 "src": "/img/maskable_icon_x48.png",
32 "sizes": "48x48",
33 "type": "image/png",
34 "purpose": "any"
35 },
36 {
37 "src": "/img/maskable_icon_x72.png",
38 "sizes": "72x72",
39 "type": "image/png",
40 "purpose": "any"
41 },
42 {
43 "src": "/img/maskable_icon_x96.png",
44 "sizes": "96x96",
45 "type": "image/png",
46 "purpose": "maskable"
47 },
48 {
49 "src": "/img/maskable_icon_x128.png",
50 "sizes": "128x128",
51 "type": "image/png",
52 "purpose": "any"
53 },
54 {
55 "src": "/img/maskable_icon_x192.png",
56 "sizes": "192x192",
57 "type": "image/png",
58 "purpose": "any"
59 },
60 {
61 "src": "/img/maskable_icon_x384.png",
62 "sizes": "384x384",
63 "type": "image/png",
64 "purpose": "any"
65 },
66 {
67 "src": "/img/maskable_icon_x512.png",
68 "sizes": "512x512",
69 "type": "image/png",
70 "purpose": "any"
71 },
72 {
73 "src": "/img/maskable_icon.png",
74 "sizes": "3413x3413",
75 "type": "image/png",
76 "purpose": "any"
77 },
78 {
79 "src": "/img/icono2048.png",
80 "sizes": "2048x2048",
81 "type": "image/png",
82 "purpose": "any"
83 },
84 {
85 "src": "/img/maskable_icon_x48.png",
86 "sizes": "48x48",
87 "type": "image/png",
88 "purpose": "maskable"
89 },
90 {
91 "src": "/img/maskable_icon_x72.png",
92 "sizes": "72x72",
93 "type": "image/png",
94 "purpose": "maskable"
95 },
96 {
97 "src": "/img/maskable_icon_x96.png",
98 "sizes": "96x96",
99 "type": "image/png",
100 "purpose": "maskable"
101 },
102 {
103 "src": "/img/maskable_icon_x128.png",
104 "sizes": "128x128",
105 "type": "image/png",
106 "purpose": "maskable"
107 },
108 {
109 "src": "/img/maskable_icon_x192.png",
110 "sizes": "192x192",
111 "type": "image/png",
112 "purpose": "maskable"
113 },
114 {
115 "src": "/img/maskable_icon_x384.png",
116 "sizes": "384x384",
117 "type": "image/png",
118 "purpose": "maskable"
119 },
120 {
121 "src": "/img/maskable_icon_x512.png",
122 "sizes": "512x512",
123 "type": "image/png",
124 "purpose": "maskable"
125 },
126 {
127 "src": "/img/maskable_icon.png",
128 "sizes": "3413x3413",
129 "type": "image/png",
130 "purpose": "maskable"
131 }
132 ]
133}

26. instruccionesListadoSw.txt

1Generar el listado de archivos del sw.js desde Visual Studio Code.
21. Abrir una terminal desde el menú
3 Terminal > New Terminal
4
52. Desde la terminal introducir la orden:
6 Get-ChildItem -path . -Recurse | Select Directory,Name | Out-File archivos.txt
7
83. Abrir el archivo generado, que se llama
9 archivos.txt
10 y sobre este, realizar los pasos que siguen:
11
124. Quita del archivo archivos.txt:
13 * el encabezado,
14 * todas las carpetas,
15 * el archivo .vscode/settings.json,
16 * el archivo .htaccess,
17 * el archivo archivos.txt,
18 * este archivo (instruccionesListadoSw.txt),
19 * el archivo jsconfig.json,
20 * el archivo sw.js,
21 * el archivo de la base de datos, que termina en ".bd" y
22 está en la carpeta srv,
23 * todos los archivos de php y
24 * las líneas en blanco del final
25
265. Cambia los \ por / desde Visual Studio Code con las siguientes
27 combinaciones de teclas:
28
29 Ctrl+H En el diálogo que aparece introduce lo siguiente:
30 Find:\
31 Replace:/
32
33 Clic en el icono Reemplaza todo o Replace All y luego teclea ESC
34
356. Coloca las comillas y coma del final de cada línea desde Visual
36 Studio Code con las siguientes combinaciones de teclas:
37
38 Ctrl+H En el diálogo que aparece, selecciona el botón
39 ".*"
40 e introduce lo siguiente:
41 Find:\s*$
42 Replace:",
43
44 Clic en el icono Reemplaza todo o Replace All y luego teclea ESC
45
467. Marca la carpeta inicial, presiona la combinación de teclas:
47
48 Shift+Ctrl+L
49
50 borra la selección, teclea " y luego ESC
51
528. Cambia las secuencias de espacios por / con las siguientes
53 combinaciones de teclas:
54
55 Ctrl+H En el diálogo que aparece, selecciona el botón
56 ".*"
57 e introduce lo siguiente:
58 Find:\s+
59 Replace:/
60
61 Clic en el icono Reemplaza todo o Replace All y luego teclea ESC
62
639. Cambia las "/ por " con las siguientes combinaciones de teclas:
64
65 Ctrl+H En el diálogo que aparece, quita la selección del botón
66 ".*"
67 e introduce lo siguiente:
68 Find:"/
69 Replace:"
70
71 Clic en el icono Reemplaza todo o Replace All y luego teclea ESC
72
7310. Copia el texto al archivo
74 sw.js
75 en el contenido del arreglo llamado ARCHIVOS, pero recuerda
76 mantener el último elemento, que dice:
77 "/"

27. archivos.txt

1"ayuda.html",
2"botones.html",
3"campos.html",
4"favicon.ico",
5"formulario.html",
6"iconos.html",
7"index.html",
8"interruptor.html",
9"navbar.html",
10"navtab.html",
11"navTabFixed.html",
12"one-line.html",
13"secundaria.html",
14"segmentado.html",
15"select.html",
16"site.webmanifest",
17"slider.html",
18"tarjetas.html",
19"three-line.html",
20"two-line.html",
21"css/dark-hc.css",
22"css/dark-mc.css",
23"css/dark.css",
24"css/estilos.css",
25"css/light-hc.css",
26"css/light-mc.css",
27"css/light.css",
28"css/transicion_completa.css",
29"css/transicion_pestanas.css",
30"img/Escultura_de_coyote.jpeg",
31"img/icono2048.png",
32"img/maskable_icon.png",
33"img/maskable_icon_x128.png",
34"img/maskable_icon_x192.png",
35"img/maskable_icon_x384.png",
36"img/maskable_icon_x48.png",
37"img/maskable_icon_x512.png",
38"img/maskable_icon_x72.png",
39"img/maskable_icon_x96.png",
40"img/pexels-craig-dennis-3701822.jpg",
41"img/pexels-creative-workshop-3978352.jpg",
42"img/pexels-erik-karits-3732453.jpg",
43"img/pexels-esteban-arango-10226903.jpg",
44"img/pexels-moises-patrício-10961948.jpg",
45"img/pexels-ralph-2270848.jpg",
46"img/pexels-rasmus-svinding-35435.jpg",
47"img/pexels-steve-397857.jpg",
48"img/pexels-vadim-b-141496.jpg",
49"img/screenshot_horizontal.png",
50"img/screenshot_vertical.png",
51"js/configura.js",
52"js/nav-bar.js",
53"js/nav-drw.js",
54"js/nav-tab-fixed.js",
55"js/nav-tab-scrollable.js",
56"js/registraServiceWorker.js",
57"lib/css/material-symbols-outlined.css",
58"lib/css/md-cards.css",
59"lib/css/md-fab-primary.css",
60"lib/css/md-filled-button.css",
61"lib/css/md-filled-text-field.css",
62"lib/css/md-list.css",
63"lib/css/md-menu.css",
64"lib/css/md-navigation-bar.css",
65"lib/css/md-outline-button.css",
66"lib/css/md-ripple.css",
67"lib/css/md-segmented-button.css",
68"lib/css/md-slider-field.css",
69"lib/css/md-standard-icon-button.css",
70"lib/css/md-switch.css",
71"lib/css/md-tab.css",
72"lib/css/md-top-app-bar.css",
73"lib/css/roboto.css",
74"lib/fonts/MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].codepoints",
75"lib/fonts/MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].ttf",
76"lib/fonts/MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].woff2",
77"lib/fonts/roboto-v32-latin-regular.woff2",
78"lib/js/abreElementoHtml.js",
79"lib/js/cierraElementoHtmo.js",
80"lib/js/exportaAHtml.js",
81"lib/js/getAttribute.js",
82"lib/js/htmlentities.js",
83"lib/js/muestraError.js",
84"lib/js/muestraTextoDeAyuda.js",
85"lib/js/ProblemDetails.js",
86"lib/js/querySelector.js",
87"lib/js/resaltaSiEstasEn.js",
88"lib/js/const/ES_APPLE.js",
89"lib/js/custom/md-menu-button.js",
90"lib/js/custom/md-options-menu.js",
91"lib/js/custom/md-overflow-button.js",
92"lib/js/custom/md-overflow-menu.js",
93"lib/js/custom/md-select-menu.js",
94"lib/js/custom/md-slider-field.js",
95"lib/js/custom/md-top-app-bar.js",
96"lib/js/custom/MdNavigationDrawer.js",
97"material-tokens/css/baseline.css",
98"material-tokens/css/colors.css",
99"material-tokens/css/elevation.css",
100"material-tokens/css/motion.css",
101"material-tokens/css/palette.css",
102"material-tokens/css/shape.css",
103"material-tokens/css/state.css",
104"material-tokens/css/typography.css",
105"material-tokens/css/theme/dark.css",
106"material-tokens/css/theme/light.css",
107"ungap/custom-elements.js",

28. sw.js

1/* Este archivo debe estar colocado en la carpeta raíz del sitio.
2 *
3 * Cualquier cambio en el contenido de este archivo hace que el service
4 * worker se reinstale. */
5
6/**
7 * Cambia el número de la versión cuando cambia el contenido de los
8 * archivos.
9 *
10 * El número a la izquierda del punto (.), en este caso <q>1</q>, se
11 * conoce como número mayor y se cambia cuando se realizan
12 * modificaciones grandes o importantes.
13 *
14 * El número a la derecha del punto (.), en este caso <q>00</q>, se
15 * conoce como número menor y se cambia cuando se realizan
16 * modificaciones menores.
17 */
18const VERSION = "1.00"
19
20/**
21 * Nombre de la carpeta de caché.
22 */
23const CACHE = "pwamd"
24
25/**
26 * Archivos requeridos para que la aplicación funcione fuera de
27 * línea.
28 */
29const ARCHIVOS = [
30 "ayuda.html",
31 "botones.html",
32 "campos.html",
33 "favicon.ico",
34 "formulario.html",
35 "iconos.html",
36 "index.html",
37 "interruptor.html",
38 "navbar.html",
39 "navtab.html",
40 "navTabFixed.html",
41 "one-line.html",
42 "secundaria.html",
43 "segmentado.html",
44 "select.html",
45 "site.webmanifest",
46 "slider.html",
47 "tarjetas.html",
48 "three-line.html",
49 "two-line.html",
50 "css/dark-hc.css",
51 "css/dark-mc.css",
52 "css/dark.css",
53 "css/estilos.css",
54 "css/light-hc.css",
55 "css/light-mc.css",
56 "css/light.css",
57 "css/transicion_completa.css",
58 "css/transicion_pestanas.css",
59 "img/Escultura_de_coyote.jpeg",
60 "img/icono2048.png",
61 "img/maskable_icon.png",
62 "img/maskable_icon_x128.png",
63 "img/maskable_icon_x192.png",
64 "img/maskable_icon_x384.png",
65 "img/maskable_icon_x48.png",
66 "img/maskable_icon_x512.png",
67 "img/maskable_icon_x72.png",
68 "img/maskable_icon_x96.png",
69 "img/pexels-craig-dennis-3701822.jpg",
70 "img/pexels-creative-workshop-3978352.jpg",
71 "img/pexels-erik-karits-3732453.jpg",
72 "img/pexels-esteban-arango-10226903.jpg",
73 "img/pexels-moises-patrício-10961948.jpg",
74 "img/pexels-ralph-2270848.jpg",
75 "img/pexels-rasmus-svinding-35435.jpg",
76 "img/pexels-steve-397857.jpg",
77 "img/pexels-vadim-b-141496.jpg",
78 "img/screenshot_horizontal.png",
79 "img/screenshot_vertical.png",
80 "js/configura.js",
81 "js/nav-bar.js",
82 "js/nav-drw.js",
83 "js/nav-tab-fixed.js",
84 "js/nav-tab-scrollable.js",
85 "js/registraServiceWorker.js",
86 "lib/css/material-symbols-outlined.css",
87 "lib/css/md-cards.css",
88 "lib/css/md-fab-primary.css",
89 "lib/css/md-filled-button.css",
90 "lib/css/md-filled-text-field.css",
91 "lib/css/md-list.css",
92 "lib/css/md-menu.css",
93 "lib/css/md-navigation-bar.css",
94 "lib/css/md-outline-button.css",
95 "lib/css/md-ripple.css",
96 "lib/css/md-segmented-button.css",
97 "lib/css/md-slider-field.css",
98 "lib/css/md-standard-icon-button.css",
99 "lib/css/md-switch.css",
100 "lib/css/md-tab.css",
101 "lib/css/md-top-app-bar.css",
102 "lib/css/roboto.css",
103 "lib/fonts/MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].codepoints",
104 "lib/fonts/MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].ttf",
105 "lib/fonts/MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].woff2",
106 "lib/fonts/roboto-v32-latin-regular.woff2",
107 "lib/js/abreElementoHtml.js",
108 "lib/js/cierraElementoHtmo.js",
109 "lib/js/exportaAHtml.js",
110 "lib/js/getAttribute.js",
111 "lib/js/htmlentities.js",
112 "lib/js/muestraError.js",
113 "lib/js/muestraTextoDeAyuda.js",
114 "lib/js/ProblemDetails.js",
115 "lib/js/querySelector.js",
116 "lib/js/resaltaSiEstasEn.js",
117 "lib/js/const/ES_APPLE.js",
118 "lib/js/custom/md-menu-button.js",
119 "lib/js/custom/md-options-menu.js",
120 "lib/js/custom/md-overflow-button.js",
121 "lib/js/custom/md-overflow-menu.js",
122 "lib/js/custom/md-select-menu.js",
123 "lib/js/custom/md-slider-field.js",
124 "lib/js/custom/md-top-app-bar.js",
125 "lib/js/custom/MdNavigationDrawer.js",
126 "material-tokens/css/baseline.css",
127 "material-tokens/css/colors.css",
128 "material-tokens/css/elevation.css",
129 "material-tokens/css/motion.css",
130 "material-tokens/css/palette.css",
131 "material-tokens/css/shape.css",
132 "material-tokens/css/state.css",
133 "material-tokens/css/typography.css",
134 "material-tokens/css/theme/dark.css",
135 "material-tokens/css/theme/light.css",
136 "ungap/custom-elements.js",
137 "/"
138]
139
140// Verifica si el código corre dentro de un service worker.
141if (self instanceof ServiceWorkerGlobalScope) {
142 // Evento al empezar a instalar el servide worker,
143 self.addEventListener("install",
144 (/** @type {ExtendableEvent} */ evt) => {
145 console.log("El service worker se está instalando.")
146 evt.waitUntil(llenaElCache())
147 })
148
149 // Evento al solicitar información a la red.
150 self.addEventListener("fetch", (/** @type {FetchEvent} */ evt) => {
151 if (evt.request.method === "GET") {
152 evt.respondWith(buscaLaRespuestaEnElCache(evt))
153 }
154 })
155
156 // Evento cuando el service worker se vuelve activo.
157 self.addEventListener("activate",
158 () => console.log("El service worker está activo."))
159}
160
161async function llenaElCache() {
162 console.log("Intentando cargar caché:", CACHE)
163 // Borra todos los cachés.
164 const keys = await caches.keys()
165 for (const key of keys) {
166 await caches.delete(key)
167 }
168 // Abre el caché de este service worker.
169 const cache = await caches.open(CACHE)
170 // Carga el listado de ARCHIVOS.
171 await cache.addAll(ARCHIVOS)
172 console.log("Cache cargado:", CACHE)
173 console.log("Versión:", VERSION)
174}
175
176/** @param {FetchEvent} evt */
177async function buscaLaRespuestaEnElCache(evt) {
178 // Abre el caché.
179 const cache = await caches.open(CACHE)
180 const request = evt.request
181 /* Busca la respuesta a la solicitud en el contenido del caché, sin
182 * tomar en cuenta la parte después del símbolo "?" en la URL. */
183 const response = await cache.match(request, { ignoreSearch: true })
184 if (response === undefined) {
185 /* Si no la encuentra, empieza a descargar de la red y devuelve
186 * la promesa. */
187 return fetch(request)
188 } else {
189 // Si la encuentra, devuelve la respuesta encontrada en el caché.
190 return response
191 }
192}

29. Carpeta « css »

Versión para imprimir.

A. css / dark-hc.css

1.dark-high-contrast {
2 --md-sys-color-primary: rgb(251 250 255);
3 --md-sys-color-surface-tint: rgb(170 199 255);
4 --md-sys-color-on-primary: rgb(0 0 0);
5 --md-sys-color-primary-container: rgb(177 203 255);
6 --md-sys-color-on-primary-container: rgb(0 0 0);
7 --md-sys-color-secondary: rgb(251 250 255);
8 --md-sys-color-on-secondary: rgb(0 0 0);
9 --md-sys-color-secondary-container: rgb(194 203 224);
10 --md-sys-color-on-secondary-container: rgb(0 0 0);
11 --md-sys-color-tertiary: rgb(255 249 250);
12 --md-sys-color-on-tertiary: rgb(0 0 0);
13 --md-sys-color-tertiary-container: rgb(225 192 229);
14 --md-sys-color-on-tertiary-container: rgb(0 0 0);
15 --md-sys-color-error: rgb(255 249 249);
16 --md-sys-color-on-error: rgb(0 0 0);
17 --md-sys-color-error-container: rgb(255 186 177);
18 --md-sys-color-on-error-container: rgb(0 0 0);
19 --md-sys-color-background: rgb(17 19 24);
20 --md-sys-color-on-background: rgb(226 226 233);
21 --md-sys-color-surface: rgb(17 19 24);
22 --md-sys-color-on-surface: rgb(255 255 255);
23 --md-sys-color-surface-variant: rgb(68 71 78);
24 --md-sys-color-on-surface-variant: rgb(251 250 255);
25 --md-sys-color-outline: rgb(200 202 212);
26 --md-sys-color-outline-variant: rgb(200 202 212);
27 --md-sys-color-shadow: rgb(0 0 0);
28 --md-sys-color-scrim: rgb(0 0 0);
29 --md-sys-color-inverse-surface: rgb(226 226 233);
30 --md-sys-color-inverse-on-surface: rgb(0 0 0);
31 --md-sys-color-inverse-primary: rgb(0 41 89);
32 --md-sys-color-primary-fixed: rgb(221 231 255);
33 --md-sys-color-on-primary-fixed: rgb(0 0 0);
34 --md-sys-color-primary-fixed-dim: rgb(177 203 255);
35 --md-sys-color-on-primary-fixed-variant: rgb(0 22 52);
36 --md-sys-color-secondary-fixed: rgb(222 231 253);
37 --md-sys-color-on-secondary-fixed: rgb(0 0 0);
38 --md-sys-color-secondary-fixed-dim: rgb(194 203 224);
39 --md-sys-color-on-secondary-fixed-variant: rgb(13 22 38);
40 --md-sys-color-tertiary-fixed: rgb(252 221 255);
41 --md-sys-color-on-tertiary-fixed: rgb(0 0 0);
42 --md-sys-color-tertiary-fixed-dim: rgb(225 192 229);
43 --md-sys-color-on-tertiary-fixed-variant: rgb(35 14 41);
44 --md-sys-color-surface-dim: rgb(17 19 24);
45 --md-sys-color-surface-bright: rgb(55 57 62);
46 --md-sys-color-surface-container-lowest: rgb(12 14 19);
47 --md-sys-color-surface-container-low: rgb(25 28 32);
48 --md-sys-color-surface-container: rgb(29 32 36);
49 --md-sys-color-surface-container-high: rgb(40 42 47);
50 --md-sys-color-surface-container-highest: rgb(51 53 58);
51}
52

B. css / dark-mc.css

1.dark-medium-contrast {
2 --md-sys-color-primary: rgb(177 203 255);
3 --md-sys-color-surface-tint: rgb(170 199 255);
4 --md-sys-color-on-primary: rgb(0 22 52);
5 --md-sys-color-primary-container: rgb(116 145 199);
6 --md-sys-color-on-primary-container: rgb(0 0 0);
7 --md-sys-color-secondary: rgb(194 203 224);
8 --md-sys-color-on-secondary: rgb(13 22 38);
9 --md-sys-color-secondary-container: rgb(136 145 165);
10 --md-sys-color-on-secondary-container: rgb(0 0 0);
11 --md-sys-color-tertiary: rgb(225 192 229);
12 --md-sys-color-on-tertiary: rgb(35 14 41);
13 --md-sys-color-tertiary-container: rgb(164 135 169);
14 --md-sys-color-on-tertiary-container: rgb(0 0 0);
15 --md-sys-color-error: rgb(255 186 177);
16 --md-sys-color-on-error: rgb(55 0 1);
17 --md-sys-color-error-container: rgb(255 84 73);
18 --md-sys-color-on-error-container: rgb(0 0 0);
19 --md-sys-color-background: rgb(17 19 24);
20 --md-sys-color-on-background: rgb(226 226 233);
21 --md-sys-color-surface: rgb(17 19 24);
22 --md-sys-color-on-surface: rgb(251 250 255);
23 --md-sys-color-surface-variant: rgb(68 71 78);
24 --md-sys-color-on-surface-variant: rgb(200 202 212);
25 --md-sys-color-outline: rgb(160 163 172);
26 --md-sys-color-outline-variant: rgb(128 131 140);
27 --md-sys-color-shadow: rgb(0 0 0);
28 --md-sys-color-scrim: rgb(0 0 0);
29 --md-sys-color-inverse-surface: rgb(226 226 233);
30 --md-sys-color-inverse-on-surface: rgb(40 42 47);
31 --md-sys-color-inverse-primary: rgb(41 72 120);
32 --md-sys-color-primary-fixed: rgb(214 227 255);
33 --md-sys-color-on-primary-fixed: rgb(0 17 43);
34 --md-sys-color-primary-fixed-dim: rgb(170 199 255);
35 --md-sys-color-on-primary-fixed-variant: rgb(19 54 101);
36 --md-sys-color-secondary-fixed: rgb(218 226 249);
37 --md-sys-color-on-secondary-fixed: rgb(8 17 33);
38 --md-sys-color-secondary-fixed-dim: rgb(190 198 220);
39 --md-sys-color-on-secondary-fixed-variant: rgb(46 54 71);
40 --md-sys-color-tertiary-fixed: rgb(250 216 253);
41 --md-sys-color-on-tertiary-fixed: rgb(29 8 35);
42 --md-sys-color-tertiary-fixed-dim: rgb(221 188 224);
43 --md-sys-color-on-tertiary-fixed-variant: rgb(69 46 74);
44 --md-sys-color-surface-dim: rgb(17 19 24);
45 --md-sys-color-surface-bright: rgb(55 57 62);
46 --md-sys-color-surface-container-lowest: rgb(12 14 19);
47 --md-sys-color-surface-container-low: rgb(25 28 32);
48 --md-sys-color-surface-container: rgb(29 32 36);
49 --md-sys-color-surface-container-high: rgb(40 42 47);
50 --md-sys-color-surface-container-highest: rgb(51 53 58);
51}
52

C. css / dark.css

1.dark {
2 --md-sys-color-primary: rgb(170 199 255);
3 --md-sys-color-surface-tint: rgb(170 199 255);
4 --md-sys-color-on-primary: rgb(10 48 95);
5 --md-sys-color-primary-container: rgb(40 71 119);
6 --md-sys-color-on-primary-container: rgb(214 227 255);
7 --md-sys-color-secondary: rgb(190 198 220);
8 --md-sys-color-on-secondary: rgb(40 49 65);
9 --md-sys-color-secondary-container: rgb(62 71 89);
10 --md-sys-color-on-secondary-container: rgb(218 226 249);
11 --md-sys-color-tertiary: rgb(221 188 224);
12 --md-sys-color-on-tertiary: rgb(63 40 68);
13 --md-sys-color-tertiary-container: rgb(87 62 92);
14 --md-sys-color-on-tertiary-container: rgb(250 216 253);
15 --md-sys-color-error: rgb(255 180 171);
16 --md-sys-color-on-error: rgb(105 0 5);
17 --md-sys-color-error-container: rgb(147 0 10);
18 --md-sys-color-on-error-container: rgb(255 218 214);
19 --md-sys-color-background: rgb(17 19 24);
20 --md-sys-color-on-background: rgb(226 226 233);
21 --md-sys-color-surface: rgb(17 19 24);
22 --md-sys-color-on-surface: rgb(226 226 233);
23 --md-sys-color-surface-variant: rgb(68 71 78);
24 --md-sys-color-on-surface-variant: rgb(196 198 208);
25 --md-sys-color-outline: rgb(142 144 153);
26 --md-sys-color-outline-variant: rgb(68 71 78);
27 --md-sys-color-shadow: rgb(0 0 0);
28 --md-sys-color-scrim: rgb(0 0 0);
29 --md-sys-color-inverse-surface: rgb(226 226 233);
30 --md-sys-color-inverse-on-surface: rgb(46 48 54);
31 --md-sys-color-inverse-primary: rgb(65 95 145);
32 --md-sys-color-primary-fixed: rgb(214 227 255);
33 --md-sys-color-on-primary-fixed: rgb(0 27 62);
34 --md-sys-color-primary-fixed-dim: rgb(170 199 255);
35 --md-sys-color-on-primary-fixed-variant: rgb(40 71 119);
36 --md-sys-color-secondary-fixed: rgb(218 226 249);
37 --md-sys-color-on-secondary-fixed: rgb(19 28 43);
38 --md-sys-color-secondary-fixed-dim: rgb(190 198 220);
39 --md-sys-color-on-secondary-fixed-variant: rgb(62 71 89);
40 --md-sys-color-tertiary-fixed: rgb(250 216 253);
41 --md-sys-color-on-tertiary-fixed: rgb(40 19 46);
42 --md-sys-color-tertiary-fixed-dim: rgb(221 188 224);
43 --md-sys-color-on-tertiary-fixed-variant: rgb(87 62 92);
44 --md-sys-color-surface-dim: rgb(17 19 24);
45 --md-sys-color-surface-bright: rgb(55 57 62);
46 --md-sys-color-surface-container-lowest: rgb(12 14 19);
47 --md-sys-color-surface-container-low: rgb(25 28 32);
48 --md-sys-color-surface-container: rgb(29 32 36);
49 --md-sys-color-surface-container-high: rgb(40 42 47);
50 --md-sys-color-surface-container-highest: rgb(51 53 58);
51}
52

D. css / estilos.css

1/* Selecciona el tema claro para Material Design 3. Puedes elegir
2 * light.css, light-mc.css o light-hc.css */
3@import url(light.css) screen and (prefers-color-scheme: light);
4/* Selecciona el tema oscuro para Material Design 3. Puedes elegir
5 * dark.css, dark-mc.css o dark-hc.css */
6@import url(dark.css) screen and (prefers-color-scheme: dark);
7/* Definiciones para Material Design 3 */
8@import url(../material-tokens/css/baseline.css);
9/* Fonts utilizados */
10@import url(../lib/css/roboto.css);
11@import url(../lib/css/material-symbols-outlined.css);
12/* CSS de elementos utilizados */
13@import url(../lib/css/md-ripple.css);
14@import url(../lib/css/md-top-app-bar.css);
15@import url(../lib/css/md-menu.css);
16@import url(../lib/css/md-standard-icon-button.css);
17@import url(../lib/css/md-fab-primary.css);
18@import url(../lib/css/md-filled-button.css);
19@import url(../lib/css/md-filled-text-field.css);
20@import url(../lib/css/md-outline-button.css);
21@import url(../lib/css/md-switch.css);
22@import url(../lib/css/md-slider-field.css);
23@import url(../lib/css/md-segmented-button.css);
24@import url(../lib/css/md-list.css);
25@import url(../lib/css/md-cards.css);
26@import url(../lib/css/md-tab.css);
27@import url(../lib/css/md-navigation-bar.css);
28
29html {
30 /* Indica los temas del sistema operativo que son soportados. */
31 color-scheme: light dark;
32 --tabWidth: 3.75rem;
33 --anchoNav: 22.5rem;
34}
35
36main {
37 max-width: 600px;
38 margin-left: auto;
39 margin-right: auto;
40}
41
42/* Quita un borde rojo que coloca Firefox. */
43:-moz-ui-invalid {
44 box-shadow: none;
45}
46
47body {
48 margin: 0;
49 font-family: var(--md-sys-typescale-body-large-font);
50 font-weight: var(--md-sys-typescale-body-large-weight);
51 font-size: var(--md-sys-typescale-body-large-size);
52 font-style: var(--md-sys-typescale-body-large-font-style);
53 letter-spacing: var(--md-sys-typescale-body-large-tracking);
54 line-height: var(--md-sys-typescale-body-large-line-height);
55 text-transform: var(--md-sys-typescale-body-large-text-transform);
56 text-decoration: var(--md-sys-typescale-body-large-text-decoration);
57 color: var(--md-sys-color-on-background);
58 background-color: var(--md-sys-color-background);
59 /* Las siguientes líneas Evita los cambios de apariencia al cargar estilos y
60 + custom elements, que son conocidos como Flash Of Unstyled Content (fouc). */
61 opacity: 0;
62 animation-name: fouc;
63 animation-fill-mode: forwards;
64 animation-duration: 1.5s;
65}
66
67@keyframes fouc {
68 to {
69 opacity: 1;
70 }
71}
72
73html {
74 --Font: -apple-system, BlinkMacSystemFont, roboto, sans-serif;
75 --colIntIos: white;
76 --colIntIosOnBk: #2acc2a;
77 --colIntIosOnBkFc: #1bbb1b;
78 --colIntIosOffBk: #dbdbdb;
79 --colIntIosOffBkFc: #BDBDBD;
80 /* Plain typeface */
81 --md-ref-typeface-plain: var(--Font);
82 /* Brand typeface */
83 --md-ref-typeface-brand: var(--Font);
84 --md-sys-typescale-label-large-weight-prominent:
85 var(--md-ref-typeface-weight-bold);
86 --md-box_shadow_level4:
87 0 var(--md-sys-elevation-level4) var(--md-sys-elevation-level4) var(--md-sys-color-shadow);
88 --md-box_shadow_level3:
89 0 var(--md-sys-elevation-level3) var(--md-sys-elevation-level3) var(--md-sys-color-shadow);
90 --md-box_shadow_level2:
91 0 var(--md-sys-elevation-level2) var(--md-sys-elevation-level2) var(--md-sys-color-shadow);
92 --md-box_shadow_level1:
93 0 var(--md-sys-elevation-level1) var(--md-sys-elevation-level1) var(--md-sys-color-shadow);
94 --md-box_shadow_level0: none;
95 --iconSize: 1.5rem;
96 --avatarSize: 2.5rem;
97 --imageSize: 3.5rem;
98 --videoWidth: 7.125rem;
99 --videoHeight: 4rem;
100 --scroll-headline-duracion: 2s;
101 --md-sys-state-focus-indicator-outer-offset: 0.125rem;
102 --md-sys-state-focus-indicator-thickness: 0.1875rem;
103 /* Pressed state layer opacity */
104 --state-pressed-transparency-percentage: 84%;
105 /* Focus state layer opacity */
106 --state-focus-transparency-percentage: 88%;
107 /* Hover state layer opacity */
108 --state-hover-transparency-percentage: 92%;
109}
110
111p {
112 margin: 1rem;
113}
114
115a {
116 color: var(--md-sys-color-on-background);
117}
118
119@media (prefers-color-scheme: light) {
120 html {
121 --md-riple-color: #00000020;
122 }
123}
124
125@media (prefers-color-scheme: dark) {
126 html {
127 --md-riple-color: #ffffff40;
128 }
129}
130
131@keyframes salePorLaIzquierda {
132 to {
133 translate: -100vw 0;
134 }
135}
136
137@keyframes entraPorLaDerecha {
138 from {
139 translate: 100vw 0;
140 }
141}
142
143@keyframes aparece {
144 from {
145 opacity: 0;
146 }
147}
148
149@keyframes desvanece {
150 to {
151 opacity: 0;
152 }
153}

E. css / light-hc.css

1.light-high-contrast {
2 --md-sys-color-primary: rgb(0 33 74);
3 --md-sys-color-surface-tint: rgb(65 95 145);
4 --md-sys-color-on-primary: rgb(255 255 255);
5 --md-sys-color-primary-container: rgb(35 67 115);
6 --md-sys-color-on-primary-container: rgb(255 255 255);
7 --md-sys-color-secondary: rgb(25 34 50);
8 --md-sys-color-on-secondary: rgb(255 255 255);
9 --md-sys-color-secondary-container: rgb(58 67 84);
10 --md-sys-color-on-secondary-container: rgb(255 255 255);
11 --md-sys-color-tertiary: rgb(48 26 53);
12 --md-sys-color-on-tertiary: rgb(255 255 255);
13 --md-sys-color-tertiary-container: rgb(82 58 88);
14 --md-sys-color-on-tertiary-container: rgb(255 255 255);
15 --md-sys-color-error: rgb(78 0 2);
16 --md-sys-color-on-error: rgb(255 255 255);
17 --md-sys-color-error-container: rgb(140 0 9);
18 --md-sys-color-on-error-container: rgb(255 255 255);
19 --md-sys-color-background: rgb(249 249 255);
20 --md-sys-color-on-background: rgb(25 28 32);
21 --md-sys-color-surface: rgb(249 249 255);
22 --md-sys-color-on-surface: rgb(0 0 0);
23 --md-sys-color-surface-variant: rgb(224 226 236);
24 --md-sys-color-on-surface-variant: rgb(33 36 43);
25 --md-sys-color-outline: rgb(64 67 74);
26 --md-sys-color-outline-variant: rgb(64 67 74);
27 --md-sys-color-shadow: rgb(0 0 0);
28 --md-sys-color-scrim: rgb(0 0 0);
29 --md-sys-color-inverse-surface: rgb(46 48 54);
30 --md-sys-color-inverse-on-surface: rgb(255 255 255);
31 --md-sys-color-inverse-primary: rgb(229 236 255);
32 --md-sys-color-primary-fixed: rgb(35 67 115);
33 --md-sys-color-on-primary-fixed: rgb(255 255 255);
34 --md-sys-color-primary-fixed-dim: rgb(4 44 91);
35 --md-sys-color-on-primary-fixed-variant: rgb(255 255 255);
36 --md-sys-color-secondary-fixed: rgb(58 67 84);
37 --md-sys-color-on-secondary-fixed: rgb(255 255 255);
38 --md-sys-color-secondary-fixed-dim: rgb(36 45 61);
39 --md-sys-color-on-secondary-fixed-variant: rgb(255 255 255);
40 --md-sys-color-tertiary-fixed: rgb(82 58 88);
41 --md-sys-color-on-tertiary-fixed: rgb(255 255 255);
42 --md-sys-color-tertiary-fixed-dim: rgb(59 36 64);
43 --md-sys-color-on-tertiary-fixed-variant: rgb(255 255 255);
44 --md-sys-color-surface-dim: rgb(217 217 224);
45 --md-sys-color-surface-bright: rgb(249 249 255);
46 --md-sys-color-surface-container-lowest: rgb(255 255 255);
47 --md-sys-color-surface-container-low: rgb(243 243 250);
48 --md-sys-color-surface-container: rgb(237 237 244);
49 --md-sys-color-surface-container-high: rgb(231 232 238);
50 --md-sys-color-surface-container-highest: rgb(226 226 233);
51}
52

F. css / light-mc.css

1.light-medium-contrast {
2 --md-sys-color-primary: rgb(35 67 115);
3 --md-sys-color-surface-tint: rgb(65 95 145);
4 --md-sys-color-on-primary: rgb(255 255 255);
5 --md-sys-color-primary-container: rgb(88 117 168);
6 --md-sys-color-on-primary-container: rgb(255 255 255);
7 --md-sys-color-secondary: rgb(58 67 84);
8 --md-sys-color-on-secondary: rgb(255 255 255);
9 --md-sys-color-secondary-container: rgb(108 117 136);
10 --md-sys-color-on-secondary-container: rgb(255 255 255);
11 --md-sys-color-tertiary: rgb(82 58 88);
12 --md-sys-color-on-tertiary: rgb(255 255 255);
13 --md-sys-color-tertiary-container: rgb(135 107 140);
14 --md-sys-color-on-tertiary-container: rgb(255 255 255);
15 --md-sys-color-error: rgb(140 0 9);
16 --md-sys-color-on-error: rgb(255 255 255);
17 --md-sys-color-error-container: rgb(218 52 46);
18 --md-sys-color-on-error-container: rgb(255 255 255);
19 --md-sys-color-background: rgb(249 249 255);
20 --md-sys-color-on-background: rgb(25 28 32);
21 --md-sys-color-surface: rgb(249 249 255);
22 --md-sys-color-on-surface: rgb(25 28 32);
23 --md-sys-color-surface-variant: rgb(224 226 236);
24 --md-sys-color-on-surface-variant: rgb(64 67 74);
25 --md-sys-color-outline: rgb(92 95 103);
26 --md-sys-color-outline-variant: rgb(120 122 131);
27 --md-sys-color-shadow: rgb(0 0 0);
28 --md-sys-color-scrim: rgb(0 0 0);
29 --md-sys-color-inverse-surface: rgb(46 48 54);
30 --md-sys-color-inverse-on-surface: rgb(240 240 247);
31 --md-sys-color-inverse-primary: rgb(170 199 255);
32 --md-sys-color-primary-fixed: rgb(88 117 168);
33 --md-sys-color-on-primary-fixed: rgb(255 255 255);
34 --md-sys-color-primary-fixed-dim: rgb(62 92 142);
35 --md-sys-color-on-primary-fixed-variant: rgb(255 255 255);
36 --md-sys-color-secondary-fixed: rgb(108 117 136);
37 --md-sys-color-on-secondary-fixed: rgb(255 255 255);
38 --md-sys-color-secondary-fixed-dim: rgb(83 92 111);
39 --md-sys-color-on-secondary-fixed-variant: rgb(255 255 255);
40 --md-sys-color-tertiary-fixed: rgb(135 107 140);
41 --md-sys-color-on-tertiary-fixed: rgb(255 255 255);
42 --md-sys-color-tertiary-fixed-dim: rgb(109 83 114);
43 --md-sys-color-on-tertiary-fixed-variant: rgb(255 255 255);
44 --md-sys-color-surface-dim: rgb(217 217 224);
45 --md-sys-color-surface-bright: rgb(249 249 255);
46 --md-sys-color-surface-container-lowest: rgb(255 255 255);
47 --md-sys-color-surface-container-low: rgb(243 243 250);
48 --md-sys-color-surface-container: rgb(237 237 244);
49 --md-sys-color-surface-container-high: rgb(231 232 238);
50 --md-sys-color-surface-container-highest: rgb(226 226 233);
51}
52

G. css / light.css

1.light {
2 --md-sys-color-primary: rgb(65 95 145);
3 --md-sys-color-surface-tint: rgb(65 95 145);
4 --md-sys-color-on-primary: rgb(255 255 255);
5 --md-sys-color-primary-container: rgb(214 227 255);
6 --md-sys-color-on-primary-container: rgb(0 27 62);
7 --md-sys-color-secondary: rgb(86 95 113);
8 --md-sys-color-on-secondary: rgb(255 255 255);
9 --md-sys-color-secondary-container: rgb(218 226 249);
10 --md-sys-color-on-secondary-container: rgb(19 28 43);
11 --md-sys-color-tertiary: rgb(112 85 117);
12 --md-sys-color-on-tertiary: rgb(255 255 255);
13 --md-sys-color-tertiary-container: rgb(250 216 253);
14 --md-sys-color-on-tertiary-container: rgb(40 19 46);
15 --md-sys-color-error: rgb(186 26 26);
16 --md-sys-color-on-error: rgb(255 255 255);
17 --md-sys-color-error-container: rgb(255 218 214);
18 --md-sys-color-on-error-container: rgb(65 0 2);
19 --md-sys-color-background: rgb(249 249 255);
20 --md-sys-color-on-background: rgb(25 28 32);
21 --md-sys-color-surface: rgb(249 249 255);
22 --md-sys-color-on-surface: rgb(25 28 32);
23 --md-sys-color-surface-variant: rgb(224 226 236);
24 --md-sys-color-on-surface-variant: rgb(68 71 78);
25 --md-sys-color-outline: rgb(116 119 127);
26 --md-sys-color-outline-variant: rgb(196 198 208);
27 --md-sys-color-shadow: rgb(0 0 0);
28 --md-sys-color-scrim: rgb(0 0 0);
29 --md-sys-color-inverse-surface: rgb(46 48 54);
30 --md-sys-color-inverse-on-surface: rgb(240 240 247);
31 --md-sys-color-inverse-primary: rgb(170 199 255);
32 --md-sys-color-primary-fixed: rgb(214 227 255);
33 --md-sys-color-on-primary-fixed: rgb(0 27 62);
34 --md-sys-color-primary-fixed-dim: rgb(170 199 255);
35 --md-sys-color-on-primary-fixed-variant: rgb(40 71 119);
36 --md-sys-color-secondary-fixed: rgb(218 226 249);
37 --md-sys-color-on-secondary-fixed: rgb(19 28 43);
38 --md-sys-color-secondary-fixed-dim: rgb(190 198 220);
39 --md-sys-color-on-secondary-fixed-variant: rgb(62 71 89);
40 --md-sys-color-tertiary-fixed: rgb(250 216 253);
41 --md-sys-color-on-tertiary-fixed: rgb(40 19 46);
42 --md-sys-color-tertiary-fixed-dim: rgb(221 188 224);
43 --md-sys-color-on-tertiary-fixed-variant: rgb(87 62 92);
44 --md-sys-color-surface-dim: rgb(217 217 224);
45 --md-sys-color-surface-bright: rgb(249 249 255);
46 --md-sys-color-surface-container-lowest: rgb(255 255 255);
47 --md-sys-color-surface-container-low: rgb(243 243 250);
48 --md-sys-color-surface-container: rgb(237 237 244);
49 --md-sys-color-surface-container-high: rgb(231 232 238);
50 --md-sys-color-surface-container-highest: rgb(226 226 233);
51}
52

H. css / transicion_completa.css

1
2@view-transition {
3 navigation: auto;
4}
5
6::view-transition-group(root) {
7 animation-duration: var(--md-sys-motion-duration-700);
8}
9
10html::view-transition-old(root) {
11 animation-name: desvanece;
12}
13
14html::view-transition-new(root) {
15 animation-delay: var(--md-sys-motion-duration-700);
16 animation-name: aparece;
17}

I. css / transicion_pestanas.css

1@view-transition {
2 navigation: auto;
3}
4
5#headline {
6 view-transition-name: encabezado;
7}
8
9main {
10 view-transition-name: contenido;
11}
12
13::view-transition-group(encabezado) {
14 animation-duration: var(--md-sys-motion-duration-1000);
15}
16
17::view-transition-group(contenido) {
18 animation-duration: var(--md-sys-motion-duration-1000);
19}
20
21html::view-transition-old(encabezado) {
22 animation-name: salePorLaIzquierda;
23}
24
25html::view-transition-new(encabezado) {
26 animation-name: entraPorLaDerecha;
27}
28
29html::view-transition-old(contenido) {
30 animation-name: salePorLaIzquierda;
31}
32
33html::view-transition-new(contenido) {
34 animation-duration: var(--md-sys-motion-duration-700);
35 animation-name: entraPorLaDerecha;
36}

30. favicon.ico

favicon.ico

31. Carpeta « img »

Versión para imprimir.

A. img / Escultura_de_coyote.jpeg

Coyote de Neza

B. img / icono2048.png

icono2048.png

C. img / maskable_icon.png

maskable_icon.png

D. img / maskable_icon_x128.png

maskable_icon_x128.png

E. img / maskable_icon_x192.png

maskable_icon_x192.png

F. img / maskable_icon_x384.png

maskable_icon_x384.png

G. img / maskable_icon_x48.png

maskable_icon_x48.png

H. img / maskable_icon_x512.png

maskable_icon_x512.png

I. img / maskable_icon_x72.png

maskable_icon_x72.png

J. img / maskable_icon_x96.png

maskable_icon_x96.png

K. img / pexels-craig-dennis-3701822.jpg

Ciudad de San Francisco

L. img / pexels-creative-workshop-3978352.jpg

Perro

M. img / pexels-erik-karits-3732453.jpg

Buho

N. img / pexels-esteban-arango-10226903.jpg

Coyote

O. img / pexels-moises-patrício-10961948.jpg

Avatar de Ana

P. img / pexels-ralph-2270848.jpg

León

Q. img / pexels-rasmus-svinding-35435.jpg

Oso

R. img / pexels-steve-397857.jpg

Lobo

S. img / pexels-vadim-b-141496.jpg

Gato

T. img / screenshot_horizontal.png

screenshot_horizontal.png

U. img / screenshot_vertical.png

screenshot_vertical.png

32. Carpeta « lib »

Versión para imprimir.

A. Carpeta « lib / css »

1. lib / css / material-symbols-outlined.css

1@font-face {
2 font-family: 'Material Symbols Outlined';
3 font-style: normal;
4 src:
5 url(../fonts/MaterialSymbolsOutlined[FILL\,GRAD\,opsz\,wght].woff2) format('woff2'),
6 url(../fonts/MaterialSymbolsOutlined[FILL\,GRAD\,opsz\,wght].ttf) format('truetype');
7}
8
9.material-symbols-outlined {
10 font-family: 'Material Symbols Outlined';
11 font-weight: normal;
12 font-style: normal;
13 font-size: 1.5rem;
14 width: 1.5rem;
15 height: 1.5rem;
16 /* Preferred icon size */
17 display: inline-block;
18 line-height: 1;
19 text-transform: none;
20 letter-spacing: normal;
21 word-wrap: normal;
22 white-space: nowrap;
23 direction: ltr;
24}

2. lib / css / md-cards.css

1.md-cards {
2 margin: 0.5rem;
3 gap: 0.5rem;
4 display: grid;
5 grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
6}
7
8/* container */
9.md-cards>*::before {
10 content: "";
11 position: absolute;
12 z-index: -2;
13 top: 0;
14 right: 0;
15 left: 0;
16 bottom: 0;
17 background-color: var(--md-sys-color-surface-variant);
18}
19
20/* state layer */
21.md-cards>*::after {
22 content: "";
23 position: absolute;
24 z-index: -1;
25 top: 0;
26 right: 0;
27 left: 0;
28 bottom: 0;
29 background-color: transparent;
30}
31
32.md-cards>* {
33 position: relative;
34 display: block;
35 text-decoration: none;
36 color: var(--md-sys-color-on-surface-variant);
37 border-radius: 0.75rem;
38 overflow: hidden;
39 box-shadow: var(--md-box_shadow_level0);
40}
41
42/* state layer */
43.md-cards>:hover::after {
44 background-color: var(--md-sys-color-on-surface-variant);
45 opacity: var(--md-sys-state-hover-state-layer-opacity);
46}
47
48.md-cards>a:hover {
49 box-shadow: var(--md-box_shadow_level1);
50}
51
52/* state layer */
53.md-cards>:focus::after {
54 background-color: var(--md-sys-color-on-surface-variant);
55 opacity: var(--md-sys-state-focus-state-layer-opacity);
56}
57
58.md-cards>a:focus {
59 outline: none;
60}
61
62/* state layer */
63.md-cards>:active::after {
64 background-color: var(--md-sys-color-on-surface-variant);
65 opacity: var(--md-sys-state-pressed-state-layer-opacity);
66}
67
68.md-cards a:active {
69 background-position: center;
70 background-image:
71 radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
72 background-size: 100%;
73 animation-name: md-ripple;
74 animation-duration: var(--md-sys-motion-duration-500);
75 box-shadow: var(--md-box_shadow_level0) !important;
76}
77
78.md-cards>*>* {
79 display: block;
80}
81
82.md-cards figure {
83 border-radius: 0.75rem;
84 padding: 0;
85 margin: 0;
86 width: 100%;
87}
88
89.md-cards figure * {
90 border-radius: 0.75rem;
91 width: 100%;
92}
93
94.md-cards .headline {
95 margin: 1rem;
96 font-family: var(--md-sys-typescale-headline-small-font);
97 font-weight: var(--md-sys-typescale-headline-small-weight);
98 font-size: var(--md-sys-typescale-headline-small-size);
99 font-style: var(--md-sys-typescale-headline-small-font-style);
100 letter-spacing: var(--md-sys-typescale-headline-small-tracking);
101 line-height: var(--md-sys-typescale-headline-small-line-height);
102 text-transform: var(--md-sys-typescale-headline-small-text-transform);
103 text-decoration: var(--md-sys-typescale-headline-small-text-decoration);
104}
105
106.md-cards a .headline {
107 text-decoration: underline;
108}
109
110.md-cards .supporting {
111 margin: 1rem;
112 font-family: var(--md-sys-typescale-body-large-font);
113 font-weight: var(--md-sys-typescale-body-large-weight);
114 font-size: var(--md-sys-typescale-body-large-size);
115 font-style: var(--md-sys-typescale-body-large-font-style);
116 letter-spacing: var(--md-sys-typescale-body-large-tracking);
117 line-height: var(--md-sys-typescale-body-large-line-height);
118 text-transform: var(--md-sys-typescale-body-large-text-transform);
119 text-decoration: var(--md-sys-typescale-body-large-text-decoration);
120}

3. lib / css / md-fab-primary.css

1.md-fab-primary {
2 position: relative;
3 display: inline-block;
4 border: none;
5 width: 3.5rem;
6 height: 3.5rem;
7 border-radius: var(--md-sys-shape-corner-large-default-size);
8 overflow: hidden;
9 padding: 0;
10 padding-block: 0;
11 padding-inline: 0;
12 text-decoration: none;
13 background-color: var(--md-sys-color-primary-container);
14 box-shadow: var(--md-box_shadow_level3);
15}
16
17.md-fab-primary[hidden] {
18 display: none;
19}
20
21/* state layer */
22.md-fab-primary::after {
23 content: "";
24 position: absolute;
25 top: 0;
26 right: 0;
27 left: 0;
28 bottom: 0;
29}
30
31.md-fab-primary span {
32 position: relative;
33 color: var(--md-sys-color-on-primary-container);
34}
35
36.md-fab-primary:hover {
37 box-shadow: var(--md-box_shadow_level4);
38}
39
40.md-fab-primary:hover::after {
41 background-color: var(--md-sys-color-on-primary-container);
42 opacity: var(--md-sys-state-hover-state-layer-opacity);
43}
44
45.md-fab-primary:hover span {
46 color: var(--md-sys-color-on-primary-container);
47}
48
49
50.md-fab-primary:focus {
51 box-shadow: var(--md-box_shadow_level3);
52 outline:none;
53 /* outline:
54 var(--md-sys-color-secondary) var(--md-sys-state-focus-indicator-thickness);
55 outline-offset: var(--md-sys-state-focus-indicator-outer-offset); */
56}
57
58.md-fab-primary:focus::after {
59 background-color: var(--md-sys-color-on-primary-container);
60 opacity: var(--md-sys-state-focus-state-layer-opacity);
61}
62
63.md-fab-primary:focus span {
64 color: var(--md-sys-color-on-primary-container);
65}
66
67.md-fab-primary:active {
68 box-shadow: var(--md-box_shadow_level3);
69 background-position: center;
70 background-image:
71 radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
72 background-size: 100%;
73 animation-name: md-ripple;
74 animation-duration: var(--md-sys-motion-duration-500);
75}
76
77.md-fab-primary:active::after {
78 background-color: var(--md-sys-color-on-primary-container);
79 opacity: var(--md-sys-state-pressed-state-layer-opacity);
80}
81
82.md-fab-primary:active span {
83 color: var(--md-sys-color-on-primary-container);
84}

4. lib / css / md-filled-button.css

1/* container */
2.md-filled-button::before {
3 content: "";
4 position: absolute;
5 z-index: -2;
6 top: 0;
7 right: 0;
8 left: 0;
9 bottom: 0;
10 background-color: var(--md-sys-color-primary);
11}
12
13/* state layer */
14.md-filled-button::after {
15 content: "";
16 position: absolute;
17 z-index: -1;
18 top: 0;
19 right: 0;
20 left: 0;
21 bottom: 0;
22 background-color: transparent;
23}
24
25/* label, shape */
26.md-filled-button {
27 position: relative;
28 box-sizing: border-box;
29 border-radius: 1.25rem;
30 height: 2.5rem;
31 line-height: 2.5rem;
32 padding: 0 1.5rem;
33 border: none;
34 background-color: transparent;
35 box-shadow: var(--md-box_shadow_level0);
36 font-family: var(--md-sys-typescale-label-large-font);
37 font-weight: var(--md-sys-typescale-label-large-weight);
38 font-size: var(--md-sys-typescale-label-large-size);
39 font-style: var(--md-sys-typescale-label-large-font-style);
40 letter-spacing: var(--md-sys-typescale-label-large-tracking);
41 text-transform: var(--md-sys-typescale-label-large-text-transform);
42 text-decoration: var(--md-sys-typescale-label-large-text-decoration);
43 color: var(--md-sys-color-on-primary);
44 white-space: nowrap;
45 text-overflow: ellipsis;
46 overflow: hidden;
47}
48
49/* label, shape */
50.md-filled-button:hover {
51 color: var(--md-sys-color-on-primary);
52 box-shadow: var(--md-box_shadow_level1);
53}
54
55/* state layer */
56.md-filled-button:hover::after {
57 background-color: var(--md-sys-color-on-primary);
58 opacity: var(--md-sys-state-hover-state-layer-opacity);
59}
60
61/* label, shape */
62.md-filled-button:focus {
63 outline: none;
64 color: var(--md-sys-color-on-primary);
65 box-shadow: var(--md-box_shadow_level0) !important;
66}
67
68/* state layer */
69.md-filled-button:focus::after {
70 background-color: var(--md-sys-color-on-primary);
71 opacity: var(--md-sys-state-focus-state-layer-opacity);
72}
73
74/* label, shape */
75.md-filled-button:active {
76 color: var(--md-sys-color-on-primary);
77 background-position: center;
78 background-image:
79 radial-gradient(circle, var(--md-sys-color-on-primary-container) 1%, transparent 1%);
80 background-size: 100%;
81 animation-name: md-ripple;
82 animation-duration: var(--md-sys-motion-duration-500);
83 box-shadow: var(--md-box_shadow_level0) !important;
84}
85
86/* state layer */
87.md-filled-button:active::after {
88 background-color: var(--md-sys-color-on-primary);
89 opacity: var(--md-sys-state-pressed-state-layer-opacity);
90}
91
92/* label, shape */
93.md-filled-button:disabled {
94 background-color: transparent !important;
95 color: var(--md-sys-color-on-surface) !important;
96 opacity: 0.38 !important;
97 box-shadow: var(--md-box_shadow_level0) !important;
98}
99
100/* container */
101.md-filled-button:disabled::before {
102 background-color: var(--md-sys-color-on-surface) !important;
103 opacity: 0.12 !important;
104}
105
106/* state layer */
107.md-filled-button:disabled::after {
108 background-color: transparent !important;
109 opacity: 1 !important;
110}

5. lib / css / md-filled-text-field.css

1.md-filled-text-field {
2 position: relative;
3 overflow: hidden;
4 display: flex;
5 flex-direction: column;
6 align-items: stretch;
7 padding-top: calc(0.5rem + var(--md-sys-typescale-body-small-line-height));
8 border-top-left-radius: var(--md-sys-shape-corner-extra-small-top-top-left);
9 border-top-right-radius: var(--md-sys-shape-corner-extra-small-top-top-right);
10 overflow: hidden;
11}
12
13/* container */
14.md-filled-text-field::before {
15 content: "";
16 position: absolute;
17 z-index: -2;
18 top: 0;
19 right: 0;
20 left: 0;
21 bottom: 0;
22 background-color: var(--md-sys-color-surface-container-highest);
23}
24
25/* state layer */
26.md-filled-text-field::after {
27 content: "";
28 position: absolute;
29 z-index: -1;
30 top: 0;
31 right: 0;
32 left: 0;
33 bottom: 0;
34 background-color: transparent;
35}
36
37.md-filled-text-field span,
38.md-filled-text-field label {
39 position: absolute;
40 top: 0.5rem;
41 left: 1rem;
42 right: 1rem;
43 display: block;
44 transform: translateY(1rem);
45 transition-property: transform;
46 transition-duration: var(--md-sys-motion-duration-300);
47 white-space: nowrap;
48 text-overflow: ellipsis;
49 overflow: hidden;
50 color: var(--md-sys-color-on-surface-variant);
51 font-family: var(--md-sys-typescale-body-large-font);
52 font-weight: var(--md-sys-typescale-body-large-weight);
53 font-size: var(--md-sys-typescale-body-large-size);
54 font-style: var(--md-sys-typescale-body-large-font-style);
55 letter-spacing: var(--md-sys-typescale-body-large-tracking);
56 line-height: var(--md-sys-typescale-body-large-line-height);
57 text-transform: var(--md-sys-typescale-body-large-text-transform);
58 text-decoration: var(--md-sys-typescale-body-large-text-decoration);
59}
60
61.md-filled-text-field :not(:placeholder-shown)+span,
62.md-filled-text-field :not(:placeholder-shown)+label,
63.md-filled-text-field .populated+span,
64.md-filled-text-field .populated+label,
65.md-filled-text-field:focus-within span,
66.md-filled-text-field:focus-within label,
67.md-filled-text-field.float span,
68.md-filled-text-field.float label {
69 transform: translateY(0);
70 font-family: var(--md-sys-typescale-body-small-font);
71 font-weight: var(--md-sys-typescale-body-small-weight);
72 font-size: var(--md-sys-typescale-body-small-size);
73 font-style: var(--md-sys-typescale-body-small-font-style);
74 letter-spacing: var(--md-sys-typescale-body-small-tracking);
75 line-height: var(--md-sys-typescale-body-small-line-height);
76 text-transform: var(--md-sys-typescale-body-small-text-transform);
77 text-decoration: var(--md-sys-typescale-body-small-text-decoration);
78}
79
80.md-filled-text-field :not(label, span, small) {
81 position: relative;
82 caret-color: var(--md-sys-color-primary);
83 min-height: 2rem;
84 box-sizing: border-box;
85 padding-left: 1rem;
86 padding-bottom: 0.5rem;
87 padding-right: 1rem;
88 border: none;
89 resize: none;
90 color: var(--md-sys-color-on-surface);
91 font-family: var(--md-sys-typescale-body-large-font);
92 font-weight: var(--md-sys-typescale-body-large-weight);
93 font-size: var(--md-sys-typescale-body-large-size);
94 font-style: var(--md-sys-typescale-body-large-font-style);
95 letter-spacing: var(--md-sys-typescale-body-large-tracking);
96 line-height: var(--md-sys-typescale-body-large-line-height);
97 text-transform: var(--md-sys-typescale-body-large-text-transform);
98 text-decoration: var(--md-sys-typescale-body-large-text-decoration);
99 background-color: transparent;
100 outline: none;
101 border-bottom-width: 0.0625rem;
102 border-bottom-style: solid;
103 border-bottom-color: var(--md-sys-color-on-surface-variant);
104}
105
106.md-filled-text-field ::placeholder {
107 color: transparent;
108}
109
110.md-filled-text-field small {
111 display: block;
112 color: var(--md-sys-color-on-surface-variant);
113 background-color: var(--md-sys-color-background);
114 font-family: var(--md-sys-typescale-body-small-font);
115 font-weight: var(--md-sys-typescale-body-small-weight);
116 font-size: var(--md-sys-typescale-body-small-size);
117 font-style: var(--md-sys-typescale-body-small-font-style);
118 letter-spacing: var(--md-sys-typescale-body-small-tracking);
119 line-height: var(--md-sys-typescale-body-small-line-height);
120 text-transform: var(--md-sys-typescale-body-small-text-transform);
121 text-decoration: var(--md-sys-typescale-body-small-text-decoration);
122 padding: 0.25rem 1rem 0 1rem;
123 white-space: nowrap;
124 text-overflow: ellipsis;
125 overflow: hidden;
126}
127
128.md-filled-text-field:hover span,
129.md-filled-text-field:hover label {
130 color: var(--md-sys-color-on-surface-variant);
131}
132
133.md-filled-text-field:hover :not(label, span, small) {
134 padding-bottom: 0.5rem;
135 border-bottom-width: 0.0625rem;
136 border-bottom-color: var(--md-sys-color-on-surface);
137}
138
139.md-filled-text-field:hover::after {
140 background-color: var(--md-sys-color-on-surface);
141 opacity: var(--md-sys-state-hover-state-layer-opacity);
142}
143
144.md-filled-text-field:hover small {
145 color: var(--md-sys-color-on-surface-variant);
146}
147
148.md-filled-text-field:focus-within span,
149.md-filled-text-field:focus-within label {
150 color: var(--md-sys-color-primary);
151}
152
153.md-filled-text-field :focus {
154 color: var(--md-sys-color-on-surface);
155 outline: none;
156 padding-bottom: 0.4375rem;
157 border-bottom-width: 0.125rem;
158 border-bottom-color: var(--md-sys-color-primary);
159}
160
161.md-filled-text-field:hover :focus {
162 padding-bottom: 0.4375rem;
163 border-bottom-width: 0.125rem;
164}
165
166.md-filled-text-field:focus-within small {
167 color: var(--md-sys-color-on-surface-variant);
168}
169
170.md-filled-text-field :invalid {
171 color: var(--md-sys-color-on-surface);
172 border-bottom-color: var(--md-sys-color-error);
173}
174
175.md-filled-text-field :invalid+span,
176.md-filled-text-field :invalid+label {
177 color: var(--md-sys-color-error);
178}
179
180.md-filled-text-field :invalid~small,
181.md-filled-text-field:hover :invalid~small,
182.md-filled-text-field:focus-within .input-text:invalid~small {
183 color: var(--md-sys-color-error);
184}
185
186.md-filled-text-field :invalid:focus {
187 caret-color: var(--md-sys-color-error);
188 border-bottom-color: var(--md-sys-color-error);
189}
190
191.md-filled-text-field:hover :invalid {
192 color: var(--md-sys-color-on-surface);
193 border-bottom-color: var(--md-sys-color-error);
194}

6. lib / css / md-list.css

1.md-list {
2 margin: 0.5rem 0;
3 padding: 0;
4 list-style-type: none;
5}
6
7.md-list .md-one-line,
8.md-list .md-two-line,
9.md-list .md-three-line {
10 position: relative;
11 display: flex;
12 box-sizing: border-box;
13}
14
15/* container */
16.md-list .md-one-line::before,
17.md-list .md-two-line::before,
18.md-list .md-three-line::before {
19 content: "";
20 position: absolute;
21 z-index: -2;
22 top: 0;
23 right: 0;
24 left: 0;
25 bottom: 0;
26 background-color: var(--md-sys-color-surface);
27}
28
29/* state layer */
30.md-list .md-one-line::after,
31.md-list .md-two-line::after,
32.md-list .md-three-line::after {
33 content: "";
34 position: absolute;
35 z-index: -1;
36 top: 0;
37 right: 0;
38 left: 0;
39 bottom: 0;
40 background-color: transparent;
41}
42
43.md-list .md-one-line {
44 align-items: center;
45 gap: 1rem;
46 min-height: 3.5rem;
47 padding: 0.5rem 1.5rem 0.5rem 1rem;
48}
49
50.md-list .md-one-line.video,
51.md-list .md-two-line.video {
52 padding: 0.75rem 1.5rem 0.75rem 0;
53}
54
55.md-list .md-two-line,
56.md-list .md-three-line {
57 flex-flow: column;
58}
59
60.md-list .md-two-line {
61 justify-content: center;
62 min-height: 4.5rem;
63 padding: 0.5rem 1.5rem 0.5rem 1rem;
64}
65
66.md-list .md-two-line.icon,
67.md-list .md-two-line.avatar,
68.md-list .md-two-line.image,
69.md-list .md-two-line.video,
70.md-list .md-three-line.icon,
71.md-list .md-three-line.avatar,
72.md-list .md-three-line.image,
73.md-list .md-three-line.video {
74 display: grid;
75 column-gap: 1rem;
76 row-gap: 0;
77 grid-template-areas:
78 "img headline"
79 "img supporting";
80}
81
82.md-list .md-two-line.icon,
83.md-list .md-two-line.avatar,
84.md-list .md-two-line.image,
85.md-list .md-two-line.video {
86 align-content: center;
87 grid-template-rows: 1fr 1fr;
88}
89
90.md-list .md-two-line.icon,
91.md-list .md-three-line.icon {
92 grid-template-columns: var(--iconSize) 1fr;
93}
94
95.md-list .md-two-line.avatar,
96.md-list .md-three-line.avatar {
97 grid-template-columns: var(--avatarSize) 1fr;
98}
99
100.md-list .md-two-line.image,
101.md-list .md-three-line.image {
102 grid-template-columns: var(--imageSize) 1fr;
103}
104
105.md-list .md-two-line.video,
106.md-list .md-three-line.video {
107 grid-template-columns: var(--videoWidth) 1fr;
108}
109
110.md-list .md-three-line {
111 align-content: flex-start;
112 min-height: 5.5rem;
113 padding: 0.75rem 1.5rem 0.75rem 1rem;
114}
115
116.md-list .md-three-line.video {
117 padding: 0.75rem 1.5rem 0.75rem 0;
118}
119
120.md-list .md-three-line.icon,
121.md-list .md-three-line.avatar,
122.md-list .md-three-line.image,
123.md-list .md-three-line.video {
124 align-content: start;
125 grid-template-rows: var(--md-sys-typescale-label-large-line-height) 1fr;
126}
127
128/* state layer */
129.md-list .md-one-line:hover::after,
130.md-list .md-two-line:hover::after,
131.md-list .md-three-line:hover::after {
132 background-color: var(--md-sys-color-on-surface);
133 opacity: var(--md-sys-state-hover-state-layer-opacity);
134}
135
136/* state layer */
137.md-list a.md-one-line:focus::after,
138.md-list a.md-two-line:focus::after,
139.md-list a.md-three-line:focus::after,
140.md-list a.md-one-line:focus-visible::after,
141.md-list a.md-two-line:focus-visible::after,
142.md-list a.md-three-line:focus-visible::after {
143 background-color: var(--md-sys-color-on-surface);
144 opacity: var(--md-sys-state-focus-state-layer-opacity);
145}
146
147.md-list a:focus,
148.md-list a:focus-visible {
149 outline: none;
150}
151
152.md-list a:active {
153 background-position: center;
154 background-image:
155 radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
156 background-size: 100%;
157 animation-name: md-ripple;
158 animation-duration: var(--md-sys-motion-duration-500);
159 box-shadow: var(--md-box_shadow_level0) !important;
160}
161
162/* state layer */
163.md-list a.md-one-line:active::after,
164.md-list a.md-two-line:active::after,
165.md-list a.md-three-line:active::after {
166 background-color: var(--md-sys-color-on-surface);
167 opacity: var(--md-sys-state-pressed-state-layer-opacity);
168}
169
170.md-list a.md-two-line,
171.md-list a.md-three-line {
172 text-decoration: none;
173}
174
175.md-list a.md-two-line .headline,
176.md-list a.md-three-line .headline {
177 text-decoration: underline;
178}
179
180.md-list .headline {
181 grid-area: headline;
182 display: block;
183 box-sizing: border-box;
184 color: var(--md-sys-color-on-surface);
185 font-family: var(--md-sys-typescale-body-large-font);
186 font-weight: var(--md-sys-typescale-body-large-weight);
187 font-size: var(--md-sys-typescale-body-large-size);
188 font-style: var(--md-sys-typescale-body-large-font-style);
189 letter-spacing: var(--md-sys-typescale-body-large-tracking);
190 line-height: var(--md-sys-typescale-body-large-line-height);
191 text-transform: var(--md-sys-typescale-body-large-text-transform);
192 text-decoration: var(--md-sys-typescale-body-large-text-decoration);
193 max-height: var(--md-sys-typescale-body-large-line-height);
194 white-space: nowrap;
195 text-overflow: ellipsis;
196 overflow: hidden;
197}
198
199.md-list .md-two-line.icon .headline,
200.md-list .md-two-line.avatar .headline,
201.md-list .md-two-line.image .headline,
202.md-list .md-two-line.video .headline,
203.md-list .md-three-line.icon .headline,
204.md-list .md-three-line.avatar .headline,
205.md-list .md-three-line.image .headline,
206.md-list .md-three-line.video .headline {
207 align-self: end;
208}
209
210.md-list .supporting {
211 grid-area: supporting;
212 display: -webkit-box;
213 -webkit-box-orient: vertical;
214 overflow: hidden;
215 box-sizing: border-box;
216 align-self: start;
217 font-family: var(--md-sys-typescale-body-medium-font);
218 font-weight: var(--md-sys-typescale-body-medium-weight);
219 font-size: var(--md-sys-typescale-body-medium-size);
220 font-style: var(--md-sys-typescale-body-medium-font-style);
221 letter-spacing: var(--md-sys-typescale-body-medium-tracking);
222 line-height: var(--md-sys-typescale-body-medium-line-height);
223 text-transform: var(--md-sys-typescale-body-medium-text-transform);
224 text-decoration: var(--md-sys-typescale-body-medium-text-decoration);
225}
226
227.md-list .md-two-line .supporting {
228 max-height: var(--md-sys-typescale-body-medium-line-height);
229 line-clamp: 1;
230 -webkit-line-clamp: 1;
231}
232
233.md-list .md-three-line .supporting {
234 max-height: calc(2 * var(--md-sys-typescale-body-medium-line-height));
235 line-clamp: 2;
236 -webkit-line-clamp: 2;
237}
238
239.md-list .avatar img,
240.md-list .avatar label,
241.md-list .avatar .material-symbols-outlined:first-child {
242 flex-shrink: 0;
243 background-color: var(--md-sys-color-primary-container);
244 color: var(--md-sys-color-on-primary-container);
245 border-radius: 50%;
246 width: var(--avatarSize);
247 height: var(--avatarSize);
248}
249
250.md-list .avatar label {
251 display: inline-block;
252 font-family: var(--md-sys-typescale-title-medium-font);
253 font-weight: var(--md-sys-typescale-title-medium-weight);
254 font-size: var(--md-sys-typescale-title-medium-size);
255 font-style: var(--md-sys-typescale-title-medium-font-style);
256 letter-spacing: var(--md-sys-typescale-title-medium-tracking);
257 line-height: var(--md-sys-typescale-title-medium-line-height);
258 text-transform: var(--md-sys-typescale-title-medium-text-transform);
259 text-decoration: var(--md-sys-typescale-title-medium-text-decoration);
260 overflow: hidden;
261}
262
263.md-list .avatar .material-symbols-outlined:first-child {
264 font-size: var(--avatarSize);
265}
266
267.md-list .avatar.md-two-line img,
268.md-list .avatar.md-two-line label,
269.md-list .avatar.md-two-line .material-symbols-outlined:first-child {
270 grid-area: img;
271 align-self: center;
272}
273
274.md-list .avatar.md-three-line img,
275.md-list .avatar.md-three-line label,
276.md-list .avatar.md-three-line .material-symbols-outlined:first-child {
277 grid-area: img;
278 align-self: start;
279}
280
281.md-list .icon img,
282.md-list .icon .material-symbols-outlined:first-child {
283 flex-shrink: 0;
284 color: var(--md-sys-color-on-surface-variant);
285 width: var(--iconSize);
286 height: var(--iconSize);
287}
288
289.md-list .icon .material-symbols-outlined:first-child {
290 font-size: var(--iconSize);
291}
292
293.md-list .icon.md-two-line img,
294.md-list .icon.md-two-line .material-symbols-outlined:first-child {
295 grid-area: img;
296 align-self: center;
297}
298
299.md-list .icon.md-three-line img,
300.md-list .icon.md-three-line .material-symbols-outlined:first-child {
301 grid-area: img;
302 align-self: start;
303}
304
305.md-list .video img {
306 flex-shrink: 0;
307 color: var(--md-sys-color-on-surface-variant);
308 width: var(--videoWidth);
309 height: var(--videoHeight);
310}
311
312.md-list .video.md-two-line img {
313 grid-area: img;
314 align-self: center;
315}
316
317.md-list .video.md-three-line img {
318 grid-area: img;
319 align-self: start;
320}
321
322.md-list .image img,
323.md-list .image .material-symbols-outlined:first-child {
324 flex-shrink: 0;
325 color: var(--md-sys-color-on-surface-variant);
326 width: var(--imageSize);
327 height: var(--imageSize);
328}
329
330.md-list .image .material-symbols-outlined:first-child {
331 font-size: var(--imageSize);
332}
333
334.md-list .image.md-two-line img,
335.md-list .image.md-two-line .material-symbols-outlined:first-child {
336 grid-area: img;
337 align-self: center;
338}
339
340.md-list .image.md-three-line img,
341.md-list .image.md-three-line .material-symbols-outlined:first-child {
342 grid-area: img;
343 align-self: start;
344}

7. lib / css / md-menu.css

1.md-menu {
2 display: none;
3 z-index: 2;
4 box-sizing: border-box;
5 cursor: default;
6 padding: 0.25rem 0;
7 border-radius:
8 var(--md-sys-shape-corner-extra-small-default-size);
9 background-color: var(--md-sys-color-surface-container-low);
10 box-shadow: var(--md-box_shadow_level2);
11 transform: translateY(-50%) scaleY(0);
12 transition-timing-function:
13 cubic-bezier(var(--md-sys-motion-easing-standard-x0),
14 var(--md-sys-motion-easing-standard-y0),
15 var(--md-sys-motion-easing-standard-x1),
16 var(--md-sys-motion-easing-standard-y1));
17 transition-property: display, transform;
18 transition-behavior: allow-discrete;
19 transition-duration: var(--md-sys-motion-duration-500);
20}
21
22.md-menu.open {
23 display: block;
24 transform: translateY(0) scaleY(1);
25}
26
27@starting-style {
28 .md-menu.open {
29 display: block;
30 transform: translateY(-50%) scaleY(0);
31 }
32}
33
34/* container */
35.md-menu>*::after {
36 content: "";
37 position: absolute;
38 z-index: -2;
39 top: 0;
40 right: 0;
41 left: 0;
42 bottom: 0;
43}
44
45/* container */
46.md-menu>.selected::after {
47 background-color: var(--md-sys-color-secondary-container);
48}
49
50/* label, shape */
51.md-menu>* {
52 position: relative;
53 display: block;
54 box-sizing: border-box;
55 height: 3rem;
56 line-height: 3rem;
57 padding: 0 0.75rem;
58 color: var(--md-sys-color-on-surface);
59 font-family: var(--md-sys-typescale-label-large-font);
60 font-weight: var(--md-sys-typescale-label-large-weight);
61 font-size: var(--md-sys-typescale-label-large-size);
62 font-style: var(--md-sys-typescale-label-large-font-style);
63 letter-spacing: var(--md-sys-typescale-label-large-tracking);
64 text-transform: var(--md-sys-typescale-label-large-text-transform);
65 text-decoration: var(--md-sys-typescale-label-large-text-decoration);
66 white-space: nowrap;
67 text-overflow: ellipsis;
68 overflow: hidden;
69}
70
71/* label, shape */
72.md-menu>.selected {
73 color: var(--md-sys-color-on-secondary-container);
74}
75
76/* state layer */
77.md-menu>*::before {
78 content: "";
79 position: absolute;
80 z-index: -1;
81 top: 0;
82 right: 0;
83 left: 0;
84 bottom: 0;
85}
86
87/* icon */
88.md-menu>* span {
89 position: relative;
90 margin-right: 0.75rem;
91 vertical-align: middle;
92 color: var(--md-sys-color-on-surface-variant);
93 font-size: 1.5rem;
94 width: 1.5rem;
95 height: 1.5rem;
96}
97
98/* icon */
99.md-menu>.selected span {
100 color: var(--md-sys-color-on-secondary-container);
101}
102
103/* state layer */
104.md-menu>:hover::before {
105 background-color: var(--md-sys-color-on-surface);
106 opacity: var(--md-sys-state-hover-state-layer-opacity);
107}
108
109/* label, shape */
110.md-menu>:hover {
111 color: var(--md-sys-color-on-surface);
112}
113
114/* icon */
115.md-menu>:hover span {
116 color: var(--md-sys-color-on-surface-variant);
117}
118
119/* state layer */
120.md-menu>:focus::before {
121 background-color: var(--md-sys-color-on-surface);
122 opacity: var(--md-sys-state-focus-state-layer-opacity);
123}
124
125/* label, shape */
126.md-menu>:focus {
127 color: var(--md-sys-color-on-surface);
128 outline: none;
129}
130
131/* icon */
132.md-menu>:focus span {
133 color: var(--md-sys-color-on-surface-variant);
134}
135
136/* label, shape */
137.md-menu>:active {
138 background-position: center;
139 background-image:
140 radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
141 background-size: 100%;
142 animation-name: md-ripple;
143 animation-duration: var(--md-sys-motion-duration-500);
144 color: var(--md-sys-color-on-surface);
145}
146
147/* state layer */
148.md-menu>:active::before {
149 background-color: var(--md-sys-color-on-surface);
150 opacity: var(--md-sys-state-pressed-state-layer-opacity);
151}
152
153
154/* icon */
155.md-menu>:active span {
156 color: var(--md-sys-color-on-surface-variant);
157}
158
159.md-menu input[type="radio"] {
160 appearance: none;
161 transform: scaleX(0);
162}

8. lib / css / md-navigation-bar.css

1.md-navigation-bar {
2 display: flex;
3 justify-content: center;
4 align-items: stretch;
5 position: fixed;
6 left: 0;
7 right: 0;
8 bottom: 0;
9 background-color: var(--md-sys-color-surface-container-low);
10}
11
12.md-navigation-bar a {
13 position: relative;
14 display: block;
15 flex: 0 1 auto;
16 color: var(--md-sys-color-on-surface-variant);
17 font-family: var(--md-sys-typescale-label-medium-font);
18 font-weight: var(--md-sys-typescale-label-medium-weight);
19 font-size: var(--md-sys-typescale-label-medium-size);
20 font-style: var(--md-sys-typescale-label-medium-font-style);
21 letter-spacing: var(--md-sys-typescale-label-medium-tracking);
22 line-height: var(--md-sys-typescale-label-medium-line-height);
23 text-transform: var(--md-sys-typescale-label-medium-text-transform);
24 text-decoration: var(--md-sys-typescale-label-medium-text-decoration);
25 text-decoration: none;
26 padding-top: 0.75rem;
27 padding-bottom: 1rem;
28 padding-left: 0.25rem;
29 padding-right: 0.25rem;
30 text-align: center;
31 overflow: hidden;
32 box-sizing: border-box;
33}
34
35.md-navigation-bar a.active {
36 color: var(--md-sys-color-on-surface);
37}
38
39/* state layer */
40.md-navigation-bar a::after {
41 content: "";
42 position: absolute;
43 z-index: -2;
44 top: 0;
45 right: 0;
46 left: 0;
47 bottom: 0;
48 background-color: transparent;
49}
50
51/* state layer */
52.md-navigation-bar a:hover::after {
53 background-color: var(--md-sys-color-on-surface-variant);
54 opacity: var(--md-sys-state-hover-state-layer-opacity);
55}
56
57/* state layer */
58.md-navigation-bar a.active:hover::after {
59 background-color: var(--md-sys-color-on-surface);
60}
61
62.md-navigation-bar a:focus {
63 outline: none;
64}
65
66/* state layer */
67.md-navigation-bar a:focus::after {
68 background-color: var(--md-sys-color-on-surface-variant);
69 opacity: var(--md-sys-state-focus-state-layer-opacity);
70}
71
72/* state layer */
73.md-navigation-bar a.active:focus::after {
74 background-color: var(--md-sys-color-on-surface);
75}
76
77.md-navigation-bar a:active {
78 background-position: center;
79 background-image:
80 radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
81 background-size: 100%;
82 animation-name: md-ripple;
83 animation-duration: var(--md-sys-motion-duration-500);
84}
85
86/* state layer */
87.md-navigation-bar a:active::after {
88 background-color: var(--md-sys-color-on-surface-variant);
89 opacity: var(--md-sys-state-pressed-state-layer-opacity);
90}
91
92/* state layer */
93.md-navigation-bar a.active:active::after {
94 background-color: var(--md-sys-color-on-surface);
95}
96
97.md-navigation-bar span {
98 color: var(--md-sys-color-on-surface-variant);
99 position: relative;
100 display: block;
101 height: 2rem;
102 width: 4rem;
103 line-height: 2rem;
104 margin-bottom: 0.25rem;
105 box-sizing: border-box;
106 margin-left: auto;
107 margin-right: auto;
108 overflow: hidden;
109}
110
111.md-navigation-bar a.active span {
112 color: var(--md-sys-color-on-secondary-container);
113}
114
115.md-navigation-bar a.active {
116 font-variation-settings: 'FILL'1, 'wght'700, 'GRAD'0, 'opsz'48;
117}
118
119.md-navigation-bar span::before {
120 content: "";
121 background-color: var(--md-sys-color-secondary-container);
122 position: absolute;
123 z-index: -1;
124 top: 0;
125 left: 0;
126 height: 2rem;
127 width: 4rem;
128 border-radius: 1rem;
129 box-sizing: border-box;
130 transform: scaleX(0);
131 transition-property: transform;
132 transition-duration: var(--md-sys-motion-duration-500);
133}
134
135.md-navigation-bar a.active span::before,
136.md-navigation-bar a:active span::before {
137 transform: scaleX(1);
138}

9. lib / css / md-outline-button.css

1.md-outline-button {
2 position: relative;
3 box-sizing: border-box;
4 border-radius: 1.25rem;
5 height: 2.5rem;
6 padding: 0 1.5rem;
7 border: 0.0625rem solid var(--md-sys-color-outline);
8 background-color: transparent;
9 box-shadow: var(--md-box_shadow_level0);
10 font-family: var(--md-sys-typescale-label-large-font);
11 font-weight: var(--md-sys-typescale-label-large-weight);
12 font-size: var(--md-sys-typescale-label-large-size);
13 font-style: var(--md-sys-typescale-label-large-font-style);
14 letter-spacing: var(--md-sys-typescale-label-large-tracking);
15 text-transform: var(--md-sys-typescale-label-large-text-transform);
16 text-decoration: var(--md-sys-typescale-label-large-text-decoration);
17 color: var(--md-sys-color-primary);
18 white-space: nowrap;
19 text-overflow: ellipsis;
20 overflow: hidden;
21}
22
23/* state layer */
24.md-outline-button::after {
25 content: "";
26 position: absolute;
27 z-index: -1;
28 top: 0;
29 right: 0;
30 left: 0;
31 bottom: 0;
32 background-color: transparent;
33}
34
35.md-outline-button:hover {
36 color: var(--md-sys-color-primary);
37 border-color: var(--md-sys-color-outline);
38}
39
40/* state layer */
41.md-outline-button:hover::after {
42 background-color: var(--md-sys-color-primary);
43 opacity: var(--md-sys-state-hover-state-layer-opacity);
44}
45
46.md-outline-button:focus {
47 outline: none;
48 color: var(--md-sys-color-primary);
49 border-color: var(--md-sys-color-outline);
50}
51
52/* state layer */
53.md-outline-button:focus::after {
54 background-color: var(--md-sys-color-primary);
55 opacity: var(--md-sys-state-focus-state-layer-opacity);
56}
57
58.md-outline-button:active {
59 color: var(--md-sys-color-primary);
60 border-color: var(--md-sys-color-outline);
61 background-position: center;
62 background-image:
63 radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
64 background-size: 100%;
65 animation-name: md-ripple;
66 animation-duration: var(--md-sys-motion-duration-500);
67 box-shadow: var(--md-box_shadow_level0) !important;
68}
69
70/* state layer */
71.md-outline-button:active::after {
72 background-color: var(--md-sys-color-primary);
73 opacity: var(--md-sys-state-pressed-state-layer-opacity);
74}
75
76.md-outline-button:disabled {
77 background-color: transparent !important;
78 border-color: var(--md-sys-color-on-surface) !important;
79 color: var(--md-sys-color-on-surface) !important;
80 opacity: 0.38 !important;
81}
82
83/* container */
84.md-outline-button:disabled::after {
85 background-color: transparent !important;
86 opacity: 1 !important;
87}

10. lib / css / md-ripple.css

1@keyframes md-ripple {
2
3 from {
4 background-size: 100%;
5 }
6
7 to {
8 background-size: 15000%;
9 }
10
11}

11. lib / css / md-segmented-button.css

1.md-segmented-button {
2 display: flex;
3 align-items: stretch;
4 box-sizing: border-box;
5 border: 0.0625rem solid var(--md-sys-color-outline);
6 height: 2.5rem;
7 border-radius: 1.25rem;
8 overflow: hidden;
9}
10
11.md-segmented-button[hidden] {
12 display: none;
13}
14
15.md-segmented-button input {
16 -webkit-appearance: none;
17 appearance: none;
18 flex: 0 1 0.0625rem;
19 width: 0.0625rem;
20 height: 2.375rem;
21 margin: 0;
22 padding: 0;
23 background-color: var(--md-sys-color-outline);
24}
25
26.md-segmented-button input:first-of-type {
27 transform: scaleX(0);
28}
29
30.md-segmented-button input:focus {
31 outline: none;
32}
33
34.md-segmented-button :checked+label {
35 color: var(--md-sys-color-on-secondary-container);
36}
37
38.md-segmented-button label {
39 position: relative;
40 flex: 1 1 1.5rem;
41 display: block;
42 box-sizing: border-box;
43 height: 2.375rem;
44 line-height: 2.375rem;
45 text-align: center;
46 color: var(--md-sys-color-on-surface);
47 font-family: var(--md-sys-typescale-label-large-font);
48 font-weight: var(--md-sys-typescale-label-large-weight);
49 font-size: var(--md-sys-typescale-label-large-size);
50 font-style: var(--md-sys-typescale-label-large-font-style);
51 letter-spacing: var(--md-sys-typescale-label-large-tracking);
52 text-transform: var(--md-sys-typescale-label-large-text-transform);
53 text-decoration: var(--md-sys-typescale-label-large-text-decoration);
54 padding: 0 0.75rem;
55 overflow: hidden;
56 white-space: nowrap;
57 text-overflow: ellipsis;
58 overflow: hidden;
59}
60
61.md-segmented-button label::before {
62 /* container */
63 content: "";
64 position: absolute;
65 z-index: -2;
66 top: 0;
67 right: 0;
68 left: 0;
69 bottom: 0;
70}
71
72.md-segmented-button label::after {
73 /* state layer */
74 content: "";
75 position: absolute;
76 z-index: -1;
77 top: 0;
78 right: 0;
79 left: 0;
80 bottom: 0;
81 background-color: transparent;
82}
83
84.md-segmented-button :checked+label::before {
85 /* container */
86 background-color: var(--md-sys-color-secondary-container);
87}
88
89.md-segmented-button label span {
90 vertical-align: middle;
91 color: var(--md-sys-color-on-surface);
92 font-size: 1.125rem;
93 width: 1.125rem;
94 height: 1.125rem;
95 margin-right: 0.5rem;
96}
97
98
99.md-segmented-button label span:first-child {
100 display: none;
101}
102
103.md-segmented-button :checked+label span:first-child {
104 display: inline-block;
105 color: var(--md-sys-color-on-secondary-container);
106}
107
108/* state layer */
109.md-segmented-button label:hover::after {
110 background-color: var(--md-sys-color-on-surface);
111 opacity: var(--md-sys-state-hover-state-layer-opacity);
112}
113
114/* state layer */
115.md-segmented-button :checked+label:hover::after {
116 background-color: var(--md-sys-color-on-secondary-container);
117}
118
119/* state layer */
120.md-segmented-button :focus+label::after {
121 background-color: var(--md-sys-color-on-surface);
122 opacity: var(--md-sys-state-focus-state-layer-opacity);
123}
124
125/* state layer */
126.md-segmented-button :focus:checked+label::after {
127 background-color: var(--md-sys-color-on-secondary-container);
128}
129
130.md-segmented-button label:active,
131.md-segmented-button :active+label {
132 background-position: center;
133 background-image:
134 radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
135 background-size: 100%;
136 animation-name: md-ripple;
137 animation-duration: var(--md-sys-motion-duration-500);
138}
139
140/* state layer */
141.md-segmented-button :active+label::after {
142 background-color: var(--md-sys-color-on-surface);
143 opacity: var(--md-sys-state-pressed-state-layer-opacity);
144}
145
146/* state layer */
147.md-segmented-button :active:checked+label::after {
148 background-color: var(--md-sys-color-on-secondary-container);
149}

12. lib / css / md-slider-field.css

1md-slider-field input::-webkit-slider-runnable-track {
2 height: 0.25rem;
3 border-radius: 0.125rem;
4}
5
6md-slider-field input::-webkit-slider-thumb {
7 -webkit-appearance: none;
8 background-color: var(--md-sys-color-primary);
9 width: 1.25rem;
10 height: 1.25rem;
11 border-radius: 0.625rem;
12 margin-top: -0.5625rem;
13}
14
15md-slider-field input:hover::-webkit-slider-thumb {
16 box-shadow: 0 0 0 0.625rem color-mix(in srgb, var(--md-sys-color-primary), transparent var(--state-hover-transparency-percentage));
17}
18
19md-slider-field input:focus::-webkit-slider-thumb {
20 box-shadow: 0 0 0 0.625rem color-mix(in srgb, var(--md-sys-color-primary), transparent var(--state-focus-transparency-percentage));
21}
22
23md-slider-field input:active::-webkit-slider-thumb {
24 box-shadow: 0 0 0 0.625rem color-mix(in srgb, var(--md-sys-color-primary), transparent var(--state-pressed-transparency-percentage)) !important;
25 background-position: center;
26 background-image:
27 radial-gradient(circle, var(--md-sys-color-primary-container) 1%, transparent 1%);
28 background-size: 100%;
29 animation-name: md-ripple;
30 animation-duration: var(--md-sys-motion-duration-500);
31}
32
33md-slider-field.material::-moz-range-track {
34 height: 0.25rem;
35 border-radius: 0.125rem;
36}
37
38md-slider-field input::-moz-range-thumb {
39 -webkit-appearance: none;
40 appearance: none;
41 background-color: var(--md-sys-color-primary);
42 width: 1.25rem;
43 height: 1.25rem;
44 border: none;
45 border-radius: 0.625rem;
46}
47
48md-slider-field input:hover::-moz-range-thumb {
49 box-shadow: 0 0 0 0.625rem color-mix(in srgb, var(--md-sys-color-primary), transparent var(--state-hover-transparency-percentage));
50}
51
52md-slider-field input:focus::-moz-range-thumb {
53 box-shadow: 0 0 0 0.625rem color-mix(in srgb, var(--md-sys-color-primary), transparent var(--state-focus-transparency-percentage));
54}
55
56md-slider-field input:active::-moz-range-thumb {
57 box-shadow: 0 0 0 0.625rem color-mix(in srgb, var(--md-sys-color-primary), transparent var(--state-pressed-transparency-percentage)) !important;
58 background-position: center;
59 background-image:
60 radial-gradient(circle, var(--md-sys-color-primary-container) 1%, transparent 1%);
61 background-size: 100%;
62 animation-name: md-ripple;
63 animation-duration: var(--md-sys-motion-duration-500);
64}

13. lib / css / md-standard-icon-button.css

1.md-standard-icon-button {
2 position: relative;
3 display: inline-block;
4 border: none;
5 padding: 0.25rem;
6 background-color: transparent;
7 text-decoration: none;
8 border-radius: 50%;
9 overflow: hidden;
10}
11
12.md-standard-icon-button[hidden] {
13 display: none;
14}
15
16/* state layer */
17.md-standard-icon-button::after {
18 content: "";
19 position: absolute;
20 top: 0.25rem;
21 right: 0.25rem;
22 left: 0.25rem;
23 bottom: 0.25rem;
24 border-radius: 50%;
25}
26
27.md-standard-icon-button span {
28 position: relative;
29 padding: 0.5rem;
30 color: var(--md-sys-color-on-surface-variant);
31 font-size: 1.5rem;
32 width: 1.5rem;
33 height: 1.5rem;
34}
35
36.md-standard-icon-button.avatar span {
37 padding: 0.3125rem;
38 font-size: 1.875rem;
39 width: 1.875rem;
40 height: 1.875rem;
41}
42
43.md-standard-icon-button:hover::after {
44 background-color: var(--md-sys-color-on-surface-variant);
45 opacity: var(--md-sys-state-hover-state-layer-opacity);
46}
47
48.md-standard-icon-button:hover span {
49 color: var(--md-sys-color-on-surface-variant);
50}
51
52.md-standard-icon-button:focus {
53 outline: none;
54}
55
56.md-standard-icon-button:focus::after {
57 background-color: var(--md-sys-color-on-surface-variant);
58 opacity: var(--md-sys-state-focus-state-layer-opacity);
59}
60
61.md-standard-icon-button:focus span {
62 color: var(--md-sys-color-on-surface-variant);
63}
64
65.md-standard-icon-button:active {
66 background-position: center;
67 background-image:
68 radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
69 background-size: 100%;
70 animation-name: md-ripple;
71 animation-duration: var(--md-sys-motion-duration-500);
72}
73
74.md-standard-icon-button:active::after {
75 background-color: var(--md-sys-color-on-surface-variant);
76 opacity: var(--md-sys-state-pressed-state-layer-opacity);
77}
78
79.md-standard-icon-button:active span {
80 -color: var(--md-sys-color-on-surface-variant);
81}
82
83.md-standard-icon-button:disabled::after {
84 background-color: transparent !important;
85 opacity: 1;
86}
87
88.md-standard-icon-button:disabled span {
89 color: var(--md-sys-color-on-surface) !important;
90 opacity: 0.38;
91}
92
93.md-standard-icon-button:disabled:active {
94 background-image: none;
95 animation-name: none;
96 animation-duration: unset;
97}

14. lib / css / md-switch.css

1.md-switch {
2 -webkit-appearance: none;
3 appearance: none;
4 position: relative;
5 display: inline-block;
6 vertical-align: middle;
7 box-sizing: content-box;
8 padding: 0;
9 padding-block: 0;
10 padding-inline: 0;
11}
12
13.md-switch:focus {
14 outline: none;
15}
16
17/* Track */
18body.material .md-switch {
19 width: 3rem;
20 height: 1.75rem;
21 border-radius: 1rem;
22 border: 0.125rem solid var(--md-sys-color-outline);
23 background-color: var(--md-sys-color-surface-container-highest);
24}
25
26body.material .md-switch:checked {
27 background-color: var(--md-sys-color-primary);
28}
29
30/* State */
31body.material .md-switch::before {
32 content: "";
33 display: none;
34 position: absolute;
35 height: 2.5rem;
36 width: 2.5rem;
37 border-radius: 1.25rem;
38 top: -0.375rem;
39 left: -0.375rem;
40}
41
42body.material .md-switch:checked:before {
43 left: auto;
44 right: -0.375rem;
45}
46
47/* Handle */
48body.material .md-switch::after {
49 content: "";
50 display: inline-block;
51 position: absolute;
52 transition-property: all;
53 transition-duration: var(--md-sys-motion-duration-700);
54 height: 1rem;
55 width: 1rem;
56 border-radius: 0.5rem;
57 top: 0.375rem;
58 left: 0.375rem;
59 background-color: var(--md-sys-color-outline);
60 box-shadow: var(--md-box_shadow_level1);
61}
62
63body.material .md-switch:checked:after {
64 height: 1.5rem;
65 width: 1.5rem;
66 border-radius: 0.75rem;
67 top: 0.125rem;
68 left: auto;
69 right: 0.125rem;
70 background-color: var(--md-sys-color-on-primary);
71}
72
73body.material .md-switch:hover::before {
74 display: inline-block;
75 background-color: var(--md-sys-color-on-surface);
76 opacity: var(--md-sys-state-hover-state-layer-opacity);
77}
78
79body.material .md-switch:checked:hover::before {
80 background-color: var(--md-sys-color-primary);
81}
82
83body.material .md-switch:hover::after {
84 background-color: var(--md-sys-color-on-surface-variant);
85}
86
87body.material .md-switch:checked:hover::after {
88 background-color: var(--md-sys-color-primary-container);
89}
90
91body.material .md-switch:focus::before {
92 display: inline-block;
93 background-color: var(--md-sys-color-on-surface);
94 opacity: var(--md-sys-state-focus-state-layer-opacity);
95}
96
97body.material .md-switch:checked:focus::before {
98 background-color: var(--md-sys-color-primary);
99}
100
101body.material .md-switch:focus::after {
102 background-color: var(--md-sys-color-on-surface-variant);
103}
104
105body.material .md-switch:checked:focus::after {
106 background-color: var(--md-sys-color-primary-container);
107}
108
109body.material .md-switch:active::before {
110 display: inline-block;
111 background-color: var(--md-sys-color-on-surface);
112 opacity: var(--md-sys-state-focus-state-layer-opacity);
113}
114
115
116body.material .md-switch:checked:active::before {
117 background-color: var(--md-sys-color-primary);
118}
119
120body.material .md-switch:active::after {
121 width: 1.75rem;
122 height: 1.75rem;
123 top: 0;
124 left: 0;
125 border-radius: 0.875rem;
126 background-position: center;
127 animation-name: md-ripple;
128 animation-duration: var(--md-sys-motion-duration-500);
129 background-size: 100%;
130 background-color: var(--md-sys-color-on-surface-variant);
131 background-image:
132 radial-gradient(circle, var(--md-sys-color-primary-container) 1%, transparent 1%);
133 box-shadow: var(--md-box_shadow_level1), 0 0 0 0.375rem color-mix(in srgb, var(--md-sys-color-on-surface), transparent var(--state-pressed-transparency-percentage)) !important;
134}
135
136body.material .md-switch:checked:active::after {
137 left: auto;
138 right: 0;
139 background-color: var(--md-sys-color-primary-container);
140 background-image:
141 radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
142 box-shadow: var(--md-box_shadow_level1), 0 0 0 0.375rem color-mix(in srgb, var(--md-sys-color-primary), transparent var(--state-pressed-transparency-percentage)) !important;
143}
144
145body.apple .md-switch {
146 width: 3rem;
147 border-radius: 0.875rem;
148 height: 1.75rem;
149 background-color: var(--colIntIosOffBk);
150}
151
152body.apple .md-switch:checked {
153 background-color: var(--colIntIosOnBk);
154}
155
156body.apple .md-switch:focus {
157 background-color: var(--colIntIosOffBkFc);
158}
159
160body.apple .md-switch:checked:focus {
161 background-color: var(--colIntIosOnBkFc);
162}
163
164body.apple .md-switch::after {
165 content: "";
166 display: inline-block;
167 position: absolute;
168 width: 1.5rem;
169 height: 1.5rem;
170 border-radius: 0.75rem;
171 top: 0.125rem;
172 left: 0.125rem;
173 background-color: var(--colIntIos);
174}
175
176body.apple .md-switch:checked::after {
177 left: auto;
178 right: 0.125rem;
179 border-color: var(--colIntIosOnBk);
180}
181
182body.apple .md-switch:focus::after {
183 border-color: var(--colIntIosOffBkFc);
184}
185
186body.apple .md-switch:checked:focus::after {
187 border-color: var(--colIntIosOnBkFc);
188}

15. lib / css / md-tab.css

1.md-tab {
2 display: flex;
3 background-color: transparent;
4 align-items: stretch;
5 flex-wrap: nowrap;
6 overflow-x: auto;
7 position: sticky;
8 z-index: 1;
9}
10
11.md-tab.fixed {
12 justify-content: center;
13}
14
15.md-tab.scrollable {
16 padding-left: 2rem;
17 gap: 1rem;
18}
19
20.md-tab.scroll {
21 background-color: var(--md-sys-color-surface-container-low);
22}
23
24.md-tab a {
25 position: relative;
26 display: flex;
27 flex-direction: column;
28 justify-content: start;
29 align-items: center;
30 color: var(--md-sys-color-on-surface-variant);
31 font-family: var(--md-sys-typescale-title-small-font);
32 font-weight: var(--md-sys-typescale-title-small-weight);
33 font-size: var(--md-sys-typescale-title-small-size);
34 font-style: var(--md-sys-typescale-title-small-font-style);
35 letter-spacing: var(--md-sys-typescale-title-small-tracking);
36 line-height: var(--md-sys-typescale-title-small-line-height);
37 text-transform: var(--md-sys-typescale-title-small-text-transform);
38 text-decoration: var(--md-sys-typescale-title-small-text-decoration);
39 text-align: center;
40 box-sizing: border-box;
41 border-bottom: 0.1875rem solid var(--md-sys-color-surface);
42}
43
44.md-tab.fixed a {
45 flex: 0 0 var(--tabWidth);
46}
47
48.md-tab.scrollable a {
49 flex: 0 0 auto;
50}
51
52.md-tab a.active {
53 border-bottom-color: var(--md-sys-color-primary);
54}
55
56/* state layer */
57.md-tab a::after {
58 content: "";
59 position: absolute;
60 z-index: -1;
61 top: 0;
62 right: 0;
63 left: 0;
64 bottom: 0;
65 background-color: transparent;
66}
67
68.md-tab span {
69 font-size: var(--iconSize);
70 height: var(--iconSize);
71 width: var(--iconSize);
72 color: var(--md-sys-color-on-surface-variant);
73}
74
75.md-tab .active span {
76 color: var(--md-sys-color-primary);
77}
78
79.md-tab a:hover {
80 color: var(--md-sys-color-on-surface);
81}
82
83/* state layer */
84.md-tab a:hover::after {
85 background-color: var(--md-sys-color-on-surface);
86 opacity: var(--md-sys-state-hover-state-layer-opacity);
87}
88
89.md-tab a.active:hover {
90 color: var(--md-sys-color-primary);
91}
92
93/* state layer */
94.md-tab a.active:hover::after {
95 background-color: var(--md-sys-color-primary);
96 opacity: var(--md-sys-state-hover-state-layer-opacity);
97}
98
99.md-tab a:hover span {
100 color: var(--md-sys-color-on-surface);
101}
102
103.md-tab a.active:hover span {
104 color: var(--md-sys-color-primary);
105}
106
107.md-tab a:focus {
108 outline: none;
109}
110
111/* state layer */
112.md-tab a:focus::after {
113 background-color: var(--md-sys-color-on-surface);
114 opacity: var(--md-sys-state-focus-state-layer-opacity);
115}
116
117/* state layer */
118.md-tab a.active:focus::after {
119 background-color: var(--md-sys-color-primary);
120 opacity: var(--md-sys-state-hover-state-layer-opacity);
121}
122
123.md-tab a:active {
124 background-position: center;
125 background-image:
126 radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
127 background-size: 100%;
128 animation-name: md-ripple;
129 animation-duration: var(--md-sys-motion-duration-500);
130}
131
132/* state layer */
133.md-tab a:active::after {
134 background-color: var(--md-sys-color-on-surface);
135 opacity: var(--md-sys-state-pressed-state-layer-opacity);
136}
137
138/* state layer */
139.md-tab a.active:active::after {
140 background-color: var(--md-sys-color-primary);
141 opacity: var(--md-sys-state-pressed-state-layer-opacity);
142}

16. lib / css / md-top-app-bar.css

1.md-headline {
2 box-sizing: border-box;
3 margin: 0;
4 color: var(--md-sys-color-on-surface);
5 background-color: var(--md-sys-color-surface);
6 transition-property: color;
7 transition-duration: var(--md-sys-motion-duration-1000);
8 transition-timing-function: ease-in;
9}
10
11.md-headline.scroll-adicional {
12 color: var(--md-sys-color-surface-container-low);
13 background-color: var(--md-sys-color-surface-container-low);
14}
15
16.md-headline.scroll {
17 color: var(--md-sys-color-surface);
18}
19
20.md-headline.headline-small {
21 padding: 0 1rem 1.5rem 1rem;
22}
23
24.md-headline.headline-medium {
25 padding: 0 1rem 1.75rem 1rem;
26}
27
28md-top-app-bar[headline] h1 {
29 opacity: 0;
30 transition-property: opacity;
31 transition-duration: var(--md-sys-motion-duration-1000);
32}
33
34md-top-app-bar[headline].scroll h1 {
35 opacity: 1;
36 transition-timing-function: ease-in;
37}

17. lib / css / roboto.css

1/* roboto-regular - latin */
2@font-face {
3 /* Revisa
4 * https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display
5 * para otras opciones. */
6 font-display: swap;
7 font-family: 'Roboto';
8 font-style: normal;
9 font-weight: 400;
10 /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
11 src: url('../fonts/roboto-v32-latin-regular.woff2') format('woff2');
12}

B. Carpeta « lib / fonts »

1. lib / fonts / MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].codepoints

2. lib / fonts / MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].ttf

3. lib / fonts / MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].woff2

4. lib / fonts / roboto-v32-latin-regular.woff2

C. Carpeta « lib / js »

1. lib / js / abreElementoHtml.js

1/**
2 * @param { HTMLElement } elementoHtml
3 */
4export function abreElementoHtml(elementoHtml) {
5 elementoHtml.classList.add("open")
6}

2. lib / js / cierraElementoHtmo.js

1/**
2 * @param { HTMLElement } elementoHtml
3 */
4export function cierraElementoHtmo(elementoHtml) {
5 elementoHtml.classList.remove("open")
6}
7

3. lib / js / exportaAHtml.js

1/**
2 * Permite que los eventos de html usen la función.
3 * @param {function} functionInstance
4 */
5export function exportaAHtml(functionInstance) {
6 window[nombreDeFuncionParaHtml(functionInstance)] = functionInstance
7}
8
9/**
10 * @param {function} valor
11 */
12export function nombreDeFuncionParaHtml(valor) {
13 const names = valor.name.split(/\s+/g)
14 return names[names.length - 1]
15}

4. lib / js / getAttribute.js

1/**
2 * @param {HTMLElement} elementoHtml
3 * @param {string} nombre
4 * @returns {string}
5 */
6export function getAttribute(elementoHtml, nombre) {
7 const valor = elementoHtml.getAttribute(nombre)
8 return valor === null ? "" : valor
9}

5. lib / js / htmlentities.js

1/**
2 * Codifica un texto para que cambie los caracteres
3 * especiales y no se pueda interpretar como
4 * etiiqueta HTML. Esta técnica evita la inyección
5 * de código.
6 * @param { string } texto
7 * @returns { string } un texto que no puede
8 * interpretarse como HTML. */
9export function htmlentities(texto) {
10 return texto.replace(/[<>"']/g, textoDetectado => {
11 switch (textoDetectado) {
12 case "<": return "<"
13 case ">": return ">"
14 case '"': return """
15 case "'": return "'"
16 default: return textoDetectado
17 }
18 })
19}

6. lib / js / muestraError.js

1import { exportaAHtml } from "./exportaAHtml.js"
2import { ProblemDetails } from "./ProblemDetails.js"
3
4/**
5 * Muestra un error en la consola y en un cuadro de
6 * alerta el mensaje de una excepción.
7 * @param { ProblemDetails | Error | null } error descripción del error.
8 */
9export function muestraError(error) {
10
11 if (error === null) {
12
13 console.error("Error")
14 alert("Error")
15
16 } else if (error instanceof ProblemDetails) {
17
18 let mensaje = error.title
19 if (error.detail) {
20 mensaje += `\n\n${error.detail}`
21 }
22 mensaje += `\n\nCódigo: ${error.status}`
23 if (error.type) {
24 mensaje += ` ${error.type}`
25 }
26
27 console.error(mensaje)
28 console.error(error)
29 console.error("Headers:")
30 error.headers.forEach((valor, llave) => console.error(llave, "=", valor))
31 alert(mensaje)
32
33 } else {
34
35 console.error(error)
36 alert(error.message)
37
38 }
39
40}
41
42exportaAHtml(muestraError)

7. lib / js / muestraTextoDeAyuda.js

1import { exportaAHtml } from "./exportaAHtml.js"
2
3/**
4 * Si un elemento HTML tiene un mensaje de validación, lo
5 * muestra en su elemento de ayuda; en caso contrario, muestra
6 * un mensaje de ayuda.
7 * @param { {
8 * validity: { valid: boolean };
9 * validationMessage: string
10 * } } elementoHtml elemento que contiene datos de validación.
11 * @param { HTMLElement } elementoDeAyuda elemento fonde
12 * se muestran los elementos de validación para elementoHtml.
13 * @param { string } mensajeDeAyuda mensaje de ayuda cuando el
14 * estado de elementoHtml es válido.
15 */
16export function muestraTextoDeAyuda(elementoHtml, elementoDeAyuda,
17 mensajeDeAyuda) {
18 if (elementoHtml.validity.valid) {
19 elementoDeAyuda.textContent = mensajeDeAyuda
20 } else {
21 elementoDeAyuda.textContent = elementoHtml.validationMessage
22 }
23}
24
25exportaAHtml(muestraTextoDeAyuda)

8. lib / js / ProblemDetails.js

1/**
2 * Detalle de los errores devueltos por un servicio.
3 */
4export class ProblemDetails extends Error {
5
6 /**
7 * @param {number} status
8 * @param {Headers} headers
9 * @param {string} title
10 * @param {string} [type]
11 * @param {string} [detail]
12 */
13 constructor(status, headers, title, type, detail) {
14 super(title)
15 /**
16 * @readonly
17 */
18 this.status = status
19 /**
20 * @readonly
21 */
22 this.headers = headers
23 /**
24 * @readonly
25 */
26 this.type = type
27 /**
28 * @readonly
29 */
30 this.detail = detail
31 /**
32 * @readonly
33 */
34 this.title = title
35 }
36
37}

9. lib / js / querySelector.js

1/**
2 * @template { HTMLElement } T
3 * @param { Document | Element | ShadowRoot } raiz
4 * @param { string } query
5 * @returns { T }
6 */
7export function querySelector(raiz, query) {
8 /** @type { T | null } */
9 const resutado = raiz.querySelector(query)
10 if (resutado === null)
11 throw new Error(`No se encuentra ${query}.`)
12 return resutado
13}

10. lib / js / resaltaSiEstasEn.js

1import { querySelector } from "./querySelector.js"
2
3/**
4 * @param {string[]} paginas
5 */
6export function resaltaSiEstasEn(paginas) {
7
8 const pathname = location.pathname
9
10 for (const pagina of paginas) {
11
12 if (pathname === pagina) {
13 setTimeout(() => {
14 const tab = document.querySelector(".active")
15 if (tab !== null && tab.closest(".scrollable") !== null) {
16 tab.scrollIntoView({ inline: "center", block: "end" })
17 }
18 })
19 return `class="active"`
20 }
21
22 }
23
24 return ""
25
26}

11. Carpeta « lib / js / const »

A. lib / js / const / ES_APPLE.js

1export const ES_APPLE = /.*(iPad|iPhone|iPod|Mac).*/.test(navigator.userAgent)

12. Carpeta « lib / js / custom »

A. lib / js / custom / md-menu-button.js

1import { MdNavigationDrawer } from "./MdNavigationDrawer.js"
2
3export class MdMenuButton extends HTMLButtonElement {
4
5 constructor() {
6 super()
7 this.abreDrawer = this.abreDrawer.bind(this)
8 }
9
10 connectedCallback() {
11 this.type = "button"
12 this.classList.add("md-standard-icon-button")
13 this.innerHTML = /* HTML */
14 `<span class="material-symbols-outlined">menu</span>`
15 this.addEventListener("click", this.abreDrawer)
16 }
17
18 disconnectedCallback() {
19 this.removeEventListener("click", this.abreDrawer)
20 }
21
22 abreDrawer() {
23 const drawer = document.querySelector(".drawer")
24 if (drawer instanceof MdNavigationDrawer) {
25 drawer.abre()
26 }
27 }
28}
29
30customElements.define("md-menu-button", MdMenuButton, { extends: "button" })

B. lib / js / custom / md-options-menu.js

1import { abreElementoHtml } from "../abreElementoHtml.js"
2import { cierraElementoHtmo } from "../cierraElementoHtmo.js"
3import { querySelector } from "../querySelector.js"
4
5export class MdOptionsMenu extends HTMLElement {
6
7 getContent() {
8 return /* HTML */`
9
10 <style>
11
12 :host {
13 position: absolute;
14 }
15
16 </style>
17
18 <slot></slot>`
19 }
20
21 constructor() {
22 super()
23 const shadow = this.attachShadow({ mode: "open" })
24 shadow.innerHTML = this.getContent()
25 this._configuraOpciones = this._configuraOpciones.bind(this)
26
27 /**
28 * @private
29 * @type { HTMLSlotElement }
30 */
31 this._slot = querySelector(shadow, "slot")
32 /**
33 * @private
34 * @type { HTMLElement[] }
35 */
36 this._opciones = []
37 this._slot.addEventListener("slotchange", this._configuraOpciones)
38 }
39
40 connectedCallback() {
41 this.classList.add("md-menu")
42 this.role = "listbox"
43 }
44
45 /**
46 * @returns {readonly Readonly<HTMLElement>[]}
47 */
48 get opciones() {
49 return this._opciones
50 }
51
52 get seleccion() {
53 /** @type { HTMLInputElement | null } */
54 const seleccionado = this.querySelector(".selected")
55 return seleccionado === null ? "" : seleccionado.value
56 }
57
58 _configuraOpciones() {
59 /**
60 * @type {HTMLElement[]}
61 */
62 const opciones = []
63 for (const opcion of this._slot.assignedElements()) {
64 opcion.role = "option"
65 if (opcion instanceof HTMLElement) {
66 opciones.push(opcion)
67 }
68 }
69 this._opciones = opciones
70 }
71
72 abre() {
73 abreElementoHtml(this)
74 }
75
76
77 cierra() {
78 cierraElementoHtmo(this)
79 }
80
81 /**
82 * @param {string} value
83 */
84 muestraValue(value) {
85 let texto = ""
86 for (const opcion of this._opciones) {
87 if (opcion.dataset.value === value) {
88 opcion.classList.add("selected")
89 let textContent = opcion.textContent
90 if (texto === "" && textContent !== null) {
91 textContent = textContent.trim()
92 if (textContent !== "") {
93 texto = textContent
94 }
95 }
96 } else {
97 opcion.classList.remove("selected")
98 }
99 }
100 return texto
101 }
102
103}
104
105customElements.define("md-options-menu", MdOptionsMenu)

C. lib / js / custom / md-overflow-button.js

1import { ES_APPLE } from "../const/ES_APPLE.js"
2
3export class MdOverflowButton extends HTMLButtonElement {
4
5 connectedCallback() {
6 this.type = "button"
7 this.classList.add("md-standard-icon-button")
8 this.innerHTML = ES_APPLE
9 ? /* HTML */
10 `<span style="color: var(--md-sys-color-on-surface-variant)"
11 class="material-symbols-outlined">
12 more_horiz
13 </span>`
14 : /* HTML */
15 `<span style="color: var(--md-sys-color-on-surface-variant)"
16 class="material-symbols-outlined">
17 more_vert
18 </span>`
19 }
20
21}
22
23customElements
24 .define("md-overflow-button", MdOverflowButton, { extends: "button" })

D. lib / js / custom / md-overflow-menu.js

1import { abreElementoHtml } from "../abreElementoHtml.js"
2import { cierraElementoHtmo } from "../cierraElementoHtmo.js"
3
4export class MdOverflowMenu extends HTMLElement {
5
6 getContent() {
7 return /* HTML */`
8
9 <style>
10
11 :host {
12 position: fixed;
13 min-width: 7rem;
14 max-width: 280px;
15 }
16
17 ::slotted(*) {
18 text-align: start;
19 width: 100%;
20 border: none;
21 background-color: transparent;
22 }
23
24 </style>
25
26 <slot></slot>`
27 }
28
29 constructor() {
30 super()
31 const shadow = this.attachShadow({ mode: "open" })
32 shadow.innerHTML = this.getContent()
33 this.clicCierra = this.clicCierra.bind(this)
34 /**
35 * @private
36 * @type {HTMLButtonElement| null}
37 */
38 this._toggleButton = null
39 }
40
41 connectedCallback() {
42 this.classList.add("md-menu")
43 this.role = "menu"
44 }
45
46 /**
47 * @param {HTMLButtonElement} toggleButton
48 */
49 alterna(toggleButton) {
50 this._toggleButton = toggleButton
51 const top = toggleButton.offsetTop + toggleButton.offsetHeight - 4
52 const right =
53 innerWidth - (toggleButton.offsetLeft + toggleButton.offsetWidth) - 3
54 this.style.top = `${top}px`
55 this.style.right = `${right}px`
56 const list = this.classList
57 if (list.contains("open")) {
58 this.cierra()
59 } else {
60 this.abre()
61 }
62 }
63
64 abre() {
65 document.addEventListener("click", this.clicCierra)
66 abreElementoHtml(this)
67 }
68
69 cierra() {
70 document.removeEventListener("click", this.clicCierra)
71 cierraElementoHtmo(this)
72 }
73
74 /**
75 * @param {Event} evt
76 */
77 clicCierra(evt) {
78 const target = evt.target
79 if (this.classList.contains("open")
80 && this._toggleButton !== null
81 && target instanceof HTMLElement
82 && !this._toggleButton.contains(target)) {
83 this.cierra()
84 }
85 }
86}
87
88customElements.define("md-overflow-menu", MdOverflowMenu)

E. lib / js / custom / md-select-menu.js

1import { getAttribute } from "../getAttribute.js"
2import { querySelector } from "../querySelector.js"
3import { MdOptionsMenu } from "./md-options-menu.js"
4
5export class MdSelectMenu extends HTMLElement {
6
7 static get observedAttributes() {
8 return ["options", "value", "required"]
9 }
10
11 getContent() {
12 return /* HTML */ `
13 <link rel="stylesheet" href="/lib/css/material-symbols-outlined.css">
14
15 <style>
16 :host {
17 display: block;
18 cursor: default;
19 }
20
21 output {
22 display: block;
23 padding-right: 2rem;
24 white-space: nowrap;
25 text-overflow: ellipsis;
26 overflow: hidden;
27 }
28
29 #up {
30 position: absolute;
31 bottom: 0.5rem;
32 right: 0.75rem;
33 display: none;
34 color: var(--md-sys-color-on-surface-variant);
35 }
36
37 #down {
38 position: absolute;
39 bottom: 0.5rem;
40 right: 0.75rem;
41 color: var(--md-sys-color-on-surface-variant);
42 }
43
44 :host(.open) #up {
45 display: inline-block;
46 }
47
48 :host(.open) #down {
49 display: none;
50 }
51
52 :host(:invalid) #up,
53 :host(:invalid) #down {
54 color: var(--md-sys-color-error);
55 }
56
57 </style>
58 <output></output>
59 <span id="down" class="material-symbols-outlined">
60 arrow_drop_down
61 </span>
62 <span id="up" class="material-symbols-outlined">
63 arrow_drop_up
64 </span>`
65 }
66
67 constructor() {
68 super()
69
70 const shadow = this.attachShadow({ mode: "open" })
71 shadow.innerHTML = this.getContent()
72
73 this._alterna = this._alterna.bind(this)
74 this._onKeyDown = this._onKeyDown.bind(this)
75 this._cierra = this._cierra.bind(this)
76 this._clicEnDialogo = this._clicEnDialogo.bind(this)
77 this.clicExterno = this.clicExterno.bind(this)
78 this.muestraValue = this.muestraValue.bind(this)
79
80 /**
81 * @private
82 * @type {string}
83 */
84 this._customValidity = ""
85
86 /**
87 * @private
88 * @type { HTMLOutputElement }
89 */
90 this.output = querySelector(shadow, "output")
91 /**
92 * @private
93 * @type { MdOptionsMenu | null }
94 */
95 this._optionsMenu = null
96 /**
97 * @protected
98 * @readonly
99 */
100 this._internals = this.attachInternals()
101 this._internals.role = "select"
102 addEventListener("load", this.muestraValue)
103 }
104
105 connectedCallback() {
106 this.tabIndex = 0
107 this.role = "combobox"
108 this.ariaHasPopup = "listbox"
109 this.ariaExpanded = "false"
110 this["aria-controls"] = this.options
111 this.addEventListener("keydown", this._onKeyDown)
112 const parentElement = this.parentElement
113 if (parentElement !== null) {
114 parentElement.addEventListener("click", this._alterna)
115 }
116 }
117
118 /**
119 * @param {string} nombreDeAtributo
120 * @param {string} _valorAnterior
121 * @param {string} _nuevoValor
122 */
123 attributeChangedCallback(nombreDeAtributo, _valorAnterior, _nuevoValor) {
124 switch (nombreDeAtributo) {
125 case "options":
126 this._cambiaOptions()
127 break
128 case "value":
129 this.muestraValue()
130 break
131 case "required":
132 this.checkValidity()
133 break
134 }
135 }
136
137 get options() {
138 return getAttribute(this, "options")
139 }
140
141 set options(options) {
142 this.setAttribute("options", options)
143 }
144
145 _cambiaOptions() {
146 if (this._optionsMenu !== null) {
147 this._optionsMenu = null
148 }
149 this["aria-controls"] = this.options
150 }
151
152 get required() {
153 return this.hasAttribute("required")
154 }
155
156 set required(required) {
157 this.toggleAttribute("required", Boolean(required))
158 }
159
160 get value() {
161 return getAttribute(this, "value")
162 }
163
164 set value(value) {
165 this.setAttribute("value", value)
166 }
167
168 get name() {
169 return getAttribute(this, "name")
170 }
171
172 set name(name) {
173 this.setAttribute("name", name)
174 }
175
176 muestraValue() {
177 const value = this.value
178 this._internals.setFormValue(value)
179
180 // En un futuro se usará esto en vez de la clase populated.
181 // if (value === "") {
182 // this._internals.states.delete("populated")
183 // } else {
184 // this._internals.states.add("populated")
185 // }
186
187 if (this.isConnected) {
188 if (value === "") {
189 this.classList.remove("populated")
190 } else {
191 this.classList.add("populated")
192 }
193 this._checkValidity()
194 const optionsMenu = this.optionsMenu
195 if (optionsMenu !== null) {
196 this.output.value = optionsMenu.muestraValue(value)
197 }
198 }
199 }
200
201 get form() {
202 return this._internals && this._internals.form
203 }
204
205 get willValidate() {
206 return this._internals ? this._internals.willValidate : true
207 }
208
209 /**
210 * @param {string} message
211 */
212 setCustomValidity(message) {
213 this._customValidity = message
214 this._checkValidity()
215 }
216
217 /**
218 * @returns {ValidityState}
219 */
220 get validity() {
221 return this._internals.validity
222 }
223
224 checkValidity() {
225 return this._internals.checkValidity()
226 }
227
228 reportValidity() {
229 return this._internals.reportValidity()
230 }
231
232 get validationMessage() {
233 return this._internals.validationMessage
234 }
235 /** @returns {boolean} */
236 _checkValidity() {
237 if (this._customValidity !== "") {
238 this._internals.setValidity({ customError: true }, this._customValidity)
239 return false
240 } else if (this.required && this.value === "") {
241 this._internals.setValidity({ valueMissing: true }, "Seleccione una opción.")
242 return false
243 } else {
244 this._internals.setValidity({})
245 return true
246 }
247 }
248
249 /** @private */
250 _alterna() {
251 if (this.classList.contains("open")) {
252 this._cierra()
253 } else {
254 this._abre()
255 }
256 }
257
258 /** @private */
259 _abre() {
260 this.classList.add("open")
261 const parentElement = this.parentElement
262 if (parentElement !== null) {
263 const optionsMenu = this.optionsMenu
264 if (optionsMenu !== null) {
265 optionsMenu.style.top = `${parentElement.offsetTop + 58}px`
266 optionsMenu.style.left = `${parentElement.offsetLeft}px`
267 optionsMenu.style.width = `${parentElement.offsetWidth}px`
268 optionsMenu.abre()
269 this.focus()
270 optionsMenu.addEventListener("click", this._clicEnDialogo)
271 }
272 this.ariaExpanded = "true"
273 document.addEventListener("click", this.clicExterno)
274 }
275 }
276
277 /** @private */
278 _cierra() {
279 this.classList.remove("open")
280 const optionsMenu = this.optionsMenu
281 if (optionsMenu !== null) {
282 optionsMenu.cierra()
283 optionsMenu.removeEventListener("click", this._clicEnDialogo)
284 }
285 this.ariaExpanded = "false"
286 document.removeEventListener("click", this.clicExterno)
287 this.dispatchEvent(new Event("input", { bubbles: true }))
288 }
289
290 get optionsMenu() {
291 if (this._optionsMenu === null) {
292 if (this.options !== "") {
293 const optionsMenu = document.getElementById(this.options)
294 if (optionsMenu instanceof MdOptionsMenu) {
295 this._optionsMenu = optionsMenu
296 } else {
297 throw new Error(`Valor incorrecto para options: "${this.options}".`)
298 }
299 }
300 }
301 return this._optionsMenu
302 }
303
304 /** @private */
305 _avanzaOpcion() {
306 const i = this._valueIndex
307 if (i > -1) {
308 const optionsMenu = this.optionsMenu
309 if (optionsMenu !== null) {
310 const opciones = optionsMenu.opciones
311 if (i < opciones.length - 1) {
312 this.value = getAttribute(opciones[i + 1], "data-value")
313 }
314 }
315 }
316 }
317
318 /** @private */
319 _retrocedeOpcion() {
320 const i = this._valueIndex
321 if (i > -1) {
322 const optionsMenu = this.optionsMenu
323 if (optionsMenu !== null) {
324 const opciones = optionsMenu.opciones
325 if (i > 0) {
326 this.value = getAttribute(opciones[i - 1], "data-value")
327 }
328 }
329 }
330 }
331
332 /**
333 * @private
334 * @returns {number}
335 */
336 get _valueIndex() {
337 const value = this.value
338 const optionsMenu = this.optionsMenu
339 return (optionsMenu === null
340 ? -1
341 : optionsMenu.opciones.findIndex(opcion => opcion.dataset.value === value))
342 }
343
344 /**
345 * @private
346 * @param {Event} event
347 */
348 _clicEnDialogo(event) {
349 const target = event.target
350 const optionsMenu = this.optionsMenu
351 let value = ""
352 if (optionsMenu !== null) {
353 for (const opcion of optionsMenu.opciones) {
354 if (opcion === target) {
355 opcion.classList.add("selected")
356 value = getAttribute(opcion, "data-value")
357 } else {
358 opcion.classList.remove("selected")
359 }
360 }
361 }
362 this.value = value
363 this._cierra()
364 this.focus()
365}
366
367 /**
368 * @param {Event} evt
369 */
370 clicExterno(evt) {
371 const target = evt.target
372 const parentElement = this.parentElement
373 const optionsMenu = this._optionsMenu
374 if (this.classList.contains("open")
375 && target instanceof HTMLElement
376 && parentElement !== null
377 && !parentElement.contains(target)
378 && optionsMenu !== null
379 && !optionsMenu.contains(target)) {
380 this._cierra()
381 }
382 }
383
384 /**
385 * @param { KeyboardEvent } event
386 */
387 _onKeyDown(event) {
388 const key = event.key
389 const optionsMenu = this._optionsMenu
390 if (optionsMenu !== null) {
391 if (optionsMenu.classList.contains("open")) {
392 if (key === "ArrowDown") {
393 event.preventDefault()
394 this._avanzaOpcion()
395 } else if (key === "ArrowUp") {
396 event.preventDefault()
397 this._retrocedeOpcion()
398 } else if (key === "Escape") {
399 event.preventDefault()
400 this._cierra()
401 } else if (key === " ") {
402 event.preventDefault()
403 this._cierra()
404 } else if (key === "Tab") {
405 this._cierra()
406 } else {
407 event.preventDefault()
408 }
409 } else if (key === " ") {
410 event.preventDefault()
411 this._abre()
412 } else if (key === "Tab") {
413 this._cierra()
414 } else {
415 event.preventDefault()
416 }
417 }
418 }
419
420}
421
422MdSelectMenu.formAssociated = true
423
424customElements.define("md-select-menu", MdSelectMenu)

F. lib / js / custom / md-slider-field.js

1import { querySelector } from "../querySelector.js"
2
3export class MdSliderField extends HTMLElement {
4
5 getContent() {
6 return /* HTML */`
7 <style>
8 :host {
9 display: block;
10 margin: 1rem;
11 }
12
13 :host([hidden]) {
14 display: none;
15 }
16
17 #label::slotted(*) {
18 display: block;
19 white-space: nowrap;
20 text-overflow: ellipsis;
21 overflow: hidden;
22 color: var(--md-sys-color-on-surface-variant);
23 font-family: var(--md-sys-typescale-body-small-font);
24 font-weight: var(--md-sys-typescale-body-small-weight);
25 font-size: var(--md-sys-typescale-body-small-size);
26 font-style: var(--md-sys-typescale-body-small-font-style);
27 letter-spacing: var(--md-sys-typescale-body-small-tracking);
28 line-height: var(--md-sys-typescale-body-small-line-height);
29 text-transform: var(--md-sys-typescale-body-small-text-transform);
30 text-decoration: var(--md-sys-typescale-body-small-text-decoration);
31 }
32
33 [name="slider"]::slotted(input) {
34 -webkit-appearance: none;
35 appearance: none;
36 height: 0.25rem;
37 border-radius: 0.125rem;
38 background-image:
39 linear-gradient(to right, var(--md-sys-color-primary) 0%, var(--md-sys-color-primary) 50%, var(--md-sys-color-surface-container-highest) 50%, var(--md-sys-color-surface-container-highest) 100%);
40 }
41
42 [name="slider"]::slotted(input:focus) {
43 outline: none;
44 }
45
46 [name="supporting"]::slotted(*) {
47 display: block;
48 color: var(--md-sys-color-on-surface-variant);
49 font-family: var(--md-sys-typescale-body-small-font);
50 font-weight: var(--md-sys-typescale-body-small-weight);
51 font-size: var(--md-sys-typescale-body-small-size);
52 font-style: var(--md-sys-typescale-body-small-font-style);
53 letter-spacing: var(--md-sys-typescale-body-small-tracking);
54 line-height: var(--md-sys-typescale-body-small-line-height);
55 text-transform: var(--md-sys-typescale-body-small-text-transform);
56 text-decoration: var(--md-sys-typescale-body-small-text-decoration);
57 padding-top: 0.5rem;
58 white-space: nowrap;
59 text-overflow: ellipsis;
60 overflow: hidden;
61 }
62 </style>
63 <slot id="label"></slot>
64 <slot name="slider"></slot>
65 <slot name="supporting"></slot>`
66 }
67
68 constructor() {
69 super()
70 const shadow = this.attachShadow({ mode: "open", delegatesFocus: true })
71 shadow.innerHTML = this.getContent()
72 this._configuraSlider = this._configuraSlider.bind(this)
73 this.analiza = this.analiza.bind(this)
74
75 /**
76 * @private
77 * @type {HTMLSlotElement}
78 */
79 this._slotSlider = querySelector(shadow, '[name="slider"]')
80 /**
81 * @private
82 * @type {HTMLInputElement|null}
83 */
84 this._input = null
85 this._slotSlider.addEventListener("slotchange", this._configuraSlider)
86 }
87
88 /** @private */
89 _configuraSlider() {
90 if (this._input !== null) {
91 this._input.removeEventListener("input", this.analiza)
92 this._input = null
93 }
94 for (const input of this._slotSlider.assignedElements()) {
95 if (input instanceof HTMLInputElement) {
96 this._input = input
97 input.addEventListener("input", this.analiza)
98 this.analiza()
99 }
100 }
101 }
102
103 analiza() {
104 const i = this._input
105 if (i !== null) {
106 const v = i.valueAsNumber
107 const min = parseFloat(i.min)
108 const max = parseFloat(i.max)
109 const value = (v - min) / (max - min) * 100
110 i.title = v.toString()
111 i.style.background =
112 `linear-gradient(to right, var(--md-sys-color-primary) 0%, var(--md-sys-color-primary) ${value
113 }%, var(--md-sys-color-surface-container-highest) ${value
114 }%, var(--md-sys-color-surface-container-highest) 100%)`
115 }
116 }
117
118}
119
120customElements.define("md-slider-field", MdSliderField)

G. lib / js / custom / md-top-app-bar.js

1import { ES_APPLE } from "../const/ES_APPLE.js"
2import { getAttribute } from "../getAttribute.js"
3import { querySelector } from "../querySelector.js"
4
5class MdTopAppBar extends HTMLElement {
6
7 getContent() {
8 return /* HTML */`
9 <style>
10
11 :host {
12 display: flex;
13 box-sizing: border-box;
14 align-items: center;
15 padding: 0 0.25rem;
16 background-color: var(--md-sys-color-surface);
17 position: sticky;
18 z-index: 1;
19 left: env(titlebar-area-x, 0);
20 top: env(titlebar-area-y, 0);
21 height: env(titlebar-area-height, 4rem);
22 width: env(titlebar-area-width, 100%);
23 }
24
25 :host(.apple) {
26 height: env(titlebar-area-height, 3rem);
27 }
28
29 :host(.scroll) {
30 background-color: var(--md-sys-color-surface-container-low);
31 }
32
33 #navigation {
34 flex: 0 0 auto;
35 overflow: hidden
36 }
37
38 #navigation ::slotted(*) {
39 color: var(--md-sys-color-on-surface);
40 }
41
42 #acciones {
43 margin-left: auto;
44 flex: 0 0 auto;
45 overflow: hidden
46 }
47
48 :host(.centrado) #acciones,
49 :host(.center-aligned) #acciones {
50 flex: 0 0 3rem;
51 overflow: hidden
52 }
53
54 #headline::slotted(*) {
55 -webkit-app-region: drag;
56 flex: 1 1 auto;
57 white-space: nowrap;
58 text-overflow: ellipsis;
59 overflow: hidden;
60 font-family: var(--md-sys-typescale-title-large-font);
61 font-weight: var(--md-sys-typescale-title-large-weight);
62 font-size: var(--md-sys-typescale-title-large-size);
63 font-style: var(--md-sys-typescale-title-large-font-style);
64 letter-spacing: var(--md-sys-typescale-title-large-tracking);
65 line-height: var(--md-sys-typescale-title-large-line-height);
66 text-transform: var(--md-sys-typescale-title-large-text-transform);
67 text-decoration: var(--md-sys-typescale-title-large-text-decoration);
68 color: var(--md-sys-color-on-surface);
69 }
70
71 :host(.center-aligned) #headline::slotted(*) {
72 flex: 1 1 auto;
73 text-align: center
74 }
75
76 </style>
77
78 <span id="navigation">
79 <slot name="navigation"></slot>
80 </span>
81 <slot id="headline"></slot>
82 <span id="acciones">
83 <slot name="action"></slot>
84 </span>`
85 }
86
87 constructor() {
88 super()
89 if (ES_APPLE) {
90 document.body.classList.add("apple")
91 document.body.classList.remove("material")
92 } else {
93 document.body.classList.add("material")
94 document.body.classList.remove("apple")
95 }
96
97 /**
98 * @private
99 * @readonly
100 */
101 const shadow = this.attachShadow({ mode: "open" })
102 shadow.innerHTML = this.getContent()
103 this._configuraAction = this._configuraAction.bind(this)
104 /**
105 * @private
106 * @type {number}
107 */
108 this._posY = 0
109 /**
110 * @private
111 * @type {boolean}
112 */
113 this._scrolling = false
114 /**
115 * @private
116 * @type { HTMLSlotElement }
117 */
118 this._navigation = querySelector(shadow, '[name="navigation"]')
119 /**
120 * @private
121 * @type { HTMLSlotElement }
122 */
123 this._action = querySelector(shadow, '[name="action"]')
124 /**
125 * @private
126 * @type { HTMLHeadingElement | null }
127 */
128 this._headline = null
129 /**
130 * @private
131 * @type { HTMLElement | null }
132 */
133 this._adicional = null
134 this._action.addEventListener("slotchange", this._configuraAction)
135 addEventListener("scroll", () => this._onScroll())
136 addEventListener("load", () => this.configurOtros())
137 }
138
139 connectedCallback() {
140 this.role = "toolbar"
141 this._configuraAction()
142 }
143
144 configurOtros() {
145 const idHeadline = getAttribute(this, "headline")
146 if (idHeadline !== "") {
147 const headline = document.getElementById(idHeadline)
148 if (headline instanceof HTMLHeadingElement) {
149 this._headline = headline
150 if (this.classList.contains("apple") || this.classList.contains("medium")) {
151 headline.classList.add("md-headline", "headline-small")
152 } else {
153 headline.classList.add("md-headline", "headline-medium")
154 }
155 }
156 }
157 const idAdicional = getAttribute(this, "adicional")
158 if (idAdicional !== "") {
159 this._adicional = document.getElementById(idAdicional)
160 if (this._adicional !== null) {
161 if (this.classList.contains("apple")) {
162 this._adicional.style.top = "env(titlebar-area-height, 3rem)"
163 } else {
164 this._adicional.style.top = "env(titlebar-area-height, 4rem)"
165 }
166 }
167 }
168 }
169
170 _configuraAction() {
171 const assignedElements = this._action.assignedElements()
172 if (this.isConnected) {
173 if (ES_APPLE) {
174 this.classList.add("apple")
175 this.classList.remove("material")
176 } else {
177 this.classList.add("material")
178 this.classList.remove("apple")
179 }
180 if (this.classList.contains("center-aligned")) {
181 this.classList.remove("centrado")
182 this.classList.remove("justificado")
183 } else {
184 if (ES_APPLE && assignedElements.length <= 1) {
185 this.classList.add("centrado")
186 this.classList.remove("justificado")
187 } else {
188 this.classList.add("justificado")
189 this.classList.remove("centrado")
190 }
191 }
192 }
193 }
194
195 /** @private */
196 _onScroll() {
197 this._posY = scrollY
198 if (!this._scrolling) {
199 requestAnimationFrame(() => this._avanza())
200 }
201 this._scrolling = true
202 }
203
204 /** @private */
205 _avanza() {
206 if (this._posY === 0) {
207 this.classList.remove("scroll")
208 if (this._headline !== null) {
209 if (this._adicional === null) {
210 this._headline.classList.remove("scroll")
211 } else {
212 this._headline.classList.remove("scroll-adicional")
213 }
214 }
215 if (this._adicional !== null) {
216 this._adicional.classList.remove("scroll")
217 }
218 } else {
219 this.classList.add("scroll")
220 if (this._headline !== null) {
221 if (this._adicional === null) {
222 this._headline.classList.add("scroll")
223 } else {
224 this._headline.classList.add("scroll-adicional")
225 }
226 }
227 if (this._adicional !== null) {
228 this._adicional.classList.add("scroll")
229 }
230 }
231 this._scrolling = false
232 }
233
234}
235
236customElements.define("md-top-app-bar", MdTopAppBar)

H. lib / js / custom / MdNavigationDrawer.js

1import { abreElementoHtml } from "../abreElementoHtml.js"
2import { cierraElementoHtmo } from "../cierraElementoHtmo.js"
3import { querySelector } from "../querySelector.js"
4
5export class MdNavigationDrawer extends HTMLElement {
6
7 /**
8 * @returns {string}
9 */
10 getHipervinculos() { throw new Error("abstract") }
11
12 getContent() {
13 return /* HTML */`
14
15 <link rel="stylesheet" href="/lib/css/material-symbols-outlined.css">
16 <link rel="stylesheet" href="/lib/css/md-ripple.css">
17 <link rel="stylesheet" href="/material-tokens/css/shape.css">
18 <link rel="stylesheet" href="/material-tokens/css/motion.css">
19
20 <style>
21
22 :host {
23 display: block;
24 }
25
26 :host([hidden]) {
27 display: none;
28 }
29
30 nav {
31 display: none;
32 flex-direction: column;
33 position: fixed;
34 z-index: 4;
35 box-sizing: border-box;
36 top: 0;
37 left: 0;
38 bottom: 0;
39 width: var(--anchoNav);
40 max-width: 80vw;
41 overflow: hidden;
42 overscroll-behavior: contain;
43 background-color: var(--md-sys-color-surface-container-low);
44 transform: translateX(-100%);
45 transition-property: display, transform;
46 transition-behavior: allow-discrete;
47 }
48
49 nav.open {
50 display: flex;
51 transform: translateX(0);
52 }
53
54 nav>div {
55 flex-grow: 1;
56 overflow: auto;
57 padding: 0.75rem 1rem;
58 }
59
60 h1 {
61 margin: 0;
62 height: 3.5rem;
63 line-height: 3.5rem;
64 padding: 0 0 0 0.75rem;
65 white-space: nowrap;
66 text-overflow: ellipsis;
67 overflow: hidden;
68 color: var(--md-sys-color-on-surface-variant);
69 font-family: var(--md-sys-typescale-title-small-font);
70 font-weight: var(--md-sys-typescale-title-small-weight);
71 font-size: var(--md-sys-typescale-title-small-size);
72 font-style: var(--md-sys-typescale-title-small-font-style);
73 letter-spacing: var(--md-sys-typescale-title-small-tracking);
74 text-transform: var(--md-sys-typescale-title-small-text-transform);
75 text-decoration: var(--md-sys-typescale-title-small-text-decoration);
76 }
77
78 a::after { /* container inactive */
79 content: "";
80 position: absolute;
81 z-index: -2;
82 top: 0;
83 right: 0;
84 left: 0;
85 bottom: 0;
86 }
87
88 a.active::after { /* container */
89 background-color: var(--md-sys-color-secondary-container);
90 }
91
92 a { /* label, shape inactive */
93 position: relative;
94 display: block;
95 box-sizing: border-box;
96 height: 3.5rem;
97 line-height: 3.5rem;
98 padding: 0 0.75rem;
99 border-radius: 1.75rem;
100 color: var(--md-sys-color-on-surface-variant);
101 font-family: var(--md-sys-typescale-label-large-font);
102 font-weight: var(--md-sys-typescale-label-large-weight);
103 font-size: var(--md-sys-typescale-label-large-size);
104 font-style: var(--md-sys-typescale-label-large-font-style);
105 letter-spacing: var(--md-sys-typescale-label-large-tracking);
106 text-transform: var(--md-sys-typescale-label-large-text-transform);
107 text-decoration: var(--md-sys-typescale-label-large-text-decoration);
108 overflow: hidden;
109 white-space: nowrap;
110 text-overflow: ellipsis;
111 }
112
113 a.active { /* label, shape */
114 font-weight: var(--md-sys-typescale-label-large-weight-prominent);
115 color: var(--md-sys-color-on-secondary-container);
116 }
117
118 a::before { /* state layer */
119 content: "";
120 position: absolute;
121 z-index: -1;
122 top: 0;
123 right: 0;
124 left: 0;
125 bottom: 0;
126 }
127
128 a span { /* inactive icon */
129 position: relative;
130 margin-right: 0.75rem;
131 vertical-align: middle;
132 color: var(--md-sys-color-on-surface-variant);
133 font-size: 1.5rem;
134 width: 1.5rem;
135 height: 1.5rem;
136 }
137
138 a.active span { /* icon */
139 color: var(--md-sys-color-on-secondary-container);
140 }
141
142 #scrim {
143 display: none;
144 position: fixed;
145 z-index: 3;
146 top: 0;
147 left: 0;
148 bottom: 0;
149 right: 0;
150 opacity: 0.4;
151 background-color: var(--md-ref-palette-neutral-variant20);
152 transform: translateX(-100%);
153 transition-property: display, transform;
154 transition-behavior: allow-discrete;
155 }
156
157 #scrim.open {
158 display: block;
159 transform: translateX(0);
160 }
161
162 @starting-style {
163 nav.open{
164 display: flex;
165 transform: translateX(-100%);
166 }
167 #scrim.open {
168 display: block;
169 transform: translateX(-100%);
170 }
171 }
172
173 a:hover { /* inactive label, shape */
174 color: var(--md-sys-color-on-surface);
175 }
176
177 a.active:hover { /* active label, shape */
178 color: var(--md-sys-color-on-secondary-container);
179 }
180
181 a:hover::before { /* inactive state layer */
182 background-color: var(--md-sys-color-on-surface);
183 opacity: var(--md-sys-state-hover-state-layer-opacity);
184 }
185
186 a.active:hover::before { /* state layer */
187 background-color: var(--md-sys-color-on-secondary-container);
188 }
189
190 a:hover span { /* inactive icon */
191 color: var(--md-sys-color-on-surface);
192 }
193
194 a.active:hover span { /* icon */
195 color: var(--md-sys-color-on-secondary-container);
196 }
197
198 a:focus { /* inactive label, shape */
199 outline: none;
200 color: var(--md-sys-color-on-surface);
201 }
202
203 a.active:focus { /* label, shape */
204 color: var(--md-sys-color-on-secondary-container);
205 }
206
207 a:focus::before { /* inactive state layer */
208 background-color: var(--md-sys-color-on-surface);
209 opacity: var(--md-sys-state-focus-state-layer-opacity);
210 }
211
212 a.active:focus::before { /* state layer */
213 background-color: var(--md-sys-color-on-secondary-container);
214 }
215
216 a:focus span { /* inactive icon */
217 color: var(--md-sys-color-on-surface);
218 }
219
220 a.active:focus span { /* icon */
221 color: var(--md-sys-color-on-secondary-container);
222 }
223
224 a:active { /* inactive pressed label, shape */
225 background-position: center;
226 background-image:
227 radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
228 background-size: 100%;
229 animation-name: md-ripple;
230 animation-duration: var(--md-sys-motion-duration-500);
231 color: var(--md-sys-color-on-surface);
232 }
233
234 a.active:active { /* active pressed label, shape */
235 color: var(--md-sys-color-on-secondary-container);
236 }
237
238 a:active::before { /* inactive pressed state layer */
239 background-color: var(--md-sys-color-on-surface);
240 opacity: var(--md-sys-state-pressed-state-layer-opacity);
241 }
242
243 a.active:active::before { /* active pressed state layer */
244 background-color: var(--md-sys-color-on-secondary-container);
245 }
246
247 a:active span { /* inactive pressed icon */
248 color: var(--md-sys-color-on-surface);
249 }
250
251 a.active:focus span { /* active pressed icon */
252 color: var(--md-sys-color-on-secondary-container);
253 }
254
255 </style>
256
257 <div id="scrim"class="duration-700 easing-standard"></div>
258 <nav class="large-end duration-700 easing-standard"><div></div></nav>`
259 }
260
261 constructor() {
262 super()
263 const shadow = this.attachShadow({ mode: "open", delegatesFocus: true })
264 shadow.innerHTML = this.getContent()
265 this.cierra = this.cierra.bind(this)
266
267 /** @type {HTMLElement} */
268 this._nav = querySelector(shadow, "nav")
269
270 /** @type {HTMLUListElement} */
271 this._div = querySelector(this._nav, "div")
272
273 /** @type {HTMLUListElement} */
274 this._scrim = querySelector(shadow, "#scrim")
275 this._scrim.addEventListener("click", this.cierra)
276 }
277
278 connectedCallback() {
279 this.classList.add("drawer")
280 this._div.innerHTML = this.getHipervinculos()
281 }
282
283 abre() {
284 abreElementoHtml(this._nav)
285 abreElementoHtml(this._scrim)
286 }
287
288 cierra() {
289 cierraElementoHtmo(this._nav)
290 cierraElementoHtmo(this._scrim)
291 }
292
293}

33. Carpeta « material-tokens »

Versión para imprimir.

A. Carpeta « material-tokens / css »

1. material-tokens / css / baseline.css

1/*
2 Copyright 2016 Google Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17@import url(palette.css);
18@import url(typography.css);
19@import url(colors.css);
20@import url(shape.css);
21@import url(motion.css);
22@import url(state.css);
23@import url(elevation.css);
24@import url(theme/light.css) screen and (prefers-color-scheme: light);
25@import url(theme/dark.css) screen and (prefers-color-scheme: dark);
26

2. material-tokens / css / colors.css

1/*
2 Copyright 2016 Google Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17.primary {
18 color: var(--md-sys-color-on-primary);
19 background-color: var(--md-sys-color-primary);
20}
21.on-primary {
22 color: var(--md-sys-color-primary);
23 background-color: var(--md-sys-color-on-primary);
24}
25.primary-container {
26 color: var(--md-sys-color-on-primary-container);
27 background-color: var(--md-sys-color-primary-container);
28}
29.on-primary-container {
30 color: var(--md-sys-color-primary-container);
31 background-color: var(--md-sys-color-on-primary-container);
32}
33.secondary {
34 color: var(--md-sys-color-on-secondary);
35 background-color: var(--md-sys-color-secondary);
36}
37.on-secondary {
38 color: var(--md-sys-color-secondary);
39 background-color: var(--md-sys-color-on-secondary);
40}
41.secondary-container {
42 color: var(--md-sys-color-on-secondary-container);
43 background-color: var(--md-sys-color-secondary-container);
44}
45.on-secondary-container {
46 color: var(--md-sys-color-secondary-container);
47 background-color: var(--md-sys-color-on-secondary-container);
48}
49.tertiary {
50 color: var(--md-sys-color-on-tertiary);
51 background-color: var(--md-sys-color-tertiary);
52}
53.on-tertiary {
54 color: var(--md-sys-color-tertiary);
55 background-color: var(--md-sys-color-on-tertiary);
56}
57.tertiary-container {
58 color: var(--md-sys-color-on-tertiary-container);
59 background-color: var(--md-sys-color-tertiary-container);
60}
61.on-tertiary-container {
62 color: var(--md-sys-color-tertiary-container);
63 background-color: var(--md-sys-color-on-tertiary-container);
64}
65.background {
66 color: var(--md-sys-color-on-background);
67 background-color: var(--md-sys-color-background);
68}
69.surface {
70 color: var(--md-sys-color-on-surface);
71 background-color: var(--md-sys-color-surface);
72}
73.surface-variant {
74 color: var(--md-sys-color-on-surface-variant);
75 background-color: var(--md-sys-color-surface-variant);
76}
77.on-surface-variant {
78 color: var(--md-sys-color-surface-variant);
79 background-color: var(--md-sys-color-on-surface-variant);
80}
81.outline {
82 border: 1px solid var(--md-sys-color-outline);
83}
84.inverse-surface {
85 color: var(--md-sys-color-on-inverse-surface);
86 background-color: var(--md-sys-color-inverse-surface);
87}
88.on-inverse-surface {
89 color: var(--md-sys-color-inverse-surface);
90 background-color: var(--md-sys-color-on-inverse-surface);
91}
92.inverse-primary {
93 color: var(--md-sys-color-on-inverse-primary);
94 background-color: var(--md-sys-color-inverse-primary);
95}
96.on-inverse-primary {
97 color: var(--md-sys-color-inverse-primary);
98 background-color: var(--md-sys-color-on-inverse-primary);
99}
100.surface-tint {
101 background-color: var(--md-sys-color-on-surface-tint);
102}
103.error {
104 color: var(--md-sys-color-on-error);
105 background-color: var(--md-sys-color-error);
106}
107.on-error {
108 color: var(--md-sys-color-error);
109 background-color: var(--md-sys-color-on-error);
110}
111.error-container {
112 color: var(--md-sys-color-on-error-container);
113 background-color: var(--md-sys-color-error-container);
114}
115.on-error-container {
116 color: var(--md-sys-color-error-container);
117 background-color: var(--md-sys-color-on-error-container);
118}
119.black {
120 background-color: var(--md-ref-palette-black);
121}
122.black-text {
123 color: var(--md-ref-palette-black);
124}
125.white {
126 background-color: var(--md-ref-palette-white);
127}
128.white-text {
129 color: var(--md-ref-palette-white);
130}
131

3. material-tokens / css / elevation.css

1/*
2 Copyright 2016 Google Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17:root {
18 /* Surface tint color */
19 --md-sys-elevation-surface-tint-color: var(--md-sys-color-primary);
20 /* +5 */
21 --md-sys-elevation-level5-value: 12px;
22 --md-sys-elevation-level5-unit: 1px;
23 --md-sys-elevation-level5: 12px;
24 /* +4 */
25 --md-sys-elevation-level4-value: 8px;
26 --md-sys-elevation-level4-unit: 1px;
27 --md-sys-elevation-level4: 8px;
28 /* +3 */
29 --md-sys-elevation-level3-value: 6px;
30 --md-sys-elevation-level3-unit: 1px;
31 --md-sys-elevation-level3: 6px;
32 /* +2 */
33 --md-sys-elevation-level2-value: 3px;
34 --md-sys-elevation-level2-unit: 1px;
35 --md-sys-elevation-level2: 3px;
36 /* +1 */
37 --md-sys-elevation-level1-value: 1px;
38 --md-sys-elevation-level1-unit: 1px;
39 --md-sys-elevation-level1: 1px;
40 /* 0 */
41 --md-sys-elevation-level0-value: 0px;
42 --md-sys-elevation-level0-unit: 1px;
43 --md-sys-elevation-level0: 0px;
44}
45.elevation-0 {
46 box-shadow: var(--md-sys-elevation-level0);
47}
48.elevation-1 {
49 box-shadow: var(--md-sys-elevation-level1);
50}
51.elevation-2 {
52 box-shadow: var(--md-sys-elevation-level2);
53}
54.elevation-3 {
55 box-shadow: var(--md-sys-elevation-level3);
56}
57.elevation-4 {
58 box-shadow: var(--md-sys-elevation-level4);
59}
60.elevation-5 {
61 box-shadow: var(--md-sys-elevation-level5);
62}
63

4. material-tokens / css / motion.css

1/*
2 Copyright 2016 Google Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17:root {
18 /* Emphasized decelerate easing (out) */
19 --md-sys-motion-easing-emphasized-decelerate-x0: 0.05000000074505806;
20 --md-sys-motion-easing-emphasized-decelerate-y0: 0.699999988079071;
21 --md-sys-motion-easing-emphasized-decelerate-x1: 0.10000000149011612;
22 --md-sys-motion-easing-emphasized-decelerate-y1: 1;
23 /* Emphasized accelerate easing (in) */
24 --md-sys-motion-easing-emphasized-accelerate-x0: 0.30000001192092896;
25 --md-sys-motion-easing-emphasized-accelerate-y0: 0;
26 --md-sys-motion-easing-emphasized-accelerate-x1: 0.800000011920929;
27 --md-sys-motion-easing-emphasized-accelerate-y1: 0.15000000596046448;
28 /* Standard decelerate easing (out) */
29 --md-sys-motion-easing-standard-decelerate-x0: 0;
30 --md-sys-motion-easing-standard-decelerate-y0: 0;
31 --md-sys-motion-easing-standard-decelerate-x1: 0;
32 --md-sys-motion-easing-standard-decelerate-y1: 1;
33 /* Standard accelerate easing (in) */
34 --md-sys-motion-easing-standard-accelerate-x0: 0.30000001192092896;
35 --md-sys-motion-easing-standard-accelerate-y0: 0;
36 --md-sys-motion-easing-standard-accelerate-x1: 1;
37 --md-sys-motion-easing-standard-accelerate-y1: 1;
38 /* Duration 1000ms */
39 --md-sys-motion-duration-1000: 1000ms;
40 /* Duration 900ms */
41 --md-sys-motion-duration-900: 900ms;
42 /* Duration 800ms */
43 --md-sys-motion-duration-800: 800ms;
44 /* Duration 700ms */
45 --md-sys-motion-duration-700: 700ms;
46 /* Duration 600ms */
47 --md-sys-motion-duration-600: 600ms;
48 /* Duration 550ms */
49 --md-sys-motion-duration-550: 550ms;
50 /* Duration 500ms */
51 --md-sys-motion-duration-500: 500ms;
52 /* Duration 450ms */
53 --md-sys-motion-duration-450: 450ms;
54 /* Duration 400ms */
55 --md-sys-motion-duration-400: 400ms;
56 /* Duration 350ms */
57 --md-sys-motion-duration-350: 350ms;
58 /* Duration 300ms */
59 --md-sys-motion-duration-300: 300ms;
60 /* Duration 250ms */
61 --md-sys-motion-duration-250: 250ms;
62 /* Duration 200ms */
63 --md-sys-motion-duration-200: 200ms;
64 /* Duration 150ms */
65 --md-sys-motion-duration-150: 150ms;
66 /* Duration 100ms */
67 --md-sys-motion-duration-100: 100ms;
68 /* Duration 50ms */
69 --md-sys-motion-duration-50: 50ms;
70 /* Standard easing (in and out) */
71 --md-sys-motion-easing-standard-x0: 0.20000000298023224;
72 --md-sys-motion-easing-standard-y0: 0;
73 --md-sys-motion-easing-standard-x1: 0;
74 --md-sys-motion-easing-standard-y1: 1;
75 /* Linear easing */
76 --md-sys-motion-easing-linear-x0: 0;
77 --md-sys-motion-easing-linear-y0: 0;
78 --md-sys-motion-easing-linear-x1: 1;
79 --md-sys-motion-easing-linear-y1: 1;
80 /* Emphasized */
81 --md-sys-motion-easing-emphasized-x0: 0.20000000298023224;
82 --md-sys-motion-easing-emphasized-y0: 0;
83 --md-sys-motion-easing-emphasized-x1: 0;
84 --md-sys-motion-easing-emphasized-y1: 1;
85 /* Motion path */
86 --md-sys-motion-path-standard-path: 1;
87}
88.duration-50 {
89 transition-duration: var(--md-sys-motion-duration-50);
90}
91.duration-100 {
92 transition-duration: var(--md-sys-motion-duration-100);
93}
94.duration-150 {
95 transition-duration: var(--md-sys-motion-duration-150);
96}
97.duration-200 {
98 transition-duration: var(--md-sys-motion-duration-200);
99}
100.duration-250 {
101 transition-duration: var(--md-sys-motion-duration-250);
102}
103.duration-300 {
104 transition-duration: var(--md-sys-motion-duration-300);
105}
106.duration-350 {
107 transition-duration: var(--md-sys-motion-duration-350);
108}
109.duration-400 {
110 transition-duration: var(--md-sys-motion-duration-400);
111}
112.duration-450 {
113 transition-duration: var(--md-sys-motion-duration-450);
114}
115.duration-500 {
116 transition-duration: var(--md-sys-motion-duration-500);
117}
118.duration-550 {
119 transition-duration: var(--md-sys-motion-duration-550);
120}
121.duration-600 {
122 transition-duration: var(--md-sys-motion-duration-600);
123}
124.duration-700 {
125 transition-duration: var(--md-sys-motion-duration-700);
126}
127.duration-800 {
128 transition-duration: var(--md-sys-motion-duration-800);
129}
130.duration-900 {
131 transition-duration: var(--md-sys-motion-duration-900);
132}
133.duration-1000 {
134 transition-duration: var(--md-sys-motion-duration-1000);
135}
136.easing-standard {
137 transition-timing-function: cubic-bezier(
138 var(--md-sys-motion-easing-standard-x0),
139 var(--md-sys-motion-easing-standard-y0),
140 var(--md-sys-motion-easing-standard-x1),
141 var(--md-sys-motion-easing-standard-y1)
142 );
143}
144.easing-linear {
145 transition-timing-function: cubic-bezier(
146 var(--md-sys-motion-easing-linear-x0),
147 var(--md-sys-motion-easing-linear-y0),
148 var(--md-sys-motion-easing-linear-x1),
149 var(--md-sys-motion-easing-linear-y1)
150 );
151}
152.easing-standard-accelerate {
153 transition-timing-function: cubic-bezier(
154 var(--md-sys-motion-easing-standard-accelerate-x0),
155 var(--md-sys-motion-easing-standard-accelerate-y0),
156 var(--md-sys-motion-easing-standard-accelerate-x1),
157 var(--md-sys-motion-easing-standard-accelerate-y1)
158 );
159}
160.easing-standard-decelerate {
161 transition-timing-function: cubic-bezier(
162 var(--md-sys-motion-easing-standard-decelerate-x0),
163 var(--md-sys-motion-easing-standard-decelerate-y0),
164 var(--md-sys-motion-easing-standard-decelerate-x1),
165 var(--md-sys-motion-easing-standard-decelerate-y1)
166 );
167}
168.easing-emphasized {
169 transition-timing-function: cubic-bezier(
170 var(--md-sys-motion-easing-emphasized-x0),
171 var(--md-sys-motion-easing-emphasized-y0),
172 var(--md-sys-motion-easing-emphasized-x1),
173 var(--md-sys-motion-easing-emphasized-y1)
174 );
175}
176

5. material-tokens / css / palette.css

1/*
2 Copyright 2016 Google Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17:root {
18 /* Error 0 */
19 --md-ref-palette-error0: #000000ff;
20 /* Error 10 */
21 --md-ref-palette-error10: #410e0bff;
22 /* Error 20 */
23 --md-ref-palette-error20: #601410ff;
24 /* Error 30 */
25 --md-ref-palette-error30: #8c1d18ff;
26 /* Error 40 */
27 --md-ref-palette-error40: #b3261eff;
28 /* Error 50 */
29 --md-ref-palette-error50: #dc362eff;
30 /* Error 60 */
31 --md-ref-palette-error60: #e46962ff;
32 /* Error 70 */
33 --md-ref-palette-error70: #ec928eff;
34 /* Error 80 */
35 --md-ref-palette-error80: #f2b8b5ff;
36 /* Error 90 */
37 --md-ref-palette-error90: #f9dedcff;
38 /* Error 95 */
39 --md-ref-palette-error95: #fceeeeff;
40 /* Error 99 */
41 --md-ref-palette-error99: #fffbf9ff;
42 /* Error 100 */
43 --md-ref-palette-error100: #ffffffff;
44 /* Tertiary 0 */
45 --md-ref-palette-tertiary0: #000000ff;
46 /* Tertiary 10 */
47 --md-ref-palette-tertiary10: #31111dff;
48 /* Tertiary 20 */
49 --md-ref-palette-tertiary20: #492532ff;
50 /* Tertiary 30 */
51 --md-ref-palette-tertiary30: #633b48ff;
52 /* Tertiary 40 */
53 --md-ref-palette-tertiary40: #7d5260ff;
54 /* Tertiary 50 */
55 --md-ref-palette-tertiary50: #986977ff;
56 /* Tertiary 60 */
57 --md-ref-palette-tertiary60: #b58392ff;
58 /* Tertiary 70 */
59 --md-ref-palette-tertiary70: #d29dacff;
60 /* Tertiary 80 */
61 --md-ref-palette-tertiary80: #efb8c8ff;
62 /* Tertiary 90 */
63 --md-ref-palette-tertiary90: #ffd8e4ff;
64 /* Tertiary 95 */
65 --md-ref-palette-tertiary95: #ffecf1ff;
66 /* Tertiary 99 */
67 --md-ref-palette-tertiary99: #fffbfaff;
68 /* Tertiary 100 */
69 --md-ref-palette-tertiary100: #ffffffff;
70 /* Secondary 0 */
71 --md-ref-palette-secondary0: #000000ff;
72 /* Secondary 10 */
73 --md-ref-palette-secondary10: #1d192bff;
74 /* Secondary 20 */
75 --md-ref-palette-secondary20: #332d41ff;
76 /* Secondary 30 */
77 --md-ref-palette-secondary30: #4a4458ff;
78 /* Secondary 40 */
79 --md-ref-palette-secondary40: #625b71ff;
80 /* Secondary 50 */
81 --md-ref-palette-secondary50: #7a7289ff;
82 /* Secondary 60 */
83 --md-ref-palette-secondary60: #958da5ff;
84 /* Secondary 70 */
85 --md-ref-palette-secondary70: #b0a7c0ff;
86 /* Secondary 80 */
87 --md-ref-palette-secondary80: #ccc2dcff;
88 /* Secondary 90 */
89 --md-ref-palette-secondary90: #e8def8ff;
90 /* Secondary 95 */
91 --md-ref-palette-secondary95: #f6edffff;
92 /* Secondary 99 */
93 --md-ref-palette-secondary99: #fffbfeff;
94 /* Secondary 100 */
95 --md-ref-palette-secondary100: #ffffffff;
96 /* Primary 0 */
97 --md-ref-palette-primary0: #000000ff;
98 /* Primary 10 */
99 --md-ref-palette-primary10: #21005dff;
100 /* Primary 20 */
101 --md-ref-palette-primary20: #381e72ff;
102 /* Primary 30 */
103 --md-ref-palette-primary30: #4f378bff;
104 /* Primary 40 */
105 --md-ref-palette-primary40: #6750a4ff;
106 /* Primary 50 */
107 --md-ref-palette-primary50: #7f67beff;
108 /* Primary 60 */
109 --md-ref-palette-primary60: #9a82dbff;
110 /* Primary 70 */
111 --md-ref-palette-primary70: #b69df8ff;
112 /* Primary 80 */
113 --md-ref-palette-primary80: #d0bcffff;
114 /* Primary 90 */
115 --md-ref-palette-primary90: #eaddffff;
116 /* Primary 95 */
117 --md-ref-palette-primary95: #f6edffff;
118 /* Primary 99 */
119 --md-ref-palette-primary99: #fffbfeff;
120 /* Primary 100 */
121 --md-ref-palette-primary100: #ffffffff;
122 /* Neutral Variant 0 */
123 --md-ref-palette-neutral-variant0: #000000ff;
124 /* Neutral Variant 10 */
125 --md-ref-palette-neutral-variant10: #1d1a22ff;
126 /* Neutral Variant 20 */
127 --md-ref-palette-neutral-variant20: #322f37ff;
128 /* Neutral Variant 30 */
129 --md-ref-palette-neutral-variant30: #49454fff;
130 /* Neutral Variant 40 */
131 --md-ref-palette-neutral-variant40: #605d66ff;
132 /* Neutral Variant 50 */
133 --md-ref-palette-neutral-variant50: #79747eff;
134 /* Neutral Variant 60 */
135 --md-ref-palette-neutral-variant60: #938f99ff;
136 /* Neutral Variant 70 */
137 --md-ref-palette-neutral-variant70: #aea9b4ff;
138 /* Neutral Variant 80 */
139 --md-ref-palette-neutral-variant80: #cac4d0ff;
140 /* Neutral Variant 90 */
141 --md-ref-palette-neutral-variant90: #e7e0ecff;
142 /* Neutral Variant 95 */
143 --md-ref-palette-neutral-variant95: #f5eefaff;
144 /* Neutral Variant 99 */
145 --md-ref-palette-neutral-variant99: #fffbfeff;
146 /* Neutral Variant 100 */
147 --md-ref-palette-neutral-variant100: #ffffffff;
148 /* Neutral 0 */
149 --md-ref-palette-neutral0: #000000ff;
150 /* Neutral 10 */
151 --md-ref-palette-neutral10: #1c1b1fff;
152 /* Neutral 20 */
153 --md-ref-palette-neutral20: #313033ff;
154 /* Neutral 30 */
155 --md-ref-palette-neutral30: #484649ff;
156 /* Neutral 40 */
157 --md-ref-palette-neutral40: #605d62ff;
158 /* Neutral 50 */
159 --md-ref-palette-neutral50: #787579ff;
160 /* Neutral 60 */
161 --md-ref-palette-neutral60: #939094ff;
162 /* Neutral 70 */
163 --md-ref-palette-neutral70: #aeaaaeff;
164 /* Neutral 80 */
165 --md-ref-palette-neutral80: #c9c5caff;
166 /* Neutral 90 */
167 --md-ref-palette-neutral90: #e6e1e5ff;
168 /* Neutral 95 */
169 --md-ref-palette-neutral95: #f4eff4ff;
170 /* Neutral 99 */
171 --md-ref-palette-neutral99: #fffbfeff;
172 /* Neutral 100 */
173 --md-ref-palette-neutral100: #ffffffff;
174 /* Black */
175 --md-ref-palette-black: #000000ff;
176 /* White */
177 --md-ref-palette-white: #ffffffff;
178}
179

6. material-tokens / css / shape.css

1/*
2 Copyright 2016 Google Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17:root {
18 /* Fully rounded */
19 --md-sys-shape-corner-full-family: 3px;
20 /* Extra large top rounding */
21 --md-sys-shape-corner-extra-large-top-family: 1px;
22 --md-sys-shape-corner-extra-large-top-default-size: 0px;
23 --md-sys-shape-corner-extra-large-top-top-left: 28px;
24 --md-sys-shape-corner-extra-large-top-top-right-unit: 1px;
25 --md-sys-shape-corner-extra-large-top-top-right: 28px;
26 /* Extra large rounding */
27 --md-sys-shape-corner-extra-large-family: 1px;
28 --md-sys-shape-corner-extra-large-default-size-unit: 1px;
29 --md-sys-shape-corner-extra-large-default-size: 28px;
30 /* Large top rounding */
31 --md-sys-shape-corner-large-top-family: 1px;
32 --md-sys-shape-corner-large-top-default-size-unit: 1px;
33 --md-sys-shape-corner-large-top-default-size: 0px;
34 --md-sys-shape-corner-large-top-top-left-unit: 1px;
35 --md-sys-shape-corner-large-top-top-left: 16px;
36 --md-sys-shape-corner-large-top-top-right-unit: 1px;
37 --md-sys-shape-corner-large-top-top-right: 16px;
38 /* Large end rounding */
39 --md-sys-shape-corner-large-end-family: 1px;
40 --md-sys-shape-corner-large-end-default-size-unit: 1px;
41 --md-sys-shape-corner-large-end-default-size: 0px;
42 --md-sys-shape-corner-large-end-top-right-unit: 1px;
43 --md-sys-shape-corner-large-end-top-right: 16px;
44 --md-sys-shape-corner-large-end-bottom-right-unit: 1px;
45 --md-sys-shape-corner-large-end-bottom-right: 16px;
46 /* Large rounding */
47 --md-sys-shape-corner-large-family: 1px;
48 --md-sys-shape-corner-large-default-size-unit: 1px;
49 --md-sys-shape-corner-large-default-size: 16px;
50 /* Medium rounding */
51 --md-sys-shape-corner-medium-family: 1px;
52 --md-sys-shape-corner-medium-default-size-unit: 1px;
53 --md-sys-shape-corner-medium-default-size: 12px;
54 /* Small rounding */
55 --md-sys-shape-corner-small-family: 1px;
56 --md-sys-shape-corner-small-default-size-unit: 1px;
57 --md-sys-shape-corner-small-default-size: 8px;
58 /* Extra small top rounding */
59 --md-sys-shape-corner-extra-small-top-family: 1px;
60 --md-sys-shape-corner-extra-small-top-default-size-unit: 1px;
61 --md-sys-shape-corner-extra-small-top-default-size: 0px;
62 --md-sys-shape-corner-extra-small-top-top-left-unit: 1px;
63 --md-sys-shape-corner-extra-small-top-top-left: 4px;
64 --md-sys-shape-corner-extra-small-top-top-right-unit: 1px;
65 --md-sys-shape-corner-extra-small-top-top-right: 4px;
66 /* Extra small rounding */
67 --md-sys-shape-corner-extra-small-family: 1px;
68 --md-sys-shape-corner-extra-small-default-size-unit: 1px;
69 --md-sys-shape-corner-extra-small-default-size: 4px;
70 /* No rounding */
71 --md-sys-shape-corner-none-family: 1px;
72 --md-sys-shape-corner-none-default-size-unit: 1px;
73 --md-sys-shape-corner-none-default-size: 0px;
74
75 --md-sys-shape-small: var(--md-sys-shape-corner-small-default-size);
76 --md-sys-shape-medium: var(--md-sys-shape-corner-medium-default-size);
77 --md-sys-shape-large: var(--md-sys-shape-corner-large-default-size);
78}
79
80.shape-none {
81 border-radius: var(--md-sys-shape-corner-none-default-size);
82}
83.shape-extra-small {
84 border-radius: var(--md-sys-shape-corner-extra-small-default-size);
85}
86.shape-small {
87 border-radius: var(--md-sys-shape-corner-small-default-size);
88}
89.shape-medium {
90 border-radius: var(--md-sys-shape-corner-medium-default-size);
91}
92.shape-large {
93 border-radius: var(--md-sys-shape-corner-large-default-size);
94}
95.shape-extra-large {
96 border-radius: var(--md-sys-shape-corner-extra-large-default-size);
97}
98.extra-small-top {
99 border-top-left-radius: var(--md-sys-shape-corner-extra-small-top-top-left);
100 border-top-right-radius: var(--md-sys-shape-corner-extra-small-top-top-right);
101}
102.large-end {
103 border-top-right-radius: var(--md-sys-shape-corner-large-end-top-right);
104 border-bottom-right-radius: var(--md-sys-shape-corner-large-end-bottom-right);
105}
106.large-top {
107 border-top-left-radius: var(--md-sys-shape-corner-large-top-top-left);
108 border-top-right-radius: var(--md-sys-shape-corner-large-top-top-right);
109}
110.extra-large-top {
111 border-top-left-radius: var(--md-sys-shape-corner-extra-large-top-top-left);
112 border-top-right-radius: var(--md-sys-shape-corner-extra-large-top-top-right);
113}
114

7. material-tokens / css / state.css

1/*
2 Copyright 2016 Google Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17:root {
18 /* Dragged state layer opacity */
19 --md-sys-state-dragged-state-layer-opacity: 0.1599999964237213;
20 /* Pressed state layer opacity */
21 --md-sys-state-pressed-state-layer-opacity: 0.11999999731779099;
22 /* Focus state layer opacity */
23 --md-sys-state-focus-state-layer-opacity: 0.11999999731779099;
24 /* Hover state layer opacity */
25 --md-sys-state-hover-state-layer-opacity: 0.07999999821186066;
26}
27.hover-state-layer {
28 opacity: var(--md-sys-state-hover-state-layer-opacity);
29}
30.pressed-state-layer {
31 opacity: var(--md-sys-state-pressed-state-layer-opacity);
32}
33.dragged-state-layer {
34 opacity: var(--md-sys-state-dragged-state-layer-opacity);
35}
36.focus-state-layer {
37 opacity: var(--md-sys-state-focus-state-layer-opacity);
38}
39

8. material-tokens / css / typography.css

1/*
2 Copyright 2016 Google Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/* This file is generated */
18
19/* DO NOT EDIT */
20
21:root {
22 /* Label Small */
23 --md-sys-typescale-label-small-text-transform: unset;
24 --md-sys-typescale-label-small-axis-value: unset;
25 --md-sys-typescale-label-small-font-style: unset;
26 --md-sys-typescale-label-small-text-decoration: unset;
27 /* Label Small line height */
28 --md-sys-typescale-label-small-line-height-value: 16px;
29 --md-sys-typescale-label-small-line-height-unit: 2px;
30 --md-sys-typescale-label-small-line-height: 16px;
31 /* Label Small font tracking */
32 --md-sys-typescale-label-small-tracking-value: 0.5px;
33 --md-sys-typescale-label-small-tracking-unit: 2px;
34 --md-sys-typescale-label-small-tracking: 0.5px;
35 /* Label Small font size */
36 --md-sys-typescale-label-small-size-value: 11px;
37 --md-sys-typescale-label-small-size-unit: 2px;
38 --md-sys-typescale-label-small-size: 11px;
39 /* Label Small font weight */
40 --md-sys-typescale-label-small-weight: var(--md-ref-typeface-weight-medium);
41 /* Label Small font name */
42 --md-sys-typescale-label-small-font: var(--md-ref-typeface-plain);
43 /* Label Medium */
44 --md-sys-typescale-label-medium-axis-value: unset;
45 --md-sys-typescale-label-medium-font-style: unset;
46 --md-sys-typescale-label-medium-text-decoration: unset;
47 /* Label Medium text transform */
48 --md-sys-typescale-label-medium-text-transform: 1;
49 /* Label Medium line height */
50 --md-sys-typescale-label-medium-line-height-value: 16px;
51 --md-sys-typescale-label-medium-line-height-unit: 2px;
52 --md-sys-typescale-label-medium-line-height: 16px;
53 /* Label Medium font tracking */
54 --md-sys-typescale-label-medium-tracking-value: 0.5px;
55 --md-sys-typescale-label-medium-tracking-unit: 2px;
56 --md-sys-typescale-label-medium-tracking: 0.5px;
57 /* Label Medium font size */
58 --md-sys-typescale-label-medium-size-value: 12px;
59 --md-sys-typescale-label-medium-size-unit: 2px;
60 --md-sys-typescale-label-medium-size: 12px;
61 /* Label Medium font weight */
62 --md-sys-typescale-label-medium-weight: var(--md-ref-typeface-weight-medium);
63 /* Label Medium font name */
64 --md-sys-typescale-label-medium-font: var(--md-ref-typeface-plain);
65 /* Label Large */
66 --md-sys-typescale-label-large-text-transform: unset;
67 --md-sys-typescale-label-large-axis-value: unset;
68 --md-sys-typescale-label-large-font-style: unset;
69 --md-sys-typescale-label-large-text-decoration: unset;
70 /* Label Large line height */
71 --md-sys-typescale-label-large-line-height-value: 20px;
72 --md-sys-typescale-label-large-line-height-unit: 2px;
73 --md-sys-typescale-label-large-line-height: 20px;
74 /* Label Large font tracking */
75 --md-sys-typescale-label-large-tracking-value: 0.10000000149011612px;
76 --md-sys-typescale-label-large-tracking-unit: 2px;
77 --md-sys-typescale-label-large-tracking: 0.10000000149011612px;
78 /* Label Large font size */
79 --md-sys-typescale-label-large-size-value: 14px;
80 --md-sys-typescale-label-large-size-unit: 2px;
81 --md-sys-typescale-label-large-size: 14px;
82 /* Label Large font weight */
83 --md-sys-typescale-label-large-weight: var(--md-ref-typeface-weight-medium);
84 /* Label Large font name */
85 --md-sys-typescale-label-large-font: var(--md-ref-typeface-plain);
86 /* Body Small */
87 --md-sys-typescale-body-small-text-transform: unset;
88 --md-sys-typescale-body-small-axis-value: unset;
89 --md-sys-typescale-body-small-font-style: unset;
90 --md-sys-typescale-body-small-text-decoration: unset;
91 /* Body Small line height */
92 --md-sys-typescale-body-small-line-height-value: 16px;
93 --md-sys-typescale-body-small-line-height-unit: 2px;
94 --md-sys-typescale-body-small-line-height: 16px;
95 /* Body Small font tracking */
96 --md-sys-typescale-body-small-tracking-value: 0.4000000059604645px;
97 --md-sys-typescale-body-small-tracking-unit: 2px;
98 --md-sys-typescale-body-small-tracking: 0.4000000059604645px;
99 /* Body Small font size */
100 --md-sys-typescale-body-small-size-value: 12px;
101 --md-sys-typescale-body-small-size-unit: 2px;
102 --md-sys-typescale-body-small-size: 12px;
103 /* Body Small font weight */
104 --md-sys-typescale-body-small-weight: var(--md-ref-typeface-weight-regular);
105 /* Body Small font name */
106 --md-sys-typescale-body-small-font: var(--md-ref-typeface-plain);
107 /* Body Medium */
108 --md-sys-typescale-body-medium-text-transform: unset;
109 --md-sys-typescale-body-medium-axis-value: unset;
110 --md-sys-typescale-body-medium-font-style: unset;
111 --md-sys-typescale-body-medium-text-decoration: unset;
112 /* Body Medium line height */
113 --md-sys-typescale-body-medium-line-height-value: 20px;
114 --md-sys-typescale-body-medium-line-height-unit: 2px;
115 --md-sys-typescale-body-medium-line-height: 20px;
116 /* Body Medium font tracking */
117 --md-sys-typescale-body-medium-tracking-value: 0.25px;
118 --md-sys-typescale-body-medium-tracking-unit: 2px;
119 --md-sys-typescale-body-medium-tracking: 0.25px;
120 /* Body Medium font size */
121 --md-sys-typescale-body-medium-size-value: 14px;
122 --md-sys-typescale-body-medium-size-unit: 2px;
123 --md-sys-typescale-body-medium-size: 14px;
124 /* Body Medium font weight */
125 --md-sys-typescale-body-medium-weight: var(--md-ref-typeface-weight-regular);
126 /* Body Medium font name */
127 --md-sys-typescale-body-medium-font: var(--md-ref-typeface-plain);
128 /* Body Large */
129 --md-sys-typescale-body-large-text-transform: unset;
130 --md-sys-typescale-body-large-axis-value: unset;
131 --md-sys-typescale-body-large-font-style: unset;
132 --md-sys-typescale-body-large-text-decoration: unset;
133 /* Body Large line height */
134 --md-sys-typescale-body-large-line-height-value: 24px;
135 --md-sys-typescale-body-large-line-height-unit: 2px;
136 --md-sys-typescale-body-large-line-height: 24px;
137 /* Body Large font tracking */
138 --md-sys-typescale-body-large-tracking-value: 0.5px;
139 --md-sys-typescale-body-large-tracking-unit: 2px;
140 --md-sys-typescale-body-large-tracking: 0.5px;
141 /* Body Large font size */
142 --md-sys-typescale-body-large-size-value: 16px;
143 --md-sys-typescale-body-large-size-unit: 2px;
144 --md-sys-typescale-body-large-size: 16px;
145 /* Body Large font weight */
146 --md-sys-typescale-body-large-weight: var(--md-ref-typeface-weight-regular);
147 /* Body Large font name */
148 --md-sys-typescale-body-large-font: var(--md-ref-typeface-plain);
149 /* Title Small */
150 --md-sys-typescale-title-small-text-transform: unset;
151 --md-sys-typescale-title-small-axis-value: unset;
152 --md-sys-typescale-title-small-font-style: unset;
153 --md-sys-typescale-title-small-text-decoration: unset;
154 /* Title Small line height */
155 --md-sys-typescale-title-small-line-height-value: 20px;
156 --md-sys-typescale-title-small-line-height-unit: 2px;
157 --md-sys-typescale-title-small-line-height: 20px;
158 /* Title Small font tracking */
159 --md-sys-typescale-title-small-tracking-value: 0.10000000149011612px;
160 --md-sys-typescale-title-small-tracking-unit: 2px;
161 --md-sys-typescale-title-small-tracking: 0.10000000149011612px;
162 /* Title Small font size */
163 --md-sys-typescale-title-small-size-value: 14px;
164 --md-sys-typescale-title-small-size-unit: 2px;
165 --md-sys-typescale-title-small-size: 14px;
166 /* Title Small font weight */
167 --md-sys-typescale-title-small-weight: var(--md-ref-typeface-weight-medium);
168 /* Title Small font name */
169 --md-sys-typescale-title-small-font: var(--md-ref-typeface-plain);
170 /* Title Medium */
171 --md-sys-typescale-title-medium-text-transform: unset;
172 --md-sys-typescale-title-medium-axis-value: unset;
173 --md-sys-typescale-title-medium-font-style: unset;
174 --md-sys-typescale-title-medium-text-decoration: unset;
175 /* Title Medium line height */
176 --md-sys-typescale-title-medium-line-height-value: 24px;
177 --md-sys-typescale-title-medium-line-height-unit: 2px;
178 --md-sys-typescale-title-medium-line-height: 24px;
179 /* Title Medium font tracking */
180 --md-sys-typescale-title-medium-tracking-value: 0.15000000596046448px;
181 --md-sys-typescale-title-medium-tracking-unit: 2px;
182 --md-sys-typescale-title-medium-tracking: 0.15000000596046448px;
183 /* Title Medium font size */
184 --md-sys-typescale-title-medium-size-value: 16px;
185 --md-sys-typescale-title-medium-size-unit: 2px;
186 --md-sys-typescale-title-medium-size: 16px;
187 /* Title Medium font weight */
188 --md-sys-typescale-title-medium-weight: var(--md-ref-typeface-weight-medium);
189 /* Title Medium font name */
190 --md-sys-typescale-title-medium-font: var(--md-ref-typeface-plain);
191 /* Title Large */
192 --md-sys-typescale-title-large-text-transform: unset;
193 --md-sys-typescale-title-large-axis-value: unset;
194 --md-sys-typescale-title-large-font-style: unset;
195 --md-sys-typescale-title-large-text-decoration: unset;
196 /* Title Large line height */
197 --md-sys-typescale-title-large-line-height-value: 28px;
198 --md-sys-typescale-title-large-line-height-unit: 2px;
199 --md-sys-typescale-title-large-line-height: 28px;
200 /* Title Large font tracking */
201 --md-sys-typescale-title-large-tracking-value: 0px;
202 --md-sys-typescale-title-large-tracking-unit: 2px;
203 --md-sys-typescale-title-large-tracking: 0px;
204 /* Title Large font size */
205 --md-sys-typescale-title-large-size-value: 22px;
206 --md-sys-typescale-title-large-size-unit: 2px;
207 --md-sys-typescale-title-large-size: 22px;
208 /* Title Large font weight */
209 --md-sys-typescale-title-large-weight: var(--md-ref-typeface-weight-regular);
210 /* Title Large font name */
211 --md-sys-typescale-title-large-font: var(--md-ref-typeface-brand);
212 /* Headline Small */
213 --md-sys-typescale-headline-small-text-transform: unset;
214 --md-sys-typescale-headline-small-axis-value: unset;
215 --md-sys-typescale-headline-small-font-style: unset;
216 --md-sys-typescale-headline-small-text-decoration: unset;
217 /* Headline Small line height */
218 --md-sys-typescale-headline-small-line-height-value: 32px;
219 --md-sys-typescale-headline-small-line-height-unit: 2px;
220 --md-sys-typescale-headline-small-line-height: 32px;
221 /* Headline Small font tracking */
222 --md-sys-typescale-headline-small-tracking-value: 0px;
223 --md-sys-typescale-headline-small-tracking-unit: 2px;
224 --md-sys-typescale-headline-small-tracking: 0px;
225 /* Headline Small font size */
226 --md-sys-typescale-headline-small-size-value: 24px;
227 --md-sys-typescale-headline-small-size-unit: 2px;
228 --md-sys-typescale-headline-small-size: 24px;
229 /* Headline Small font weight */
230 --md-sys-typescale-headline-small-weight: var(
231 --md-ref-typeface-weight-regular
232 );
233 /* Headline Small font name */
234 --md-sys-typescale-headline-small-font: var(--md-ref-typeface-brand);
235 /* Headline Medium */
236 --md-sys-typescale-headline-medium-text-transform: unset;
237 --md-sys-typescale-headline-medium-axis-value: unset;
238 --md-sys-typescale-headline-medium-font-style: unset;
239 --md-sys-typescale-headline-medium-text-decoration: unset;
240 /* Headline Medium line height */
241 --md-sys-typescale-headline-medium-line-height-value: 36px;
242 --md-sys-typescale-headline-medium-line-height-unit: 2px;
243 --md-sys-typescale-headline-medium-line-height: 36px;
244 /* Headline Medium font tracking */
245 --md-sys-typescale-headline-medium-tracking-value: 0px;
246 --md-sys-typescale-headline-medium-tracking-unit: 2px;
247 --md-sys-typescale-headline-medium-tracking: 0px;
248 /* Headline Medium font size */
249 --md-sys-typescale-headline-medium-size-value: 28px;
250 --md-sys-typescale-headline-medium-size-unit: 2px;
251 --md-sys-typescale-headline-medium-size: 28px;
252 /* Headline Medium font weight */
253 --md-sys-typescale-headline-medium-weight: var(
254 --md-ref-typeface-weight-regular
255 );
256 /* Headline Medium font name */
257 --md-sys-typescale-headline-medium-font: var(--md-ref-typeface-brand);
258 /* Headline Large */
259 --md-sys-typescale-headline-large-text-transform: unset;
260 --md-sys-typescale-headline-large-axis-value: unset;
261 --md-sys-typescale-headline-large-font-style: unset;
262 --md-sys-typescale-headline-large-text-decoration: unset;
263 /* Headline Large line height */
264 --md-sys-typescale-headline-large-line-height-value: 40px;
265 --md-sys-typescale-headline-large-line-height-unit: 2px;
266 --md-sys-typescale-headline-large-line-height: 40px;
267 /* Headline Large font tracking */
268 --md-sys-typescale-headline-large-tracking-value: 0px;
269 --md-sys-typescale-headline-large-tracking-unit: 2px;
270 --md-sys-typescale-headline-large-tracking: 0px;
271 /* Headline Large font size */
272 --md-sys-typescale-headline-large-size-value: 32px;
273 --md-sys-typescale-headline-large-size-unit: 2px;
274 --md-sys-typescale-headline-large-size: 32px;
275 /* Headline Large font name */
276 --md-sys-typescale-headline-large-font: var(--md-ref-typeface-brand);
277 /* Headline Large font weight */
278 --md-sys-typescale-headline-large-weight: var(
279 --md-ref-typeface-weight-regular
280 );
281 /* Display Small */
282 --md-sys-typescale-display-small-text-transform: unset;
283 --md-sys-typescale-display-small-axis-value: unset;
284 --md-sys-typescale-display-small-font-style: unset;
285 --md-sys-typescale-display-small-text-decoration: unset;
286 /* Display Small line height */
287 --md-sys-typescale-display-small-line-height-value: 44px;
288 --md-sys-typescale-display-small-line-height-unit: 2px;
289 --md-sys-typescale-display-small-line-height: 44px;
290 /* Display Small font tracking */
291 --md-sys-typescale-display-small-tracking-value: 0px;
292 --md-sys-typescale-display-small-tracking-unit: 2px;
293 --md-sys-typescale-display-small-tracking: 0px;
294 /* Display Small font size */
295 --md-sys-typescale-display-small-size-value: 36px;
296 --md-sys-typescale-display-small-size-unit: 2px;
297 --md-sys-typescale-display-small-size: 36px;
298 /* Display Small font weight */
299 --md-sys-typescale-display-small-weight: var(
300 --md-ref-typeface-weight-regular
301 );
302 /* Display Small font name */
303 --md-sys-typescale-display-small-font: var(--md-ref-typeface-brand);
304 /* Display Medium */
305 --md-sys-typescale-display-medium-text-transform: unset;
306 --md-sys-typescale-display-medium-axis-value: unset;
307 --md-sys-typescale-display-medium-font-style: unset;
308 --md-sys-typescale-display-medium-text-decoration: unset;
309 /* Display Medium line height */
310 --md-sys-typescale-display-medium-line-height-value: 52px;
311 --md-sys-typescale-display-medium-line-height-unit: 2px;
312 --md-sys-typescale-display-medium-line-height: 52px;
313 /* Display Medium font tracking */
314 --md-sys-typescale-display-medium-tracking-value: 0px;
315 --md-sys-typescale-display-medium-tracking-unit: 2px;
316 --md-sys-typescale-display-medium-tracking: 0px;
317 /* Display Medium font size */
318 --md-sys-typescale-display-medium-size-value: 45px;
319 --md-sys-typescale-display-medium-size-unit: 2px;
320 --md-sys-typescale-display-medium-size: 45px;
321 /* Display Medium font weight */
322 --md-sys-typescale-display-medium-weight: var(
323 --md-ref-typeface-weight-regular
324 );
325 /* Display Medium font name */
326 --md-sys-typescale-display-medium-font: var(--md-ref-typeface-brand);
327 /* Display Large */
328 --md-sys-typescale-display-large-text-transform: unset;
329 --md-sys-typescale-display-large-axis-value: unset;
330 --md-sys-typescale-display-large-font-style: unset;
331 --md-sys-typescale-display-large-text-decoration: unset;
332 /* Display Large line height */
333 --md-sys-typescale-display-large-line-height-value: 64px;
334 --md-sys-typescale-display-large-line-height-unit: 2px;
335 --md-sys-typescale-display-large-line-height: 64px;
336 /* Display Large font tracking */
337 --md-sys-typescale-display-large-tracking-value: -0.25px;
338 --md-sys-typescale-display-large-tracking-unit: 2px;
339 --md-sys-typescale-display-large-tracking: -0.25px;
340 /* Display Large font size */
341 --md-sys-typescale-display-large-size-value: 57px;
342 --md-sys-typescale-display-large-size-unit: 2px;
343 --md-sys-typescale-display-large-size: 57px;
344 /* Display Large font weight */
345 --md-sys-typescale-display-large-weight: var(
346 --md-ref-typeface-weight-regular
347 );
348 /* Display Large font name */
349 --md-sys-typescale-display-large-font: var(--md-ref-typeface-brand);
350 /* Plain typeface */
351 --md-ref-typeface-plain: Roboto;
352 /* Brand typeface */
353 --md-ref-typeface-brand: Roboto;
354 /* Bold weight */
355 --md-ref-typeface-weight-bold: 700;
356 /* Medium weight */
357 --md-ref-typeface-weight-medium: 500;
358 /* Regular weight */
359 --md-ref-typeface-weight-regular: 400;
360}
361
362/* Label Small */
363.label-small {
364 font-family: var(--md-sys-typescale-label-small-font);
365 font-weight: var(--md-sys-typescale-label-small-weight);
366 font-size: var(--md-sys-typescale-label-small-size);
367 font-style: var(--md-sys-typescale-label-small-font-style);
368 letter-spacing: var(--md-sys-typescale-label-small-tracking);
369 line-height: var(--md-sys-typescale-label-small-line-height);
370 text-transform: var(--md-sys-typescale-label-small-text-transform);
371 text-decoration: var(--md-sys-typescale-label-small-text-decoration);
372}
373/* Label Medium */
374.label-medium {
375 font-family: var(--md-sys-typescale-label-medium-font);
376 font-weight: var(--md-sys-typescale-label-medium-weight);
377 font-size: var(--md-sys-typescale-label-medium-size);
378 font-style: var(--md-sys-typescale-label-medium-font-style);
379 letter-spacing: var(--md-sys-typescale-label-medium-tracking);
380 line-height: var(--md-sys-typescale-label-medium-line-height);
381 text-transform: var(--md-sys-typescale-label-medium-text-transform);
382 text-decoration: var(--md-sys-typescale-label-medium-text-decoration);
383}
384/* Label Large */
385.label-large {
386 font-family: var(--md-sys-typescale-label-large-font);
387 font-weight: var(--md-sys-typescale-label-large-weight);
388 font-size: var(--md-sys-typescale-label-large-size);
389 font-style: var(--md-sys-typescale-label-large-font-style);
390 letter-spacing: var(--md-sys-typescale-label-large-tracking);
391 line-height: var(--md-sys-typescale-label-large-line-height);
392 text-transform: var(--md-sys-typescale-label-large-text-transform);
393 text-decoration: var(--md-sys-typescale-label-large-text-decoration);
394}
395/* Body Small */
396.body-small {
397 font-family: var(--md-sys-typescale-body-small-font);
398 font-weight: var(--md-sys-typescale-body-small-weight);
399 font-size: var(--md-sys-typescale-body-small-size);
400 font-style: var(--md-sys-typescale-body-small-font-style);
401 letter-spacing: var(--md-sys-typescale-body-small-tracking);
402 line-height: var(--md-sys-typescale-body-small-line-height);
403 text-transform: var(--md-sys-typescale-body-small-text-transform);
404 text-decoration: var(--md-sys-typescale-body-small-text-decoration);
405}
406/* Body Medium */
407.body-medium {
408 font-family: var(--md-sys-typescale-body-medium-font);
409 font-weight: var(--md-sys-typescale-body-medium-weight);
410 font-size: var(--md-sys-typescale-body-medium-size);
411 font-style: var(--md-sys-typescale-body-medium-font-style);
412 letter-spacing: var(--md-sys-typescale-body-medium-tracking);
413 line-height: var(--md-sys-typescale-body-medium-line-height);
414 text-transform: var(--md-sys-typescale-body-medium-text-transform);
415 text-decoration: var(--md-sys-typescale-body-medium-text-decoration);
416}
417/* Body Large */
418.body-large {
419 font-family: var(--md-sys-typescale-body-large-font);
420 font-weight: var(--md-sys-typescale-body-large-weight);
421 font-size: var(--md-sys-typescale-body-large-size);
422 font-style: var(--md-sys-typescale-body-large-font-style);
423 letter-spacing: var(--md-sys-typescale-body-large-tracking);
424 line-height: var(--md-sys-typescale-body-large-line-height);
425 text-transform: var(--md-sys-typescale-body-large-text-transform);
426 text-decoration: var(--md-sys-typescale-body-large-text-decoration);
427}
428/* Title Small */
429.title-small {
430 font-family: var(--md-sys-typescale-title-small-font);
431 font-weight: var(--md-sys-typescale-title-small-weight);
432 font-size: var(--md-sys-typescale-title-small-size);
433 font-style: var(--md-sys-typescale-title-small-font-style);
434 letter-spacing: var(--md-sys-typescale-title-small-tracking);
435 line-height: var(--md-sys-typescale-title-small-line-height);
436 text-transform: var(--md-sys-typescale-title-small-text-transform);
437 text-decoration: var(--md-sys-typescale-title-small-text-decoration);
438}
439/* Title Medium */
440.title-medium {
441 font-family: var(--md-sys-typescale-title-medium-font);
442 font-weight: var(--md-sys-typescale-title-medium-weight);
443 font-size: var(--md-sys-typescale-title-medium-size);
444 font-style: var(--md-sys-typescale-title-medium-font-style);
445 letter-spacing: var(--md-sys-typescale-title-medium-tracking);
446 line-height: var(--md-sys-typescale-title-medium-line-height);
447 text-transform: var(--md-sys-typescale-title-medium-text-transform);
448 text-decoration: var(--md-sys-typescale-title-medium-text-decoration);
449}
450/* Title Large */
451.title-large {
452 font-family: var(--md-sys-typescale-title-large-font);
453 font-weight: var(--md-sys-typescale-title-large-weight);
454 font-size: var(--md-sys-typescale-title-large-size);
455 font-style: var(--md-sys-typescale-title-large-font-style);
456 letter-spacing: var(--md-sys-typescale-title-large-tracking);
457 line-height: var(--md-sys-typescale-title-large-line-height);
458 text-transform: var(--md-sys-typescale-title-large-text-transform);
459 text-decoration: var(--md-sys-typescale-title-large-text-decoration);
460}
461/* Headline Small */
462.headline-small {
463 font-family: var(--md-sys-typescale-headline-small-font);
464 font-weight: var(--md-sys-typescale-headline-small-weight);
465 font-size: var(--md-sys-typescale-headline-small-size);
466 font-style: var(--md-sys-typescale-headline-small-font-style);
467 letter-spacing: var(--md-sys-typescale-headline-small-tracking);
468 line-height: var(--md-sys-typescale-headline-small-line-height);
469 text-transform: var(--md-sys-typescale-headline-small-text-transform);
470 text-decoration: var(--md-sys-typescale-headline-small-text-decoration);
471}
472/* Headline Medium */
473.headline-medium {
474 font-family: var(--md-sys-typescale-headline-medium-font);
475 font-weight: var(--md-sys-typescale-headline-medium-weight);
476 font-size: var(--md-sys-typescale-headline-medium-size);
477 font-style: var(--md-sys-typescale-headline-medium-font-style);
478 letter-spacing: var(--md-sys-typescale-headline-medium-tracking);
479 line-height: var(--md-sys-typescale-headline-medium-line-height);
480 text-transform: var(--md-sys-typescale-headline-medium-text-transform);
481 text-decoration: var(--md-sys-typescale-headline-medium-text-decoration);
482}
483/* Headline Large */
484.headline-large {
485 font-family: var(--md-sys-typescale-headline-large-font);
486 font-weight: var(--md-sys-typescale-headline-large-weight);
487 font-size: var(--md-sys-typescale-headline-large-size);
488 font-style: var(--md-sys-typescale-headline-large-font-style);
489 letter-spacing: var(--md-sys-typescale-headline-large-tracking);
490 line-height: var(--md-sys-typescale-headline-large-line-height);
491 text-transform: var(--md-sys-typescale-headline-large-text-transform);
492 text-decoration: var(--md-sys-typescale-headline-large-text-decoration);
493}
494/* Display Small */
495.display-small {
496 font-family: var(--md-sys-typescale-display-small-font);
497 font-weight: var(--md-sys-typescale-display-small-weight);
498 font-size: var(--md-sys-typescale-display-small-size);
499 font-style: var(--md-sys-typescale-display-small-font-style);
500 letter-spacing: var(--md-sys-typescale-display-small-tracking);
501 line-height: var(--md-sys-typescale-display-small-line-height);
502 text-transform: var(--md-sys-typescale-display-small-text-transform);
503 text-decoration: var(--md-sys-typescale-display-small-text-decoration);
504}
505/* Display Medium */
506.display-medium {
507 font-family: var(--md-sys-typescale-display-medium-font);
508 font-weight: var(--md-sys-typescale-display-medium-weight);
509 font-size: var(--md-sys-typescale-display-medium-size);
510 font-style: var(--md-sys-typescale-display-medium-font-style);
511 letter-spacing: var(--md-sys-typescale-display-medium-tracking);
512 line-height: var(--md-sys-typescale-display-medium-line-height);
513 text-transform: var(--md-sys-typescale-display-medium-text-transform);
514 text-decoration: var(--md-sys-typescale-display-medium-text-decoration);
515}
516/* Display Large */
517.display-large {
518 font-family: var(--md-sys-typescale-display-large-font);
519 font-weight: var(--md-sys-typescale-display-large-weight);
520 font-size: var(--md-sys-typescale-display-large-size);
521 font-style: var(--md-sys-typescale-display-large-font-style);
522 letter-spacing: var(--md-sys-typescale-display-large-tracking);
523 line-height: var(--md-sys-typescale-display-large-line-height);
524 text-transform: var(--md-sys-typescale-display-large-text-transform);
525 text-decoration: var(--md-sys-typescale-display-large-text-decoration);
526}
527

9. Carpeta « material-tokens / css / theme »

A. material-tokens / css / theme / dark.css

1/*
2 Copyright 2016 Google Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17:root {
18 color-scheme: dark;
19 /* Surface tint */
20 --md-sys-color-surface-tint: var(--md-sys-color-primary);
21 /* Surface tint color */
22 --md-sys-color-surface-tint-color: var(--md-sys-color-primary);
23 /* On error container */
24 --md-sys-color-on-error-container: var(--md-ref-palette-error80);
25 /* On error */
26 --md-sys-color-on-error: var(--md-ref-palette-error20);
27 /* Error container */
28 --md-sys-color-error-container: var(--md-ref-palette-error30);
29 /* On tertiary container */
30 --md-sys-color-on-tertiary-container: var(--md-ref-palette-tertiary90);
31 /* On tertiary */
32 --md-sys-color-on-tertiary: var(--md-ref-palette-tertiary20);
33 /* Tertiary container */
34 --md-sys-color-tertiary-container: var(--md-ref-palette-tertiary30);
35 /* Tertiary */
36 --md-sys-color-tertiary: var(--md-ref-palette-tertiary80);
37 /* Shadow */
38 --md-sys-color-shadow: var(--md-ref-palette-neutral0);
39 /* Error */
40 --md-sys-color-error: var(--md-ref-palette-error80);
41 /* Outline */
42 --md-sys-color-outline: var(--md-ref-palette-neutral-variant60);
43 /* On background */
44 --md-sys-color-on-background: var(--md-ref-palette-neutral90);
45 /* Background */
46 --md-sys-color-background: var(--md-ref-palette-neutral10);
47 /* Inverse on surface */
48 --md-sys-color-inverse-on-surface: var(--md-ref-palette-neutral20);
49 /* Inverse surface */
50 --md-sys-color-inverse-surface: var(--md-ref-palette-neutral90);
51 /* On surface variant */
52 --md-sys-color-on-surface-variant: var(--md-ref-palette-neutral-variant80);
53 /* On surface */
54 --md-sys-color-on-surface: var(--md-ref-palette-neutral90);
55 /* Surface Variant */
56 --md-sys-color-surface-variant: var(--md-ref-palette-neutral-variant30);
57 /* Surface */
58 --md-sys-color-surface: var(--md-ref-palette-neutral10);
59 /* On secondary container */
60 --md-sys-color-on-secondary-container: var(--md-ref-palette-secondary90);
61 /* On secondary */
62 --md-sys-color-on-secondary: var(--md-ref-palette-secondary20);
63 /* Secondary container */
64 --md-sys-color-secondary-container: var(--md-ref-palette-secondary30);
65 /* Secondary */
66 --md-sys-color-secondary: var(--md-ref-palette-secondary80);
67 /* Inverse primary */
68 --md-sys-color-inverse-primary: var(--md-ref-palette-primary40);
69 /* On primary container */
70 --md-sys-color-on-primary-container: var(--md-ref-palette-primary90);
71 /* On primary */
72 --md-sys-color-on-primary: var(--md-ref-palette-primary20);
73 /* Primary container */
74 --md-sys-color-primary-container: var(--md-ref-palette-primary30);
75 /* Primary */
76 --md-sys-color-primary: var(--md-ref-palette-primary80);
77}
78

B. material-tokens / css / theme / light.css

1/*
2 Copyright 2016 Google Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17:root {
18 color-scheme: light;
19 /* Surface tint */
20 --md-sys-color-surface-tint: var(--md-sys-color-primary);
21 /* Surface tint color */
22 --md-sys-color-surface-tint-color: var(--md-sys-color-primary);
23 /* On error container */
24 --md-sys-color-on-error-container: var(--md-ref-palette-error10);
25 /* On error */
26 --md-sys-color-on-error: var(--md-ref-palette-error100);
27 /* Error container */
28 --md-sys-color-error-container: var(--md-ref-palette-error90);
29 /* On tertiary container */
30 --md-sys-color-on-tertiary-container: var(--md-ref-palette-tertiary10);
31 /* On tertiary */
32 --md-sys-color-on-tertiary: var(--md-ref-palette-tertiary100);
33 /* Tertiary container */
34 --md-sys-color-tertiary-container: var(--md-ref-palette-tertiary90);
35 /* Tertiary */
36 --md-sys-color-tertiary: var(--md-ref-palette-tertiary40);
37 /* Shadow */
38 --md-sys-color-shadow: var(--md-ref-palette-neutral0);
39 /* Error */
40 --md-sys-color-error: var(--md-ref-palette-error40);
41 /* Outline */
42 --md-sys-color-outline: var(--md-ref-palette-neutral-variant50);
43 /* On background */
44 --md-sys-color-on-background: var(--md-ref-palette-neutral10);
45 /* Background */
46 --md-sys-color-background: var(--md-ref-palette-neutral99);
47 /* Inverse on surface */
48 --md-sys-color-inverse-on-surface: var(--md-ref-palette-neutral95);
49 /* Inverse surface */
50 --md-sys-color-inverse-surface: var(--md-ref-palette-neutral20);
51 /* On surface variant */
52 --md-sys-color-on-surface-variant: var(--md-ref-palette-neutral-variant30);
53 /* On surface */
54 --md-sys-color-on-surface: var(--md-ref-palette-neutral10);
55 /* Surface Variant */
56 --md-sys-color-surface-variant: var(--md-ref-palette-neutral-variant90);
57 /* Surface */
58 --md-sys-color-surface: var(--md-ref-palette-neutral99);
59 /* On secondary container */
60 --md-sys-color-on-secondary-container: var(--md-ref-palette-secondary10);
61 /* On secondary */
62 --md-sys-color-on-secondary: var(--md-ref-palette-secondary100);
63 /* Secondary container */
64 --md-sys-color-secondary-container: var(--md-ref-palette-secondary90);
65 /* Secondary */
66 --md-sys-color-secondary: var(--md-ref-palette-secondary40);
67 /* Inverse primary */
68 --md-sys-color-inverse-primary: var(--md-ref-palette-primary80);
69 /* On primary container */
70 --md-sys-color-on-primary-container: var(--md-ref-palette-primary10);
71 /* On primary */
72 --md-sys-color-on-primary: var(--md-ref-palette-primary100);
73 /* Primary container */
74 --md-sys-color-primary-container: var(--md-ref-palette-primary90);
75 /* Primary */
76 --md-sys-color-primary: var(--md-ref-palette-primary40);
77}
78

34. Carpeta « ungap »

Versión para imprimir.

A. ungap / custom-elements.js

35. jsconfig.json

1{
2 "compilerOptions": {
3 "checkJs": true,
4 "strictNullChecks": true,
5 "target": "ES6",
6 "module": "Node16",
7 "moduleResolution": "Node16",
8 "lib": [
9 "ES2017",
10 "WebWorker",
11 "DOM"
12 ]
13 }
14}

36. Resumen