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! :)

Sugestões de assuntos? Envie aqui
Copyright © 2024 Angularizando