Skip to content

Commit

Permalink
feat: add BaseButton component
Browse files Browse the repository at this point in the history
  • Loading branch information
im36-123 committed Sep 3, 2019
1 parent 6cd2390 commit 7dce43f
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 100 deletions.
127 changes: 127 additions & 0 deletions src/components/Button/BaseButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import * as React from 'react'
import styled, { css } from 'styled-components'

import { InjectedProps } from '../../hocs/withTheme'

import { hoverable } from '../../hocs/hoverable'
import { isTouchDevice } from '../../libs/ua'

type Tag = 'button' | 'a'
type Size = 'default' | 's'

interface BaseProps {
size?: Size
children?: React.ReactNode
className?: string
prefix?: React.ReactNode
suffix?: React.ReactNode
square?: boolean
wide?: boolean
}

export const buttonFactory: <Props extends BaseProps>(
tag: Tag,
) => React.FC<Props & InjectedProps> = tag => ({
size = 'default',
className = '',
square = false,
children = '',
prefix = '',
suffix = '',
theme,
...props
}) => {
const Tag = hoverable()(Base.withComponent(tag))

// prettier-ignore
const classNames = `${size} ${className} ${square ? 'square' : ''} ${prefix ? 'prefix' : ''} ${suffix ? 'suffix' : ''}`

return (
<Tag className={classNames} theme={theme} {...props}>
{prefix && <Prefix theme={theme}>{prefix}</Prefix>}
{children}
{suffix && <Suffix theme={theme}>{suffix}</Suffix>}
</Tag>
)
}

const Base: any = styled.div`
${({ theme }: InjectedProps) => {
const { frame, size, interaction } = theme
return css`
display: inline-flex;
justify-content: center;
align-items: center;
width: ${({ wide }: any) => (wide ? '100%;' : 'auto')};
min-width: 2rem;
vertical-align: middle;
border: none;
border-radius: ${frame.border.radius.m};
color: #fff;
font-family: inherit;
font-weight: bold;
text-align: center;
text-decoration: none;
box-sizing: border-box;
cursor: pointer;
transition: ${isTouchDevice ? 'none' : `all ${interaction.hover.animation}`};
&.default {
font-size: ${size.pxToRem(size.font.TALL)};
height: 40px;
line-height: 40px;
padding: 0 ${size.pxToRem(size.space.XS)};
}
&.s {
font-size: ${size.pxToRem(size.font.SHORT)};
height: 27px;
line-height: 27px;
padding: 0 ${size.pxToRem(size.space.XXS)};
}
&.square {
width: 40px;
line-height: 40px;
padding: 0;
&.s {
width: 27px;
min-width: 27px;
}
}
&[disabled] {
cursor: not-allowed;
}
&.suffix {
justify-content: space-between;
}
&.prefix {
justify-content: left;
}
`
}}
`

const Prefix = styled.span`
${({ theme }: InjectedProps) => {
const { size } = theme
return css`
display: inline-flex;
margin-right: ${size.pxToRem(size.space.XXS)};
`
}}
`
const Suffix = styled.span`
${({ theme }: InjectedProps) => {
const { size } = theme
return css`
display: inline-flex;
margin-left: ${size.pxToRem(size.space.XXS)};
`
}}
`
110 changes: 10 additions & 100 deletions src/components/Button/PrimaryButton.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import * as React from 'react'
import styled, { css } from 'styled-components'

import { InjectedProps, withTheme } from '../../hocs/withTheme'
import { buttonFactory } from './BaseButton'

import { hoverable } from '../../hocs/hoverable'
import { InjectedProps, withTheme } from '../../hocs/withTheme'
import { isTouchDevice } from '../../libs/ua'

type Tag = 'button' | 'a'
type Size = 'default' | 's'

interface ClickEvent {
Expand Down Expand Up @@ -34,122 +33,33 @@ interface AnchorProps extends BaseProps {
rel?: string
}

const buttonFactory: <Props extends BaseProps>(
tag: Tag,
) => React.FC<Props & InjectedProps> = tag => ({
size = 'default',
className = '',
square = false,
children = '',
prefix = '',
suffix = '',
theme,
...props
}) => {
const Tag = hoverable()(Base.withComponent(tag))

// prettier-ignore
const classNames = `${size} ${className} ${square ? 'square' : ''} ${prefix ? 'prefix' : ''} ${suffix ? 'suffix' : ''}`

return (
<Tag className={classNames} theme={theme} {...props}>
{prefix && <Prefix theme={theme}>{prefix}</Prefix>}
{children}
{suffix && <Suffix theme={theme}>{suffix}</Suffix>}
</Tag>
)
}

const ButtonComponent: React.FC<ButtonProps & InjectedProps> = buttonFactory<ButtonProps>('button')
const ButtonAnchorComponent: React.FC<AnchorProps & InjectedProps> = buttonFactory<AnchorProps>('a')

export const PrimaryButton = withTheme(ButtonComponent)
export const PrimaryButtonAnchor = withTheme(ButtonAnchorComponent)

const Base: any = styled.div`
const injectStyle = (
component: React.FC<ButtonProps & InjectedProps> | React.FC<AnchorProps & InjectedProps>,
) => styled(component)`
${({ theme }: InjectedProps) => {
const { palette, frame, size, interaction } = theme
const { palette, interaction } = theme
return css`
display: inline-flex;
justify-content: center;
align-items: center;
width: ${({ wide }: any) => (wide ? '100%;' : 'auto')};
min-width: 2rem;
vertical-align: middle;
border: none;
border-radius: ${frame.border.radius.m};
background-color: ${palette.MAIN};
color: #fff;
font-family: inherit;
font-weight: bold;
text-align: center;
text-decoration: none;
box-sizing: border-box;
cursor: pointer;
transition: ${isTouchDevice ? 'none' : `all ${interaction.hover.animation}`};
&.default {
font-size: ${size.pxToRem(size.font.TALL)};
height: 40px;
line-height: 40px;
padding: 0 ${size.pxToRem(size.space.XS)};
}
&.s {
font-size: ${size.pxToRem(size.font.SHORT)};
height: 27px;
line-height: 27px;
padding: 0 ${size.pxToRem(size.space.XXS)};
}
&.hover {
background-color: ${palette.hoverColor(palette.MAIN)};
}
&.square {
width: 40px;
line-height: 40px;
padding: 0;
&.s {
width: 27px;
min-width: 27px;
}
}
&[disabled] {
background-color: ${palette.disableColor(palette.MAIN)};
color: ${palette.disableColor('#fff')};
cursor: not-allowed;
}
&.suffix {
justify-content: space-between;
}
&.prefix {
justify-content: left;
}
`
}}
`

const Prefix = styled.span`
${({ theme }: InjectedProps) => {
const { size } = theme
return css`
display: inline-flex;
margin-right: ${size.pxToRem(size.space.XXS)};
`
}}
`
const Suffix = styled.span`
${({ theme }: InjectedProps) => {
const { size } = theme
return css`
display: inline-flex;
margin-left: ${size.pxToRem(size.space.XXS)};
`
}}
`
export const PrimaryButton: React.FC<ButtonProps> = withTheme(injectStyle(ButtonComponent))
export const PrimaryButtonAnchor: React.FC<AnchorProps> = withTheme(
injectStyle(ButtonAnchorComponent),
)

0 comments on commit 7dce43f

Please sign in to comment.