Skip to content

Commit 59fce28

Browse files
authored
feat(material-experimental/mdc-radio): add functionality and s… (#18272)
* feat(material-experimental/mdc-radio): add functionality and styling * fix lint * new goldens * fix view engine tests * comments
1 parent 474c838 commit 59fce28

File tree

14 files changed

+1327
-61
lines changed

14 files changed

+1327
-61
lines changed

src/dev-app/mdc-radio/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ ng_module(
1111
],
1212
deps = [
1313
"//src/material-experimental/mdc-radio",
14+
"//src/material/button",
15+
"//src/material/checkbox",
16+
"@npm//@angular/forms",
1417
"@npm//@angular/router",
1518
],
1619
)

src/dev-app/mdc-radio/mdc-radio-demo-module.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,18 @@ import {NgModule} from '@angular/core';
1010
import {MatRadioModule} from '@angular/material-experimental/mdc-radio';
1111
import {RouterModule} from '@angular/router';
1212
import {MdcRadioDemo} from './mdc-radio-demo';
13+
import {FormsModule} from '@angular/forms';
14+
import {MatButtonModule} from '@angular/material/button';
15+
import {MatCheckboxModule} from '@angular/material/checkbox';
16+
import {CommonModule} from '@angular/common';
1317

1418
@NgModule({
1519
imports: [
20+
CommonModule,
1621
MatRadioModule,
22+
FormsModule,
23+
MatButtonModule,
24+
MatCheckboxModule,
1725
RouterModule.forChild([{path: '', component: MdcRadioDemo}]),
1826
],
1927
declarations: [MdcRadioDemo],
Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,63 @@
11
<h1>Basic Example</h1>
22
<section class="demo-section">
3-
<mat-radio-button name="group1">Option 1</mat-radio-button>
3+
<mat-radio-button name="group1" checked>Option 1</mat-radio-button>
44
<mat-radio-button name="group1">Option 2</mat-radio-button>
5-
<mat-radio-button name="group1" disabled>Option 3 (Disabled)</mat-radio-button>
5+
<mat-radio-button name="group1" disabled="true">Option 3 (disabled)</mat-radio-button>
6+
</section>
7+
8+
<h1>Color Example</h1>
9+
<section class="demo-section">
10+
<mat-radio-button name="group2">Default (accent)</mat-radio-button>
11+
<mat-radio-button name="group2" color="primary">Primary</mat-radio-button>
12+
<mat-radio-button name="group2" color="accent">Accent</mat-radio-button>
13+
<mat-radio-button name="group2" color="warn">Warn</mat-radio-button>
14+
</section>
15+
16+
<h1>Group Color Example</h1>
17+
<section class="demo-section">
18+
<mat-radio-group color="warn">
19+
<mat-radio-button name="group3" value="1">Option 1</mat-radio-button>
20+
<mat-radio-button name="group3" value="2">Option 2</mat-radio-button>
21+
<mat-radio-button name="group3" value="3">Option 3</mat-radio-button>
22+
<mat-radio-button name="group3" value="4" color="primary">Option with color override</mat-radio-button>
23+
</mat-radio-group>
24+
</section>
25+
26+
<h1>Dynamic Example</h1>
27+
<section class="demo-section">
28+
<div>
29+
<span>isDisabled: {{isDisabled}}</span>
30+
<button mat-raised-button (click)="isDisabled=!isDisabled" class="demo-button">
31+
Disable buttons
32+
</button>
33+
</div>
34+
<div>
35+
<span>isRequired: {{isRequired}}</span>
36+
<button mat-raised-button (click)="isRequired=!isRequired" class="demo-button">
37+
Require buttons
38+
</button>
39+
</div>
40+
<div>
41+
<span><mat-checkbox [(ngModel)]="isAlignEnd">Align end</mat-checkbox></span>
42+
</div>
43+
<mat-radio-group
44+
name="my_options"
45+
[disabled]="isDisabled"
46+
[required]="isRequired"
47+
[labelPosition]="isAlignEnd ? 'after' : 'before'">
48+
<mat-radio-button value="option_1">Option 1</mat-radio-button>
49+
<mat-radio-button value="option_2">Option 2</mat-radio-button>
50+
<mat-radio-button value="option_3">Option 3</mat-radio-button>
51+
</mat-radio-group>
52+
</section>
53+
54+
<h1>Favorite Season Example</h1>
55+
<h2>Dynamic Example with two-way data-binding</h2>
56+
<section class="demo-section">
57+
<mat-radio-group name="more_options" [(ngModel)]="favoriteSeason">
58+
<mat-radio-button *ngFor="let season of seasonOptions" name="more_options" [value]="season">
59+
{{season}}
60+
</mat-radio-button>
61+
</mat-radio-group>
62+
<p>Your favorite season is: {{favoriteSeason}}</p>
663
</section>
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,13 @@
1-
// TODO: copy in demo styles from existing mat-radio demo.
1+
.demo-button {
2+
margin: 8px;
3+
text-transform: uppercase;
4+
}
5+
6+
.demo-section {
7+
margin: 8px;
8+
padding: 16px;
9+
10+
.mat-radio-button {
11+
margin: 8px;
12+
}
13+
}

src/dev-app/mdc-radio/mdc-radio-demo.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,14 @@ import {Component} from '@angular/core';
1414
styleUrls: ['mdc-radio-demo.css'],
1515
})
1616
export class MdcRadioDemo {
17+
isAlignEnd: boolean = false;
18+
isDisabled: boolean = false;
19+
isRequired: boolean = false;
20+
favoriteSeason: string = 'Autumn';
21+
seasonOptions = [
22+
'Winter',
23+
'Spring',
24+
'Summer',
25+
'Autumn',
26+
];
1727
}

