Merged
commit
8114e9e93b
|
@ -1,3 +1,8 @@
|
|||
// -- TODO
|
||||
// · Highlight coincidences
|
||||
// · Support templates as the dropdown component
|
||||
// · Inline autocomplete
|
||||
|
||||
/* global React */
|
||||
|
||||
import { addons } from 'react/addons';
|
||||
|
@ -207,6 +212,7 @@ export default React.createClass({
|
|||
{...this.props}
|
||||
label=''
|
||||
value=''
|
||||
className={style.input}
|
||||
onBlur={this.handleBlur}
|
||||
onChange={this.handleQueryChange}
|
||||
onFocus={this.handleFocus}
|
||||
|
|
|
@ -65,3 +65,7 @@ $autocomplete-suggestion-color-active: unquote("rgb(#{$palette-grey-200})");
|
|||
background-color: $autocomplete-suggestion-color-active;
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
|
|
@ -53,14 +53,16 @@ export default React.createClass({
|
|||
},
|
||||
|
||||
render () {
|
||||
let labelClassName = style[this.props.disabled ? 'disabled' : 'field'];
|
||||
let checkboxClassName = style[this.state.checked ? 'checked' : 'check'];
|
||||
if (this.props.className) labelClassName += ` ${this.props.className}`;
|
||||
let fieldClassName = style.field;
|
||||
let checkboxClassName = style.check;
|
||||
if (this.props.disabled) fieldClassName += ` ${style.disabled}`;
|
||||
if (this.props.className) fieldClassName += ` ${this.props.className}`;
|
||||
if (this.state.checked) checkboxClassName += ` ${style.checked}`;
|
||||
|
||||
return (
|
||||
<label
|
||||
data-react-toolbox='checkbox'
|
||||
className={labelClassName}
|
||||
className={fieldClassName}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
<input
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@import "../variables";
|
||||
|
||||
$checkbox-total-height: 1.8 * $unit;
|
||||
$checkbox-size: 1.8 * $unit;
|
||||
$checkbox-transition-duration: .2s;
|
||||
|
@ -34,8 +35,8 @@ $checked-focus-color: unquote("rgba(#{$color-primary}, 0.26)") !default;
|
|||
overflow: hidden;
|
||||
opacity: 0;
|
||||
|
||||
&:focus:not(&:active) {
|
||||
+ .check:before {
|
||||
&:focus:not(&:active) + .check {
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
|
@ -50,7 +51,7 @@ $checked-focus-color: unquote("rgba(#{$color-primary}, 0.26)") !default;
|
|||
border-radius: 50%;
|
||||
}
|
||||
|
||||
+ .checked:before {
|
||||
&.checked:before {
|
||||
background-color: $checked-focus-color;
|
||||
}
|
||||
}
|
||||
|
@ -63,33 +64,34 @@ $checked-focus-color: unquote("rgba(#{$color-primary}, 0.26)") !default;
|
|||
height: $checkbox-size;
|
||||
vertical-align: top;
|
||||
cursor: pointer;
|
||||
border: 2px solid $checkbox-text-color;
|
||||
border-color: $checkbox-text-color;
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-radius: 2px;
|
||||
transition-timing-function: $animation-curve-default;
|
||||
transition-duration: $checkbox-transition-duration;
|
||||
transition-property: background-color;
|
||||
}
|
||||
|
||||
.checked {
|
||||
@extend .check;
|
||||
background-color: $checkbox-color;
|
||||
border-color: $checkbox-color;
|
||||
&.checked {
|
||||
background-color: $checkbox-color;
|
||||
border-color: $checkbox-color;
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
top: -.1 * $unit;
|
||||
left: .4 * $unit;
|
||||
width: .7 * $unit;
|
||||
height: 1.2 * $unit;
|
||||
content: "";
|
||||
border-color: #fff;
|
||||
border-style: solid;
|
||||
border-top: 0;
|
||||
border-right-width: 2px;
|
||||
border-bottom-width: 2px;
|
||||
border-left: 0;
|
||||
transform: rotate(45deg);
|
||||
animation: checkmark-expand 140ms ease-out forwards;
|
||||
&:after {
|
||||
position: absolute;
|
||||
top: -.1 * $unit;
|
||||
left: .4 * $unit;
|
||||
width: .7 * $unit;
|
||||
height: 1.2 * $unit;
|
||||
content: "";
|
||||
border-color: #fff;
|
||||
border-style: solid;
|
||||
border-top: 0;
|
||||
border-right-width: 2px;
|
||||
border-bottom-width: 2px;
|
||||
border-left: 0;
|
||||
transform: rotate(45deg);
|
||||
animation: checkmark-expand 140ms ease-out forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,21 +102,19 @@ $checked-focus-color: unquote("rgba(#{$color-primary}, 0.26)") !default;
|
|||
}
|
||||
|
||||
.disabled {
|
||||
@extend .field;
|
||||
|
||||
.text {
|
||||
> .text {
|
||||
color: $checkbox-disabled-color;
|
||||
}
|
||||
|
||||
.check {
|
||||
> .check {
|
||||
cursor: auto;
|
||||
border-color: $checkbox-disabled-color;
|
||||
}
|
||||
|
||||
.checked {
|
||||
cursor: auto;
|
||||
background-color: $checkbox-disabled-color;
|
||||
border-color: transparent;
|
||||
&.checked {
|
||||
cursor: auto;
|
||||
background-color: $checkbox-disabled-color;
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
// -- TODO
|
||||
// · Add support for icons
|
||||
// · Add a char counter
|
||||
// · Make textfield to grow as content grows
|
||||
|
||||
/* global React */
|
||||
|
||||
import { addons } from 'react/addons';
|
||||
import style from './style';
|
||||
import style from './style.scss';
|
||||
|
||||
export default React.createClass({
|
||||
mixins: [addons.PureRenderMixin],
|
||||
|
@ -12,6 +17,7 @@ export default React.createClass({
|
|||
className: React.PropTypes.string,
|
||||
disabled: React.PropTypes.bool,
|
||||
error: React.PropTypes.string,
|
||||
floating: React.PropTypes.bool,
|
||||
label: React.PropTypes.string,
|
||||
multiline: React.PropTypes.bool,
|
||||
onBlur: React.PropTypes.func,
|
||||
|
@ -27,6 +33,7 @@ export default React.createClass({
|
|||
return {
|
||||
className: '',
|
||||
disabled: false,
|
||||
floating: true,
|
||||
multiline: false,
|
||||
required: false,
|
||||
type: 'text'
|
||||
|
@ -34,93 +41,55 @@ export default React.createClass({
|
|||
},
|
||||
|
||||
getInitialState () {
|
||||
return {
|
||||
checked: this.props.value,
|
||||
error: this.props.error,
|
||||
touch: ['checkbox', 'radio'].indexOf(this.props.type) !== -1,
|
||||
value: this.props.value,
|
||||
focus: false,
|
||||
valid: false
|
||||
};
|
||||
},
|
||||
|
||||
onBlur (event) {
|
||||
this.setState({focus: false});
|
||||
if (this.props.onBlur) this.props.onBlur(event, this);
|
||||
return { value: this.props.value };
|
||||
},
|
||||
|
||||
onChange (event) {
|
||||
if (this.state.touch) {
|
||||
this.setState({checked: event.target.checked, error: undefined});
|
||||
} else {
|
||||
this.setState({value: event.target.value, error: undefined});
|
||||
}
|
||||
if (this.props.onChange) this.props.onChange(event, this);
|
||||
},
|
||||
|
||||
onFocus (event) {
|
||||
this.setState({focus: true});
|
||||
if (this.props.onFocus) this.props.onFocus(event, this);
|
||||
},
|
||||
|
||||
onKeyPress (event) {
|
||||
this.setState({focus: true});
|
||||
if (this.props.onKeyPress) this.props.onKeyPress(event, this);
|
||||
this.setState({value: event.target.value}, () => {
|
||||
if (this.props.onChange) this.props.onChange(event, this);
|
||||
});
|
||||
},
|
||||
|
||||
renderInput () {
|
||||
let className = style.input;
|
||||
if (this.state.value && this.state.value.length > 0) className += ` ${style.filled}`;
|
||||
|
||||
if (this.props.multiline) {
|
||||
return (
|
||||
<textarea
|
||||
ref='input'
|
||||
{...this.props}
|
||||
className={className}
|
||||
onChange={this.onChange}
|
||||
onKeyPress={this.onKeyPress}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
value={this.state.value} />
|
||||
);
|
||||
} else if (this.props.type === 'file') {
|
||||
return (
|
||||
<input
|
||||
ref='input'
|
||||
{...this.props}
|
||||
value={undefined}
|
||||
onChange={this.onChange} />
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<input
|
||||
ref='input'
|
||||
{...this.props}
|
||||
className={className}
|
||||
value={this.state.value}
|
||||
checked={this.state.checked}
|
||||
onBlur={this.onBlur}
|
||||
onChange={this.onChange}
|
||||
onFocus={this.onFocus}
|
||||
onKeyPress={this.onKeyPress} />
|
||||
onChange={this.onChange} />
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
render () {
|
||||
let className = `${style.root} ${this.props.className}`;
|
||||
if (this.props.type) className += ` ${this.props.type}`;
|
||||
if (this.state.checked) className += ' checked';
|
||||
if (this.props.disabled) className += ' disabled';
|
||||
if (this.state.error) className += ' error';
|
||||
if (this.state.focus) className += ' focus';
|
||||
if (this.props.type === 'hidden') className += ' hidden';
|
||||
if (this.state.touch) className += ' touch';
|
||||
if (this.props.type === 'radio') className += ' radio';
|
||||
if (this.state.value && this.state.value.length > 0) className += ' valid';
|
||||
let className = style.root;
|
||||
let labelClassName = style.label;
|
||||
if (this.props.error) className += ` ${style.errored}`;
|
||||
if (this.props.disabled) className += ` ${style.disabled}`;
|
||||
if (this.props.className) className += ` ${this.props.className}`;
|
||||
if (this.props.type === 'hidden') className += ` ${style.hidden}`;
|
||||
if (!this.props.floating) labelClassName += ` ${style.fixed}`;
|
||||
|
||||
return (
|
||||
<div data-react-toolbox='input' className={className}>
|
||||
{ this.renderInput() }
|
||||
<span className='bar'></span>
|
||||
{ this.props.label ? <label>{this.props.label}</label> : null }
|
||||
{ this.state.error ? <span className='error'>{this.state.error}</span> : null }
|
||||
<span className={style.bar}></span>
|
||||
{ this.props.label ? <label className={labelClassName}>{this.props.label}</label> : null }
|
||||
{ this.props.error ? <span className={style.error}>{this.props.error}</span> : null }
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@ -134,21 +103,10 @@ export default React.createClass({
|
|||
},
|
||||
|
||||
getValue () {
|
||||
if (this.props.type === 'file') {
|
||||
return this.state.value;
|
||||
} else if (this.refs.input) {
|
||||
return this.refs.input.getDOMNode()[this.state.touch ? 'checked' : 'value'];
|
||||
}
|
||||
return this.state.value;
|
||||
},
|
||||
|
||||
setError (data = 'Unknown error') {
|
||||
this.setState({error: this.props.error || data});
|
||||
},
|
||||
|
||||
setValue (argData) {
|
||||
let data = this.state.touch && argData === undefined ? false : argData;
|
||||
let attributes = { value: data };
|
||||
if (this.state.touch && data) attributes.checked = data;
|
||||
this.setState(attributes);
|
||||
setValue (value) {
|
||||
this.setState({value: value});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
@import "../variables";
|
||||
@import "../mixins";
|
||||
|
||||
$input-padding: 2 * $unit;
|
||||
$input-field-height: 1.6 * $unit;
|
||||
$input-field-padding: .8 * $unit;
|
||||
$input-field-font-size: 1.6 * $unit;
|
||||
$input-label-font-size: 1.2 * $unit;
|
||||
$input-focus-label-top: .6 * $unit;
|
||||
$input-text-background-color: transparent !default;
|
||||
$input-text-label-color: unquote("rgba(#{$color-black}, 0.26)") !default;
|
||||
$input-text-bottom-border-color: unquote("rgba(#{$color-black}, 0.12)") !default;
|
||||
$input-text-highlight-color: unquote("rgb(#{$color-primary})") !default;
|
||||
$input-text-disabled-color: $input-text-bottom-border-color !default;
|
||||
$input-text-disabled-text-color: $input-text-label-color !default;
|
||||
$input-text-error-color: unquote("rgb(222, 50, 38)") !default;
|
||||
|
||||
.root {
|
||||
position: relative;
|
||||
padding: $input-padding 0;
|
||||
}
|
||||
|
||||
.input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: $input-field-padding 0;
|
||||
font-size: $input-field-font-size;
|
||||
color: $color-text;
|
||||
background-color: $input-text-background-color;
|
||||
border: 0;
|
||||
border-bottom: 1px solid $input-text-bottom-border-color;
|
||||
outline: none;
|
||||
|
||||
&:focus {
|
||||
~ .bar:before, ~ .bar:after {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
~ .label:not(.fixed) {
|
||||
color: $input-text-highlight-color;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus, &.filled {
|
||||
~ .label:not(.fixed) {
|
||||
top: $input-focus-label-top;
|
||||
font-size: $input-label-font-size;
|
||||
}
|
||||
}
|
||||
|
||||
&.filled ~ .label.fixed {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
position: absolute;
|
||||
top: $input-padding + $input-field-padding;
|
||||
left: 0;
|
||||
font-size: $input-field-font-size;
|
||||
line-height: $input-field-font-size;
|
||||
color: $input-text-label-color;
|
||||
pointer-events: none;
|
||||
transition-timing-function: $animation-curve-default;
|
||||
transition-duration: $animation-duration;
|
||||
transition-property: top, font-size, color;
|
||||
}
|
||||
|
||||
.bar {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
||||
&:before, &:after {
|
||||
@include material-animation-default();
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
content: "";
|
||||
background-color: $input-text-highlight-color;
|
||||
transition-property: width, background-color;
|
||||
}
|
||||
|
||||
&:before {
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
&:after {
|
||||
right: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
font-size: $input-label-font-size;
|
||||
line-height: 1.6 * $unit;
|
||||
color: $input-text-error-color;
|
||||
}
|
||||
|
||||
.disabled > .input {
|
||||
color: $input-text-disabled-text-color;
|
||||
border-bottom-style: dotted;
|
||||
}
|
||||
|
||||
.errored {
|
||||
padding-bottom: 0;
|
||||
|
||||
> .input {
|
||||
border-bottom-color: $input-text-error-color;
|
||||
|
||||
&:focus {
|
||||
~ .label:not(.fixed) {
|
||||
color: $input-text-error-color;
|
||||
}
|
||||
|
||||
~ .bar:before, ~ .bar:after {
|
||||
background-color: $input-text-error-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
@import '../constants'
|
||||
|
||||
:local(.root)
|
||||
position : relative
|
||||
margin-bottom : SPACE
|
||||
input, textarea, label
|
||||
font-size : FONT_SIZE_NORMAL
|
||||
font-weight : FONT_WEIGHT_NORMAL
|
||||
|
||||
// -- Style
|
||||
RADIUS = (SPACE / 8)
|
||||
&.touch
|
||||
// -- Children
|
||||
input
|
||||
pointer-events : all
|
||||
z-index : 2
|
||||
position : absolute
|
||||
left : 0
|
||||
width : 100%
|
||||
height : 100%
|
||||
opacity : 0
|
||||
.bar, label
|
||||
position : relative
|
||||
display : inline-block
|
||||
vertical-align : middle
|
||||
.bar
|
||||
width : SPACE
|
||||
height : SPACE
|
||||
margin-right : (SPACE / 1.32)
|
||||
border-radius : RADIUS
|
||||
box-shadow : inset 0 0 0 RADIUS TEXT
|
||||
transition-property background-color, box-shadow
|
||||
transition-duration ANIMATION_DURATION
|
||||
transition-timing-function ANIMATION_EASE
|
||||
&:before
|
||||
z-index : -1
|
||||
position : absolute
|
||||
left : -(SPACE)
|
||||
top : -(SPACE)
|
||||
display : block
|
||||
content : ""
|
||||
width : SIZE = (3 * SPACE)
|
||||
height : SIZE
|
||||
border-radius : 50%
|
||||
opacity : 0
|
||||
&:after
|
||||
display : block
|
||||
width : SPACE
|
||||
color : WHITE
|
||||
text-align : center
|
||||
transform scale(0)
|
||||
transition transform ANIMATION_DURATION ANIMATION_DELAY ANIMATION_EASE
|
||||
label
|
||||
font-size : FONT_SIZE_SMALL
|
||||
color : TEXT
|
||||
// -- Style
|
||||
&:not(.radio) .bar:after
|
||||
content : "✓"
|
||||
&.radio .bar
|
||||
border-radius : 50%
|
||||
&.disabled .bar
|
||||
box-shadow inset 0 0 0 RADIUS DIVIDER
|
||||
&.checked
|
||||
&.radio .bar
|
||||
box-shadow : inset 0 0 0 RADIUS ACCENT, inset 0 0 0 (RADIUS * 2.5) WHITE
|
||||
&:not(.radio) .bar
|
||||
box-shadow : none
|
||||
.bar
|
||||
background-color : ACCENT
|
||||
&:before
|
||||
background-color : alpha(ACCENT, .5)
|
||||
animation-name ripple-touch
|
||||
animation-iteration-count 1
|
||||
animation-timing-function ANIMATION_EASE
|
||||
animation-duration (2 * ANIMATION_DURATION)
|
||||
&:after
|
||||
transform scale(1)
|
||||
|
||||
&:not(.touch)
|
||||
// -- Stylesheets
|
||||
&.focus
|
||||
input, textarea
|
||||
outline : none
|
||||
~ .bar:before, ~ .bar:after
|
||||
width : 50%
|
||||
&:invalid
|
||||
& ~ label
|
||||
color : CANCEL
|
||||
& ~ .bar:before, & ~ .bar:after
|
||||
background-color : CANCEL
|
||||
&.focus , &.valid
|
||||
input, textarea
|
||||
& ~ label
|
||||
top : -(SPACE / 2)
|
||||
font-size : FONT_SIZE_TINY
|
||||
color : PRIMARY
|
||||
input[type="date"]
|
||||
& ~ label
|
||||
top : -(SPACE / 2)
|
||||
font-size : FONT_SIZE_TINY
|
||||
color : PRIMARY
|
||||
&:not(.focus)
|
||||
input, textarea
|
||||
&:invalid:not(:required)
|
||||
border-bottom-color : CANCEL
|
||||
&.error
|
||||
input, textarea
|
||||
border-bottom-color : CANCEL
|
||||
|
||||
// -- Children
|
||||
input, textarea
|
||||
display : block
|
||||
padding : (SPACE / 2) 0
|
||||
width : 100%
|
||||
color : TEXT
|
||||
background-color : transparent
|
||||
border : none
|
||||
border-bottom : 1px solid DIVIDER
|
||||
// -- Attributes
|
||||
&:disabled
|
||||
color : TEXT_SECONDARY
|
||||
border-bottom-style : dotted
|
||||
|
||||
label
|
||||
position : absolute
|
||||
left : 0
|
||||
top : (SPACE / 2)
|
||||
color : TEXT_SECONDARY
|
||||
transition-property top, font-size, color
|
||||
transition-duration ANIMATION_DURATION
|
||||
transition-timing-function ANIMATION_EASE
|
||||
|
||||
.bar
|
||||
position : relative
|
||||
display : block
|
||||
width : 100%
|
||||
&:before, &:after
|
||||
content : ''
|
||||
position : absolute
|
||||
height : 2px
|
||||
width : 0
|
||||
bottom : 0
|
||||
background-color : PRIMARY
|
||||
transition-property width, background-color
|
||||
transition-duration ANIMATION_DURATION
|
||||
transition-timing-function ANIMATION_EASE
|
||||
&:before
|
||||
left : 50%
|
||||
&:after
|
||||
right : 50%
|
||||
|
||||
&.hidden
|
||||
display : none
|
||||
|
||||
// -- Children
|
||||
label
|
||||
pointer-events : none
|
||||
.error
|
||||
position : absolute
|
||||
right : (SPACE / 4)
|
||||
bottom : -(SPACE / 1.25)
|
||||
font-size : (FONT_SIZE_TINY * 0.9)
|
||||
color : CANCEL
|
||||
|
||||
@keyframes ripple-touch
|
||||
0%
|
||||
transform scale(0)
|
||||
opacity : 1
|
||||
100%
|
||||
transform scale(1)
|
||||
opacity : 0
|
|
@ -1,4 +1,5 @@
|
|||
import expect from 'expect';
|
||||
import style from '../../progress_bar/style';
|
||||
import utils from '../../utils/testing';
|
||||
import ProgressBar from '../index';
|
||||
|
||||
|
@ -56,8 +57,8 @@ describe('ProgressBar', function () {
|
|||
|
||||
it('contains mode and className in its className', function () {
|
||||
progressBar = utils.shallowRenderComponent(ProgressBar, {mode: 'determinate', className: 'tight'});
|
||||
expect(progressBar.props.className).toContain('determinate');
|
||||
expect(progressBar.props.className).toContain('tight');
|
||||
expect(progressBar.props.className).toContain(style.determinate);
|
||||
expect(progressBar.props.className).toContain(style.tight);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* global React */
|
||||
|
||||
import { addons } from 'react/addons';
|
||||
import css from './style';
|
||||
import style from './style';
|
||||
import prefixer from '../utils/prefixer';
|
||||
|
||||
export default React.createClass({
|
||||
|
@ -45,8 +45,8 @@ export default React.createClass({
|
|||
|
||||
renderCircular () {
|
||||
return (
|
||||
<svg className={css.circle}>
|
||||
<circle className={css.circlePath} style={this.circularStyle()} cx='30' cy='30' r='25' />
|
||||
<svg className={style.circle}>
|
||||
<circle className={style.path} style={this.circularStyle()} cx='30' cy='30' r='25' />
|
||||
</svg>
|
||||
);
|
||||
},
|
||||
|
@ -66,17 +66,17 @@ export default React.createClass({
|
|||
const {buffer, value} = this.linearStyle();
|
||||
return (
|
||||
<div>
|
||||
<span ref='buffer' data-ref='buffer' className={css.bufferBar} style={buffer}></span>
|
||||
<span ref='value' data-ref='value' className={css.valueBar} style={value}></span>
|
||||
<span ref='buffer' data-ref='buffer' className={style.buffer} style={buffer}></span>
|
||||
<span ref='value' data-ref='value' className={style.value} style={value}></span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
render () {
|
||||
let className = this.props.type === 'linear' ? css.linearBar : css.circularBar;
|
||||
let className = this.props.type === 'linear' ? style.linear : style.circular;
|
||||
if (this.props.mode) className += ` ${style[this.props.mode]}`;
|
||||
if (this.props.multicolor) className += ` ${style.multicolor}`;
|
||||
if (this.props.className) className += ` ${this.props.className}`;
|
||||
if (this.props.mode) className += ` ${this.props.mode}`;
|
||||
if (this.props.multicolor) className += ` multicolor`;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
@import "../variables";
|
||||
|
||||
$progress-height: .4 * $unit;
|
||||
$progress-main-color: unquote("rgb(#{$color-primary})") !default;
|
||||
$progress-secondary-color: unquote("rgba(#{$color-primary-contrast}, 0.7)") !default;
|
||||
$circle-wrapper-width: 60;
|
||||
$circle-radius: 25;
|
||||
$scale-ratio: $circle-radius / 20;
|
||||
|
||||
.linear {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: $progress-height;
|
||||
overflow: hidden;
|
||||
background: $color-divider;
|
||||
|
||||
&.indeterminate .value {
|
||||
transform-origin: center center;
|
||||
animation: linear-indeterminate-bar 1s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
.value, .buffer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
transition-timing-function: $animation-curve-default;
|
||||
transition-duration: $animation-duration;
|
||||
transform: scaleX(0);
|
||||
transform-origin: left center;
|
||||
}
|
||||
|
||||
.value {
|
||||
background-color: $progress-main-color;
|
||||
}
|
||||
|
||||
.buffer {
|
||||
background-image: linear-gradient(to right, $progress-secondary-color, $progress-secondary-color),
|
||||
linear-gradient(to right, $progress-main-color, $progress-main-color);
|
||||
}
|
||||
|
||||
.circular {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: $circle-wrapper-width * 1px;
|
||||
height: $circle-wrapper-width * 1px;
|
||||
transform: rotate(-90deg);
|
||||
|
||||
&.indeterminate {
|
||||
.circle {
|
||||
animation: circular-indeterminate-bar-rotate 2s linear infinite;
|
||||
}
|
||||
|
||||
.path {
|
||||
animation: circular-indeterminate-bar-dash 1.5s ease-in-out infinite;
|
||||
stroke-dasharray: $scale-ratio * 1, $scale-ratio * 200;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
|
||||
&.multicolor .path {
|
||||
animation: circular-indeterminate-bar-dash 1.5s ease-in-out infinite,
|
||||
colors (1.5s * 4) ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.path {
|
||||
transition: stroke-dasharray $animation-duration $animation-curve-default;
|
||||
stroke-dasharray: 0, $scale-ratio * 200;
|
||||
stroke-dashoffset: 0;
|
||||
stroke-linecap: round;
|
||||
stroke-miterlimit: 20;
|
||||
stroke-width: 4;
|
||||
stroke: $progress-main-color;
|
||||
fill: none;
|
||||
}
|
||||
|
||||
@keyframes linear-indeterminate-bar {
|
||||
0% {
|
||||
transform: translate(-50%) scaleX(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translate(-0%) scaleX(.3);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(50%) scaleX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes circular-indeterminate-bar-rotate {
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes circular-indeterminate-bar-dash {
|
||||
0% {
|
||||
stroke-dasharray: $scale-ratio * 1, $scale-ratio * 200;
|
||||
stroke-dashoffset: $scale-ratio * 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
stroke-dasharray: $scale-ratio * 89, $scale-ratio * 200;
|
||||
stroke-dashoffset: $scale-ratio * -35;
|
||||
}
|
||||
|
||||
100% {
|
||||
stroke-dasharray: $scale-ratio * 89, $scale-ratio * 200;
|
||||
stroke-dashoffset: $scale-ratio * -124;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes colors {
|
||||
0% {
|
||||
stroke: #4285f4;
|
||||
}
|
||||
|
||||
25% {
|
||||
stroke: #de3e35;
|
||||
}
|
||||
|
||||
50% {
|
||||
stroke: #f7c223;
|
||||
}
|
||||
|
||||
75% {
|
||||
stroke: #1b9a59;
|
||||
}
|
||||
|
||||
100% {
|
||||
stroke: #4285f4;
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
@import '../constants'
|
||||
|
||||
CIRCLE_WRAPPER_WIDTH = 60 // You need to change cx and cy in markup too
|
||||
CIRCLE_RADIUS = 25 // You need to change r in the markup too
|
||||
SCALE_RATIO = CIRCLE_RADIUS/20
|
||||
|
||||
// -- Linear progress bar
|
||||
:local(.linearBar)
|
||||
display : inline-block
|
||||
position : relative
|
||||
height : PROGRESS_BAR_HEIGHT
|
||||
width : 100%
|
||||
background : darken(BACKGROUND, 7.5%)
|
||||
overflow : hidden
|
||||
|
||||
:local(.valueBar), :local(.bufferBar)
|
||||
position : absolute
|
||||
bottom : 0
|
||||
left : 0
|
||||
right : 0
|
||||
top : 0
|
||||
transform : scaleX(0)
|
||||
transform-origin : left center
|
||||
transition-duration : ANIMATION_DURATION
|
||||
transition-timing-function : ANIMATION_EASE
|
||||
|
||||
:local(.valueBar)
|
||||
background-color : ACCENT
|
||||
|
||||
:local(.bufferBar)
|
||||
background-color : alpha(ACCENT, 15%)
|
||||
|
||||
:local(.linearBar).indeterminate :local(.valueBar)
|
||||
transform-origin : center center
|
||||
animation : linear-indeterminate-bar 1s linear infinite
|
||||
|
||||
// -- Circular progress bar
|
||||
:local(.circularBar)
|
||||
display : inline-block
|
||||
position : relative
|
||||
height : CIRCLE_WRAPPER_WIDTH * 1px
|
||||
width : CIRCLE_WRAPPER_WIDTH * 1px
|
||||
transform : rotate(-90deg)
|
||||
|
||||
:local(.circle)
|
||||
height : 100%
|
||||
width : 100%
|
||||
|
||||
:local(.circlePath)
|
||||
stroke-dasharray : 0, SCALE_RATIO * 200
|
||||
stroke-dashoffset : 0
|
||||
stroke-linecap : round
|
||||
stroke-miterlimit : 20
|
||||
stroke-width : 4
|
||||
stroke : ACCENT
|
||||
fill : none
|
||||
transition : stroke-dasharray ANIMATION_DURATION ANIMATION_EASE
|
||||
|
||||
:local(.circularBar).indeterminate
|
||||
:local(.circle)
|
||||
animation : circular-indeterminate-bar-rotate 2s linear infinite
|
||||
|
||||
:local(.circlePath)
|
||||
stroke-dasharray : SCALE_RATIO * 1, SCALE_RATIO * 200
|
||||
stroke-dashoffset : 0
|
||||
animation : circular-indeterminate-bar-dash 1.5s ease-in-out infinite
|
||||
|
||||
&.multicolor :local(.circlePath)
|
||||
animation : circular-indeterminate-bar-dash 1.5s ease-in-out infinite, colors (1.5s*4) ease-in-out infinite
|
||||
|
||||
// -- Animations
|
||||
@keyframes linear-indeterminate-bar
|
||||
0%
|
||||
transform : translate(-50%) scaleX(0)
|
||||
50%
|
||||
transform : translate(-0%) scaleX(0.3)
|
||||
100%
|
||||
transform : translate(50%) scaleX(0)
|
||||
|
||||
@keyframes circular-indeterminate-bar-rotate
|
||||
100%
|
||||
transform : rotate(360deg)
|
||||
|
||||
@keyframes circular-indeterminate-bar-dash
|
||||
0%
|
||||
stroke-dasharray : SCALE_RATIO * 1, SCALE_RATIO * 200
|
||||
stroke-dashoffset : SCALE_RATIO * 0
|
||||
50%
|
||||
stroke-dasharray : SCALE_RATIO * 89, SCALE_RATIO * 200
|
||||
stroke-dashoffset : SCALE_RATIO * -35
|
||||
100%
|
||||
stroke-dasharray : SCALE_RATIO * 89, SCALE_RATIO * 200
|
||||
stroke-dashoffset : SCALE_RATIO * -124
|
||||
|
||||
@keyframes colors
|
||||
0%
|
||||
stroke: #4285F4
|
||||
25%
|
||||
stroke: #DE3E35
|
||||
50%
|
||||
stroke: #F7C223
|
||||
75%
|
||||
stroke: #1B9A59
|
||||
100%
|
||||
stroke: #4285F4
|
|
@ -3,6 +3,7 @@
|
|||
import expect from 'expect';
|
||||
import sinon from 'sinon';
|
||||
import utils from '../../utils/testing';
|
||||
import style from '../../slider/style';
|
||||
import ProgressBar from '../../progress_bar';
|
||||
import Input from '../../input';
|
||||
import Slider from '../index';
|
||||
|
@ -109,10 +110,10 @@ describe('Slider', function () {
|
|||
|
||||
it('contains the proper number of snaps when snapped', function () {
|
||||
slider = utils.shallowRenderComponent(Slider, {editable: true, pinned: true});
|
||||
expect(slider.props.className).toContain('ring');
|
||||
expect(slider.props.className).toContain('pinned');
|
||||
expect(slider.props.className).toContain(style.ring);
|
||||
expect(slider.props.className).toContain(style.pinned);
|
||||
slider = utils.shallowRenderComponent(Slider, {editable: true, value: 50});
|
||||
expect(slider.props.className).toNotContain('ring');
|
||||
expect(slider.props.className).toNotContain(style.ring);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* global React */
|
||||
|
||||
import css from './style';
|
||||
import style from './style';
|
||||
import utils from '../utils';
|
||||
import ProgressBar from '../progress_bar';
|
||||
import Input from '../input';
|
||||
|
@ -70,8 +70,8 @@ export default React.createClass({
|
|||
utils.events.removeEventsFromDocument(this.getKeyboardEvents());
|
||||
},
|
||||
|
||||
onInputChange (event) {
|
||||
this.setState({value: this.trimValue(event.target.value) });
|
||||
onInputChange () {
|
||||
this.setState({value: this.trimValue(this.refs.input.getValue()) });
|
||||
},
|
||||
|
||||
onKeyDown (event) {
|
||||
|
@ -176,10 +176,10 @@ export default React.createClass({
|
|||
renderSnaps () {
|
||||
if (this.props.snaps) {
|
||||
return (
|
||||
<div ref='snaps' className={css.snaps}>
|
||||
<div ref='snaps' className={style.snaps}>
|
||||
{
|
||||
utils.range(0, (this.props.max - this.props.min) / this.props.step).map(i => {
|
||||
return (<div key={`span-${i}`} className={css.snap}></div>);
|
||||
return (<div key={`span-${i}`} className={style.snap}></div>);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
@ -192,7 +192,7 @@ export default React.createClass({
|
|||
return (
|
||||
<Input
|
||||
ref='input'
|
||||
className={css.input}
|
||||
className={style.input}
|
||||
onChange={this.onInputChange}
|
||||
value={this.valueForInput(this.state.value)} />
|
||||
);
|
||||
|
@ -202,39 +202,39 @@ export default React.createClass({
|
|||
render () {
|
||||
let knobStyles = utils.prefixer({transform: `translateX(${this.knobOffset()}px)`});
|
||||
let className = this.props.className;
|
||||
if (this.props.editable) className += ' editable';
|
||||
if (this.props.pinned) className += ' pinned';
|
||||
if (this.state.pressed) className += ' pressed';
|
||||
if (this.state.value === this.props.min) className += ' ring';
|
||||
if (this.props.editable) className += ` ${style.editable}`;
|
||||
if (this.props.pinned) className += ` ${style.pinned}`;
|
||||
if (this.state.pressed) className += ` ${style.pressed}`;
|
||||
if (this.state.value === this.props.min) className += ` ${style.ring}`;
|
||||
|
||||
return (
|
||||
<div
|
||||
data-react-toolbox='slider'
|
||||
className={css.root + className}
|
||||
className={style.root + className}
|
||||
tabIndex='0'
|
||||
onFocus={this.onSliderFocus}
|
||||
onBlur={this.onSliderBlur} >
|
||||
|
||||
<div
|
||||
ref='slider'
|
||||
className={css.container}
|
||||
className={style.container}
|
||||
onTouchStart={this.onTouchStart}
|
||||
onMouseDown={this.onMouseDown} >
|
||||
|
||||
<div
|
||||
ref='knob'
|
||||
className={css.knob}
|
||||
className={style.knob}
|
||||
style={knobStyles}
|
||||
onMouseDown={this.onMouseDown}
|
||||
onTouchStart={this.onTouchStart} >
|
||||
<div className={css.knobInner} data-value={parseInt(this.state.value)}></div>
|
||||
<div className={style.innerknob} data-value={parseInt(this.state.value)}></div>
|
||||
</div>
|
||||
|
||||
<div className={css.progress}>
|
||||
<div className={style.progress}>
|
||||
<ProgressBar
|
||||
ref='progressbar'
|
||||
mode='determinate'
|
||||
className={css.progressInner}
|
||||
className={style.innerprogress}
|
||||
value={this.state.value}
|
||||
max={this.props.max}
|
||||
min={this.props.min}/>
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
@import "../variables";
|
||||
|
||||
$slider-main-color: unquote("rgb(#{$color-primary})") !default;
|
||||
$slider-main-color-contrast: unquote("rgb(#{$color-primary-contrast})") !default;
|
||||
$slider-snap-color: unquote("rgb(#{$color-black})") !default;
|
||||
$slider-knob-size: 3.2 * $unit;
|
||||
$slider-inner-knob-size: 1.2 * $unit;
|
||||
$slider-snap-size: .2 * $unit;
|
||||
$slider-input-width: 5 * $unit;
|
||||
$slider-bar-height: .2 * $unit;
|
||||
$slider-pin-size: 2.6 * $unit;
|
||||
$slider-pin-elevation: 1.7 * $unit;
|
||||
$slider-side-separation: 1 * $unit;
|
||||
$slider-empty-knob-border: .2 * $unit;
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
width: calc(100% - #{$slider-knob-size});
|
||||
height: $slider-knob-size;
|
||||
margin-right: $slider-knob-size;
|
||||
user-select: none;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: $slider-side-separation + $slider-knob-size;
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-left: $slider-side-separation;
|
||||
}
|
||||
}
|
||||
|
||||
.knob {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: $z-index-higher;
|
||||
display: flex;
|
||||
width: $slider-knob-size;
|
||||
height: $slider-knob-size;
|
||||
flex-direction: row;
|
||||
background-color: transparent;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.innerknob {
|
||||
z-index: $z-index-high;
|
||||
width: $slider-inner-knob-size;
|
||||
height: $slider-inner-knob-size;
|
||||
background-color: $slider-main-color;
|
||||
border-radius: 50%;
|
||||
transition-timing-function: $animation-curve-default;
|
||||
transition-duration: .1s;
|
||||
transition-property: height, width, background-color, border;
|
||||
}
|
||||
|
||||
.snaps {
|
||||
position: absolute;
|
||||
top: $slider-knob-size / 2 - $slider-snap-size / 2;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: calc(100% + #{$slider-snap-size});
|
||||
height: $slider-snap-size;
|
||||
flex-direction: row;
|
||||
pointer-events: none;
|
||||
|
||||
&:after {
|
||||
display: block;
|
||||
width: $slider-snap-size;
|
||||
height: $slider-snap-size;
|
||||
content: "";
|
||||
background-color: $slider-snap-color;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.snap {
|
||||
flex: 1;
|
||||
|
||||
&:after {
|
||||
display: block;
|
||||
width: $slider-snap-size;
|
||||
height: $slider-snap-size;
|
||||
content: "";
|
||||
background-color: $slider-snap-color;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
width: $slider-input-width;
|
||||
padding: 0;
|
||||
margin-bottom: 0;
|
||||
|
||||
> input {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.progress {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: $slider-knob-size / 2;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.innerprogress {
|
||||
position: absolute;
|
||||
top: $slider-knob-size / 2 - $slider-bar-height / 2;
|
||||
height: $slider-bar-height;
|
||||
|
||||
[data-ref="value"] {
|
||||
transition-duration: 0s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.root:focus .knob:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: $z-index-normal;
|
||||
content: "";
|
||||
background-color: $slider-main-color;
|
||||
border-radius: 50%;
|
||||
opacity: .26;
|
||||
}
|
||||
|
||||
.root.editable {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:local(.root).pinned :local(.innerknob) {
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: $slider-pin-size;
|
||||
height: $slider-pin-size;
|
||||
margin-left: ($slider-knob-size - $slider-pin-size) / 2;
|
||||
content: "";
|
||||
background-color: $slider-main-color;
|
||||
border-radius: 50% 50% 50% 0;
|
||||
transition: transform .2s ease, background-color .18s ease;
|
||||
transform: rotate(-45deg) scale(0) translate(0);
|
||||
}
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: $slider-knob-size;
|
||||
height: $slider-pin-size;
|
||||
font-size: 10px;
|
||||
color: $color-background;
|
||||
text-align: center;
|
||||
content: attr(data-value);
|
||||
transition: transform .2s ease, background-color .18s ease;
|
||||
transform: scale(0) translate(0);
|
||||
}
|
||||
}
|
||||
|
||||
.root.pressed {
|
||||
&.pinned .innerknob {
|
||||
&:before {
|
||||
transition-delay: 100ms;
|
||||
transform: rotate(-45deg) scale(1) translate($slider-pin-elevation, - $slider-pin-elevation);
|
||||
}
|
||||
|
||||
&:after {
|
||||
transition-delay: 100ms;
|
||||
transform: scale(1) translate(0, - $slider-pin-elevation);
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.pinned) {
|
||||
&.ring .progress {
|
||||
left: $slider-knob-size / 2 + ($slider-knob-size - $slider-empty-knob-border * 2) / 2;
|
||||
width: calc(100% - #{($slider-knob-size - $slider-empty-knob-border * 2) / 2});
|
||||
}
|
||||
|
||||
.innerknob {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.root.ring {
|
||||
.innerknob {
|
||||
background-color: transparent;
|
||||
border: $slider-empty-knob-border solid $color-divider;
|
||||
|
||||
&:before {
|
||||
background-color: $slider-main-color;
|
||||
}
|
||||
}
|
||||
|
||||
.progress {
|
||||
left: $slider-knob-size / 2 + $slider-empty-knob-border * 2;
|
||||
width: calc(100% - #{$slider-empty-knob-border * 2});
|
||||
transition: left 0.18s ease, width 0.18s ease;
|
||||
}
|
||||
|
||||
&.pinned {
|
||||
.innerknob {
|
||||
background-color: $color-background;
|
||||
}
|
||||
|
||||
.progress {
|
||||
left: $slider-knob-size / 2;
|
||||
width: calc(100%);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,163 +0,0 @@
|
|||
@import '../constants'
|
||||
|
||||
RANGE_SIDE_SEPARATION = 20px
|
||||
|
||||
:local(.container)
|
||||
height : 32px
|
||||
margin-right : 32px
|
||||
position : relative
|
||||
user-select : none
|
||||
width : calc(100% - 32px)
|
||||
&:not(:last-child)
|
||||
margin-right : RANGE_SIDE_SEPARATION + 32px
|
||||
&:not(:first-child)
|
||||
margin-left : RANGE_SIDE_SEPARATION
|
||||
|
||||
:local(.knob)
|
||||
align-items : center
|
||||
background-color : transparent
|
||||
display : flex
|
||||
flex-direction : row
|
||||
height : 32px
|
||||
justify-content : center
|
||||
left : 0
|
||||
position : relative
|
||||
top : 0
|
||||
width : 32px
|
||||
z-index : 5
|
||||
|
||||
:local(.knobInner)
|
||||
background-color : ACCENT
|
||||
border-radius : 50%
|
||||
height : 12px
|
||||
transition-duration : 0.1s
|
||||
transition-property : height, width, background-color, border
|
||||
transition-timing-function : ease
|
||||
width : 12px
|
||||
z-index : 4
|
||||
|
||||
:local(.snaps)
|
||||
display : flex
|
||||
flex-direction : row
|
||||
height : 2px
|
||||
left : 0
|
||||
pointer-events : none
|
||||
position : absolute
|
||||
top : 15px
|
||||
width : calc(100% + 2px)
|
||||
&:after
|
||||
background-color : black
|
||||
border-radius : 50%
|
||||
content : ""
|
||||
display : block
|
||||
height : 2px
|
||||
width : 2px
|
||||
|
||||
:local(.snap)
|
||||
flex : 1
|
||||
&:after
|
||||
background-color : black
|
||||
border-radius : 50%
|
||||
content : ""
|
||||
display : block
|
||||
height : 2px
|
||||
width : 2px
|
||||
|
||||
:local(.input)
|
||||
margin-bottom : 0
|
||||
text-align : center
|
||||
width : 40px
|
||||
|
||||
:local(.progress)
|
||||
height : 100%
|
||||
left : 16px
|
||||
position : absolute
|
||||
top : 0
|
||||
width : 100%
|
||||
|
||||
:local(.progressInner)
|
||||
height : 2px
|
||||
position : absolute
|
||||
top : 15px
|
||||
|
||||
[data-ref="value"]
|
||||
transition-duration : 0s
|
||||
|
||||
// When its focused
|
||||
:local(.root):focus :local(.knob):before
|
||||
background-color : ACCENT
|
||||
border-radius : 50%
|
||||
bottom : 0
|
||||
content : ""
|
||||
left : 0
|
||||
position : absolute
|
||||
right : 0
|
||||
top : 0
|
||||
opacity : .26
|
||||
z-index : 2
|
||||
|
||||
:local(.root).editable
|
||||
display : flex
|
||||
align-items : center
|
||||
flex-direction : row
|
||||
|
||||
// When its pinned
|
||||
:local(.root).pinned :local(.knobInner)
|
||||
&:before
|
||||
content : ""
|
||||
position : absolute
|
||||
top : 0
|
||||
background-color : ACCENT
|
||||
left : 0
|
||||
width : 26px
|
||||
height : 26px
|
||||
margin-left : 3px
|
||||
border-radius : 50% 50% 50% 0
|
||||
transition-delay : 1s
|
||||
transform : rotate(-45deg) scale(0) translate(0)
|
||||
transition : transform .2s ease, background-color .18s ease
|
||||
|
||||
&:after
|
||||
color : white
|
||||
content : attr(data-value)
|
||||
font-size : 10px
|
||||
height : 26px
|
||||
left : 0
|
||||
position : absolute
|
||||
text-align : center
|
||||
top : 0
|
||||
transform : scale(0) translate(0)
|
||||
transition : transform .2s ease, background-color .18s ease
|
||||
width : 32px
|
||||
|
||||
// When the knob is pressed
|
||||
:local(.root).pressed.pinned :local(.knobInner)
|
||||
&:before
|
||||
transition-delay : 100ms
|
||||
transform : rotate(-45deg) scale(1) translate(17px, -17px)
|
||||
|
||||
&:after
|
||||
transition-delay : 100ms
|
||||
transform : scale(1) translate(0, -17px)
|
||||
|
||||
:local(.root).pressed:not(.pinned) :local(.knobInner)
|
||||
height : 100%
|
||||
transform : translateZ(0)
|
||||
width : 100%
|
||||
|
||||
:local(.root).pressed:not(.pinned).ring :local(.progress)
|
||||
left : 30px
|
||||
width : calc(100% - 14px)
|
||||
|
||||
// When there is no current value
|
||||
:local(.root).ring :local(.knobInner)
|
||||
background-color : transparent
|
||||
border : 2px solid #c8c8c8
|
||||
|
||||
:local(.root).ring :local(.knobInner):before
|
||||
background-color : #c8c8c8
|
||||
|
||||
:local(.root).ring :local(.progress)
|
||||
left : 20px
|
||||
transition : left 0.18s ease, width 0.18s ease
|
||||
width : calc(100% - 4px)
|
|
@ -17,10 +17,11 @@ module.exports = function (config) {
|
|||
reporters: ['dots'],
|
||||
preprocessors: {'tests.webpack.js': ['webpack']},
|
||||
webpack: {
|
||||
resolve: { extensions: ['', '.jsx', '.cjsx', '.coffee', '.js', '.json', '.styl'] },
|
||||
resolve: { extensions: ['', '.jsx', '.scss', '.js', '.json', '.styl'] },
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /(\.js|\.jsx)$/, exclude: /(node_modules)/, loader: 'babel' },
|
||||
{ test: /(\.scss|\.css)$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader!sass') },
|
||||
{ test: /\.styl$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[hash:base64:5]!stylus-loader') }
|
||||
]
|
||||
},
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/* global React */
|
||||
|
||||
import Input from '../../components/input';
|
||||
|
||||
export default React.createClass({
|
||||
displayName: 'InputTest',
|
||||
|
||||
render () {
|
||||
return (
|
||||
<section>
|
||||
<h5>Inputs</h5>
|
||||
<p>lorem ipsum...</p>
|
||||
<Input type="text" label="Firstname" icon="bookmark" />
|
||||
<Input type="email" label="Label fixed" icon="bookmark" floating={false} />
|
||||
<Input type="text" label="Phone Number" icon="bookmark" />
|
||||
<Input type="text" label="Disabled field" disabled />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
});
|
|
@ -43,14 +43,13 @@ export default React.createClass({
|
|||
render () {
|
||||
return (
|
||||
<section>
|
||||
<h2>Progress bars</h2>
|
||||
|
||||
<p>Determinate</p>
|
||||
<ProgressBar mode="determinate" value={this.state.progress} buffer={this.state.buffer}/>
|
||||
<p>Indeterminate...</p>
|
||||
<ProgressBar mode="indeterminate"/>
|
||||
<p>Circular</p>
|
||||
<ProgressBar type="circular" mode="indeterminate"/>
|
||||
<h5>Progress bars</h5>
|
||||
<p style={{margin: '10px auto'}}>Determinate</p>
|
||||
<ProgressBar mode='determinate' value={this.state.progress} buffer={this.state.buffer}/>
|
||||
<p style={{margin: '10px auto'}}>Indeterminate...</p>
|
||||
<ProgressBar mode='indeterminate'/>
|
||||
<p style={{margin: '10px auto'}}>Circular</p>
|
||||
<ProgressBar type='circular' mode='indeterminate'/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,14 +8,13 @@ export default React.createClass({
|
|||
render () {
|
||||
return (
|
||||
<section>
|
||||
<h2 style={{marginTop: '1rem'}}>Sliders</h2>
|
||||
<h5>Sliders</h5>
|
||||
<p>Normal slider</p>
|
||||
<Slider />
|
||||
<p>With steps, initial value and editable</p>
|
||||
<Slider value={5} min={0} max={10} editable />
|
||||
<p>Pinned and with snaps</p>
|
||||
|
||||
<Slider pinned value={1} min={0} max={10} step={1} editable />
|
||||
<Slider pinned snaps value={1} min={0} max={10} step={1} editable />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
app { padding: 1.6rem; }
|
||||
app > h1, app > h3 { line-height: 100%; }
|
||||
app h5 { margin-top: 3.2rem; }
|
||||
app p { margin-bottom: 1.6rem; opacity: 0.5;}
|
||||
app p { margin-bottom: 1rem; opacity: 0.5;}
|
||||
app [data-react-toolbox='card'] {
|
||||
margin: 1.6rem 1.6rem 0 0;
|
||||
display: inline-block;
|
||||
|
|
|
@ -7,12 +7,13 @@ import Checkbox from './components/checkbox';
|
|||
import Dialog from './components/dialog';
|
||||
import Drawer from './components/drawer';
|
||||
import Dropdown from './components/dropdown';
|
||||
import Input from './components/input';
|
||||
import Progress from './components/progress';
|
||||
import RadioGroup from './components/radio_group';
|
||||
import Slider from './components/slider';
|
||||
import Switch from './components/switch';
|
||||
// import FontIcon from './components/font_icon';
|
||||
// import Form from './components/form';
|
||||
// import Progress from './components/progress';
|
||||
// import Slider from './components/slider';
|
||||
// import Pickers from './components/pickers';
|
||||
// import Tabs from './components/tabs';
|
||||
|
||||
|
@ -31,7 +32,10 @@ const Test = React.createClass({
|
|||
<Dialog />
|
||||
<Drawer />
|
||||
<Dropdown />
|
||||
<Input />
|
||||
<Progress />
|
||||
<RadioGroup />
|
||||
<Slider />
|
||||
<Switch />
|
||||
</app>
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue