Skip to content

Commit 30ecbd0

Browse files
committed
refactor(material/button): introduce tokens for horizontal layout
In M3 the buttons will have a different padding. These changes introduce tokens that will allow us to customize it. **Note:** the text button in M3 has a different padding depending on whether it has icons so it needs an additional token.
1 parent 635bc6c commit 30ecbd0

File tree

8 files changed

+136
-32
lines changed

8 files changed

+136
-32
lines changed

src/dev-app/button/button-demo.html

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ <h4 class="demo-section-header">Text Buttons [mat-button]</h4>
168168
with icons
169169
<mat-icon iconPositionEnd>favorite</mat-icon>
170170
</button>
171+
<button mat-button>
172+
<mat-icon>home</mat-icon>
173+
with icons
174+
</button>
171175
</section>
172176

173177
<h4 class="demo-section-header">Raised Buttons [mat-raised-button]</h4>
@@ -186,6 +190,10 @@ <h4 class="demo-section-header">Raised Buttons [mat-raised-button]</h4>
186190
with icons
187191
<mat-icon iconPositionEnd>favorite</mat-icon>
188192
</button>
193+
<button mat-raised-button>
194+
<mat-icon>home</mat-icon>
195+
with icons
196+
</button>
189197
</section>
190198

191199
<h4 class="demo-section-header">Stroked Buttons [mat-stroked-button]</h4>
@@ -204,6 +212,10 @@ <h4 class="demo-section-header">Stroked Buttons [mat-stroked-button]</h4>
204212
with icons
205213
<mat-icon iconPositionEnd>favorite</mat-icon>
206214
</button>
215+
<button mat-stroked-button>
216+
<mat-icon>home</mat-icon>
217+
with icons
218+
</button>
207219
</section>
208220

209221
<h4 class="demo-section-header">Flat Buttons [mat-flat-button]</h4>
@@ -222,9 +234,13 @@ <h4 class="demo-section-header">Flat Buttons [mat-flat-button]</h4>
222234
with icons
223235
<mat-icon iconPositionEnd>favorite</mat-icon>
224236
</button>
237+
<button mat-flat-button>
238+
<mat-icon>home</mat-icon>
239+
with icons
240+
</button>
225241
</section>
226242

227-
<h4 class="demo-section-header"> Icon Buttons [mat-icon-button]</h4>
243+
<h4 class="demo-section-header">Icon Buttons [mat-icon-button]</h4>
228244
<section>
229245
<button mat-icon-button>
230246
<mat-icon>cached</mat-icon>

src/material/button/_button-base.scss

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,48 @@
133133
}
134134
}
135135
}
136+
137+
@mixin mat-private-button-horizontal-layout($prefix, $slots, $has-with-icon-padding) {
138+
@include token-utils.use-tokens($prefix, $slots) {
139+
$icon-spacing: token-utils.get-token-variable-reference(icon-spacing, true);
140+
$icon-offset: token-utils.get-token-variable-reference(icon-offset, true);
141+
$horizontal-padding: token-utils.get-token-variable-reference(horizontal-padding, true);
142+
padding: 0 $horizontal-padding;
143+
144+
@if ($has-with-icon-padding) {
145+
$with-icon-horizontal-padding:
146+
token-utils.get-token-variable-reference(with-icon-horizontal-padding, true);
147+
148+
// stylelint-disable-next-line selector-class-pattern
149+
&:has(.material-icons, mat-icon, [matButtonIcon]) {
150+
padding: 0 $with-icon-horizontal-padding;
151+
}
152+
}
153+
154+
// MDC expects button icons to contain this HTML content:
155+
// ```html
156+
// <span class="mdc-button__icon material-icons">favorite</span>
157+
// ```
158+
// However, Angular Material expects a `mat-icon` instead. The following
159+
// styles will lay out the icons appropriately.
160+
& > .mat-icon {
161+
margin-right: $icon-spacing;
162+
margin-left: $icon-offset;
163+
164+
[dir='rtl'] & {
165+
margin-right: $icon-offset;
166+
margin-left: $icon-spacing;
167+
}
168+
}
169+
170+
.mdc-button__label + .mat-icon {
171+
margin-right: $icon-offset;
172+
margin-left: $icon-spacing;
173+
174+
[dir='rtl'] & {
175+
margin-right: $icon-spacing;
176+
margin-left: $icon-offset;
177+
}
178+
}
179+
}
180+
}

