[Recompose] When nesting affects Style
In CSS we use the descendant selector to style elements based on their nesting. Thankfully in React we don't need to consider this most of the time because this nesting of elements happens within the bounds of a single component.
However occasionally the nesting of components affects the styles. In these rare cases we can use context to influence styles yielding a user friendly api to our components.
The html structure should looks like:
<ButtonGroup isVertical>
<Button element={'a'}>Click</Button>
<Button element={'a'}>Click</Button>
</ButtonGroup>
So what ButtonGroup should do is affect its child elements alignments and styling (marign or padding).

So if html is like:
<ButtonGroup>
<Button element={'a'}>Click</Button>
<Button element={'a'}>Click</Button>
</ButtonGroup>
It should looks like:

In the article, only point out 3 important thing, so rest of stuff, go to the github.
1. Styling ButtonGroup component itself, add padding it.
We have a default theme.js file to config the theme:
export default {
color: {
keyColor: '#3f8bae',
textLight: '#fff',
},
number: {
buttonRadius: 5,
buttonGroupSpace: 6,
},
string: {
mainFontFamily: 'sans-serif'
}
}
'buttonGroupSpace' is the one to control the padding for ButtonGroup.
And we have the function to modify style according to the theme ready in hocs.js:
export const themeStyle = mapThemeToStyle => mapProps(
props => {
const { theme, style } = props; return {
...props,
style: [
mapThemeToStyle(theme, props),
style
]
};
}
);
So what we need to do is give 'mapThemeToStyle' fucntion to enable it modify the style according to the theme.
ButtonGroup.js:
import React, {PropTypes} from 'react';
import {
addStyle,
getTheme,
themeStyle
} from './hocs';
import {
setDisplayName,
compose
} from 'recompose';
import Radium from 'radium';
const mapThemeToStyle = ({number}, porps) => ({
padding: (number.buttonGroupSpace || 6) * 1
});
const ButtonGroup = ({ children, ...rest }) => (
<div {...rest}>
{children}
</div>
);
const enhance = compose(
setDisplayName('ButtonGroup'),
getTheme,
themeStyle(mapThemeToStyle),
addStyle({
padding: 6,
display: 'flex'
}),
Radium
);
export default enhance(ButtonGroup);
Notice that 'themeStyle' can override 'addStyle' function, 'compose' read from buttom to top.
2. Pass context down from ButtonGroup to Button.
For the Buttons inside ButtonGroup, we want each has some margin instead of stick with each other. So we need one way to tell whether the Buttons are inside ButtonGroup or not.
One way is to use Context. From ButtonGroup we provide a context called 'buttonGroup', boolean value.
We can use recompose's withContext method:
import React, {PropTypes} from 'react';
import {
addStyle,
getTheme,
themeStyle
} from './hocs';
import {
setDisplayName,
withContext,
compose
} from 'recompose';
import Radium from 'radium';
const mapThemeToStyle = ({number}, porps) => ({
padding: (number.buttonGroupSpace || 6) * 1
});
const ButtonGroup = ({ children, ...rest }) => (
<div {...rest}>
{children}
</div>
);
const enhance = compose(
setDisplayName('ButtonGroup'),
getTheme,
themeStyle(mapThemeToStyle),
withContext(
{buttonGroup: PropTypes.bool}, // define the context type
(props) => ({buttonGroup: true}) // set the value of context
),
addStyle({
padding: 60,
display: 'flex'
}),
Radium
);
export default enhance(ButtonGroup);
Now, because the concept of 'Context' is for re-useable. We put 'buttonGroup' context into hocs.js:
import {
getContext
} from 'recompose';
export const getButtonGroup = getContext({
buttonGroup: PropTypes.bool
});
It uses 'getContext' from recompose lib.
Now, in the Button.js, we can get the context on props:
import React from 'react';
import {
mapProps,
compose,
defaultProps,
setDisplayName,
componentFromProp
} from 'recompose';
import Radium from 'radium'; import {
getTheme,
themeStyle,
addStyle,
getButtonGroup
} from './hocs'; const mapThemeToStyle = ({
color,
number,
string
}, props) => {
return {
...(color.keyColor &&
{backgroundColor: color.keyColor} || {}
),
...(props.buttonGroup &&
{margin: number.buttonGroupSpace} || {}
),
color: color.textLight,
borderRadius: number.buttonRadius,
fontFamily: string.mainFontFamily
};
}; const style = {
backgroundColor: 'red',
borderWidth: 0,
borderStyle: 'solid',
boxSizing: 'border-box',
fontFamily: 'sans-serif',
fontSize: 18,
borderRadius: 3,
fontWeight: 100,
padding: 12,
verticalAlign: 'middle',
whiteSpace: 'nowrap',
color: 'white',
alignItems: 'center',
justifyContent: 'center',
textDecoration: 'none',
display: 'flex',
flex: 1,
cursor: 'pointer',
':hover': {
backgroundColor: 'purple'
}
}; const enhance = compose(
getButtonGroup,
getTheme, // using the container's defined theme
themeStyle(mapThemeToStyle), // apply the default theme to the component
addStyle(style),
setDisplayName('Button'),
defaultProps({
element: 'button'
}),
Radium
);
export default enhance(componentFromProp('element'));
Once 'buttonGroup' is true, it will add margin for each Buttons inside ButtonGroup.
3. 'isVertical' prop.
We can add this prop on to the html:
<ButtonGroup isVertical>
<Button element={'a'}>Click</Button>
<Button element={'a'}>Click</Button>
</ButtonGroup>
Then in the ButtonGroup.js, we can check that whether this props exists, if yes, then set display direction to 'column' otherwise to 'row'.
import React, {PropTypes} from 'react';
import {
addStyle,
getTheme,
themeStyle
} from './hocs';
import {
setDisplayName,
withContext,
compose
} from 'recompose';
import Radium from 'radium';
const mapThemeToStyle = ({number}, porps) => ({
padding: (number.buttonGroupSpace || ) * ,
flexDirection: porps.isVertical ? 'column': 'row'
});
const ButtonGroup = ({ children, ...rest }) => (
<div {...rest}>
{children}
</div>
);
const enhance = compose(
setDisplayName('ButtonGroup'),
getTheme,
themeStyle(mapThemeToStyle),
withContext(
{buttonGroup: PropTypes.bool},
(props) => ({buttonGroup: true})
),
addStyle({
padding: ,
display: 'flex'
}),
Radium
);
export default enhance(ButtonGroup);
[Recompose] When nesting affects Style的更多相关文章
- 《C Elements of Style》 书摘
<C Elements of Style> 书摘 学完C语言和数据结构后,虽然能解决一些问题,但总觉得自己写的程序丑陋,不专业.这时候看到了Steve Oualline写的<C El ...
- WPF整理-Style
"Consistency in a user interface is an important trait; there are many facets of consistency, ...
- A CIRCULAR PROGRESSBAR STYLE USING AN ATTACHED VIEWMODEL
This blog post describes how to re-template the Silverlight ProgressBar control to render a circular ...
- BootStrap入门教程 (一) :手脚架Scaffolding(全局样式(Global Style),格网系统(Grid System),流式格网(Fluid grid System),自定义(Customing),布局(Layouts))
2011年,twitter的“一小撮”工程师为了提高他们内部的分析和管理能力,用业余时间为他们的产品构建了一套易用.优雅.灵活.可扩展的前端工具集--BootStrap.Bootstrap由MARK ...
- linux c coding style
Linux kernel coding style This is a short document describing the preferred coding style for the lin ...
- [中英对照]Linux kernel coding style | Linux内核编码风格
Linux kernel coding style | Linux内核编码风格 This is a short document describing the preferred coding sty ...
- Google JavaScript Style Guide
转自:http://google.github.io/styleguide/javascriptguide.xml Google JavaScript Style Guide Revision 2.9 ...
- [Recompose] Compute Expensive Props Lazily using Recompose
Learn how to use the 'withPropsOnChange' higher order component to help ensure that expensive prop c ...
- [Recompose] Show a Spinner While a Component is Loading using Recompose
Learn how to use the 'branch' and 'renderComponent' higher-order components to show a spinner while ...
随机推荐
- 读书笔记-Java设计模式
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! Java的封装性很好,拿访问控制符来讲,没有权限的类或方法是不能访问的.如public,都可访问:p ...
- Leetcode:populating_next_right_pointers_in_each_node题解
一. 题目 对于结构体:struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } ...
- Xcode7 的两个小坑
Xcode7 还在 beta.时不时崩一下什么的倒也是预料之中的事.没料到的是之前用着好好的,今天升完 El Capitan 之后,模拟器竟然不见了,设备倒是在 schema 栏右边里能看到.只是注明 ...
- Google Web Toolkit(GWT) 在windows下环境搭建
1.什么是GWT? Google Web Toolkit(简称GWT,读作/ˈɡwɪt/),是一个前端使用JavaScript,后端使用Java的AJAX framework,以Apache许可证2. ...
- Maven在dos窗口中的命令
转自:https://www.cnblogs.com/zyjava/p/4310957.html 1.配置环境变量 MAVEN_HOME : D:\apache-maven-3.0.2 MAVEN : ...
- UVA 11800 - Determine the Shape 几何
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- C++卷积神经网络实例:tiny_cnn代码具体解释(8)——partial_connected_layer层结构类分析(上)
在之前的博文中我们已经将顶层的网络结构都介绍完毕,包括卷积层.下採样层.全连接层,在这篇博文中主要有两个任务.一是总体贯通一下卷积神经网络在对图像进行卷积处理的整个流程,二是继续我们的类分析.这次须要 ...
- POJ 3169 Layout (HDU 3592) 差分约束
http://poj.org/problem?id=3169 http://acm.hdu.edu.cn/showproblem.php?pid=3592 题目大意: 一些母牛按序号排成一条直线.有两 ...
- C API函数描写叙述(S-W)
25.2.3.59. mysql_select_db() int mysql_select_db(MYSQL *mysql, const char *db) 描写叙述 使由db指定的数据库成为由mys ...
- Activex调试以及m_hWnd为空 解决办法
1. 点击[开始]->[运行] 命令:regedit.2. 定位到HKEY_LOCALMACHINE -> SOFTWARE -> Microsoft -> Internet ...