Checkbox improvements

- Switch to using CSS masks for transparent tick. Sorry, IE, you get a white tick.
- Some small visual tweaks (rounded corners, alignment).
- Tidying up the JS
master
Sérgio Gomes 2015-01-29 15:14:13 +00:00
parent 83fd3af6e4
commit f363e1ad06
4 changed files with 76 additions and 119 deletions

View File

@ -6,7 +6,8 @@ $checkbox-label-height: 24px;
$checkbox-button-size: 16px;
$checkbox-inner-margin: 2px;
$checkbox-padding: 8px;
$checkbox-top-offset: ($checkbox-label-height - $checkbox-button-size) / 2;
$checkbox-top-offset:
($checkbox-label-height - $checkbox-button-size - $checkbox-inner-margin) / 2;
$checkbox-ripple-size: $checkbox-label-height * 1.5;
.wsk-checkbox {
@ -64,6 +65,7 @@ $checkbox-ripple-size: $checkbox-label-height * 1.5;
overflow: hidden;
border: 2px solid $checkbox-off-color;
border-radius: 2px;
z-index: 2;
@ -102,62 +104,27 @@ $checkbox-ripple-size: $checkbox-label-height * 1.5;
}
}
@mixin checkbox-tick-component {
.wsk-checkbox__tick-outline {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
mask: url("tick-mask.svg#mask");
background-color: transparent;
background: transparent;
@include material-animation-default(0.28s);
transition-property: background-color;
transition-property: background;
.wsk-checkbox.is-checked & {
background-color: $checkbox-color;
background: $checkbox-color url("tick.svg");
}
.wsk-checkbox.is-checked.is-disabled & {
background-color: $checkbox-disabled-color;
background: $checkbox-disabled-color url("tick.svg");
}
}
.wsk-checkbox__tick-outline {
transform: translate(-15%, -60%) rotate(45deg);
@include checkbox-tick-component();
}
.wsk-checkbox__bottom-right {
transform: translate(55%, 30%) rotate(45deg);
@include checkbox-tick-component();
}
.wsk-checkbox__bottom-left {
transform: translate(-55%, 60%) rotate(45deg);
@include checkbox-tick-component();
}
.wsk-checkbox__bottom {
transform: translate(0%, 80%);
@include checkbox-tick-component();
.wsk-checkbox.is-checked.is-disabled & {
background-color: transparent;
}
}
.wsk-checkbox__top-left {
transform: translate(-95%, -20%) rotate(45deg);
@include checkbox-tick-component();
.wsk-checkbox.is-checked.is-disabled & {
transform: translate(-105%, -10%) rotate(45deg);
}
}
.wsk-checkbox__top-right {
transform: translate(85%, -70%) rotate(45deg);
@include checkbox-tick-component();
}
.wsk-checkbox__label {
position: relative;
cursor: pointer;

View File

@ -30,42 +30,21 @@ MaterialCheckbox.prototype.Constant_ = {
* @private
*/
MaterialCheckbox.prototype.CssClasses_ = {
WSK_CHECKBOX_INPUT: 'wsk-checkbox__input',
WSK_CHECKBOX_BOX_OUTLINE: 'wsk-checkbox__box-outline',
WSK_CHECKBOX_FOCUS_HELPER: 'wsk-checkbox__focus-helper',
WSK_CHECKBOX_TICK_OUTLINE: 'wsk-checkbox__tick-outline',
WSK_CHECKBOX_BOT_RIGHT: 'wsk-checkbox__bottom-right',
WSK_CHECKBOX_BOT_LEFT: 'wsk-checkbox__bottom-left',
WSK_CHECKBOX_BOTTOM: 'wsk-checkbox__bottom',
WSK_CHECKBOX_TOP_LEFT: 'wsk-checkbox__top-left',
WSK_CHECKBOX_TOP_RIGHT: 'wsk-checkbox__top-right',
WSK_JS_RIPPLE_EFFECT: 'wsk-js-ripple-effect',
WSK_JS_RIPPLE_EFFECT_IGNORE_EVENTS: 'wsk-js-ripple-effect--ignore-events',
WSK_CHECKBOX_RIPPLE_CONTAINER: 'wsk-checkbox__ripple-container',
WSK_RIPPLE_CENTER: 'wsk-ripple--center',
WSK_RIPPLE: 'wsk-ripple',
INPUT: 'wsk-checkbox__input',
BOX_OUTLINE: 'wsk-checkbox__box-outline',
FOCUS_HELPER: 'wsk-checkbox__focus-helper',
TICK_OUTLINE: 'wsk-checkbox__tick-outline',
RIPPLE_EFFECT: 'wsk-js-ripple-effect',
RIPPLE_IGNORE_EVENTS: 'wsk-js-ripple-effect--ignore-events',
RIPPLE_CONTAINER: 'wsk-checkbox__ripple-container',
RIPPLE_CENTER: 'wsk-ripple--center',
RIPPLE: 'wsk-ripple',
IS_FOCUSED: 'is-focused',
IS_DISABLED: 'is-disabled',
IS_CHECKED: 'is-checked'
IS_CHECKED: 'is-checked',
IS_UPGRADED: 'is-upgraded'
};
/**
* Handle change of state.
* @param {Event} event The event that fired.
@ -77,7 +56,6 @@ MaterialCheckbox.prototype.onChange_ = function(event) {
this.updateClasses_(this.btnElement_, this.element_);
};
/**
* Handle focus of element.
* @param {Event} event The event that fired.
@ -89,7 +67,6 @@ MaterialCheckbox.prototype.onFocus_ = function(event) {
this.element_.classList.add(this.CssClasses_.IS_FOCUSED);
};
/**
* Handle lost focus of element.
* @param {Event} event The event that fired.
@ -101,7 +78,6 @@ MaterialCheckbox.prototype.onBlur_ = function(event) {
this.element_.classList.remove(this.CssClasses_.IS_FOCUSED);
};
/**
* Handle mouseup.
* @param {Event} event The event that fired.
@ -113,7 +89,6 @@ MaterialCheckbox.prototype.onMouseUp_ = function(event) {
this.blur_();
};
/**
* Handle class updates.
* @param {HTMLElement} button The button whose classes we should update.
@ -136,7 +111,6 @@ MaterialCheckbox.prototype.updateClasses_ = function(button, label) {
}
};
/**
* Add blur.
* @private
@ -151,7 +125,6 @@ MaterialCheckbox.prototype.blur_ = function(event) {
}.bind(this), this.Constant_.TINY_TIMEOUT);
};
/**
* Initialize element.
*/
@ -160,76 +133,48 @@ MaterialCheckbox.prototype.init = function() {
if (this.element_) {
this.btnElement_ = this.element_.querySelector('.' +
this.CssClasses_.WSK_CHECKBOX_INPUT);
this.CssClasses_.INPUT);
var boxOutline = document.createElement('span');
boxOutline.classList.add(this.CssClasses_.WSK_CHECKBOX_BOX_OUTLINE);
boxOutline.classList.add(this.CssClasses_.BOX_OUTLINE);
var tickContainer = document.createElement('span');
tickContainer.classList.add(this.CssClasses_.WSK_CHECKBOX_FOCUS_HELPER);
tickContainer.classList.add(this.CssClasses_.FOCUS_HELPER);
var tickOutline = document.createElement('span');
tickOutline.classList.add(this.CssClasses_.WSK_CHECKBOX_TICK_OUTLINE);
var bottomRight = document.createElement('span');
bottomRight.classList.add(this.CssClasses_.WSK_CHECKBOX_BOT_RIGHT);
var bottomLeft = document.createElement('span');
bottomLeft.classList.add(this.CssClasses_.WSK_CHECKBOX_BOT_LEFT);
var bottom = document.createElement('span');
bottom.classList.add(this.CssClasses_.WSK_CHECKBOX_BOTTOM);
var topLeft = document.createElement('span');
topLeft.classList.add(this.CssClasses_.WSK_CHECKBOX_TOP_LEFT);
var topRight = document.createElement('span');
topRight.classList.add(this.CssClasses_.WSK_CHECKBOX_TOP_RIGHT);
tickOutline.classList.add(this.CssClasses_.TICK_OUTLINE);
boxOutline.appendChild(tickOutline);
boxOutline.appendChild(topLeft);
boxOutline.appendChild(topRight);
boxOutline.appendChild(bottomRight);
boxOutline.appendChild(bottomLeft);
boxOutline.appendChild(bottom);
this.element_.appendChild(tickContainer);
this.element_.appendChild(boxOutline);
var rippleContainer;
if (this.element_.classList.contains(
this.CssClasses_.WSK_JS_RIPPLE_EFFECT)) {
this.element_.classList.add(
this.CssClasses_.WSK_JS_RIPPLE_EFFECT_IGNORE_EVENTS);
if (this.element_.classList.contains(this.CssClasses_.RIPPLE_EFFECT)) {
this.element_.classList.add(this.CssClasses_.RIPPLE_IGNORE_EVENTS);
rippleContainer = document.createElement('span');
rippleContainer.classList.add(
this.CssClasses_.WSK_CHECKBOX_RIPPLE_CONTAINER);
rippleContainer.classList.add(this.CssClasses_.WSK_JS_RIPPLE_EFFECT);
rippleContainer.classList.add(this.CssClasses_.WSK_RIPPLE_CENTER);
rippleContainer.classList.add(this.CssClasses_.RIPPLE_CONTAINER);
rippleContainer.classList.add(this.CssClasses_.RIPPLE_EFFECT);
rippleContainer.classList.add(this.CssClasses_.RIPPLE_CENTER);
var ripple = document.createElement('span');
ripple.classList.add(this.CssClasses_.WSK_RIPPLE);
ripple.classList.add(this.CssClasses_.RIPPLE);
rippleContainer.appendChild(ripple);
this.element_.appendChild(rippleContainer);
}
this.btnElement_.addEventListener('change', this.onChange_.bind(this));
this.btnElement_.addEventListener('focus', this.onFocus_.bind(this));
this.btnElement_.addEventListener('blur', this.onBlur_.bind(this));
this.element_.addEventListener('mouseup', this.onMouseUp_.bind(this));
rippleContainer.addEventListener('mouseup', this.onMouseUp_.bind(this));
this.updateClasses_(this.btnElement_, this.element_);
this.element_.classList.add('is-upgraded');
this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
}
};
// The component registers itself. It can assume componentHandler is available
// in the global scope.
componentHandler.register({

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
viewBox="0 0 1 1"
preserveAspectRatio="xMinYMin meet">
<defs>
<clipPath id="clip">
<path
d="M 0,0 0,1 1,1 1,0 0,0 z M 0.8534375,0.1671875 0.9596875,0.273125 0.429375,0.8034375 0.323125,0.9096875 0.2171875,0.8034375 0.0403125,0.626875 0.1465625,0.520625 0.323125,0.6975 0.8534375,0.1671875 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
</clipPath>
<mask id="mask" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<path
d="M 0,0 0,1 1,1 1,0 0,0 z M 0.8534375,0.1671875 0.9596875,0.273125 0.429375,0.8034375 0.323125,0.9096875 0.2171875,0.8034375 0.0403125,0.626875 0.1465625,0.520625 0.323125,0.6975 0.8534375,0.1671875 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
</mask>
</defs>
<rect
width="1"
height="1"
x="0"
y="0"
clip-path="url(#clip)"
style="fill:#000000;fill-opacity:1;stroke:none" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
viewBox="0 0 1 1"
preserveAspectRatio="xMinYMin meet">
<path
d="M 0.04038059,0.6267767 0.14644661,0.52071068 0.42928932,0.80355339 0.3232233,0.90961941 z M 0.21715729,0.80355339 0.85355339,0.16715729 0.95961941,0.2732233 0.3232233,0.90961941 z"
id="rect3780"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
</svg>

After

Width:  |  Height:  |  Size: 648 B