Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
feat(checkbox): add indeterminate checkbox support
Browse files Browse the repository at this point in the history
Closes #7643
  • Loading branch information
Derek Louie authored and jelbourn committed Apr 25, 2016
1 parent 6775d89 commit cd987f0
Show file tree
Hide file tree
Showing 13 changed files with 381 additions and 164 deletions.
3 changes: 2 additions & 1 deletion gulp/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ module.exports = {
],
themeBaseFiles: [
'src/core/style/variables.scss',
'src/core/style/mixins.scss'
'src/core/style/mixins.scss',
'src/core/style/themes.scss'
],
scssBaseFiles: [
'src/core/style/color-palette.scss',
Expand Down
58 changes: 12 additions & 46 deletions src/components/checkbox/checkbox-theme.scss
Original file line number Diff line number Diff line change
@@ -1,37 +1,3 @@
@mixin checkbox-primary($checkedSelector: '.md-checked') {
.md-ripple {
color: '{{primary-600}}';
}

&#{$checkedSelector} .md-ripple {
color: '{{background-600}}';
}

.md-ink-ripple {
color: '{{foreground-2}}';
}

&#{$checkedSelector} .md-ink-ripple {
color: '{{primary-color-0.87}}';
}

._md-icon {
border-color: '{{foreground-2}}';
}

&#{$checkedSelector} ._md-icon {
background-color: '{{primary-color-0.87}}';
}

&#{$checkedSelector}.md-focused ._md-container:before {
background-color: '{{primary-color-0.26}}';
}

&#{$checkedSelector} ._md-icon:after {
border-color: '{{primary-contrast-0.87}}';
}
}

