This demo is demonstrate using fela to build dynamically styled components. We will building a button, which will cover using styling through props, a theme file, and styling based on some state (hover, active, focus, etc...). The only files that should need changing are components/Button.tsx
and theme/index.tsx
- to see a completed version of the demo that is customizable through theming
git checkout completed
-
Why use a CSS-in-JS framework
-
High level what is fela doing under the hood
-
Building a button in
components/Button.tsx
-
Update button to use Fela Component (you will recieve an error until ButtonStyle is defined)
class Button extends React.Component<IButton, {}> {
public render() {
return (
<FelaComponent
rule={ButtonStyle}
render={({ className }: any) => {
return (
<button className={className}>
{children}
</button>
);
}}
/>
);
}
}
- Add some default styles to the button using a rule named
ButtonStyle
function ButtonStyle(props: IButton): any {
return {
color: "grey",
borderColor: "rgb(230, 232, 233)",
borderWidth: "1px",
borderStyle: "solid",
borderRadius: "4px",
cursor: "pointer",
padding: "8px 10px",
}
}
- Add some styling for psuedo classes
function ButtonStyle(props: IButton): any {
return {
color: "grey",
borderColor: "grey",
borderWidth: "1px",
borderStyle: "solid",
borderRadius: "4px",
cursor: "pointer",
padding: "8px 10px",
onFocus: {
outline: "none"
},
onHover: {
color: "lightgrey",
borderColor: "lightgrey"
},
onActive: {
color: "darkgrey",
borderColor: "darkgrey"
}
}
}
- Style Button as a function of props, lets add a prop
bg
and add background and a disabled state toButtonStyle
function ButtonStyle(props: IButton): any {
const style: any = {
background: props.bg,
borderColor: "rgb(230, 232, 233)",
borderWidth: "1px",
borderStyle: "solid",
borderRadius: "4px",
cursor: "pointer",
padding: "8px 10px",
onFocus: {
outline: "none"
},
onHover: {
color: "lightgrey",
borderColor: "lightgrey"
},
onActive: {
color: "darkgrey",
borderColor: "darkgrey"
}
}
if (props.disabled) {
style.cursor = "not-allowed";
style.onHover = undefined;
}
return style
}
- Use a theme file to style button
in theme/index.tsx
lets define "primary"
export default {
primary: {
background: "mediumseagreen",
color: "green",
onActive: {
background: "darkgreen"
},
onHover: {
background: "lightgreen"
}
}
}
now add a primary prop to button
lastly update your ButtonStyle
function
function ButtonStyle(props: IButton): any {
const style: any = {
background: props.bg,
borderColor: "rgb(230, 232, 233)",
borderWidth: "1px",
borderStyle: "solid",
borderRadius: "4px",
cursor: "pointer",
padding: "8px 10px",
onFocus: {
outline: "none"
},
onHover: {
color: "lightgrey",
borderColor: "lightgrey"
},
onActive: {
color: "darkgrey",
borderColor: "darkgrey"
}
}
if (props.primary) {
_.merge(style, props.theme.primary)
}
if (props.disabled) {
style.cursor = "not-allowed";
style.onHover = undefined;
}
return style