src/material-experimental/mdc-radio/BUILD.bazel

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package(default_visibility = ["//visibility:public"])
22

3-
load("//src/e2e-app:test_suite.bzl", "e2e_test_suite")
43
load(
54
"//tools:defaults.bzl",
6-
"ng_e2e_test_library",
75
"ng_module",
6+
"ng_test_library",
7+
"ng_web_test_suite",
88
"sass_binary",
99
"sass_library",
1010
)
@@ -18,7 +18,12 @@ ng_module(
1818
assets = [":radio_scss"] + glob(["**/*.html"]),
1919
module_name = "@angular/material-experimental/mdc-radio",
2020
deps = [
21+
"//src/cdk/a11y",
22+
"//src/cdk/coercion",
23+
"//src/cdk/collections",
2124
"//src/material/core",
25+
"//src/material/radio",
26+
"@npm//@angular/forms",
2227
"@npm//@material/radio",
2328
],
2429
)
@@ -44,18 +49,32 @@ sass_binary(
4449
],
4550
)
4651

47-
ng_e2e_test_library(
48-
name = "e2e_test_sources",
49-
srcs = glob(["**/*.e2e.spec.ts"]),
52+
###########
53+
# Testing
54+
###########
55+
56+
ng_test_library(
57+
name = "radio_tests_lib",
58+
srcs = glob(
59+
["**/*.spec.ts"],
60+
exclude = ["**/*.e2e.spec.ts"],
61+
),
5062
deps = [
51-
"//src/cdk/testing/private/e2e",
63+
":mdc-radio",
64+
"//src/cdk/testing/private",
65+
"@npm//@angular/forms",
66+
"@npm//@angular/platform-browser",
67+
"@npm//@material/radio",
5268
],
5369
)
5470

55-
e2e_test_suite(
56-
name = "e2e_tests",
71+
ng_web_test_suite(
72+
name = "unit_tests",
73+
static_files = [
74+
"@npm//:node_modules/@material/radio/dist/mdc.radio.js",
75+
],
5776
deps = [
58-
":e2e_test_sources",
59-
"//src/cdk/testing/private/e2e",
77+
":radio_tests_lib",
78+
"//src/material-experimental:mdc_require_config.js",
6079
],
6180
)
Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,38 @@
11
@import '../mdc-helpers/mdc-helpers';
2+
@import '@material/radio/mixins';
3+
@import '@material/radio/variables';
24

35
@mixin mat-radio-theme-mdc($theme) {
6+
// Save original values of MDC global variables. We need to save these so we can restore the
7+
// variables to their original values and prevent unintended side effects from using this mixin.
8+
$orig-mdc-radio-baseline-theme-color: $mdc-radio-baseline-theme-color;
9+
410
@include mat-using-mdc-theme($theme) {
5-
// TODO: MDC theme styles here.
11+
$mdc-radio-baseline-theme-color: primary !global;
12+
13+
.mat-mdc-radio-button {
14+
&.mat-primary {
15+
@include mdc-radio-without-ripple($query: $mat-theme-styles-query);
16+
}
17+
18+
&.mat-accent {
19+
$mdc-radio-baseline-theme-color: secondary !global;
20+
@include mdc-radio-without-ripple($query: $mat-theme-styles-query);
21+
}
22+
23+
&.mat-warn {
24+
$mdc-radio-baseline-theme-color: error !global;
25+
@include mdc-radio-without-ripple($query: $mat-theme-styles-query);
26+
}
27+
}
628
}
29+
30+
// Restore original values of MDC global variables.
31+
$mdc-radio-baseline-theme-color: $orig-mdc-radio-baseline-theme-color !global;
732
}
833

934
@mixin mat-radio-typography-mdc($config) {
1035
@include mat-using-mdc-typography($config) {
11-
// TODO: MDC typography styles here.
36+
@include mdc-radio-without-ripple($query: $mat-typography-styles-query);
1237
}
1338
}

src/material-experimental/mdc-radio/module.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88

99
import {CommonModule} from '@angular/common';
1010
import {NgModule} from '@angular/core';
11-
import {MatCommonModule} from '@angular/material/core';
12-
import {MatRadioButton} from './radio';
11+
import {MatCommonModule, MatRippleModule} from '@angular/material/core';
12+
import {MatRadioButton, MatRadioGroup} from './radio';
1313

1414
@NgModule({
15-
imports: [MatCommonModule, CommonModule],
16-
exports: [MatRadioButton, MatCommonModule],
17-
declarations: [MatRadioButton],
15+
imports: [MatCommonModule, CommonModule, MatRippleModule],
16+
exports: [MatRadioGroup, MatRadioButton],
17+
declarations: [MatRadioGroup, MatRadioButton],
1818
})
1919
export class MatRadioModule {
2020
}
Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,34 @@
1-
<div class="mdc-form-field">
1+
<div class="mdc-form-field" #formField
2+
[class.mdc-form-field--align-end]="labelPosition == 'before'">
23
<div class="mdc-radio" [ngClass]="_classes">
3-
<input class="mdc-radio__native-control" type="radio" [id]="inputId" [disabled]="disabled">
4+
<input #input class="mdc-radio__native-control" type="radio"
5+
[id]="inputId"
6+
[checked]="checked"
7+
[disabled]="disabled"
8+
[tabIndex]="tabIndex"
9+
[attr.name]="name"
10+
[attr.value]="value"
11+
[required]="required"
12+
[attr.aria-label]="ariaLabel"
13+
[attr.aria-labelledby]="ariaLabelledby"
14+
[attr.aria-describedby]="ariaDescribedby"
15+
(change)="_onInputChange($event)"
16+
(click)="_onInputClick($event)">
417
<div class="mdc-radio__background">
518
<div class="mdc-radio__outer-circle"></div>
619
<div class="mdc-radio__inner-circle"></div>
720
</div>
21+
<div class="mdc-radio__ripple"></div>
22+
<div mat-ripple class="mat-radio-ripple"
23+
[matRippleTrigger]="formField"
24+
[matRippleDisabled]="_isRippleDisabled()"
25+
[matRippleCentered]="true"
26+
[matRippleRadius]="20"
27+
[matRippleAnimation]="{enterDuration: 150}">
28+
<div class="mat-ripple-element mat-radio-persistent-ripple"></div>
29+
</div>
830
</div>
9-
<label [for]="inputId" #label>
31+
<label [for]="inputId">
1032
<ng-content></ng-content>
1133
</label>
1234
</div>
Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
11
@import '@material/radio/mixins.import';
2+
@import '@material/radio/variables.import';
23
@import '@material/form-field/mixins.import';
34
@import '../mdc-helpers/mdc-helpers';
45

5-
66
@include mdc-radio-without-ripple($query: $mat-base-styles-query);
77
@include mdc-form-field-core-styles($query: $mat-base-styles-query);
8+
9+
// This is necessary because we do not depend on MDC's ripple, but have our own that should be
10+
// positioned correctly. This can be removed once we start using MDC's ripple implementation.
11+
.mat-mdc-radio-button .mat-radio-ripple {
12+
position: absolute;
13+
left: calc(50% - #{$mdc-radio-icon-size});
14+
top: calc(50% - #{$mdc-radio-icon-size});
15+
height: $mdc-radio-icon-size * 2;
16+
width: $mdc-radio-icon-size * 2;
17+
z-index: 1;
18+
pointer-events: none;
19+
20+
.mat-ripple-element:not(.mat-radio-persistent-ripple) {
21+
opacity: $mdc-radio-ripple-opacity;
22+
}
23+
}

0 commit comments

Comments
 (0)