src/material/button/_button-theme.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@
111111
tokens-mdc-protected-button.get-unthemable-tokens());
112112
@include mdc-button-outlined-theme.theme(
113113
tokens-mdc-outlined-button.get-unthemable-tokens());
114+
115+
@include token-utils.create-token-values(tokens-mat-text-button.$prefix,
116+
tokens-mat-text-button.get-unthemable-tokens());
117+
@include token-utils.create-token-values(tokens-mat-filled-button.$prefix,
118+
tokens-mat-filled-button.get-unthemable-tokens());
119+
@include token-utils.create-token-values(tokens-mat-protected-button.$prefix,
120+
tokens-mat-protected-button.get-unthemable-tokens());
121+
@include token-utils.create-token-values(tokens-mat-outlined-button.$prefix,
122+
tokens-mat-outlined-button.get-unthemable-tokens());
114123
}
115124
}
116125
}

src/material/button/button.scss

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
@use 'sass:map';
22
@use '@material/button/button' as mdc-button;
3-
@use '@material/button/button-base' as mdc-button-base;
43
@use '@material/button/variables' as mdc-button-variables;
54
@use '@material/button/button-text-theme' as mdc-button-text-theme;
65
@use '@material/button/button-filled-theme' as mdc-button-filled-theme;
76
@use '@material/button/button-protected-theme' as mdc-button-protected-theme;
87
@use '@material/button/button-outlined-theme' as mdc-button-outlined-theme;
8+
@use '@material/typography/typography' as mdc-typography;
99
@use '@material/theme/custom-properties' as mdc-custom-properties;
1010

1111
@use './button-base';
@@ -31,6 +31,8 @@
3131
$mdc-text-button-slots: tokens-mdc-text-button.get-token-slots();
3232

