Skip to content

Commit 6367b16

Browse files
committed
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
1 parent 3504664 commit 6367b16

File tree

7 files changed

+172
-79
lines changed

7 files changed

+172
-79
lines changed

src/button/ux-button-theme.css

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -108,63 +108,3 @@ styles.button.fab:focus {
108108
box-shadow: ${$design.elevationFocus};
109109
transition-delay: 0s;
110110
}
111-
112-
.paper-ripple {
113-
display: block;
114-
position: absolute;
115-
top: 0;
116-
left: 0;
117-
right: 0;
118-
bottom: 0;
119-
border-radius: inherit;
120-
overflow: hidden;
121-
pointer-events: none;
122-
}
123-
124-
.paper-ripple .paper-ripple__background,
125-
.paper-ripple .paper-ripple__waves,
126-
.paper-ripple .paper-ripple__wave-container,
127-
.paper-ripple .paper-ripple__wave {
128-
pointer-events: none;
129-
position: absolute;
130-
top: 0;
131-
left: 0;
132-
width: 100%;
133-
height: 100%;
134-
}
135-
136-
.paper-ripple .paper-ripple__background,
137-
.paper-ripple .paper-ripple__wave {
138-
opacity: 0;
139-
}
140-
141-
.paper-ripple .paper-ripple__waves,
142-
.paper-ripple .paper-ripple__wave {
143-
overflow: hidden;
144-
}
145-
146-
.paper-ripple .paper-ripple__wave-container,
147-
.paper-ripple .paper-ripple__wave {
148-
border-radius: 50%;
149-
}
150-
151-
.paper-ripple .paper-ripple__background {
152-
will-change: opacity, background-color;
153-
}
154-
155-
.paper-ripple .paper-ripple__wave {
156-
will-change: opacity, transform;
157-
}
158-
159-
.paper-ripple .paper-ripple__wave-container {
160-
will-change: transform;
161-
}
162-
163-
.paper-ripple--round .paper-ripple__background,
164-
.paper-ripple--round .paper-ripple__waves {
165-
border-radius: 50%;
166-
}
167-
168-
.paper-ripple--round .paper-ripple__wave-container {
169-
overflow: hidden;
170-
}

src/button/ux-button.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<template role="button">
2+
<require from="../effects/paper-ripple.css"></require>
23
<require from="./ux-button-theme"></require>
34

45
<button ref="button" styles.button class="

src/checkbox/ux-checkbox-theme.css

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,41 @@ styles.checkbox {
33
align-items: center;
44
margin: auto;
55
cursor: pointer;
6+
outline: none;
67
}
78

