Skip to content

feat(material/button): add the ability to interact with disabled buttons #28242

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
Dec 11, 2023
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
@@ -0,0 +1,3 @@
button {
margin-right: 8px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<button
mat-raised-button
disabled
disabledInteractive
matTooltip="This is a tooltip!">Disabled button allowing interactivity</button>

<button
mat-raised-button
disabled
matTooltip="This is a tooltip!">Default disabled button</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {Component} from '@angular/core';
import {MatButton} from '@angular/material/button';
import {MatTooltip} from '@angular/material/tooltip';

/**
* @title Interactive disabled buttons
*/
@Component({
selector: 'button-disabled-interactive-example',
templateUrl: 'button-disabled-interactive-example.html',
styleUrls: ['button-disabled-interactive-example.css'],
standalone: true,
imports: [MatButton, MatTooltip],
})
export class ButtonDisabledInteractiveExample {}
1 change: 1 addition & 0 deletions src/components-examples/material/button/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export {ButtonOverviewExample} from './button-overview/button-overview-example';
export {ButtonTypesExample} from './button-types/button-types-example';
export {ButtonDisabledInteractiveExample} from './button-disabled-interactive/button-disabled-interactive-example';
export {ButtonHarnessExample} from './button-harness/button-harness-example';
2 changes: 2 additions & 0 deletions src/dev-app/button/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ ng_module(
],
deps = [
"//src/material/button",
"//src/material/checkbox",
"//src/material/icon",
"//src/material/tooltip",
],
)

Expand Down
169 changes: 141 additions & 28 deletions src/dev-app/button/button-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,52 @@ <h4 class="demo-section-header">Buttons</h4>
</button>
</section>
<section>
<button mat-button disabled>normal</button>
<button mat-raised-button disabled>raised</button>
<button mat-stroked-button disabled>stroked</button>
<button mat-flat-button disabled>flat</button>
<button mat-fab disabled>
<button
mat-button
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">normal</button>
<button
mat-raised-button
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">raised</button>
<button
mat-stroked-button
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">stroked</button>
<button
mat-flat-button
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">flat</button>
<button
mat-fab
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">
<mat-icon>check</mat-icon>
</button>
<button mat-mini-fab disabled>
<button
mat-mini-fab
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">
<mat-icon>check</mat-icon>
</button>
<button mat-fab extended disabled>Search</button>
<button mat-fab extended disabled>
<button
mat-fab
extended
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">Search</button>
<button
mat-fab
extended
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">
<mat-icon>check</mat-icon>
Search
<mat-icon iconPositionEnd>check</mat-icon>
Expand All @@ -57,18 +91,61 @@ <h4 class="demo-section-header">Anchors</h4>
</a>
</section>
<section>
<a href="//www.google.com" disabled mat-button color="primary">SEARCH</a>
<a href="//www.google.com" disabled mat-raised-button>SEARCH</a>
<a href="//www.google.com" disabled mat-stroked-button color="primary">SEARCH</a>
<a href="//www.google.com" disabled mat-flat-button>SEARCH</a>
<a href="//www.google.com" disabled mat-fab>
<a
href="//www.google.com"
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText"
mat-button
color="primary">SEARCH</a>
<a
href="//www.google.com"
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText"
mat-raised-button>SEARCH</a>
<a
href="//www.google.com"
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText"
mat-stroked-button color="primary">SEARCH</a>
<a
href="//www.google.com"
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText"
mat-flat-button>SEARCH</a>
<a
href="//www.google.com"
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText"
mat-fab>
<mat-icon>check</mat-icon>
</a>
<a href="//www.google.com" disabled mat-mini-fab>
<a
href="//www.google.com"
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText"
mat-mini-fab>
<mat-icon>check</mat-icon>
</a>
<a href="//www.google.com" disabled mat-fab extended>Search</a>
<a href="//www.google.com" disabled mat-fab extended>
<a
href="//www.google.com"
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText"
mat-fab
extended>Search</a>
<a
href="//www.google.com"
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText"
mat-fab
extended>
<mat-icon>check</mat-icon>
Search
<mat-icon iconPositionEnd>check</mat-icon>
Expand All @@ -81,7 +158,11 @@ <h4 class="demo-section-header">Text Buttons [mat-button]</h4>
<button mat-button color="primary">primary</button>
<button mat-button color="accent">accent</button>
<button mat-button color="warn">warn</button>
<button mat-button disabled>disabled</button>
<button
mat-button
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">disabled</button>
<button mat-button>
<mat-icon>home</mat-icon>
with icons
Expand All @@ -95,7 +176,11 @@ <h4 class="demo-section-header">Raised Buttons [mat-raised-button]</h4>
<button mat-raised-button color="primary">primary</button>
<button mat-raised-button color="accent">accent</button>
<button mat-raised-button color="warn">warn</button>
<button mat-raised-button disabled>disabled</button>
<button
mat-raised-button
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">disabled</button>
<button mat-raised-button>
<mat-icon>home</mat-icon>
with icons
Expand All @@ -109,7 +194,11 @@ <h4 class="demo-section-header">Stroked Buttons [mat-stroked-button]</h4>
<button mat-stroked-button color="primary">primary</button>
<button mat-stroked-button color="accent">accent</button>
<button mat-stroked-button color="warn">warn</button>
<button mat-stroked-button disabled>disabled</button>
<button
mat-stroked-button
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">disabled</button>
<button mat-stroked-button>
<mat-icon>home</mat-icon>
with icons
Expand All @@ -123,7 +212,11 @@ <h4 class="demo-section-header">Flat Buttons [mat-flat-button]</h4>
<button mat-flat-button color="primary">primary</button>
<button mat-flat-button color="accent">accent</button>
<button mat-flat-button color="warn">warn</button>
<button mat-flat-button disabled>disabled</button>
<button
mat-flat-button
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">disabled</button>
<button mat-flat-button>
<mat-icon>home</mat-icon>
with icons
Expand All @@ -145,12 +238,16 @@ <h4 class="demo-section-header"> Icon Buttons [mat-icon-button]</h4>
<button mat-icon-button color="warn">
<mat-icon>trending_up</mat-icon>
</button>
<button mat-icon-button disabled>
<button
mat-icon-button
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">
<mat-icon>visibility</mat-icon>
</button>
</section>

