Skip to content

feat(material/button): add support for tonal button #30638

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
section {
display: table;
display: flex;
align-items: center;
}

.example-label {
display: table-cell;
font-size: 14px;
margin-left: 8px;
margin: 0 16px 0 8px;
min-width: 120px;
}

.example-button-row {
display: table-cell;
max-width: 600px;
}

Expand All @@ -23,9 +22,3 @@ section {
justify-content: space-between;
flex-wrap: wrap;
}

.example-button-container {
display: flex;
justify-content: center;
width: 140px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<a matButton href="https://www.google.com/" target="_blank">Link</a>
</div>
</section>
<mat-divider></mat-divider>
<mat-divider/>
<section>
<div class="example-label">Elevated</div>
<div class="example-button-row">
Expand All @@ -15,7 +15,7 @@
<a matButton="elevated" href="https://www.google.com/" target="_blank">Link</a>
</div>
</section>
<mat-divider></mat-divider>
<mat-divider/>
<section>
<div class="example-label">Outlined</div>
<div class="example-button-row">
Expand All @@ -24,16 +24,25 @@
<a matButton="outlined" href="https://www.google.com/" target="_blank">Link</a>
</div>
</section>
<mat-divider></mat-divider>
<mat-divider/>
<section>
<div class="example-label">Filled</div>
<div class="example-button-row">
<button matButton="filled" >Basic</button>
<button matButton="filled" disabled>Disabled</button>
<button matButton="filled">Basic</button>
<button matButton="filled" disabled>Disabled</button>
<a matButton="filled" href="https://www.google.com/" target="_blank">Link</a>
</div>
</section>
<mat-divider></mat-divider>
<mat-divider/>
<section>
<div class="example-label">Tonal</div>
<div class="example-button-row">
<button matButton="tonal" >Basic</button>
<button matButton="tonal" disabled>Disabled</button>
<a matButton="tonal" href="https://www.google.com/" target="_blank">Link</a>
</div>
</section>
<mat-divider/>
<section>
<div class="example-label">Icon</div>
<div class="example-button-row">
Expand All @@ -47,64 +56,51 @@
</div>
</div>
</section>
<mat-divider></mat-divider>
<mat-divider/>
<section>
<div class="example-label">Floating Action Button (FAB)</div>
<div class="example-button-row">
<div class="example-flex-container">
<div class="example-button-container">
<button matFab aria-label="Example icon button with a delete icon">
<mat-icon>delete</mat-icon>
</button>
</div>
<div class="example-button-container">
<button matFab disabled aria-label="Example icon button with a heart icon">
<mat-icon>favorite</mat-icon>
</button>
</div>
<button matFab aria-label="Example icon button with a delete icon">
<mat-icon>delete</mat-icon>
</button>
<button matFab disabled aria-label="Example icon button with a heart icon">
<mat-icon>favorite</mat-icon>
</button>
</div>
</div>
</section>
<mat-divider></mat-divider>
<mat-divider/>
<section>
<div class="example-label">Mini FAB</div>
<div class="example-button-row">
<div class="example-flex-container">
<div class="example-button-container">
<button matMiniFab aria-label="Example icon button with a menu icon">
<mat-icon>menu</mat-icon>
</button>
</div>
<div class="example-button-container">
<button matMiniFab disabled aria-label="Example icon button with a home icon">
<mat-icon>home</mat-icon>
</button>
</div>
<button matMiniFab aria-label="Example icon button with a menu icon">
<mat-icon>menu</mat-icon>
</button>
<button matMiniFab disabled aria-label="Example icon button with a home icon">
<mat-icon>home</mat-icon>
</button>
</div>
</div>
</section>
<mat-divider/>
<section>
<div class="example-label">Extended FAB</div>
<div class="example-button-row">
<div class="example-flex-container">
<div class="example-button-container">
<button matFab extended>
<mat-icon>favorite</mat-icon>
Basic
</button>
</div>
<div class="example-button-container">
<button matFab extended disabled>
<mat-icon>favorite</mat-icon>
Disabled
</button>
</div>
<div class="example-button-container">
<a matFab extended routerLink=".">
<mat-icon>favorite</mat-icon>
Link
</a>
</div>
<button matFab extended>
<mat-icon>favorite</mat-icon>
Basic
</button>
<button matFab extended disabled>
<mat-icon>favorite</mat-icon>
Disabled
</button>
<a matFab extended routerLink=".">
<mat-icon>favorite</mat-icon>
Link
</a>
</div>
</div>
</section>
2 changes: 1 addition & 1 deletion src/dev-app/button/button-demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,5 @@ export class ButtonDemo {
toggleDisable = false;
tooltipText = 'This is a button tooltip!';
disabledInteractive = false;
appearances: MatButtonAppearance[] = ['text', 'elevated', 'outlined', 'filled'];
appearances: MatButtonAppearance[] = ['text', 'elevated', 'outlined', 'filled', 'tonal'];
}
52 changes: 52 additions & 0 deletions src/material/button/_button-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
@use '../core/tokens/m2/mat/protected-button' as tokens-mat-protected-button;
@use '../core/tokens/m2/mdc/text-button' as tokens-mdc-text-button;
@use '../core/tokens/m2/mat/text-button' as tokens-mat-text-button;
@use '../core/tokens/m2/mat/tonal-button' as tokens-mat-tonal-button;
@use '../core/style/sass-utils';

@mixin _text-button-variant($theme, $palette) {
Expand Down Expand Up @@ -81,6 +82,15 @@
@include token-utils.create-token-values(tokens-mat-outlined-button.$prefix, $mat-tokens);
}

@mixin _tonal-button-variant($theme, $palette) {
@include token-utils.create-token-values(tokens-mat-tonal-button.$prefix, if(
$palette,
tokens-mat-tonal-button.private-get-color-palette-color-tokens($theme, $palette),
tokens-mat-tonal-button.get-color-tokens($theme)
));
}


@mixin _theme-from-tokens($tokens, $options...) {
@include validation.selector-defined(
'Calls to Angular Material theme mixins with an M3 theme must be wrapped in a selector'
Expand Down Expand Up @@ -125,6 +135,11 @@
tokens-mat-outlined-button.$prefix,
$options...
);
$mat-tonal-button-tokens: token-utils.get-tokens-for(
$tokens,
tokens-mat-tonal-button.$prefix,
$options...
);

@include token-utils.create-token-values(tokens-mdc-text-button.$prefix, $mdc-text-button-tokens);
@include token-utils.create-token-values(
Expand Down Expand Up @@ -152,6 +167,10 @@
tokens-mat-outlined-button.$prefix,
$mat-outlined-button-tokens
);
@include token-utils.create-token-values(
tokens-mat-tonal-button.$prefix,
$mat-tonal-button-tokens
);
}

/// Outputs base theme styles (styles not dependent on the color, typography, or density settings)
Expand Down Expand Up @@ -195,6 +214,10 @@
tokens-mat-outlined-button.$prefix,
tokens-mat-outlined-button.get-unthemable-tokens()
);
@include token-utils.create-token-values(
tokens-mat-tonal-button.$prefix,
tokens-mat-tonal-button.get-unthemable-tokens()
);
}
}
}
Expand All @@ -211,6 +234,7 @@
@include sass-utils.current-selector-or-root() {
@include _text-button-variant($theme, null);
@include _filled-button-variant($theme, null);
@include _tonal-button-variant($theme, null);
@include _protected-button-variant($theme, null);
@include _outlined-button-variant($theme, null);
}
Expand Down Expand Up @@ -270,6 +294,20 @@
@include _outlined-button-variant($theme, warn);
}
}

