-
-
Save vjeux/8e27dd06c64dc566bfee705e1b19cb18 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Solution #1: Generic Override (like CSS) | |
var ButtonGroup = React.createClass({ | |
render() { | |
return <div>{this.props.buttons.map((btn, i) => | |
<Button style={{ | |
...(i !== 0 && {marginLeft: 0}) | |
...(i !== this.props.buttons.length - 1 && {marginRight: 0}) | |
}} /> | |
)}</div>; | |
} | |
}); | |
var Button = React.createClass({ | |
render() { | |
return <div style={{ | |
...styles.button, | |
...this.props.style, | |
}} />; | |
} | |
}); | |
// Solution #2: Encapsulated behavior | |
var ButtonGroup = React.createClass({ | |
render() { | |
return <div>{this.props.buttons.map((btn, i) => | |
<Button | |
hasLeftSibling={i !== 0} | |
hasRightSibling={i !== this.props.buttons.length - 1} | |
/> | |
)}</div>; | |
} | |
}); | |
var Button = React.createClass({ | |
render() { | |
return <div style={{ | |
...styles.button, | |
...(hasLeftSibling && {marginLeft: 0}), | |
...(hasRightSibling && {marginRight: 0}), | |
}} />; | |
} | |
}); |
here's a take on the above with glamor -
let addToButtStyle = merge(
not(':first-child', { margin:0 }),
lastChild({ marginRight: 10 })
)
class ButtonGroup extends React.Component {
render() {
return <div>
{this.props.labels.map(label =>
<Button style={addToButtStyle}>{label}</Button>)}
</div>
}
}
let defaultStyle = {
marginLeft: 10,
display: 'inline',
border: '1px solid black'
}
class Button extends React.Component {
render() {
return <div {...merge(defaultStyle, this.props.style)}>{this.props.children}</div>
}
}
// alternately, with context
@btnmerge(merge( // assume this decorator magically comes from button.js
not(':first-child', { margin:0 }),
lastChild({ marginRight: 10 })
))
class ButtonGroup extends React.Component {
render() {
return <div>
{this.props.labels.map(label =>
<Button>{label}</Button>) // no props!
}
</div>
}
}
// button.js
let defaultStyle = {
marginLeft: 10,
display: 'inline',
border: '1px solid black'
}
class Button extends React.Component {
static contextTypes = {
// yada yada
}
render() {
return <div {...merge(defaultStyle, this.context.buttStyle)}>{this.props.children}</div>
}
}
Trying to move discussion to styled-components/spec#5.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've been struggling with this as well, working on Elemental UI.
@taion's example is exactly where we're falling down right now. The user (React library consumer) should control the children in the
<InlineForm>
component, which may even be nested:You want the
<LoginButton>
component to be in control of its own styles and understand how to change them when it's wrapped inside an<InlineForm>
component, rather than being on its own. This is an inversion of control to the first example, where you'd have to encapsulate understanding of how<LoginButton>
(and any other component)'s styles should change inside the Form component.I think that React context is a reasonable way to achieve this at a library level. It doesn't answer how we detect things like
firstChild
andlastChild
. Maybe adding those props in the render loop is the right answer. This solution covers most of the requirements I've got: