Vamos fazer uma tela inicial da nossa aplicação inspirada na tela inicial de flutter, contendo um exemplo de contador e botão para incrementar, e já utilizando os componentes da biblioteca Angular Material.
Criando App Inicial
Instalando Angular Material
Utilizando no terminal o angular cli, vamos criar uma nova aplicação com o comando ng new material-you
, selecionar as opções default (estilo: css, ssr: não) e adicionar a lib do angular material com o comando ng add @angular/material
, neste caso quando perguntado sobre o tema, utilizaremos a opção "custom".
Após a instalação, será criado um novo arquivo custom-theme.scss
na pasta /src, com as seguintes configurações:
// Custom Theming for Angular Material
@use '@angular/material' as mat;
@include mat.core();
$primary: mat.define-palette(mat.$indigo-palette);
$accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
$warn: mat.define-palette(mat.$red-palette);
$theme: mat.define-light-theme((
color: (
primary: $material-you-primary,
accent: $material-you-accent,
warn: $material-you-warn,
),
typography: mat.define-typography-config(),
density: 0
));
@include mat.all-component-themes($theme);
Vamos adicionar uma variável do tipo signal count
para exibir o valor do contador na tela, e o método increment()
para adicionar 1 ao valor atual. Também vamos importar os módulos necessários para os componentes a serem exibidos na tela, MatButtonModule
, MatIconModule
e MatToolbarModule
:
Importando Componentes
import { Component, signal } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatToolbarModule } from '@angular/material/toolbar';
@Component({
selector: 'app-root',
standalone: true,
imports: [MatButtonModule, MatIconModule, MatToolbarModule],
template: `
<mat-toolbar color="primary">
<span>{{ title }}</span>
</mat-toolbar>
<main>
<p>You have pushed the button this many times:</p>
<h2>{{ count() }}</h2>
<button mat-fab color="accent" (click)="increment()">
<mat-icon>add</mat-icon>
</button>
</main>
`,
styles: `
main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: calc(100vh - 56px);
}
@media (min-width: 600px) {
main {
height: calc(100vh - 64px);
}
}
.mat-mdc-fab {
position: fixed;
bottom: 20px;
right: 20px;
}
`,
})
export class AppComponent {
title = 'Material You Demo';
count = signal(0);
increment(): void {
this.count.update((value) => value + 1);
}
}
Material 3
Instalação e Configuração
Já temos nossa aplicação inicial funcionando com o angular material! Porém está com a versão antiga (v2, e inicialmente utilizando as cores índigo (primary) e pink (accent). Como queremos atualizar para a versão do material v3, primeiro precisamos instalar a lib com o comando npm i @angular/material-experimental
, em seguida adicionar as seguintes linhas no arquivo custom-theme.scss
(obs: caso queira utilizar a opção nos componentes color="accent"
, precisa passar uma paleta de cor terciária, e incluir o mixin de compatibilidade):
@use '@angular/material' as mat;
// importar nova lib
@use "@angular/material-experimental" as matx;
@include mat.core();
// nova forma de definir tema
$theme: matx.define-theme((
color: (
theme-type: light,
primary: matx.$m3-violet-palette,
tertiary: matx.$m3-green-palette, // caso queira usar 'accent' color
)
));
:root {
@include mat.all-component-themes($theme);
@include matx.color-variants-back-compat($theme); // caso queira usar 'accent' color
}
Perfeito! Agora sim os componentes já estão adaptados visualmente para a versão do material v3!
Customizando Cores
No caso do app starter em flutter, o toolbar está um pouco mais escuro, porque agora existem outras roles de cores, como por ex: surface
, inverse-primary
. Portanto para alterarmos a cor do background do componente Toolbar
, ou utilizar as cores do tema em outras partes do seu app, temos as seguintes opções:
Alternativa 1: Podemos estilizar o componente pela classe direto no arquivo custom-theme.scss
porém muitas vezes como o estilo do componente onde o toolbar é utilizado é mais específico, o css acaba não aplicando, ou muitas vezes você precisa utilizar o !important
(o que não é recomendado, porém caso precise ser o mesmo estilo para todo toolbar na aplicação toda é uma opção válida também):
.mat-toolbar {
background: mat.get-theme-color($theme, inverse-primary) !important;
}
Alternativa 2: Podemos criar variáveis nativas do CSS3 com as cores que precisamos, e podemos gerar a partir do própria paleta de cores que escolhemos no tema (utilizando a função mat.get-theme-color($theme, $color-role)
. Se no futuro quisermos trocar a cor primary do tema, serão alteradas todas as variáveis automaticamente!
Deste modo, podemos reutilizar as variáveis nos componentes filhos, como no segundo caso abaixo dentro de app.component.ts
, tanto em elementos do angular material como em outros elementos nativos html de sua preferência:
$theme: matx.define-theme((
color: (
primary: matx.$m3-violet-palette,
)
));
:root {
@include mat.all-component-themes($theme);
// variáveis de cores que dependem do tema escolhido acima
--color-primary: #{mat.get-theme-color($theme, primary)};
--color-surface: #{mat.get-theme-color($theme, surface)};
--color-inverse-primary: #{mat.get-theme-color($theme, inverse-primary)};
}
@Component({
styles: `
h2 {
color: var(--color-primary);
}
main {
background: var(--color-surface);
}
.mat-toolbar {
background: var(--color-inverse-primary);
}
`
})
export class AppComponent {}
Alternativa 3: Tão correta como a anterior, e até mais "elegante" por se dizer, se desejamos aplicar uma cor diferente do padrão para um componente e utilizar este mesmo estilo na aplicação toda, podemos inspecionar o elemento e localizar qual variável ele utiliza para modificar a cor de texto ou de fundo, e sobrescrever a variável do próprio material (tokens)!
Como não faz uso do !important
, não impedirá a modificação de um elemento filho no futuro quando necessário, sendo a melhor opção para estilização de forma global.
:root {
@include mat.all-component-themes($theme);
// variáveis de cores que dependem do tema escolhido acima
--color-primary: #{mat.get-theme-color($theme, primary)};
--color-surface: #{mat.get-theme-color($theme, surface)};
--color-inverse-primary: #{mat.get-theme-color($theme, inverse-primary)};
--color-tertiary-container: #{mat.get-theme-color($theme, tertiary-container)};
// sobrescrever variáveis (tokens) do próprio componente
--mat-toolbar-container-background-color: var(--color-inverse-primary);
--mdc-fab-container-color: var(--color-tertiary-container);
}
Caso precise de outras customizações, visite a nova página de documentação sobre Suporte ao Material 3. Vamos aproveitar para utilizar em nossos apps novos e também "modernizar" nossos apps mais antigos! Espero que tenham gostado, compartilhem com os amigos e até a próxima! :)