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

feat(select): Adding check boxes to the multi-select menu #7455

Closed
wants to merge 1 commit into from
Closed
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
72 changes: 41 additions & 31 deletions src/components/checkbox/checkbox-theme.scss
Original file line number Diff line number Diff line change
@@ -1,11 +1,46 @@
md-checkbox.md-THEME_NAME-theme {
@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}}';
}

&.md-checked .md-ripple {
color: '{{background-600}}';
}

&.md-checked.md-focused ._md-container:before {
background-color: '{{accent-color-0.26}}';
}
Expand All @@ -21,6 +56,7 @@ md-checkbox.md-THEME_NAME-theme {
._md-icon {
border-color: '{{foreground-2}}';
}

&.md-checked ._md-icon {
background-color: '{{accent-color-0.87}}';
}
Expand All @@ -31,35 +67,7 @@ md-checkbox.md-THEME_NAME-theme {

&:not([disabled]) {
&.md-primary {
.md-ripple {
color: '{{primary-600}}';
}
&.md-checked .md-ripple {
color: '{{background-600}}';
}

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

&.md-checked .md-ink-ripple {
color: '{{primary-color-0.87}}';
}

._md-icon {
border-color: '{{foreground-2}}';
}
&.md-checked ._md-icon {
background-color: '{{primary-color-0.87}}';
}

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

&.md-checked ._md-icon:after {
border-color: '{{primary-contrast-0.87}}';
}
@include checkbox-primary;
}

&.md-warn {
Expand All @@ -78,20 +86,22 @@ md-checkbox.md-THEME_NAME-theme {
._md-icon {
border-color: '{{foreground-2}}';
}

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

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

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

&[disabled] {

._md-icon {
border-color: '{{foreground-3}}';
}
Expand Down
144 changes: 78 additions & 66 deletions src/components/checkbox/checkbox.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,15 @@ $checkbox-border-width: 2px !default;
$checkbox-text-margin: 10px !default;
$checkbox-top: 12px !default;

.md-inline-form {
md-checkbox {
margin: 19px 0 18px;
}
}

md-checkbox {
box-sizing: border-box;
display: inline-block;
margin-bottom: $checkbox-margin;
white-space: nowrap;
cursor: pointer;
outline: none;
user-select: none;
position: relative;
min-width: $checkbox-width;
min-height: $checkbox-width;
@include rtl(margin-left, 0, $checkbox-margin);
@include rtl(margin-right, $checkbox-margin, 0);

&:last-of-type {
margin-left: 0;
margin-right: 0;
}

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

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

// 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(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment explaining what this mixin does

$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%;
Expand All @@ -54,11 +23,11 @@ md-checkbox {
box-sizing: border-box;
display: inline-block;

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

&:before {
box-sizing: border-box;
background-color: transparent;
Expand Down Expand Up @@ -97,49 +66,92 @@ md-checkbox {
}
}

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

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

&.md-checked ._md-icon {
&#{$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-checked ._md-icon:after {
box-sizing: border-box;
transform: rotate(45deg);
position: absolute;
left: $checkbox-width / 3;
top: $checkbox-width / 9;
display: table;
width: $checkbox-width / 3;
height: $checkbox-width * 2 / 3;
border-width: $checkbox-border-width;
border-style: solid;
border-top: 0;
border-left: 0;
content: '';
.md-inline-form {
md-checkbox {
margin: 19px 0 18px;
}
}

md-checkbox {
box-sizing: border-box;
display: inline-block;
margin-bottom: $checkbox-margin;
white-space: nowrap;
cursor: pointer;
outline: none;
user-select: none;
position: relative;
min-width: $checkbox-width;
min-height: $checkbox-width;
@include rtl(margin-left, 0, $checkbox-margin);
@include rtl(margin-right, $checkbox-margin, 0);

&:last-of-type {
margin-left: 0;
margin-right: 0;
}

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

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

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

@include checkbox-container;

._md-label {
box-sizing: border-box;
Expand Down
5 changes: 3 additions & 2 deletions src/components/select/demoOptionGroups/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ <h1 class="md-title">Pick your pizza below</h1>
</md-input-container>
<md-input-container>
<label>Topping</label>
<md-select ng-model="topping">
<md-select ng-model="selectedToppings" multiple>
<md-optgroup label="Meats">
<md-option ng-value="topping.name" ng-repeat="topping in toppings | filter: {category: 'meat' }">{{topping.name}}</md-option>
</md-optgroup>
Expand All @@ -20,6 +20,7 @@ <h1 class="md-title">Pick your pizza below</h1>
</md-select>
</md-input-container>
</div>
<p ng-if="topping">You ordered a {{size.toLowerCase()}} pizza with {{topping.toLowerCase()}}.</p>
<p ng-if="selectedToppings">You ordered a {{size.toLowerCase()}} pizza with
{{printSelectedToppings()}}.</p>
</div>
</div>
10 changes: 10 additions & 0 deletions src/components/select/demoOptionGroups/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,14 @@ angular
{ category: 'veg', name: 'Green Pepper' },
{ category: 'veg', name: 'Green Olives' }
];
$scope.selectedToppings = [];
$scope.printSelectedToppings = function printSelectedToppings(){
// If there is more than one topping, we add an 'and' and an oxford
// comma to be gramatically correct.
if (this.selectedToppings.length > 1) {
var lastTopping = ', and ' + this.selectedToppings.slice(-1)[0];
return this.selectedToppings.slice(0,-1).join(', ') + lastTopping;
}
return this.selectedToppings.join('');
};
});
9 changes: 9 additions & 0 deletions src/components/select/select-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,12 @@ md-select-menu.md-THEME_NAME-theme {
}
}
}


[md-checkbox-enabled].md-THEME_NAME-theme {
@include checkbox-primary('[selected]');

md-option ._md-text {
color: '{{background-900-0.87}}';
}
}
7 changes: 7 additions & 0 deletions src/components/select/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

var SELECT_EDGE_MARGIN = 8;
var selectNextId = 0;
var CHECKBOX_SELECTION_INDICATOR =
angular.element('<div class="_md-container"><div class="_md-icon"></div></div>');

angular.module('material.components.select', [
'material.core',
Expand Down Expand Up @@ -776,6 +778,11 @@ function OptionDirective($mdButtonInkRipple, $mdUtil) {
var optionCtrl = ctrls[0];
var selectCtrl = ctrls[1];

if (selectCtrl.isMultiple) {
element.attr('md-checkbox-enabled', '');
element.prepend(CHECKBOX_SELECTION_INDICATOR.clone());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a (hopefully simple) unit test for this.


if (angular.isDefined(attr.ngValue)) {
scope.$watch(attr.ngValue, setOptionValue);
} else if (angular.isDefined(attr.value)) {
Expand Down
17 changes: 17 additions & 0 deletions src/components/select/select.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
$select-checkbox-border-radius: 2px !default;
$select-checkbox-border-width: 2px !default;
$select-checkbox-width: rem(1.4) !default;
$select-option-height: 48px;
$select-option-padding: 16px;
$select-container-padding: 16px;
Expand Down Expand Up @@ -230,3 +233,17 @@ md-optgroup {
border: 1px solid #fff;
}
}

md-select-menu[multiple] {
md-option[md-checkbox-enabled] {
@include rtl(padding-left, $select-option-padding * 2.5, $select-option-padding);
@include rtl(padding-right, $select-option-padding, $select-option-padding * 2.5);

@include checkbox-container('[selected]');

._md-container {
@include rtl(margin-left, $select-option-padding * (2 / 3), auto);
@include rtl(margin-right, auto, $select-option-padding * (2 / 3));
}
}
}
Loading