Skip to content

Instantly share code, notes, and snippets.

@rhostem
Created October 17, 2018 06:35
Show Gist options
  • Save rhostem/8d82fd50711ea66d532cb20c5e80f1c3 to your computer and use it in GitHub Desktop.
Save rhostem/8d82fd50711ea66d532cb20c5e80f1c3 to your computer and use it in GitHub Desktop.
[React] form components set
import * as React from 'react'
import styled from 'styled-components'
import { color, mixin } from 'styles'
const CheckBoxGroup = styled.div`
display: inline-flex;
align-items: center;
& > input {
display: none;
}
& > input + label {
display: inline-block;
position: relative;
padding-left: 30px;
height: 20px;
font-size: 12px;
color: ${color.text};
margin-bottom: 0;
&:hover {
cursor: pointer;
}
&:before {
${mixin.centeredY()};
left: 0;
display: block;
width: 20px;
height: 20px;
content: ' ';
background-image: url('${
process.env.REACT_APP_CDN_URL
}/admin/btn-check-off.svg');
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
}
& > input:checked + label {
&:before {
background-image: url('${
process.env.REACT_APP_CDN_URL
}/admin/btn-check-on.svg');
}
}
`
type Props = {
id: string,
onChange: Function,
children: any,
checked: boolean,
disabled?: boolean,
name?: string,
}
class CheckBox extends React.Component<Props, any> {
static defaultProps = {
checked: false,
disabled: false,
}
render() {
const { children, id, onChange, checked, disabled, name } = this.props
return (
<CheckBoxGroup>
<input
id={id}
type="checkbox"
onChange={onChange}
checked={checked}
disabled={disabled}
name={name}
/>
<label
htmlFor={id}
style={{
opacity: disabled ? 0.6 : 1,
}}
>
{children || name}
</label>
</CheckBoxGroup>
)
}
}
export default CheckBox
// import React, { Fragment } from 'react'
import styled from 'styled-components'
import { clearFix } from 'polished'
export const FormContainer = styled.div`
margin: 12px 0;
/* FormGroup */
& > * {
&:last-child {
border-bottom: 1px solid #dee0e4;
}
}
`
export const FormGroup = styled.div`
${clearFix()};
display: flex;
font-size: 14px;
border-top: 1px solid #dee0e4;
`
/**
* label, input의 wrapper
* FormGroup을 같은 넓이로 나눈다. FormGroup에 한 세트의 label, input만 사용된다면 필요없다.
*/
export const FormContent = styled.div`
${clearFix()};
flex: 1;
`
const labelWidth = '135px'
export const FormLabel = styled.label`
float: left;
padding: 12px 10px;
width: ${labelWidth};
margin-bottom: 0;
`
/**
* input, form, select, texteditor, ...
*/
export const FormInput = styled.div`
padding: 12px 10px;
float: left;
width: calc(100% - ${labelWidth});
display: inline-flex;
align-items: center;
justify-content: flex-start;
flex-flow: row wrap;
`
import React from 'react'
import styled from 'styled-components'
const Wrap = styled.div`
position: relative;
display: block;
width: 100%;
height: 40px;
background-color: #ffffff;
border: solid 1px #dee0e4;
padding: 0 12px;
font-size: 14px;
display: flex;
align-items: center;
& > input {
flex: 1;
border: none;
background-color: transparent;
font-size: inherit;
&::placeholder {
color: #dee0e4;
}
}
`
// const Input = styled.input``
type IconType = 'PASSWORD' | 'ID' | 'PHONE'
const getIconUrl = (icon: IconType) => {
const iconUrl = {
PASSWORD: `${process.env.REACT_APP_CDN_URL}/admin/icon-login-password.png`,
ID: `${process.env.REACT_APP_CDN_URL}/admin/icon-login-id.png`,
PHONE: `${process.env.REACT_APP_CDN_URL}/admin/icon-input-phone.png`,
}
return iconUrl[icon]
}
const Icon = styled.img`
display: inline-block;
width: 20px;
height: 20px;
margin-right: 10px;
`
type Props = {
style?: Object,
icon: IconTypes,
value: string,
onChange: Function,
placeholder: string,
type: string,
}
export default ({
style, // css style
icon, // 아이콘 타입
iconSize = '20px', // 좌측 아이콘 크기
value,
onChange,
placeholder,
type, // html type
children, // 인풋 오른쪽 영역, 검색
}: Props) => {
return (
<Wrap style={style}>
{!!icon ? (
<Icon
src={getIconUrl(icon)}
style={{ width: iconSize, height: iconSize }}
/>
) : null}
<input
type={type}
value={value}
onChange={onChange}
placeholder={placeholder}
/>
{children}
</Wrap>
)
}
import React, { Component, Fragment } from 'react'
import Select from 'react-select' // https://react-select.com/
import chroma from 'chroma-js'
type Option = {
value: string, // 실제 값
label: string, // 표시 값
}
type Props = {
name: string, // name property of input tag
placeholder: string, // input placeholder
options: Option[], // options array
onChange: (
option: Object | Array<Object> | null | undefined,
action: Object
) => undefined,
}
type State = {
isClearable: boolean,
isDisabled: boolean,
isLoading: boolean,
isRtl: boolean,
isSearchable: boolean,
}
const optionBgColor = chroma('#ff9e03')
const customStyles = {
control: (base, state) => ({
...base,
borderColor: 'blue',
}),
option: (base, state) => ({
...base,
padding: '1rem',
fontWeight: state.isSelected ? 700 : 400,
backgroundColor: state.isSelected
? optionBgColor.css()
: optionBgColor.alpha(0.2).css(),
'&:hover': {
backgroundColor: 'hotpink',
},
}),
singleValue: (base, state) => {
const opacity = state.isDisabled ? 0.5 : 1
const transition = 'opacity 300ms'
return { ...base, opacity, transition }
},
}
export default class SingleSelect extends Component<Props, State> {
static defaultProps = {
name: 'select-name',
options: [],
placeholder: 'Select',
className: 'reactSelect--single',
}
state = {
isClearable: true,
isDisabled: false,
isLoading: false,
isRtl: false,
isSearchable: true,
}
toggleClearable = () =>
this.setState(state => ({ isClearable: !state.isClearable }))
toggleDisabled = () =>
this.setState(state => ({ isDisabled: !state.isDisabled }))
toggleLoading = () =>
this.setState(state => ({ isLoading: !state.isLoading }))
toggleRtl = () => this.setState(state => ({ isRtl: !state.isRtl }))
toggleSearchable = () =>
this.setState(state => ({ isSearchable: !state.isSearchable }))
render() {
const {
isClearable,
isSearchable,
isDisabled,
isLoading,
isRtl,
} = this.state
const { options, name, placeholder, onChange, className } = this.props
return (
<Fragment>å
<Select
name={name}
options={options}
defaultValue={options[0]}
placeholder={placeholder}
onChange={onChange}
styles={customStyles}
className={className}
classNamePrefix="select"
isDisabled={isDisabled}
isLoading={isLoading}
isClearable={isClearable}
isRtl={isRtl}
isSearchable={isSearchable}
/>
</Fragment>
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment