Customizing Ignite UI for Angular Theming
Este artículo le guiará a través de los detalles de la personalización de la Ignite UI for Angular aplicación de temas, la creación de temas y la optimización del tamaño de la hoja de estilo producida. El artículo muestra detalles de cómo funciona el motor de temas de Ignite UI for Angular y presenta un uso avanzado del mismo. El artículo es muy útil tanto para realizar una personalización completa de los estilos de los componentes, de modo que la aplicación Angular se adapte para que coincida con el aspecto deseado, como para hacer que la aplicación sea óptima para la implementación reduciendo los tamaños de estilo a solo lo que usa la aplicación.
Note
Este documento describe el sistema de temas en Ignite UI for Angular desde la versión 15 en adelante. Entre los ejemplos se incluyen el uso de las API de Sass proporcionadas por el motor de creación de temas y las variables CSS expuestas.
Getting Started
Usaremos el método App Builder para producir una aplicación Angular y luego modificaremos el estilo de la misma en el repositorio generado. Comenzamos creando una nueva aplicación a partir de la plantilla "Encabezado + mini navegación + contenido + panel lateral" en el App Builder y agregamos algunos componentes a la superficie de diseño.
A continuación, generamos nuestra app, utilizando Angular como objetivo, a un repositorio de GitHub, sobre el que trabajaremos tanto desde el App Builder como modificando el propio código generado. Después de clonar el repositorio y compilar el proyecto, obtenemos la aplicación Angular ejecución en su estado inicial.
Como puedes ver, la aplicación ha aplicado un tema por defecto, que es una variante de luz de material. El archivo generadostyles.scss se ve así:
/* You can add global styles to this file, and also import other style files */
// Standard CSS normalize, comment out if not required or using a different module
@use "minireset.css/minireset";
@use "@infragistics/igniteui-angular/theming" as *;
@include core();
@include typography();
@include light-theme($light-material-palette);
body {
background: hsla(var(--ig-surface-500));
color: var(--ig-surface-500-contrast);
}
html, body {
height: 100%;
}
.ig-typography {
h1, h2, h3, h4, h5, h6, p, .ig-typography__body-1 {
margin: 0;
}
}
.outer-wrapper > *:not(router-outlet) {
width: 100%;
}
Theme Customization
Queremos una variante oscura del mismo tema, añadir nuestra propia paleta de colores para que coincida con nuestra marca y cambiar la fuente aPoppins en lugar de la predeterminadaTitillium Web, todo lo cual podemos cambiar directamente a través del App Builder y podemos enviar el cambio como una pull request desde el App Builder al repositorio.
La actualizaciónstyles.scss es así:
@include core();
@include typography($font-family: "Poppins");
$custom-palette: palette(
$primary: #1028c7,
$secondary: #e0d94c,
$surface: #000,
$gray: #fff
);
@include theme(
$palette: $custom-palette,
$schema: $dark-material-schema
);
Como puedes ver, la generación de código cambió de la especifica@include light-theme($light-material-palette);, que es el tema y paleta de colores por defecto, a una inclusión genéricatheme(), que proporciona como parámetros nuestra paleta de colores personalizada y un esquema de material oscuro para la estructura de tematización. El resultado de la app de Angular de correr ahora es así:
Queremos profundizar y personalizar un tema de componente específico en nuestra aplicación y lo haremos incorporando las variables CSS para un tema de componente individual, en este caso el tema de la barra de herramientas de cuadrícula.
@include core();
@include typography($font-family: "Poppins");
$primary: #1028c7;
/* All of the components will use this custom color palette */
$custom-palette: palette(
$primary: $primary,
$secondary: #e0d94c,
$surface: #000,
$gray: #fff
);
@include theme(
$palette: $custom-palette,
$schema: $dark-material-schema
);
/* Grid Toolbar */
/* All grid toolbars will have custom background and elevations */
$toolbar-theme: grid-toolbar-theme(
$background-color: $primary
);
:host {
@include tokens($toolbar-theme);
}
/* END Grid Toolbar */
Y el resultado en nuestra aplicación ahora se ve así:
Se puede aplicar el mismo proceso para anular y personalizar cualquiera de los temas componentes individualmente.
Switching custom themes at runtime
Ahora profundicemos aún más y creemos dos versiones personalizadas del tema, que se pueden cambiar en tiempo de ejecución. Podemos hacer esto con el control/preferencia del usuario y permitirles cambiarlo en cualquier momento. Sin embargo, para el ejemplo, usaremos la preferencia de usuario definida por el sistema operativo (claro u oscuro) para aplicar un tema que coincida con la configuración actual del sistema operativo. Para ello necesitaremos dos paletas de colores:
@use "minireset.css/minireset";
@use "@infragistics/igniteui-angular/theming" as *;
@include core();
@include typography($font-family: "Poppins");
$primary-dark: #1028c7;
$primary-light: #3c55f1;
$secondary-dark: #e0d94c;
$secondary-light: #b4a904;
$custom-palette-dark: palette(
$primary: $primary-dark,
$secondary: $secondary-dark,
$surface: #000,
$gray: #ccc
);
$custom-palette-light: palette(
$primary: $primary-light,
$secondary: $secondary-light,
$surface: #fff,
$gray: #222
);
Luego nuestra definición de tema irá en el alcance general, que usaremos para la variación de luz y crearemos una sobreescritura de paleta en una@media consulta cuando se detecte la preferencia de dark color schema OS para el sistema:
@include theme(
$palette: $custom-palette-light,
$schema: $light-material-schema
);
@media (prefers-color-scheme: light) {
/* Grid Toolbar override for light color scheme */
igx-grid-toolbar {
--background-color: #{$primary-light};
--title-text-color: #{text-contrast($primary-light)};
}
/* END Grid Toolbar */
}
@media (prefers-color-scheme: dark) {
// changes native element schema (scrollbars, select, etc.)
:root {
color-scheme: dark;
}
@include palette($custom-palette-dark);
/* Grid Toolbar override for dark color scheme */
igx-grid-toolbar {
--background-color: #{$primary-dark};
--title-text-color: #{text-contrast($primary-dark)};
}
/* END Grid Toolbar */
}
Note
He cambiado laigx-grid-toolbar anulación de temas para que solo se sobrescriban dos de sus variables, en lugar de incluir todas las variables de tema usandotokens. Todas las variables de tema pueden encontrarse en el documento correspondiente de la API de SASS y son equivalentes a las variables sass, pero con el prefijo de-- en lugar de$.
Y el resultado ahora se ve así con el tema ligero del sistema operativo:
Y así es como se ve con el tema oscuro del sistema operativo:
Note
El cambio de tiempo de ejecución completo, incluido el cambio de esquema de tema Ignite UI, solo es posible si se crean dos temas completos. En el ejemplo anterior, cambiamos las paletas de colores, pero el esquema de tema sigue siendo $light-material-schema, por lo que no se utilizan todos los tonos correctos de la paleta de colores cuando cambiamos a la paleta de colores oscuros.
What can be customized
Ignite UI tematización abstrae múltiples dimensiones de la tematización y proporciona capacidades de retematización muy sólidas. Los desarrolladores y diseñadores pueden aprovechar las API del motor de temas para crear un diseño visual personalizado para sus aplicaciones, lo que les da un aspecto único al usar Ignite UI for Angular. El motor de temas también expone variables de cada una de las dimensiones, que se pueden usar para aplicar temas al resto de la estructura de la aplicación, que no se construye directamente con Ignite UI for Angular componentes como interfaz de usuario. Las dimensiones expuestas para modificaciones son:
- Colors (color palette)
- Shape (borders and radiuses)
- Elevations (shadows)
- Tipografía (fuentes y tamaños de fuente)
- Tamaño (el tamaño de la información que se ajusta en la pantalla)
Note
Si realmente desea un diseño visual totalmente personalizado, deberá modificar todas las dimensiones temáticas admitidas y aprovechará al máximo las API de Sass. Si solo necesita cambiar cosas como las fuentes y algunos colores, puede echar un vistazo a la sección de paletas y tipografía. En la mayoría de los casos, todo lo que necesitará es cambiar algunas variables CSS y no necesitará las API de Sass completas. Hemos hecho esto lo más granular posible, para que se puedan aplicar modificaciones sin resultados secundarios inesperados en el diseño visual de sus aplicaciones.
Theme Optimization
Después de realizar algunas personalizaciones, crearemos la aplicación que generamos y modificamos para ver cómo se ve el tema de nuestra aplicación en términos de tamaño.
Como puedes ver, el tema de la aplicación es ligeramente superior a 400kb, lo que se reduce a ~40kb cuando se comprime y transfiere. No es algo grande, pero ¿puede ser más óptimo? La respuesta es sí, a menos que se utilicen todos los componentes de la suite Ignite UI for Angular. La llamada@include theme() incluye todos los temas componentes, pero tenemos un mecanismo para decirle a la función qué excluir. Hay un$exclude parámetro en la mezcla de temas, que toma los nombres de los componentes como un array y excluye esos del tema en tiempo de compilación. Como no es tan fácil encontrar y listar todos los componentes disponibles en el paquete, es preferible que puedas simplemente listar todos los componentes que usas. Exponemos la lista completa de componentes como una variable, a la que tienes acceso una vez que
@use "@infragistics/igniteui-angular/theming" as *;
El array de componentes se encuentra en$components y puedes reducir esta lista con los componentes que usas y excluir todos los demás, como en este ejemplo:
$include: (
igx-navbar,
igx-ripple,
igx-icon,
igx-button,
igx-input-group,
igx-combo,
igx-nav-drawer,
igx-grid,
igx-grid-toolbar
);
@include theme(
$palette: $custom-palette,
$schema: $dark-material-schema,
/* Removing all included components from the full list and excluding the rest */
$exclude: map.keys(map.remove($components, $include...))
);
Note
Algunos temas componentes dependen de otros temas componentes.
Incluso si excluye ciertos temas, la compilación los conservará si utiliza un tema de componente, que depende de un tema excluido.
¿Cómo se ve nuestra compilación después de haber excluido ciertos temas?
Como puedes ver, el tamaño de nuestro estilo se ha reducido casi a la mitad de su tamaño original. Esto parece bastante bueno por ahora, pero ¿podemos reducirlo aún más? De hecho, sí podemos. La mayor parte del tamaño del estilo está ocupado por los componentes más grandes de la suite, en este caso elIgxTreeGridComponent que tenemos en una de nuestras vistas. Sin embargo, no usamos este componente en ninguna otra perspectiva. Podemos hacer que la vista seaigx-tree-grid una ruta cargada con pereza y podemos incluir el tema de las cuadrículas solo para esa ruta, haciendo así que nuestro css de nivel superior sea aún más pequeño. ¿Cómo se hace esto?
Comenzaremos creando un nuevo módulo y un nuevo módulo de enrutamiento en la carpeta con el componente de empleados en nuestra aplicación.
// employees.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { EmployeesRoutingModule } from './employees-routing.module';
import { EmployeesComponent } from './employees.component';
import { IgxButtonModule, IgxComboModule, IgxTreeGridModule } from '@infragistics/igniteui-angular';
@NgModule({
declarations: [
EmployeesComponent
],
imports: [
CommonModule,
EmployeesRoutingModule,
IgxComboModule,
IgxTreeGridModule,
IgxButtonModule
]
})
export class EmployeesModule { }
// employees-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { EmployeesComponent } from './employees.component';
const routes: Routes = [{ path: '', component: EmployeesComponent }];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class EmployeesRoutingModule { }
// Updated top-level app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { PageNotFoundComponent } from './error-routing/not-found/not-found.component';
import { UncaughtErrorComponent } from './error-routing/error/uncaught-error.component';
import { ErrorRoutingModule } from './error-routing/error-routing.module';
import { StatisticsComponent } from './statistics/statistics.component';
export const routes: Routes = [
{ path: '', redirectTo: 'statistics', pathMatch: 'full' },
{ path: 'error', component: UncaughtErrorComponent },
// { path: 'employees', component: EmployeesComponent, data: { text: 'Employees' } },
// lazy-loading the employees route
{ path: 'employees', loadChildren: () => import('./employees/employees.module').then(m => m.EmployeesModule) },
{ path: 'statistics', component: StatisticsComponent, data: { text: 'Statistics' } },
{ path: '**', component: PageNotFoundComponent } // must always be last
];
@NgModule({
imports: [RouterModule.forRoot(routes), ErrorRoutingModule],
exports: [RouterModule, ErrorRoutingModule]
})
export class AppRoutingModule {
}
Ahora eliminamos losIgxTreeGridModule importsIgxComboModule yEmployeesComponentapp.module.ts de nuestro porque no usamos importaciones en otras vistas y solo podemos tener una declaración de componente en todos los módulos.
Luego procederemos eliminando eligx-grid,igx-grid-toolbar yigx-combo de nuestro tema incluye, y los incluiremos aemployees.component.scss nivel directo.
/* employees.component.scss */
@use "@infragistics/igniteui-angular/theming" as *;
:host ::ng-deep {
height: 100%;
display: flex;
justify-content: flex-start;
align-items: stretch;
align-content: flex-start;
$primary: #1028c7;
@include core();
@include grid(grid-theme());
@include combo(combo-theme());
@include grid-toolbar(
grid-toolbar-theme(
$background-color: $primary,
);
}
/* Updated styles.scss */
@use "sass:map";
@use "minireset.css/minireset";
@use "@infragistics/igniteui-angular/theming" as *;
@include core();
@include typography($font-family: "Poppins");
$primary: #1028c7;
$custom-palette: palette(
$primary: $primary,
$secondary: #e0d94c,
$surface: #000,
$gray: #fff
);
$include: (
igx-navbar,
igx-ripple,
igx-icon,
igx-button,
igx-nav-drawer
);
@include theme(
$palette: $custom-palette,
$schema: $dark-material-schema,
$exclude: map.keys(map.remove($components, $include...),)
);
Note
Probablemente quieras poner todas tus variables, como los valores de la paleta de colores, en un archivo aparte_variables.scss, que puedas incluir de varios componentes para reutilizar las variables.
El resultado en términos de construcción es el siguiente:
Como puedes ver, nuestro nivelstyles.css superior bajó a poco más de 70kb, que es un poco menos de 6kb cuando se comprime. Empezamos con ~428kb, ~40kb comprimidos y conseguimos reducir esto unas 7 veces en cuanto a tamaño comprimido. El resto se entrega solo cuando se está cargando la vista que contiene losigx-tree-grid componentes y (yigx-combo componentes).
Additional Resources
Temas relacionados:
Nuestra comunidad es activa y siempre da la bienvenida a nuevas ideas.