Add theme helpers

This commit is contained in:
Jerko Steiner 2019-11-03 11:15:55 -04:00
parent 882248a367
commit 2d4cb2d275
10 changed files with 102 additions and 71 deletions

View File

@ -1,13 +1,20 @@
import React from 'react'
import styled from 'styled-components'
import { getColor, ColorSchemeProps, getBorder } from '../theme'
export interface ButtonProps {
// type: string
}
export const Button = styled.button<ColorSchemeProps>`
padding: 0.5rem;
background: transparent;
color: ${getColor};
border: ${getBorder};
border-radius: ${props => props.theme.border.radius}px;
cursor: pointer;
export class Button extends React.PureComponent<ButtonProps> {
render() {
return (
<button>{this.props.children}</button>
)
&:hover {
background: ${getColor};
color: white;
}
}
&:hover:active {
box-shadow: 0 0 3px ${getColor};
}
`

View File

@ -1,46 +0,0 @@
import React from 'react'
import {connect} from 'react-redux'
interface ComponentProps {
value: string
}
interface StateProps {
value: string
}
export class Component
extends React.PureComponent<ComponentProps, StateProps> {
constructor(props: ComponentProps) {
super(props)
this.state = {
value: props.value,
}
}
handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({
value: e.target.value,
})
}
render() {
return (
<div>
<input
autoComplete='off'
type='text'
value={this.state.value}
onChange={this.handleChange}
/>
<div>{this.state.value}</div>
</div>
)
}
}
function mapStateToProps(state: {value: string}) {
return {
value: state.value,
}
}
export const CComponent = connect(mapStateToProps)(Component)

View File

@ -27,7 +27,7 @@ const Control = styled.div`
position: relative;
`
const I = styled.span`
const Icon = styled.span`
position: absolute;
display: flex;
flex-direction: column;
@ -39,12 +39,18 @@ const I = styled.span`
top: 0;
bottom: 0;
width: 2.5rem;
color: ${props => props.theme.grey.light};
`
const TextInput = styled.input<{hasIconLeft?: boolean}>`
padding: 0.5rem 0.75rem;
padding-left: ${props => props.hasIconLeft ? '2.5rem' : '0.75rem'}
width: 100%;
&:focus + ${Icon} {
color: ${props => props.theme.grey.dark};
}
`
export class Input extends React.PureComponent<InputProps> {
@ -54,7 +60,6 @@ export class Input extends React.PureComponent<InputProps> {
}
}
render() {
const {Icon} = this.props
return (
<Field>
<Label>{this.props.label}</Label>
@ -69,7 +74,7 @@ export class Input extends React.PureComponent<InputProps> {
readOnly={!!this.props.readOnly}
required={this.props.required}
/>
{Icon && <I><Icon /></I>}
{this.props.Icon && <Icon><this.props.Icon /></Icon>}
</Control>
</Field>
)

View File

@ -1,4 +1,3 @@
// export * from './Component'
export * from './Button'
export * from './Input'
export * from './Link'

View File

@ -5,6 +5,7 @@ export * from './csrf'
export * from './login'
export * from './renderer'
export * from './test-utils'
export * from './theme'
import * as team from './team'
export { team }

View File

@ -4,6 +4,7 @@ import { FaEnvelope, FaLock, FaUser } from 'react-icons/fa'
import { Link } from 'react-router-dom'
import { Input } from '../components/Input'
import { Redirect } from '../components/Redirect'
import { Button } from '../components'
export interface RegisterFormProps {
error?: string
@ -28,12 +29,12 @@ export class RegisterForm extends React.PureComponent<RegisterFormProps> {
<p className='error has-text-danger'>{this.props.error}</p>
<Input
Icon={FaEnvelope}
label='Email'
label='Username'
name='username'
type='email'
type='text'
onChange={this.props.onChange}
value={this.props.data.username}
placeholder='Email'
placeholder='Username'
required
/>
<Input
@ -46,6 +47,15 @@ export class RegisterForm extends React.PureComponent<RegisterFormProps> {
placeholder='Password'
required
/>
<Input
Icon={FaEnvelope}
label='Email'
name='email'
type='email'
onChange={this.props.onChange}
value={this.props.data.username}
placeholder='Email'
/>
<Input
Icon={FaUser}
label='First Name'
@ -54,7 +64,6 @@ export class RegisterForm extends React.PureComponent<RegisterFormProps> {
onChange={this.props.onChange}
value={this.props.data.firstName}
placeholder='First name'
required
/>
<Input
Icon={FaUser}
@ -64,15 +73,11 @@ export class RegisterForm extends React.PureComponent<RegisterFormProps> {
onChange={this.props.onChange}
value={this.props.data.lastName}
placeholder='Last name'
required
/>
<div className='text-center'>
<input
className='button is-primary'
name='submit'
type='submit'
value='Register'
/>
<Button name='submit' type='submit'>
Register
</Button>
</div>
<p className='small center mt-1'>
Already have an account? <Link to='/auth/login'>Log in!</Link>

View File

@ -0,0 +1,6 @@
import { DefaultTheme, ThemeProps } from 'styled-components'
import { ColorScheme } from './theme'
export interface ColorSchemeProps extends ThemeProps<DefaultTheme> {
colorScheme?: ColorScheme
}

View File

@ -0,0 +1,9 @@
import { ColorSchemeProps } from './ColorSchemeProps'
export function getColor(props: ColorSchemeProps) {
return props.theme.colors[props.colorScheme || 'primary']
}
export function getBorder(props: ColorSchemeProps) {
return `${props.theme.border.width}px solid ${getColor(props)};`
}

View File

@ -0,0 +1,3 @@
export * from './getColor'
export * from './theme'
export * from './ColorSchemeProps'

View File

@ -0,0 +1,42 @@
import { DefaultTheme } from 'styled-components'
declare module 'styled-components' {
export interface DefaultTheme {
colors: {
primary: string
secondary: string
warning: string
danger: string
info: string
}
grey: {
dark: string
light: string
}
border: {
width: 1
radius: 3
}
}
}
export const theme: DefaultTheme = {
colors: {
primary: 'indigo',
secondary: 'green',
warning: 'yellow',
danger: 'red',
info: 'lightblue',
},
grey: {
dark: 'darkgrey',
light: 'lightgrey',
},
border: {
width: 1,
radius: 3,
},
}
export type ColorScheme =
'primary' | 'secondary' | 'warning' | 'danger' | 'info'