Permalink
Browse files

feat(checkbox): focus state ripple and selection

add tabindex to each base element
add checking and unchecking by space and enter keys
add ripple effect
add focus effect
  • Loading branch information...
ZHollingshead committed Apr 14, 2017
1 parent 3504664 commit 6367b1631e8ccf3fb2c15cbb0430bdbaedd03af9
@@ -108,63 +108,3 @@ styles.button.fab:focus {
box-shadow: ${$design.elevationFocus};
transition-delay: 0s;
}
-
-.paper-ripple {
- display: block;
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- border-radius: inherit;
- overflow: hidden;
- pointer-events: none;
-}
-
-.paper-ripple .paper-ripple__background,
-.paper-ripple .paper-ripple__waves,
-.paper-ripple .paper-ripple__wave-container,
-.paper-ripple .paper-ripple__wave {
- pointer-events: none;
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
-}
-
-.paper-ripple .paper-ripple__background,
-.paper-ripple .paper-ripple__wave {
- opacity: 0;
-}
-
-.paper-ripple .paper-ripple__waves,
-.paper-ripple .paper-ripple__wave {
- overflow: hidden;
-}
-
-.paper-ripple .paper-ripple__wave-container,
-.paper-ripple .paper-ripple__wave {
- border-radius: 50%;
-}
-
-.paper-ripple .paper-ripple__background {
- will-change: opacity, background-color;
-}
-
-.paper-ripple .paper-ripple__wave {
- will-change: opacity, transform;
-}
-
-.paper-ripple .paper-ripple__wave-container {
- will-change: transform;
-}
-
-.paper-ripple--round .paper-ripple__background,
-.paper-ripple--round .paper-ripple__waves {
- border-radius: 50%;
-}
-
-.paper-ripple--round .paper-ripple__wave-container {
- overflow: hidden;
-}
@@ -1,4 +1,5 @@
<template role="button">
+ <require from="../effects/paper-ripple.css"></require>
<require from="./ux-button-theme"></require>
<button ref="button" styles.button class="
@@ -3,40 +3,41 @@ styles.checkbox {
align-items: center;
margin: auto;
cursor: pointer;
+ outline: none;
}
-styles.checkbox>.box {
+styles.checkbox>.checkbox {
width: 20px;
height: 20px;
border: ${border || $swatches.grey.p700} solid 2px;
border-radius: 3px;
}
-styles.checkbox>.box+label:not(:empty) {
+styles.checkbox>.checkbox+label:not(:empty) {
margin-left: 8px;
}
-styles.checkbox>.box:hover {
+styles.checkbox>.checkbox:hover {
width: 20px;
height: 20px;
border: ${background || $design.accent} solid 2px;
border-radius: 3px;
}
-styles.checkbox.checked>.box {
+styles.checkbox.checked>.checkbox {
background-color: ${background || $design.accent};
border: ${background || $design.accent} solid 2px;
}
-styles.checkbox>.box>.background-box {
+styles.checkbox>.checkbox>.background-box {
width: 100%;
height: 100%;
transform: scale3d(0, 0, 0);
border-radius: 50%;
transition: 100ms;
}
-styles.checkbox>.box>.background-box::after {
+styles.checkbox>.checkbox>.background-box::after {
margin: auto;
display: block;
width: 6px;
@@ -50,7 +51,7 @@ styles.checkbox>.box>.background-box::after {
content: ' ';
}
-styles.checkbox.checked>.box>.background-box {
+styles.checkbox.checked>.checkbox>.background-box {
transform: scale3d(1, 1, 1);
border-radius: 0;
}
@@ -61,19 +62,52 @@ styles.checkbox[disabled="true"] {
cursor: default;
}
-styles.checkbox[disabled=""]>.box:hover,
-styles.checkbox[disabled="true"]>.box:hover {
+styles.checkbox[disabled=""]>.checkbox:hover,
+styles.checkbox[disabled="true"]>.checkbox:hover {
border: ${disabledBorder || $swatches.grey.p400} solid 2px;
border-radius: 3px;
}
-styles.checkbox.checked[disabled=""]>.box,
-styles.checkbox.checked[disabled="true"]>.box {
+styles.checkbox.checked[disabled=""]>.checkbox,
+styles.checkbox.checked[disabled="true"]>.checkbox {
background-color: ${disabledBackground || $swatches.grey.p500};
border: ${disabledBackground || $swatches.grey.p500} solid 2px;
}
-styles.checkbox[disabled=""]>.box>.background-box::after,
-styles.checkbox[disabled="true"]>.box>.background-box::after {
+styles.checkbox[disabled=""]>.checkbox>.background-box::after,
+styles.checkbox[disabled="true"]>.checkbox>.background-box::after {
border-color: ${disabledForeground || $swatches.white};
}
+
+styles.checkbox .ripplecontainer {
+ position: relative;
+ width: 0;
+ height: 0
+}
+
+styles.checkbox .ripplecontainer>.paper-ripple {
+ top: auto;
+ left: auto;
+ right: -35px;
+ bottom: -25px;
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+}
+
+.ripplecontainer>.ripple {
+ position: absolute;
+ right: -35px;
+ bottom: -25px;
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ pointer-events: none;
+ background-color: rgba(0, 0, 0, 0.22);
+ transition: transform 100ms ease-in-out;
+ transform:scale3d(0, 0, 0);
+}
+
+styles.checkbox:focus>.ripplecontainer>.ripple{
+ transform:scale3d(1, 1, 1);
+}
@@ -10,4 +10,5 @@ export class UxCheckboxTheme {
public backgroundDisabled: string;
public foregroundDisabled: string;
+ public borderDisabled: string;
}
@@ -1,8 +1,15 @@
-<template role="checkbox" styles.checkbox>
+<template styles.checkbox role="checkbox" tabindex.bind="tabindex" keyup.delegate="onKeyup($event)">
+ <require from="../effects/paper-ripple.css"></require>
<require from="./ux-checkbox-theme"></require>
-
- <div class="box" click.trigger="toggleCheckbox()">
- <div class="background-box"></div>
+
+ <div class="ripplecontainer">
+ <span class="ripple"></span>
+ </div>
+ <div class="checkbox ${effect !== null ? effect : $uxCheckboxTheme.effect}"
+ mousedown.trigger="onMouseDown($event)"
+ mouseup.trigger="onMouseUp($event)"
+ ref="checkbox">
+ <div class="background-box"></div>
</div>
<!-- Leave Inline, uses :not(:empty) selector to determine margin -->
@@ -3,6 +3,7 @@ import { bindingMode } from 'aurelia-binding';
import { inject } from 'aurelia-dependency-injection';
import { StyleEngine } from '../styles/style-engine';
import { Themable } from '../styles/themable';
+import { PaperRipple } from '../effects/paper-ripple';
import { processDesignAttributes } from '../designs/design-attributes';
@inject(Element, ViewResources, StyleEngine)
@@ -13,6 +14,7 @@ export class UxCheckbox implements Themable {
@bindable public effect = null;
@bindable public matcher = (a: any, b: any) => a === b;
@bindable public model: any;
+ @bindable public tabindex = 0;
@bindable public theme = null;
@bindable({ defaultBindingMode: bindingMode.twoWay })
@@ -22,8 +24,14 @@ export class UxCheckbox implements Themable {
@bindable public value: any = false;
public view: View;
+ private checkbox: Element;
+ private ripple: PaperRipple | null = null;
- constructor(public element: Element, public resources: ViewResources, private styleEngine: StyleEngine) { }
+ public get isDisabled() {
+ return this.disabled === true || this.disabled === '' || this.disabled === 'disabled';
+ }
+
+ constructor(public element: HTMLElement, public resources: ViewResources, private styleEngine: StyleEngine) { }
public created(_: any, myView: View) {
this.view = myView;
@@ -61,7 +69,7 @@ export class UxCheckbox implements Themable {
}
public toggleCheckbox() {
- if (this.disabled === true || this.disabled === '') {
+ if (this.isDisabled) {
return;
}
@@ -87,4 +95,47 @@ export class UxCheckbox implements Themable {
this.checked = !this.checked;
}
}
+
+ public onKeyup(e: KeyboardEvent) {
+ const key = e.which || e.keyCode;
+
+ if (key === 13) {
+ this.toggleCheckbox();
+ }
+ }
+
+ public onMouseDown(e: MouseEvent) {
+ if (e.button !== 0 || this.isDisabled) {
+ return;
+ }
+
+ if (this.checkbox.classList.contains('ripple')) {
+ if (this.ripple === null) {
+ this.ripple = new PaperRipple();
+ const container = this.element.querySelector('.ripplecontainer');
+
+ if (container != null) {
+ container.appendChild(this.ripple.$);
+ }
+ }
+
+ this.ripple.center = true;
+ this.ripple.round = true;
+
+ this.ripple.downAction(e);
+ }
+
+ this.toggleCheckbox();
+ e.preventDefault();
+ }
+
+ public onMouseUp(e: MouseEvent) {
+ if (e.button !== 0 || this.isDisabled) {
+ return;
+ }
+
+ if (this.checkbox.classList.contains('ripple') && this.ripple !== null) {
+ this.ripple.upAction();
+ }
+ }
}
@@ -0,0 +1,59 @@
+.paper-ripple {
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ border-radius: inherit;
+ overflow: hidden;
+ pointer-events: none;
+}
+
+.paper-ripple .paper-ripple__background,
+.paper-ripple .paper-ripple__waves,
+.paper-ripple .paper-ripple__wave-container,
+.paper-ripple .paper-ripple__wave {
+ pointer-events: none;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.paper-ripple .paper-ripple__background,
+.paper-ripple .paper-ripple__wave {
+ opacity: 0;
+}
+
+.paper-ripple .paper-ripple__waves,
+.paper-ripple .paper-ripple__wave {
+ overflow: hidden;
+}
+
+.paper-ripple .paper-ripple__wave-container,
+.paper-ripple .paper-ripple__wave {
+ border-radius: 50%;
+}
+
+.paper-ripple .paper-ripple__background {
+ will-change: opacity, background-color;
+}
+
+.paper-ripple .paper-ripple__wave {
+ will-change: opacity, transform;
+}
+
+.paper-ripple .paper-ripple__wave-container {
+ will-change: transform;
+}
+
+.paper-ripple--round .paper-ripple__background,
+.paper-ripple--round .paper-ripple__waves {
+ border-radius: 50%;
+}
+
+.paper-ripple--round .paper-ripple__wave-container {
+ overflow: hidden;
+}

0 comments on commit 6367b16

Please sign in to comment.