8-
styles.checkbox>.box {
9+
styles.checkbox>.checkbox {
910
width: 20px;
1011
height: 20px;
1112
border: ${border || $swatches.grey.p700} solid 2px;
1213
border-radius: 3px;
1314
}
1415

15-
styles.checkbox>.box+label:not(:empty) {
16+
styles.checkbox>.checkbox+label:not(:empty) {
1617
margin-left: 8px;
1718
}
1819

19-
styles.checkbox>.box:hover {
20+
styles.checkbox>.checkbox:hover {
2021
width: 20px;
2122
height: 20px;
2223
border: ${background || $design.accent} solid 2px;
2324
border-radius: 3px;
2425
}
2526

26-
styles.checkbox.checked>.box {
27+
styles.checkbox.checked>.checkbox {
2728
background-color: ${background || $design.accent};
2829
border: ${background || $design.accent} solid 2px;
2930
}
3031

31-
styles.checkbox>.box>.background-box {
32+
styles.checkbox>.checkbox>.background-box {
3233
width: 100%;
3334
height: 100%;
3435
transform: scale3d(0, 0, 0);
3536
border-radius: 50%;
3637
transition: 100ms;
3738
}
3839

39-
styles.checkbox>.box>.background-box::after {
40+
styles.checkbox>.checkbox>.background-box::after {
4041
margin: auto;
4142
display: block;
4243
width: 6px;
@@ -50,7 +51,7 @@ styles.checkbox>.box>.background-box::after {
5051
content: ' ';
5152
}
5253

53-
styles.checkbox.checked>.box>.background-box {
54+
styles.checkbox.checked>.checkbox>.background-box {
5455
transform: scale3d(1, 1, 1);
5556
border-radius: 0;
5657
}
@@ -61,19 +62,52 @@ styles.checkbox[disabled="true"] {
6162
cursor: default;
6263
}
6364

64-
styles.checkbox[disabled=""]>.box:hover,
65-
styles.checkbox[disabled="true"]>.box:hover {
65+
styles.checkbox[disabled=""]>.checkbox:hover,
66+
styles.checkbox[disabled="true"]>.checkbox:hover {
6667
border: ${disabledBorder || $swatches.grey.p400} solid 2px;
6768
border-radius: 3px;
6869
}
6970

70-
styles.checkbox.checked[disabled=""]>.box,
71-
styles.checkbox.checked[disabled="true"]>.box {
71+
styles.checkbox.checked[disabled=""]>.checkbox,
72+
styles.checkbox.checked[disabled="true"]>.checkbox {
7273
background-color: ${disabledBackground || $swatches.grey.p500};
7374
border: ${disabledBackground || $swatches.grey.p500} solid 2px;
7475
}
7576

76-
styles.checkbox[disabled=""]>.box>.background-box::after,
77-
styles.checkbox[disabled="true"]>.box>.background-box::after {
77+
styles.checkbox[disabled=""]>.checkbox>.background-box::after,
78+
styles.checkbox[disabled="true"]>.checkbox>.background-box::after {
7879
border-color: ${disabledForeground || $swatches.white};
7980
}
81+
82+
styles.checkbox .ripplecontainer {
83+
position: relative;
84+
width: 0;
85+
height: 0
86+
}
87+
88+
styles.checkbox .ripplecontainer>.paper-ripple {
89+
top: auto;
90+
left: auto;
91+
right: -35px;
92+
bottom: -25px;
93+
width: 50px;
94+
height: 50px;
95+
border-radius: 50%;
96+
}
97+
98+
.ripplecontainer>.ripple {
99+
position: absolute;
100+
right: -35px;
101+
bottom: -25px;
102+
width: 50px;
103+
height: 50px;
104+
border-radius: 50%;
105+
pointer-events: none;
106+
background-color: rgba(0, 0, 0, 0.22);
107+
transition: transform 100ms ease-in-out;
108+
transform:scale3d(0, 0, 0);
109+
}
110+
111+
styles.checkbox:focus>.ripplecontainer>.ripple{
112+
transform:scale3d(1, 1, 1);
113+
}

src/checkbox/ux-checkbox-theme.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ export class UxCheckboxTheme {
1010

1111
public backgroundDisabled: string;
1212
public foregroundDisabled: string;
13+
public borderDisabled: string;
1314
}

src/checkbox/ux-checkbox.html

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
<template role="checkbox" styles.checkbox>
1+
<template styles.checkbox role="checkbox" tabindex.bind="tabindex" keyup.delegate="onKeyup($event)">
2+
<require from="../effects/paper-ripple.css"></require>
23
<require from="./ux-checkbox-theme"></require>
3-
4-
<div class="box" click.trigger="toggleCheckbox()">
5-
<div class="background-box"></div>
4+
5+
<div class="ripplecontainer">
6+
<span class="ripple"></span>
7+
</div>
8+
<div class="checkbox ${effect !== null ? effect : $uxCheckboxTheme.effect}"
9+
mousedown.trigger="onMouseDown($event)"
10+
mouseup.trigger="onMouseUp($event)"
11+
ref="checkbox">
12+
<div class="background-box"></div>
613
</div>
714

815
<!-- Leave Inline, uses :not(:empty) selector to determine margin -->

src/checkbox/ux-checkbox.ts

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { bindingMode } from 'aurelia-binding';
33
import { inject } from 'aurelia-dependency-injection';
44
import { StyleEngine } from '../styles/style-engine';
55
import { Themable } from '../styles/themable';
6+
import { PaperRipple } from '../effects/paper-ripple';
67
import { processDesignAttributes } from '../designs/design-attributes';
78

89
@inject(Element, ViewResources, StyleEngine)
@@ -13,6 +14,7 @@ export class UxCheckbox implements Themable {
1314
@bindable public effect = null;
1415
@bindable public matcher = (a: any, b: any) => a === b;
1516
@bindable public model: any;
17+
@bindable public tabindex = 0;
1618
@bindable public theme = null;
1719

1820
@bindable({ defaultBindingMode: bindingMode.twoWay })
@@ -22,8 +24,14 @@ export class UxCheckbox implements Themable {
2224
@bindable public value: any = false;
2325

2426
public view: View;
27+
private checkbox: Element;
28+
private ripple: PaperRipple | null = null;
2529

26-
constructor(public element: Element, public resources: ViewResources, private styleEngine: StyleEngine) { }
30+
public get isDisabled() {
31+
return this.disabled === true || this.disabled === '' || this.disabled === 'disabled';
32+
}
33+
34+
constructor(public element: HTMLElement, public resources: ViewResources, private styleEngine: StyleEngine) { }
2735

2836
public created(_: any, myView: View) {
2937
this.view = myView;
@@ -61,7 +69,7 @@ export class UxCheckbox implements Themable {
6169
}
6270

6371
public toggleCheckbox() {
64-
if (this.disabled === true || this.disabled === '') {
72+
if (this.isDisabled) {
6573
return;
6674
}
6775

@@ -87,4 +95,47 @@ export class UxCheckbox implements Themable {
8795
this.checked = !this.checked;
8896
}
8997
}
98+
99+
public onKeyup(e: KeyboardEvent) {
100+
const key = e.which || e.keyCode;
101+
102+
if (key === 13) {
103+
this.toggleCheckbox();
104+
}
105+
}
106+
107+
public onMouseDown(e: MouseEvent) {
108+
if (e.button !== 0 || this.isDisabled) {
109+
return;
110+
}
111+
112+
if (this.checkbox.classList.contains('ripple')) {
113+
if (this.ripple === null) {
114+
this.ripple = new PaperRipple();
115+
const container = this.element.querySelector('.ripplecontainer');
116+
117+
if (container != null) {
118+
container.appendChild(this.ripple.$);
119+
}
120+
}
121+
122+
this.ripple.center = true;
123+
this.ripple.round = true;
124+
125+
this.ripple.downAction(e);
126+
}
127+
128+
this.toggleCheckbox();
129+
e.preventDefault();
130+
}
131+
132+
public onMouseUp(e: MouseEvent) {
133+
if (e.button !== 0 || this.isDisabled) {
134+
return;
135+
}
136+
137+
if (this.checkbox.classList.contains('ripple') && this.ripple !== null) {
138+
this.ripple.upAction();
139+
}
140+
}
90141
}

src/effects/paper-ripple.css

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
.paper-ripple {
2+
display: block;
3+
position: absolute;
4+
top: 0;
5+
left: 0;
6+
right: 0;
7+
bottom: 0;
8+
border-radius: inherit;
9+
overflow: hidden;
10+
pointer-events: none;
11+
}
12+
13+
.paper-ripple .paper-ripple__background,
14+
.paper-ripple .paper-ripple__waves,
15+
.paper-ripple .paper-ripple__wave-container,
16+
.paper-ripple .paper-ripple__wave {
17+
pointer-events: none;
18+
position: absolute;
19+
top: 0;
20+
left: 0;
21+
width: 100%;
22+
height: 100%;
23+
}
24+
25+
.paper-ripple .paper-ripple__background,
26+
.paper-ripple .paper-ripple__wave {
27+
opacity: 0;
28+
}
29+
30+
.paper-ripple .paper-ripple__waves,
31+
.paper-ripple .paper-ripple__wave {
32+
overflow: hidden;
33+
}
34+
35+
.paper-ripple .paper-ripple__wave-container,
36+
.paper-ripple .paper-ripple__wave {
37+
border-radius: 50%;
38+
}
39+
40+
.paper-ripple .paper-ripple__background {
41+
will-change: opacity, background-color;
42+
}
43+
44+
.paper-ripple .paper-ripple__wave {
45+
will-change: opacity, transform;
46+
}
47+
48+
.paper-ripple .paper-ripple__wave-container {
49+
will-change: transform;
50+
}
51+
52+
.paper-ripple--round .paper-ripple__background,
53+
.paper-ripple--round .paper-ripple__waves {
54+
border-radius: 50%;
55+
}
56+
57+
.paper-ripple--round .paper-ripple__wave-container {
58+
overflow: hidden;
59+
}

0 commit comments

Comments
 (0)