3333
@include mdc-button-text-theme.theme-styles($mdc-text-button-slots);
34+
@include button-base.mat-private-button-horizontal-layout(tokens-mat-text-button.$prefix,
35+
tokens-mat-text-button.get-token-slots(), true);
3436
@include button-base.mat-private-button-ripple(tokens-mat-text-button.$prefix,
3537
tokens-mat-text-button.get-token-slots());
3638
@include button-base.mat-private-button-touch-target(false, tokens-mat-text-button.$prefix,
@@ -49,6 +51,8 @@
4951
$mdc-filled-button-slots: tokens-mdc-filled-button.get-token-slots();
5052

5153
@include mdc-button-filled-theme.theme-styles($mdc-filled-button-slots);
54+
@include button-base.mat-private-button-horizontal-layout(tokens-mat-filled-button.$prefix,
55+
tokens-mat-filled-button.get-token-slots(), false);
5256
@include button-base.mat-private-button-ripple(tokens-mat-filled-button.$prefix,
5357
tokens-mat-filled-button.get-token-slots());
5458
@include button-base.mat-private-button-touch-target(false, tokens-mat-filled-button.$prefix,
@@ -76,6 +80,8 @@
7680
pressed-container-elevation: null,
7781
container-shadow-color: null,
7882
)));
83+
@include button-base.mat-private-button-horizontal-layout(tokens-mat-protected-button.$prefix,
84+
tokens-mat-protected-button.get-token-slots(), false);
7985
@include button-base.mat-private-button-ripple(tokens-mat-protected-button.$prefix,
8086
tokens-mat-protected-button.get-token-slots());
8187
@include button-base.mat-private-button-touch-target(false, tokens-mat-protected-button.$prefix,
@@ -115,6 +121,8 @@
115121
$mdc-outlined-button-slots: tokens-mdc-outlined-button.get-token-slots();
116122

117123
@include mdc-button-outlined-theme.theme-styles($mdc-outlined-button-slots);
124+
@include button-base.mat-private-button-horizontal-layout(tokens-mat-outlined-button.$prefix,
125+
tokens-mat-outlined-button.get-token-slots(), false);
118126
@include button-base.mat-private-button-ripple(tokens-mat-outlined-button.$prefix,
119127
tokens-mat-outlined-button.get-token-slots());
120128
@include button-base.mat-private-button-touch-target(false, tokens-mat-outlined-button.$prefix,
@@ -143,34 +151,17 @@
143151
.mat-mdc-outlined-button {
144152
@include button-base.mat-private-button-interactive();
145153
@include style-private.private-animation-noop();
146-
}
147154

148-
// MDC expects button icons to contain this HTML content:
149-
// ```html
150-
// <span class="mdc-button__icon material-icons">favorite</span>
151-
// ```
152-
// However, Angular Material expects a `mat-icon` instead. The following
153-
// mixins will style the icons appropriately.
154-
.mat-mdc-button {
155+
// Similar to MDC's `_icon-structure`, apart from the margin which we
156+
// handle via custom tokens in `mat-private-button-horizontal-layout`.
155157
& > .mat-icon {
156-
@include mdc-button-base.icon();
157-
}
158-
.mdc-button__label + .mat-icon {
159-
@include mdc-button-base.icon-trailing();
160-
}
161-
}
162-
163-
.mat-mdc-unelevated-button,
164-
.mat-mdc-raised-button,
165-
.mat-mdc-outlined-button {
166-
// Icons inside contained buttons have different styles due to increased button padding
167-
& > .mat-icon {
168-
@include mdc-button-base.icon();
169-
@include mdc-button-base.icon-contained();
170-
}
171-
172-
.mdc-button__label + .mat-icon {
173-
@include mdc-button-base.icon-contained-trailing();
158+
$icon-size: mdc-typography.px-to-rem(18px);
159+
display: inline-block;
160+
position: relative;
161+
vertical-align: top;
162+
font-size: $icon-size;
163+
height: $icon-size;
164+
width: $icon-size;
174165
}
175166
}
176167

src/material/core/tokens/m2/mat/_filled-button.scss

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,17 @@ $prefix: (mat, filled-button);
1212
// Tokens that can't be configured through Angular Material's current theming API,
1313
// but may be in a future version of the theming API.
1414
@function get-unthemable-tokens() {
15-
@return ();
15+
@return (
16+
// Start/end padding of the button.
17+
horizontal-padding: 16px,
18+
19+
// Space between the icon and the button's main content.
20+
icon-spacing: 8px,
21+
22+
// Amount by which to offset the icon so that its presence
23+
// doesn't increase throw off the horizontal padding.
24+
icon-offset: -4px,
25+
);
1626
}
1727

1828
// Tokens that can be configured through Angular Material's color theming API.

src/material/core/tokens/m2/mat/_outlined-button.scss

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,17 @@ $prefix: (mat, outlined-button);
1212
// Tokens that can't be configured through Angular Material's current theming API,
1313
// but may be in a future version of the theming API.
1414
@function get-unthemable-tokens() {
15-
@return ();
15+
@return (
16+
// Start/end padding of the button.
17+
horizontal-padding: 15px, // Normally it's 16px, but -1px for the outline.
18+
19+
// Space between the icon and the button's main content.
20+
icon-spacing: 8px,
21+
22+
// Amount by which to offset the icon so that its presence
23+
// doesn't increase throw off the horizontal padding.
24+
icon-offset: -4px,
25+
);
1626
}
1727

1828
// Tokens that can be configured through Angular Material's color theming API.

src/material/core/tokens/m2/mat/_protected-button.scss

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,17 @@ $prefix: (mat, protected-button);
1212
// Tokens that can't be configured through Angular Material's current theming API,
1313
// but may be in a future version of the theming API.
1414
@function get-unthemable-tokens() {
15-
@return ();
15+
@return (
16+
// Start/end padding of the button.
17+
horizontal-padding: 16px,
18+
19+
// Space between the icon and the button's main content.
20+
icon-spacing: 8px,
21+
22+
// Amount by which to offset the icon so that its presence
23+
// doesn't increase throw off the horizontal padding.
24+
icon-offset: -4px,
25+
);
1626
}
1727

1828
// Tokens that can be configured through Angular Material's color theming API.

src/material/core/tokens/m2/mat/_text-button.scss

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,20 @@ $prefix: (mat, text-button);
1212
// Tokens that can't be configured through Angular Material's current theming API,
1313
// but may be in a future version of the theming API.
1414
@function get-unthemable-tokens() {
15-
@return ();
15+
@return (
16+
// Start/end padding of the button.
17+
horizontal-padding: 8px,
18+
19+
// Start/end padding of the button when it has an icon.
20+
with-icon-horizontal-padding: 8px,
21+
22+
// Space between the icon and the button's main content.
23+
icon-spacing: 8px,
24+
25+
// Amount by which to offset the icon so that its presence
26+
// doesn't increase throw off the horizontal padding.
27+
icon-offset: 0,
28+
);
1629
}
1730

1831
// Tokens that can be configured through Angular Material's color theming API.

0 commit comments

Comments
 (0)