<h4 class="demo-section-header"> Icon Button Anchors [mat-icon-button]</h4>
<h4 class="demo-section-header">Icon Button Anchors [mat-icon-button]</h4>
<section>
<a href="#" mat-icon-button>
<mat-icon>cached</mat-icon>
Expand All @@ -164,7 +261,12 @@ <h4 class="demo-section-header"> Icon Button Anchors [mat-icon-button]</h4>
<a href="#" mat-icon-button color="warn">
<mat-icon>trending_up</mat-icon>
</a>
<a href="#" mat-icon-button disabled>
<a
href="#"
mat-icon-button
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">
<mat-icon>visibility</mat-icon>
</a>
</section>
Expand All @@ -183,7 +285,11 @@ <h4 class="demo-section-header">Fab Buttons [mat-fab]</h4>
<button mat-fab color="warn">
<mat-icon>home</mat-icon>
</button>
<button mat-fab disabled>
<button
mat-fab
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">
<mat-icon>favorite</mat-icon>
</button>
</section>
Expand All @@ -202,7 +308,11 @@ <h4 class="demo-section-header"> Mini Fab Buttons [mat-mini-fab]</h4>
<button mat-mini-fab color="warn">
<mat-icon>filter_list</mat-icon>
</button>
<button mat-mini-fab disabled>
<button
mat-mini-fab
disabled
[disabledInteractive]="disabledInteractive"
[matTooltip]="tooltipText">
<mat-icon>home</mat-icon>
</button>
</section>
Expand All @@ -212,9 +322,12 @@ <h4 class="demo-section-header">Interaction/State</h4>
<div>
<p>isDisabled: {{isDisabled}}</p>
<p>Button 1 as been clicked {{clickCounter}} times</p>
<button mat-flat-button (click)="isDisabled=!isDisabled">
{{isDisabled ? 'Enable All' : 'Disable All'}}
</button>
<p>
<mat-checkbox [(ngModel)]="disabledInteractive">Allow disabled button interactivity</mat-checkbox>
</p>
<p>
<mat-checkbox [(ngModel)]="isDisabled">All disabled</mat-checkbox>
</p>
<button mat-flat-button (click)="button1.focus()">Focus 1</button>
<button mat-flat-button (click)="button2.focus()">Focus 2</button>
<button mat-flat-button (click)="button3.focus()">Focus 3</button>
Expand Down
39 changes: 33 additions & 6 deletions src/dev-app/button/button-demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,45 @@
*/

import {Component} from '@angular/core';
import {MatButtonModule} from '@angular/material/button';
import {MatIconModule} from '@angular/material/icon';
import {FormsModule} from '@angular/forms';
import {
MatButton,
MatAnchor,
MatFabButton,
MatFabAnchor,
MatIconButton,
MatIconAnchor,
MatMiniFabButton,
MatMiniFabAnchor,
} from '@angular/material/button';
import {MatIcon} from '@angular/material/icon';
import {MatTooltip} from '@angular/material/tooltip';
import {MatCheckbox} from '@angular/material/checkbox';

@Component({
selector: 'button-demo',
templateUrl: 'button-demo.html',
styleUrls: ['button-demo.css'],
standalone: true,
imports: [MatButtonModule, MatIconModule],
imports: [
MatButton,
MatAnchor,
MatFabButton,
MatFabAnchor,
MatMiniFabButton,
MatMiniFabAnchor,
MatIconButton,
MatIconAnchor,
MatIcon,
MatTooltip,
MatCheckbox,
FormsModule,
],
})
export class ButtonDemo {
isDisabled: boolean = false;
clickCounter: number = 0;
toggleDisable: boolean = false;
isDisabled = false;
clickCounter = 0;
toggleDisable = false;
tooltipText = 'This is a button tooltip!';
disabledInteractive = false;
}
16 changes: 14 additions & 2 deletions src/material/button/_button-base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,17 @@
@include token-utils.create-token-slot(background-color, state-layer-color);
}

&.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before {
@include token-utils.create-token-slot(background-color, disabled-state-layer-color);
}

&:hover .mat-mdc-button-persistent-ripple::before {
@include token-utils.create-token-slot(opacity, hover-state-layer-opacity);
}

&.cdk-program-focused,
&.cdk-keyboard-focused {
&.cdk-keyboard-focused,
&.mat-mdc-button-disabled-interactive:focus {
.mat-mdc-button-persistent-ripple::before {
@include token-utils.create-token-slot(opacity, focus-state-layer-opacity);
}
Expand All @@ -91,11 +96,18 @@
// and note that having pointer-events may have unintended side-effects, e.g. allowing the user
// to click the target underneath the button.
@mixin mat-private-button-disabled() {
&[disabled] {
// `[disabled]` shouldn't be necessary, but we keep it to maintain
// compatibility with apps setting it through host bindings.
&[disabled],
&.mat-mdc-button-disabled {
cursor: default;
pointer-events: none;
@content;
}

&.mat-mdc-button-disabled-interactive {
pointer-events: auto;
}
}

// Hides the touch target on lower densities.
Expand Down
Loading