.mat-tonal-button {
&.mat-primary {
@include _tonal-button-variant($theme, primary);
}

&.mat-accent {
@include _tonal-button-variant($theme, accent);
}

&.mat-warn {
@include _tonal-button-variant($theme, warn);
}
}
}
}

Expand Down Expand Up @@ -313,6 +351,10 @@
tokens-mat-outlined-button.$prefix,
tokens-mat-outlined-button.get-typography-tokens($theme)
);
@include token-utils.create-token-values(
tokens-mat-tonal-button.$prefix,
tokens-mat-tonal-button.get-typography-tokens($theme)
);
}
}
}
Expand Down Expand Up @@ -357,6 +399,10 @@
tokens-mat-outlined-button.$prefix,
tokens-mat-outlined-button.get-density-tokens($theme)
);
@include token-utils.create-token-values(
tokens-mat-tonal-button.$prefix,
tokens-mat-tonal-button.get-density-tokens($theme)
);
}
}
}
Expand All @@ -371,6 +417,7 @@
$mat-protected-button-tokens: tokens-mat-protected-button.get-token-slots();
$mdc-text-button-tokens: tokens-mdc-text-button.get-token-slots();
$mat-text-button-tokens: tokens-mat-text-button.get-token-slots();
$mat-tonal-button-tokens: tokens-mat-tonal-button.get-token-slots();

@return (
(
Expand Down Expand Up @@ -413,6 +460,11 @@
tokens: $mat-text-button-tokens,
prefix: 'text-',
),
(
namespace: tokens-mat-tonal-button.$prefix,
tokens: $mat-tonal-button-tokens,
prefix: 'tonal-',
),
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/material/button/button-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {_CdkPrivateStyleLoader} from '@angular/cdk/private';
* Possible appearances for a `MatButton`.
* See https://m3.material.io/components/buttons/overview
*/
export type MatButtonAppearance = 'text' | 'filled' | 'elevated' | 'outlined';
export type MatButtonAppearance = 'text' | 'filled' | 'elevated' | 'outlined' | 'tonal';

/** Object that can be used to configure the default options for the button component. */
export interface MatButtonConfig {
Expand Down
1 change: 1 addition & 0 deletions src/material/button/button-high-contrast.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.mat-mdc-unelevated-button:not(.mdc-button--outlined),
.mat-mdc-raised-button:not(.mdc-button--outlined),
.mat-mdc-outlined-button:not(.mdc-button--outlined),
.mat-mdc-button-base.mat-tonal-button,
.mat-mdc-icon-button.mat-mdc-icon-button,
.mat-mdc-outlined-button .mdc-button__ripple {
@include cdk.high-contrast {
Expand Down
10 changes: 5 additions & 5 deletions src/material/button/button.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ There are several button variants, each applied as an attribute:
Additionally, the `matButton` has several appearances that can be set using the `matButton`
attribute, for example `matButton="outlined"`:


| Appearance | Description |
|--------------|----------------------------------------------------------------------------------|
| `text` | Default appearance. Does not have a background until the user interacts with it. |
| `elevated` | Has a background color, elevation and rounded corners. |
| `filled` | Has a flat appearance with rounded corners and no elevation. |
| `outlined` | Has an outline, rounded corners and a transparent background. |
| `text` | Default appearance. Text buttons are used for the lowest priority actions, especially when presenting multiple options. |
| `filled` | High-emphasis buttons used for final or unblocking actions in a flow, such as saving or confirming. |
| `tonal` | Medium-emphasis buttons often used for final or unblocking actions in a flow, but with less visual emphasis than a filled button. |
| `outlined` | Medium-emphasis buttons often used for actions that need attention but aren't the primary action. |
| `elevated` | Medium-emphasis buttons often used when a button requires visual separation from a patterned background. |


### Extended FAB buttons
Expand Down
Loading
Loading