Skip to content

Commit 82d752b

Browse files
devversionkara
authored andcommitted
feat(radio): support for color binding (#5068)
Closes #4677
1 parent de68202 commit 82d752b

File tree

4 files changed

+86
-20
lines changed

4 files changed

+86
-20
lines changed

src/demo-app/radio/radio-demo.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ <h1>Basic Example</h1>
44
<md-radio-button name="group1">Option 2</md-radio-button>
55
<md-radio-button name="group1" disabled="true">Option 3 (disabled)</md-radio-button>
66
</section>
7+
8+
<h1>Color Example</h1>
9+
<section class="demo-section">
10+
<md-radio-button name="group2">Default (accent)</md-radio-button>
11+
<md-radio-button name="group2" color="primary">Primary</md-radio-button>
12+
<md-radio-button name="group2" color="accent">Accent</md-radio-button>
13+
<md-radio-button name="group2" color="warn">Warn</md-radio-button>
14+
</section>
15+
716
<h1>Dynamic Example</h1>
817
<section class="demo-section">
918
<div>

src/lib/radio/_radio-theme.scss

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22
@import '../core/theming/theming';
33
@import '../core/typography/typography-utils';
44

5+
@mixin mat-radio-color($palette) {
6+
&.mat-radio-checked .mat-radio-outer-circle {
7+
border-color: mat-color($palette);
8+
}
9+
10+
.mat-radio-inner-circle {
11+
background-color: mat-color($palette);
12+
}
13+
14+
.mat-radio-ripple .mat-ripple-element {
15+
background-color: mat-color($palette, 0.26);
16+
}
17+
}
518

619
@mixin mat-radio-theme($theme) {
720
$primary: map-get($theme, primary);
@@ -14,22 +27,10 @@
1427
border-color: mat-color($foreground, secondary-text);
1528
}
1629

17-
.mat-radio-checked .mat-radio-outer-circle {
18-
border-color: mat-color($accent);
19-
}
20-
2130
.mat-radio-disabled .mat-radio-outer-circle {
2231
border-color: mat-color($foreground, disabled);
2332
}
2433

25-
.mat-radio-inner-circle {
26-
background-color: mat-color($accent);
27-
}
28-
29-
.mat-radio-ripple .mat-ripple-element {
30-
background-color: mat-color($accent, 0.26);
31-
}
32-
3334
.mat-radio-disabled {
3435
.mat-radio-ripple .mat-ripple-element, .mat-radio-inner-circle {
3536
background-color: mat-color($foreground, disabled);
@@ -39,6 +40,20 @@
3940
color: mat-color($foreground, disabled);
4041
}
4142
}
43+
44+
.mat-radio-button {
45+
&.mat-primary {
46+
@include mat-radio-color($primary);
47+
}
48+
49+
&.mat-accent {
50+
@include mat-radio-color($accent);
51+
}
52+
53+
&.mat-warn {
54+
@include mat-radio-color($warn);
55+
}
56+
}
4257
}
4358

4459
@mixin mat-radio-typography($config) {

src/lib/radio/radio.spec.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,29 @@ describe('MdRadio', () => {
332332
expect(radioInstances[1].checked).toBeFalsy('should not select the second button');
333333
expect(radioInstances[2].checked).toBeFalsy('should not select the third button');
334334
});
335+
336+
it('should apply class based on color attribute', () => {
337+
expect(radioNativeElements.every(radioEl => radioEl.classList.contains('mat-accent')))
338+
.toBe(true, 'Expected every radio element to use the accent color by default.');
339+
340+
testComponent.color = 'primary';
341+
fixture.detectChanges();
342+
343+
expect(radioNativeElements.every(radioEl => radioEl.classList.contains('mat-primary')))
344+
.toBe(true, 'Expected every radio element to use the primary color from the binding.');
345+
346+
testComponent.color = 'warn';
347+
fixture.detectChanges();
348+
349+
expect(radioNativeElements.every(radioEl => radioEl.classList.contains('mat-warn')))
350+
.toBe(true, 'Expected every radio element to use the primary color from the binding.');
351+
352+
testComponent.color = null;
353+
fixture.detectChanges();
354+
355+
expect(radioNativeElements.every(radioEl => radioEl.classList.contains('mat-accent')))
356+
.toBe(true, 'Expected every radio element to fallback to accent color if value is falsy.');
357+
});
335358
});
336359

