Pete Hunt's jsxstyle library is incredibly fun to use. It colocates your React component's styling and functionality in the same place and with the same syntax: props. In exchange for this enormous benefit and productivity boost, you must give up pseudo selectors like :hover
, :focus
, etc. as they are not possible with inline css. This makes things like buttons and inputs extremely challenging. For example, this is a button component from a current project of mine:
// Button.js
import React, { Component } from 'react'
import {Flex} from 'jsxstyle'
import L from '../LayoutConstants'
class Button extends Component {
constructor () {
super()
this.state = {
hovered: false
}
this.handleMouseEnter = this.handleMouseEnter.bind(this)
this.handleMouseLeave = this.handleMouseLeave.bind(this)
}
handleMouseEnter () {
this.setState({ hovered: true })
}
handleMouseLeave () {
this.setState({ hovered: false })
}
render () {
const { children, onClick, small, ...rest } = this.props
return (
<div
role='button'
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
onClick={onClick}
{...rest}
>
<Flex
alignItems='center'
justifyContent='center'
flexWrap='wrap'
backgroundColor={this.state.hovered ? L.blue : '#ffffff'}
fontSize='14px'
fontWeight='600'
lineHeight={small ? 1 : 1.43}
outline='0'
borderRadius='2px'
padding='8px 20px'
transition='.25s background ease, .25s color ease'
userSelect='none'
whiteSpace='nowrap'
borderColor={L.blue}
border='1px solid'
cursor='pointer'
color={this.state.hovered ? '#ffffff' : L.blue}>
{children}
</Flex>
</div>
)
}
}
export default Button
The extracted CSS:
.Button_0 {
align-items:center;
justify-content:center;
flex-wrap:wrap;
font-size:14px;
font-weight:600;
line-height:1;
outline:0px;
border-radius:2px;
padding:8px 20px;
transition:.25s background ease, .25s color ease;
user-select:none;
white-space:nowrap;
border:1px solid;
cursor:pointer;
display:flex;
}
What if jsxstyle's CSS extractor looked out for special reserved/configurable prop names such as hover
and focus
. Maybe these need to have a prefix such as xhover
, or maybe you could declare in a webpack loader. Regardless, after extracting a component's css classname, any styles found in the hover
prop would be immediately declared.
I'm aware that this would not bring jsxstyle to full parity with CSS pseudo-selectors, but it would solve ~80% the challenges with buttons and inputs.
import React from 'react'
import {Flex} from 'jsxstyle'
const Button = ({ onClick, children, ...props }) => (
<Flex
role='button'
fontSize='14px'
fontWeight='600'
outline='0'
lineHeight='1.43'
borderRadius='2px'
padding='8px 20px'
backgroundColor='#fff'
borderColor='#0070ff'
color='#0070ff'
whiteSpace='nowrap'
transition='.25s background ease, .25s color ease'
hover={{
background: '#0070ff',
color: '#fff'
}}
onClick={onCLick}
{...props}
>
{children}
</Flex>
)
export default Button
.Button_0 {
...
}
.Button_0:hover {
background: #0070ff;
color: #fff;
}
Yeah I think @meyer has a bunch of ideas how to make this more usable. A few ideas:
onClick
etc<Flex borderColor="red" hoverBorderColor="blue" />
? I.e. we prefixed "hover", "active" etc to all style props?