md-checkbox.md-THEME_NAME-theme {
.md-ripple {
color: '{{accent-600}}';
Expand All @@ -41,7 +7,7 @@ md-checkbox.md-THEME_NAME-theme {
color: '{{background-600}}';
}

&.md-checked.md-focused ._md-container:before {
&.md-checked.md-focused .md-container:before {
background-color: '{{accent-color-0.26}}';
}

Expand All @@ -53,15 +19,15 @@ md-checkbox.md-THEME_NAME-theme {
color: '{{accent-color-0.87}}';
}

._md-icon {
.md-icon {
border-color: '{{foreground-2}}';
}

&.md-checked ._md-icon {
&.md-checked .md-icon {
background-color: '{{accent-color-0.87}}';
}

&.md-checked ._md-icon:after {
&.md-checked .md-icon:after {
border-color: '{{accent-contrast-0.87}}';
}

Expand All @@ -83,38 +49,38 @@ md-checkbox.md-THEME_NAME-theme {
color: '{{warn-color-0.87}}';
}

._md-icon {
.md-icon {
border-color: '{{foreground-2}}';
}

&.md-checked ._md-icon {
&.md-checked .md-icon {
background-color: '{{warn-color-0.87}}';
}

&.md-checked.md-focused:not([disabled]) ._md-container:before {
&.md-checked.md-focused:not([disabled]) .md-container:before {
background-color: '{{warn-color-0.26}}';
}

&.md-checked ._md-icon:after {
&.md-checked .md-icon:after {
border-color: '{{background-200}}';
}
}
}

&[disabled] {
._md-icon {
.md-icon {
border-color: '{{foreground-3}}';
}

&.md-checked ._md-icon {
&.md-checked .md-icon {
background-color: '{{foreground-3}}';
}

&.md-checked ._md-icon:after {
&.md-checked .md-icon:after {
border-color: '{{background-200}}';
}

._md-label {
.md-label {
color: '{{foreground-3}}';
}
}
Expand Down
26 changes: 23 additions & 3 deletions src/components/checkbox/checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ angular
* @param {string=} ng-change Angular expression to be executed when input changes due to user interaction with the input element.
* @param {boolean=} md-no-ink Use of attribute indicates use of ripple ink effects
* @param {string=} aria-label Adds label to checkbox for accessibility.
* Defaults to checkbox's text. If no default text is found, a warning will be logged.
* Defaults to checkbox's text. If no default text is found, a warning will be logged.
* @param {expression=} md-indeterminate This determines when the checkbox should be rendered as 'indeterminate'.
* If a truthy expression or no value is passed in the checkbox renders in the md-indeterminate state.
* If falsy expression is passed in it just looks like a normal unchecked checkbox.
* The indeterminate, checked, and unchecked states are mutually exclusive. A box cannot be in any two states at the same time.
* When a checkbox is indeterminate that overrides any checked/unchecked rendering logic.
*
* @usage
* <hljs lang="html">
Expand Down Expand Up @@ -55,7 +60,7 @@ function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $
transclude: true,
require: '?ngModel',
priority: 210, // Run before ngAria
template:
template:
'<div class="md-container" md-ink-ripple md-ink-ripple-checkbox>' +
'<div class="md-icon"></div>' +
'</div>' +
Expand All @@ -69,6 +74,7 @@ function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $

function compile (tElement, tAttrs) {
var container = tElement.children();
var mdIndeterminateStateEnabled = tAttrs.hasOwnProperty('mdIndeterminate');

tAttrs.type = 'checkbox';
tAttrs.tabindex = tAttrs.tabindex || '0';
Expand All @@ -89,8 +95,13 @@ function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $
});

return function postLink(scope, element, attr, ngModelCtrl) {
var isIndeterminate;
ngModelCtrl = ngModelCtrl || $mdUtil.fakeNgModel();
$mdTheming(element);
if (mdIndeterminateStateEnabled) {
setIndeterminateState();
scope.$watch(attr.mdIndeterminate, setIndeterminateState);
}

if (attr.ngChecked) {
scope.$watch(
Expand Down Expand Up @@ -156,6 +167,7 @@ function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $
listener(ev);
}
}

function listener(ev) {
if (element[0].hasAttribute('disabled')) {
return;
Expand All @@ -171,12 +183,20 @@ function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $
}

function render() {
if(ngModelCtrl.$viewValue) {
if(ngModelCtrl.$viewValue && !isIndeterminate) {
element.addClass(CHECKED_CSS);
} else {
element.removeClass(CHECKED_CSS);
}
}

function setIndeterminateState(newValue) {
isIndeterminate = newValue !== false;
if (isIndeterminate) {
element.attr('aria-checked', 'mixed');
}
element.toggleClass('md-indeterminate', isIndeterminate);
}
};
}
}
109 changes: 4 additions & 105 deletions src/components/checkbox/checkbox.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,107 +6,6 @@ $checkbox-border-width: 2px !default;
$checkbox-text-margin: 10px !default;
$checkbox-top: 12px !default;

// This mixin allows a user to use the md-checkbox css outside of the
// md-checkbox directive.
// See src/components/select/select.scss for an example.
@mixin checkbox-container(
$checkedSelector: '.md-checked',
$width: $checkbox-width,
$height: $checkbox-height,
$border-width: $checkbox-border-width,
$border-radius: $checkbox-border-radius) {
._md-container {
position: absolute;
top: 50%;
transform: translateY(-50%);

box-sizing: border-box;
display: inline-block;

width: $width;
height: $height;
@include rtl(left, 0, auto);
@include rtl(right, auto, 0);

&:before {
box-sizing: border-box;
background-color: transparent;
border-radius: 50%;
content: '';
position: absolute;
display: block;
height: auto;
left: 0;
top: 0;
right: 0;
bottom: 0;
transition: all 0.5s;
width: auto;
}

&:after {
box-sizing: border-box;
content: '';
position: absolute;
top: -10px;
right: -10px;
bottom: -10px;
left: -10px;
}

.md-ripple-container {
position: absolute;
display: block;
width: auto;
height: auto;
left: -15px;
top: -15px;
right: -15px;
bottom: -15px;
}
}

// unchecked
._md-icon {
box-sizing: border-box;
transition: 240ms;
position: absolute;
top: 0;
left: 0;
width: $width;
height: $height;
border-width: $border-width;
border-style: solid;
border-radius: $border-radius;
}

&#{$checkedSelector} ._md-icon {
border: none;

&:after {
box-sizing: border-box;
transform: rotate(45deg);
position: absolute;
left: $width / 3;
top: $width / 9;
display: table;
width: $width / 3;
height: $width * 2 / 3;
border-width: $border-width;
border-style: solid;
border-top: 0;
border-left: 0;
content: '';
}
}

// disabled
&[disabled] {
cursor: default;
}

}

.md-inline-form {
md-checkbox {
margin: 19px 0 18px;
Expand All @@ -133,27 +32,27 @@ md-checkbox {
}

&.md-focused:not([disabled]) {
._md-container:before {
.md-container:before {
left: -8px;
top: -8px;
right: -8px;
bottom: -8px;
}

&:not(.md-checked) {
._md-container:before {
.md-container:before {
background-color: rgba(0, 0, 0, 0.12);
}
}
}

&.md-align-top-left > div._md-container {
&.md-align-top-left > div.md-container {
top: $checkbox-top;
}

@include checkbox-container;

._md-label {
.md-label {
box-sizing: border-box;
position: relative;
display: inline-block;
Expand Down
Loading

0 comments on commit cd987f0

Please sign in to comment.