337360
describe('group with ngModel', () => {
@@ -595,10 +618,16 @@ describe('MdRadio', () => {
595618
[labelPosition]="labelPos"
596619
[value]="groupValue"
597620
name="test-name">
598-
<md-radio-button value="fire" [disableRipple]="disableRipple"
599-
[disabled]="isFirstDisabled">Charmander</md-radio-button>
600-
<md-radio-button value="water" [disableRipple]="disableRipple">Squirtle</md-radio-button>
601-
<md-radio-button value="leaf" [disableRipple]="disableRipple">Bulbasaur</md-radio-button>
621+
<md-radio-button value="fire" [disableRipple]="disableRipple" [disabled]="isFirstDisabled"
622+
[color]="color">
623+
Charmander
624+
</md-radio-button>
625+
<md-radio-button value="water" [disableRipple]="disableRipple" [color]="color">
626+
Squirtle
627+
</md-radio-button>
628+
<md-radio-button value="leaf" [disableRipple]="disableRipple" [color]="color">
629+
Bulbasaur
630+
</md-radio-button>
602631
</md-radio-group>
603632
`
604633
})
@@ -608,6 +637,7 @@ class RadiosInsideRadioGroup {
608637
isFirstDisabled: boolean = false;
609638
groupValue: string = null;
610639
disableRipple: boolean = false;
640+
color: string;
611641
}
612642

613643

src/lib/radio/radio.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
} from '../core';
3030
import {coerceBooleanProperty} from '../core/coercion/boolean-property';
3131
import {mixinDisabled, CanDisable} from '../core/common-behaviors/disabled';
32+
import {CanColor, mixinColor} from '../core/common-behaviors/color';
3233

3334

3435
/**
@@ -287,6 +288,14 @@ export class MdRadioGroup extends _MdRadioGroupMixinBase
287288
}
288289
}
289290

291+
// Boilerplate for applying mixins to MdRadioButton.
292+
export class MdRadioButtonBase {
293+
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
294+
}
295+
// As per Material design specifications the selection control radio should use the accent color
296+
// palette by default. https://material.io/guidelines/components/selection-controls.html
297+
export const _MdRadioButtonMixinBase = mixinColor(MdRadioButtonBase, 'accent');
298+
290299
/**
291300
* A radio-button. May be inside of
292301
*/
@@ -295,6 +304,7 @@ export class MdRadioGroup extends _MdRadioGroupMixinBase
295304
selector: 'md-radio-button, mat-radio-button',
296305
templateUrl: 'radio.html',
297306
styleUrls: ['radio.css'],
307+
inputs: ['color'],
298308
encapsulation: ViewEncapsulation.None,
299309
host: {
300310
'[class.mat-radio-button]': 'true',
@@ -304,7 +314,8 @@ export class MdRadioGroup extends _MdRadioGroupMixinBase
304314
},
305315
changeDetection: ChangeDetectionStrategy.OnPush,
306316
})
307-
export class MdRadioButton implements OnInit, AfterViewInit, OnDestroy {
317+
export class MdRadioButton extends _MdRadioButtonMixinBase
318+
implements OnInit, AfterViewInit, OnDestroy, CanColor {
308319

309320
/** The unique ID for the radio button. */
310321
@Input() id: string = `md-radio-${_uniqueIdCounter++}`;
@@ -443,14 +454,15 @@ export class MdRadioButton implements OnInit, AfterViewInit, OnDestroy {
443454
@ViewChild('input') _inputElement: ElementRef;
444455

445456
constructor(@Optional() radioGroup: MdRadioGroup,
446-
private _elementRef: ElementRef,
447-
private _renderer: Renderer2,
457+
elementRef: ElementRef,
458+
renderer: Renderer2,
448459
private _changeDetector: ChangeDetectorRef,
449460
private _focusOriginMonitor: FocusOriginMonitor,
450461
private _radioDispatcher: UniqueSelectionDispatcher) {
462+
super(renderer, elementRef);
463+
451464
// Assertions. Ideally these should be stripped out by the compiler.
452465
// TODO(jelbourn): Assert that there's no name binding AND a parent radio group.
453-
454466
this.radioGroup = radioGroup;
455467

456468
_radioDispatcher.listen((id: string, name: string) => {

0 commit comments

Comments
 (0)