Enhaced <Form/> and <Input/>

old
Javi Jimenez Villar 2015-06-14 17:15:27 +07:00
parent 083375cdee
commit fa7d199c1f
5 changed files with 204 additions and 16 deletions

View File

@ -2,6 +2,7 @@
@todo
###
Style = require './style/form'
Button = require "./button"
Input = require "./input"

View File

@ -2,11 +2,13 @@
@todo
###
Style = require './style/input'
module.exports = React.createClass
# -- States & Properties
propTypes:
type : React.PropTypes.string.required
type : React.PropTypes.string
label : React.PropTypes.string
value : React.PropTypes.string
error : React.PropTypes.string
@ -14,47 +16,54 @@ module.exports = React.createClass
disabled : React.PropTypes.bool
multiline : React.PropTypes.bool
onChange : React.PropTypes.func
style : React.PropTypes.object
getDefaultProps: ->
type : "text"
required : false
disabled : false
multiline : false
style :
borderBottom : "solid 2px red"
getInitialState: ->
value : @props.value
checked : @props.value
error : @props.error
touch : @props.type in ["checkbox", "radio"]
# -- Events
onChange: (event) ->
@setState value: event.target.value
if @state.touch
@setState checked: event.target.checked, error: undefined
else
@setState value: event.target.value, error: undefined
@props.onChange? event, @
# -- Render
render: ->
# -- styles
style = ""
style += " error" if @props.error
# -- tag
<div data-component-input={@props.type} className={style} style={@props.style}>
className = ""
className += " disabled" if @props.disabled
className += " error" if @state.error
className += " touch" if @state.touch
className += " radio" if @props.type is "radio"
className += " checked" if @state.checked
<div data-component-input={@props.type} className={className}>
{
if @props.multiline
<textarea {...@props} onChange={@onChange}>{@state.value}</textarea>
<textarea ref="input" {...@props} onChange={@onChange}>{@state.value}</textarea>
else
<input {...@props} value={@state.value} onChange={@onChange} />
<input ref="input" {...@props} value={@state.value} checked={@state.checked} onChange={@onChange} />
}
<span className="bar"></span>
{ <label>{@props.label}</label> if @props.label }
{ <span className="error">{@props.error}</span> if @props.error }
{ <span className="error">{@state.error}</span> if @state.error }
</div>
# -- Extends
getValue: ->
@state.value
@refs.input?.getDOMNode()[if @state.touch then "checked" else "value"]
setValue: (data) ->
@setState value: data
setError: (data = "Unknown error") ->
@setState error: data
@setState error: @props.error or data

View File

@ -0,0 +1,4 @@
@import '__constants.styl'
[data-component-form]
padding : SPACE

155
components/style/input.styl Normal file
View File

@ -0,0 +1,155 @@
@import '__constants.styl'
[data-component-input]
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 COLOR
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 : COLOR
// -- Style
&:not(.radio) .bar:after
content : ""
&.radio .bar
border-radius : 50%
&.disabled .bar
box-shadow inset 0 0 0 RADIUS lighten(COLOR, 75%)
&:not(.touch)
input, textarea
display : block
padding : (SPACE / 2) 0
width : 100%
color : COLOR
background-color : transparent
border : none
border-bottom : 1px solid lighten(COLOR, 75%)
// -- Attributes
&:focus
outline : none
~ .bar:before, ~ .bar:after
width : 50%
&:focus ~ label, &:valid ~ label
top : -(SPACE / 2)
font-size : FONT_SIZE_TINY
color : THEME
&:disabled
border-bottom-style : dotted
&:invalid
&:not(:required):not(:focus)
border-bottom-color : CANCEL
&:focus ~ label
color : CANCEL
~ .bar:before, ~ .bar:after
background-color : CANCEL
label
position : absolute
left : 0
top : (SPACE / 2)
color : lighten(COLOR, 75%)
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 : THEME
transition-property width, background-color
transition-duration ANIMATION_DURATION
transition-timing-function ANIMATION_EASE
&:before
left : 50%
&:after
right : 50%
&.error
input, textarea
border-bottom-color : CANCEL
&.checked
&.radio .bar
box-shadow : inset 0 0 0 RADIUS SECONDARY, inset 0 0 0 (RADIUS * 2.5) WHITE
&:not(.radio) .bar
box-shadow : none
.bar
background-color : SECONDARY
&:before
background-color : alpha(SECONDARY, .5)
animation-name ripple-touch
animation-iteration-count 1
animation-timing-function ANIMATION_EASE
animation-duration (2 * ANIMATION_DURATION)
&:after
transform scale(1)
// -- 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

View File

@ -2,6 +2,7 @@
# -- Components
Button = require "../components/button"
Form = require "../components/form"
Test = React.createClass
getInitialState: ->
@ -24,20 +25,38 @@ Test = React.createClass
# -- Render
render: ->
attributes = [
ref: "name", label: "Your Name", required: true
ref: "name", label: "Your Name", required: true#, onChange: @onInputChange
,
ref: "description", multiline: true, label: "Description", value: "Doer"
,
ref: "birthdate", type: "date", label: "Birthdate"
,
ref: "years", type: "number", label: "Years"
,
ref: "twitter", label: "Nickname", disabled: true
,
ref: "nomad", type: "checkbox", label: "Are you a nomad?", value: true
,
ref: "cow", type: "checkbox", label: "Are you a cow?", value: false
,
ref: "girl", type: "checkbox", label: "Are you a girl?", value: false, disabled: true
,
ref: "nomad_2", type: "radio", label: "Are you a nomad_2?", value: true
,
ref: "cow_2", type: "radio", label: "Are you a cow_2?", value: false
,
ref: "girl_2", type: "radio", label: "Are you a girl_2?", value: false, disabled: true
,
type: "submit", caption: "Send", style: "primary anchor", disabled: true
]
<app>
<h1>React-Kit</h1>
<h2>New way for create</h2>
<h2>Forms</h2>
<Form attributes={attributes} />
<h3>Buttons</h3>
<Button caption="Login" disabled={not @state.submitable} />
<Button caption="Primary" style="primary" icon="access_alarm" />