4 changed files with 144 additions and 134 deletions
@ -0,0 +1,64 @@ |
|||
// @flow
|
|||
|
|||
import styled from 'styled-components' |
|||
import { |
|||
alignItems, |
|||
borderRadius, |
|||
boxShadow, |
|||
color, |
|||
flex, |
|||
flexWrap, |
|||
fontSize, |
|||
justifyContent, |
|||
space, |
|||
style, |
|||
} from 'styled-system' |
|||
|
|||
import fontFamily from 'styles/styled/fontFamily' |
|||
|
|||
export const styledTextAlign = style({ prop: 'textAlign', cssProperty: 'textAlign' }) |
|||
export const styledCursor = style({ prop: 'cursor', cssProperty: 'cursor' }) |
|||
|
|||
export default styled.div` |
|||
${alignItems}; |
|||
${borderRadius}; |
|||
${boxShadow}; |
|||
${color}; |
|||
${flex}; |
|||
${flexWrap}; |
|||
${fontFamily}; |
|||
${fontSize}; |
|||
${justifyContent}; |
|||
${space}; |
|||
${styledTextAlign}; |
|||
${styledCursor}; |
|||
|
|||
display: flex; |
|||
flex-shrink: ${p => (p.noShrink === true ? '0' : p.shrink === true ? '1' : '')}; |
|||
flex-grow: ${p => (p.grow === true ? '1' : p.grow || '')}; |
|||
flex-direction: ${p => (p.horizontal ? 'row' : 'column')}; |
|||
|
|||
overflow-y: ${p => (p.scroll === true ? 'auto' : '')}; |
|||
position: ${p => (p.relative ? 'relative' : p.sticky ? 'absolute' : '')}; |
|||
|
|||
${p => |
|||
p.selectable && |
|||
` |
|||
user-select: text; |
|||
cursor: text; |
|||
`};
|
|||
|
|||
${p => |
|||
p.sticky && |
|||
` |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
`};
|
|||
|
|||
> * + * { |
|||
margin-top: ${p => (!p.horizontal && p.flow ? `${p.theme.space[p.flow]}px` : '')}; |
|||
margin-left: ${p => (p.horizontal && p.flow ? `${p.theme.space[p.flow]}px` : '')}; |
|||
} |
|||
` |
@ -0,0 +1,23 @@ |
|||
// @flow
|
|||
|
|||
import React from 'react' |
|||
import styled from 'styled-components' |
|||
|
|||
import Text from 'components/base/Text' |
|||
import Box from './index' |
|||
|
|||
const RawCard = styled(Box).attrs({ bg: 'white', p: 3, boxShadow: 0, borderRadius: 1 })`` |
|||
|
|||
export default ({ title, ...props }: { title?: any }) => { |
|||
if (title) { |
|||
return ( |
|||
<Box flow={4} grow> |
|||
<Text color="dark" ff="Museo Sans" fontSize={6}> |
|||
{title} |
|||
</Text> |
|||
<RawCard grow {...props} /> |
|||
</Box> |
|||
) |
|||
} |
|||
return <RawCard {...props} /> |
|||
} |
@ -0,0 +1,54 @@ |
|||
// @flow
|
|||
|
|||
import React, { PureComponent } from 'react' |
|||
|
|||
import Box from './index' |
|||
|
|||
// Github like focus style:
|
|||
// - focus states are not visible by default
|
|||
// - first time user hit tab, enable global tab to see focus states
|
|||
const __IS_GLOBAL_TAB_ENABLED__ = false |
|||
|
|||
export default class Tabbable extends PureComponent< |
|||
any, |
|||
{ |
|||
isFocused: boolean, |
|||
}, |
|||
> { |
|||
state = { |
|||
isFocused: false, |
|||
} |
|||
|
|||
componentDidMount() { |
|||
window.addEventListener('keydown', this.handleKeydown) |
|||
} |
|||
|
|||
componentWillUnmount() { |
|||
window.removeEventListener('keydown', this.handleKeydown) |
|||
} |
|||
|
|||
handleFocus = () => { |
|||
if (!__IS_GLOBAL_TAB_ENABLED__) return |
|||
this.setState({ isFocused: true }) |
|||
} |
|||
|
|||
handleBlur = () => this.setState({ isFocused: false }) |
|||
|
|||
handleKeydown = (e: SyntheticKeyboardEvent<any>) => { |
|||
if ((e.which === 13 || e.which === 32) && this.state.isFocused && this.props.onClick) { |
|||
this.props.onClick(e) |
|||
} |
|||
} |
|||
|
|||
render() { |
|||
const { disabled } = this.props |
|||
return ( |
|||
<Box |
|||
tabIndex={disabled ? undefined : 0} |
|||
onFocus={this.handleFocus} |
|||
onBlur={this.handleBlur} |
|||
{...this.props} |
|||
/> |
|||
) |
|||
} |
|||
} |
@ -1,136 +1,5 @@ |
|||
// @flow
|
|||
|
|||
import React, { PureComponent } from 'react' |
|||
import styled from 'styled-components' |
|||
import { |
|||
alignItems, |
|||
borderRadius, |
|||
boxShadow, |
|||
color, |
|||
flex, |
|||
flexWrap, |
|||
fontSize, |
|||
justifyContent, |
|||
space, |
|||
style, |
|||
} from 'styled-system' |
|||
|
|||
import fontFamily from 'styles/styled/fontFamily' |
|||
|
|||
import Text from 'components/base/Text' |
|||
|
|||
const textAlign = style({ |
|||
prop: 'textAlign', |
|||
cssProperty: 'textAlign', |
|||
}) |
|||
|
|||
const cursor = style({ |
|||
prop: 'cursor', |
|||
cssProperty: 'cursor', |
|||
}) |
|||
|
|||
const Box = styled.div` |
|||
${alignItems}; |
|||
${borderRadius}; |
|||
${boxShadow}; |
|||
${color}; |
|||
${flex}; |
|||
${flexWrap}; |
|||
${fontFamily}; |
|||
${fontSize}; |
|||
${justifyContent}; |
|||
${space}; |
|||
${textAlign}; |
|||
${cursor}; |
|||
|
|||
display: flex; |
|||
flex-shrink: ${p => (p.noShrink === true ? '0' : p.shrink === true ? '1' : '')}; |
|||
flex-grow: ${p => (p.grow === true ? '1' : p.grow || '')}; |
|||
flex-direction: ${p => (p.horizontal ? 'row' : 'column')}; |
|||
|
|||
overflow-y: ${p => (p.scroll === true ? 'auto' : '')}; |
|||
position: ${p => (p.relative ? 'relative' : p.sticky ? 'absolute' : '')}; |
|||
|
|||
${p => |
|||
p.selectable && |
|||
` |
|||
user-select: text; |
|||
cursor: text; |
|||
`};
|
|||
|
|||
${p => |
|||
p.sticky && |
|||
` |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
`};
|
|||
|
|||
> * + * { |
|||
margin-top: ${p => (!p.horizontal && p.flow ? `${p.theme.space[p.flow]}px` : '')}; |
|||
margin-left: ${p => (p.horizontal && p.flow ? `${p.theme.space[p.flow]}px` : '')}; |
|||
} |
|||
` |
|||
// ^FIXME this `> * + * happen for all Box but we only need it when we do "grids".. which is not often. margin should be made explicit on user land.
|
|||
|
|||
const RawCard = styled(Box).attrs({ bg: 'white', p: 3, boxShadow: 0, borderRadius: 1 })`` |
|||
|
|||
export const Card = ({ title, ...props }: { title?: any }) => { |
|||
if (title) { |
|||
return ( |
|||
<Box flow={4} grow> |
|||
<Text color="dark" ff="Museo Sans" fontSize={6}> |
|||
{title} |
|||
</Text> |
|||
<RawCard grow {...props} /> |
|||
</Box> |
|||
) |
|||
} |
|||
return <RawCard {...props} /> |
|||
} |
|||
|
|||
Card.defaultProps = { |
|||
title: undefined, |
|||
} |
|||
|
|||
type TabbableState = { |
|||
isFocused: boolean, |
|||
} |
|||
|
|||
export class Tabbable extends PureComponent<any, TabbableState> { |
|||
state = { |
|||
isFocused: false, |
|||
} |
|||
|
|||
componentDidMount() { |
|||
window.addEventListener('keydown', this.handleKeydown) |
|||
} |
|||
|
|||
componentWillUnmount() { |
|||
window.removeEventListener('keydown', this.handleKeydown) |
|||
} |
|||
|
|||
handleFocus = () => this.setState({ isFocused: true }) |
|||
handleBlur = () => this.setState({ isFocused: false }) |
|||
|
|||
handleKeydown = (e: SyntheticKeyboardEvent<any>) => { |
|||
if ((e.which === 13 || e.which === 32) && this.state.isFocused && this.props.onClick) { |
|||
this.props.onClick(e) |
|||
} |
|||
} |
|||
|
|||
render() { |
|||
const { disabled } = this.props |
|||
return ( |
|||
<Box |
|||
tabIndex={disabled ? undefined : 0} |
|||
onFocus={this.handleFocus} |
|||
onBlur={this.handleBlur} |
|||
{...this.props} |
|||
/> |
|||
) |
|||
} |
|||
} |
|||
|
|||
export default Box |
|||
export default from './Box' |
|||
export { default as Tabbable } from './Tabbable' |
|||
export { default as Card } from './Card' |
|||
|
Loading…
Reference in new issue