Skip to content

Commit affe21c

Browse files
authored
feat(spinner): Created spinner component (#115)
* feat(spinner): Created spinner component and introduced a index.scss to include all component styles * Fixed spinner color
1 parent e694a1d commit affe21c

File tree

8 files changed

+243
-14
lines changed

8 files changed

+243
-14
lines changed

demo/index.scss

+1-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@ $use-embedded-font: true;
22
$schema: 'water-blue';
33

44
@import "~wholesale-styleguide-scss/index";
5-
@import "../src/ws-header/ws-header";
6-
@import "../src/ws-date-picker/ws-date-picker";
7-
@import "../src/ws-inline-edit/ws-inline-edit";
8-
@import "../src/ws-week-picker/ws-week-picker";
9-
@import "../src/ws-notification/ws-notification";
10-
@import "../src/ws-tiles-chart/ws-tiles-chart";
5+
@import "../src/index";
116

127
.container {
138
margin: 20px;

doc/components/spinner.md

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Spinner
2+
3+
The spinner should be shown on every user interaction where the response could take longer than 250ms.
4+
By default the spinner has the size medium with 32x32 pixel but it can be made small with 16x16 pixel or big with 48x48 pixel.
5+
To do this just set the attribute `size` with `small` or `large`.
6+
7+
<div class="row">
8+
<div class="column small-5">
9+
<ws-spinner size="large"></ws-spinner>
10+
</div>
11+
<div class="column small-5">
12+
<ws-spinner></ws-spinner>
13+
</div>
14+
<div class="column small-5 end">
15+
<ws-spinner size="small"></ws-spinner>
16+
</div>
17+
</div>
18+
```html
19+
<div class="row">
20+
<div class="column small-5">
21+
<ws-spinner size="large"></ws-spinner>
22+
</div>
23+
<div class="column small-5">
24+
<ws-spinner></ws-spinner>
25+
</div>
26+
<div class="column small-5 end">
27+
<ws-spinner size="small"></ws-spinner>
28+
</div>
29+
</div>
30+
```
31+
32+
The spinner color will be the primary color.
33+
If you want to display a spinner for instance on a button you have to change the color to white by adding
34+
the boolean attribute `is-white`.
35+
36+
<button class="mod-small">
37+
<span>Click Me</span>&nbsp;
38+
<ws-spinner size="small" is-white></ws-spinner>
39+
</button>
40+
```html
41+
<button>
42+
<span>Click Me</span>
43+
<ws-spinner size="small" is-white></ws-spinner>
44+
</button>
45+
```

src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ export {WSInlineEdit} from './ws-inline-edit/ws-inline-edit';
2020
export {WSNotification} from './ws-notification/ws-notification';
2121
export {WSWeekPicker} from './ws-week-picker/ws-week-picker';
2222
export {WSTilesChart} from './ws-tiles-chart/ws-tiles-chart';
23+
export {WSSpinner} from './ws-spinner/ws-spinner';

src/index.scss

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@import "ws-date-picker/ws-date-picker";
2+
@import "ws-header/ws-header";
3+
@import "ws-inline-edit/ws-inline-edit";
4+
@import "ws-notification/ws-notification";
5+
@import "ws-spinner/ws-spinner";
6+
@import "ws-tiles-chart/ws-tiles-chart";
7+
@import "ws-week-picker/ws-week-picker";

src/ws-spinner/ws-spinner.js

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {React, Component, PropTypes} from '../imports';
2+
3+
/**
4+
* Renders a simple spinner with the primary color
5+
* @property {string} size One of small, medium, large. Default to medium
6+
* @property {boolean} isWhite True if the spinner color should be white
7+
*/
8+
export class WSSpinner extends Component {
9+
10+
/**
11+
* @type {Object}
12+
*/
13+
static propTypes = {
14+
size: PropTypes.oneOf(['small', 'medium', 'large']),
15+
isWhite: PropTypes.bool
16+
};
17+
18+
/**
19+
* @type {Object}
20+
*/
21+
static defaultProps = {
22+
size: 'medium',
23+
isWhite: false
24+
};
25+
26+
/**
27+
* @returns {XML}
28+
*/
29+
render() {
30+
return (
31+
<div className={`spinner mod-${this.props.size} ${this.props.isWhite ? 'mod-white' : ''}`}>
32+
<div className="spinner-layer">
33+
<div className="circle-clipper left">
34+
<div className="circle" />
35+
</div>
36+
<div className="circle-clipper right">
37+
<div className="circle" />
38+
</div>
39+
</div>
40+
</div>
41+
);
42+
}
43+
}

src/ws-spinner/ws-spinner.scss

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
$include-spinner-css: true !default;
2+
$spinner-color: schema-color(4) !default;
3+
$spinner-size-small: $base-font-size !default;
4+
$spinner-size-medium: $space-xl !default;
5+
$spinner-size-large: $space-xxl !default;
6+
7+
8+
.spinner {
9+
display: inline-block;
10+
vertical-align: sub;
11+
position: relative;
12+
width: $spinner-size-medium;
13+
height: $spinner-size-medium;
14+
/* duration: 360 * ARCTIME / (ARCSTARTROT + (360-ARCSIZE)) */
15+
-webkit-animation: container-rotate 1568ms linear infinite;
16+
animation: container-rotate 1568ms linear infinite;
17+
&.mod-small {
18+
width: $spinner-size-small;
19+
height: $spinner-size-small;
20+
.spinner-layer .circle-clipper .circle {
21+
border-width: 1px;
22+
}
23+
}
24+
&.mod-large {
25+
width: $spinner-size-large;
26+
height: $spinner-size-large;
27+
.spinner-layer .circle-clipper .circle {
28+
border-width: 3px;
29+
}
30+
}
31+
&.mod-white {
32+
.spinner-layer {
33+
border-color: $white;
34+
}
35+
}
36+
.spinner-layer {
37+
position: absolute;
38+
width: 100%;
39+
height: 100%;
40+
border-color: $spinner-color;
41+
opacity: 1;
42+
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
43+
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
44+
.circle-clipper {
45+
display: inline-block;
46+
position: relative;
47+
width: 50%;
48+
height: 100%;
49+
overflow: hidden;
50+
border-color: inherit;
51+
.circle {
52+
width: 200%;
53+
height: 100%;
54+
border-width: 2px;
55+
border-style: solid;
56+
border-color: inherit;
57+
border-bottom-color: transparent !important;
58+
border-radius: 50%;
59+
-webkit-animation: none;
60+
animation: none;
61+
position: absolute;
62+
top: 0;
63+
right: 0;
64+
bottom: 0;
65+
}
66+
&.left {
67+
float: left;
68+
.circle {
69+
left: 0;
70+
border-right-color: transparent !important;
71+
-webkit-transform: rotate(129deg);
72+
transform: rotate(129deg);
73+
-webkit-animation: left-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
74+
animation: left-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
75+
}
76+
}
77+
&.right {
78+
float: right;
79+
.circle {
80+
left: -100%;
81+
border-left-color: transparent !important;
82+
-webkit-transform: rotate(-129deg);
83+
transform: rotate(-129deg);
84+
-webkit-animation: right-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
85+
animation: right-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
86+
}
87+
}
88+
}
89+
}
90+
}
91+
92+
@-webkit-keyframes container-rotate {
93+
to { -webkit-transform: rotate(360deg) }
94+
}
95+
96+
@keyframes container-rotate {
97+
to { transform: rotate(360deg) }
98+
}
99+
100+
@-webkit-keyframes fill-unfill-rotate {
101+
12.5% { -webkit-transform: rotate(135deg); } /* 0.5 * ARCSIZE */
102+
25% { -webkit-transform: rotate(270deg); } /* 1 * ARCSIZE */
103+
37.5% { -webkit-transform: rotate(405deg); } /* 1.5 * ARCSIZE */
104+
50% { -webkit-transform: rotate(540deg); } /* 2 * ARCSIZE */
105+
62.5% { -webkit-transform: rotate(675deg); } /* 2.5 * ARCSIZE */
106+
75% { -webkit-transform: rotate(810deg); } /* 3 * ARCSIZE */
107+
87.5% { -webkit-transform: rotate(945deg); } /* 3.5 * ARCSIZE */
108+
to { -webkit-transform: rotate(1080deg); } /* 4 * ARCSIZE */
109+
}
110+
111+
@keyframes fill-unfill-rotate {
112+
12.5% { transform: rotate(135deg); } /* 0.5 * ARCSIZE */
113+
25% { transform: rotate(270deg); } /* 1 * ARCSIZE */
114+
37.5% { transform: rotate(405deg); } /* 1.5 * ARCSIZE */
115+
50% { transform: rotate(540deg); } /* 2 * ARCSIZE */
116+
62.5% { transform: rotate(675deg); } /* 2.5 * ARCSIZE */
117+
75% { transform: rotate(810deg); } /* 3 * ARCSIZE */
118+
87.5% { transform: rotate(945deg); } /* 3.5 * ARCSIZE */
119+
to { transform: rotate(1080deg); } /* 4 * ARCSIZE */
120+
}
121+
122+
@-webkit-keyframes left-spin {
123+
from { -webkit-transform: rotate(130deg); }
124+
50% { -webkit-transform: rotate(-5deg); }
125+
to { -webkit-transform: rotate(130deg); }
126+
}
127+
128+
@keyframes left-spin {
129+
from { transform: rotate(130deg); }
130+
50% { transform: rotate(-5deg); }
131+
to { transform: rotate(130deg); }
132+
}
133+
134+
@-webkit-keyframes right-spin {
135+
from { -webkit-transform: rotate(-130deg); }
136+
50% { -webkit-transform: rotate(5deg); }
137+
to { -webkit-transform: rotate(-130deg); }
138+
}
139+
140+
@keyframes right-spin {
141+
from { transform: rotate(-130deg); }
142+
50% { transform: rotate(5deg); }
143+
to { transform: rotate(-130deg); }
144+
}

src/ws-week-picker/ws-week-picker.scss

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
@import "~wholesale-styleguide-scss/utils/variables";
2-
31
$padding: $space-m;
2+
43
// to allow padding with setting a transparent border
54
@mixin table-padding ($top, $right, $bottom, $left) {
65
@if $top != 0 {

tests/index.scss

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
$use-embedded-font: true;
22

33
@import "~wholesale-styleguide-scss/index";
4-
@import "../src/ws-header/ws-header";
5-
@import "../src/ws-date-picker/ws-date-picker";
6-
@import "../src/ws-inline-edit/ws-inline-edit";
7-
@import "../src/ws-week-picker/ws-week-picker";
8-
@import "../src/ws-notification/ws-notification";
9-
@import "../src/ws-tiles-chart/ws-tiles-chart";
4+
@import "../src/index";
105

116
.container {
127
margin: 20px;

0 commit comments

Comments
 (0)