Styled components documentation doesn't mention this case and I can't figure out the syntax.
How would I turn this styled component:
const StyledButton = styled.button`
color: red;
${props => props.disabled && css`
color: grey;
background-color: grey;
`}
`
into object notation:
const StyledButton = styled.button(props => ({
color: 'red',
------
}))
I know the following would solve this question, but for my use case I need to keep the logic from the first exemple. So this won't make it for me:
const StyledButton = styled.button(props => ({
color: props.disabled ? 'grey' : 'red',
backgroundColor: props.disabled ? 'grey' : transparent,
}))
Maybe this would be what you're after (or similar)
const StyledButton = styled.button((props) => {
const disabledStyles = {
color: 'grey',
'background-color': 'grey',
};
return {
color: 'red',
...(props.disabled && disabledStyles)
};
})
I definitely don't understand why you can't use the ternary approach you have above but I've had some weird reqs on projects too. Good luck
Related
I've changed my style in StyledButton tag but it doesn't reflect on webpage. Can you help what is wrong in this code
import React, { Component } from 'react';
import './App.css';
//import Radium, {StyleRoot} from 'radium';
import Person from './Person/Person';
import { render } from 'react-dom';
import styled from 'styled-components'
const StyledButton = styled.button `
background-color: ${props => props.alt ? 'red' : 'green'}; //Here I have define these property which is not reflecting in output
color: white;
font: inherit;
border: 1px solid blue;
padding: 8px;
cursor:pointer;
&:hover:{
background-color:${props => props.alt ? 'salmon' : 'green'}; //Hover Function is also not working
color:black;
}`;
class App extends Component {
state ={
persons : [
{id:'12', name: 'Max', age: 28},
{id:'21', name: 'Manu', age:29},
{id:'33', name: 'Nikhil', age:23}
]};
nameChangeHandler = (event, id) => {
const personIndex = this.state.persons.findIndex(p=>{
return p.id===id;
});
const person = {
... this.state.persons[personIndex]
};
person.name = event.target.value;
const persons =[...this.state.persons];
persons[personIndex]=person;
this.setState({ persons: persons
});
}
deletePersonHandler = (personIndex) =>{
//const persons = this.state.persons.slice();
//const persons = this.state.persons
const persons = [... this.state.persons];
persons.splice(personIndex,1);
this.setState({persons: persons})
}
togglePersonsHandler = ()=> {
const doesShow = this.state.showPersons;
this.setState({showPersons: !doesShow});
}
render()
{
let persons = null;
if(this.state.showPersons)
{
persons = (
<div>
{ this.state.persons.map((person, index) =>{
return <Person
click = { () => this.deletePersonHandler(index) }
name={person.name}
age={person.age}
key= {person.id}
changed={(event)=> this.nameChangeHandler(event, person.id)}/>
})}
</div>
);
//StyledButton.backgroundColor= 'red';
}
let classes = []
if(this.state.persons.length<=2)
{
classes.push('red');
}
if(this.state.persons.length<=1)
{
classes.push('bold');
}
return (
<div className = "App">
<h1>Hi there this is my first react application</h1>
<p className= {classes.join(' ')}>Hi this is really working</p>
<StyledButton
alt ={ this.state.showPersons }
onClick = {this.togglePersonsHandler}>Toggle Persons</StyledButton>
{ persons }
</div>
);
}
}
export default App;
Code just toggle the names and ages when user click on button and delete the names when click on the paragraph and adding certain classes these are all works fine.
I'm using styled component package on toggle button and it is not working properly, I don't why Please let me know if you understand
You've defined alt to be a transient prop, i.e. $alt, but you don't pass that prop to the StyledButton.
You've also a typo in your hover selector, there's a trailing colon (:): &:hover: should be :hover (the leading parent node selector & is also unnecessary).
const StyledButton = styled.button `
background-color: ${props => props.$alt ? 'red' : 'green'};
color: white;
font: inherit;
border: 1px solid blue;
padding: 8px;
cursor: pointer;
:hover {
background-color:${props => props.$alt ? 'salmon' : 'green'};
color:black;
}
`;
...
<StyledButton
$alt={this.state.showPersons} // <-- pass transient prop
onClick={this.togglePersonsHandler}
>
Toggle Persons
</StyledButton>
This was introduced in v5.1. If you didn't intend to declare a transient prop or you aren't on v5.1 or newer, then simply remove the $ and use the alt prop.
const StyledButton = styled.button `
background-color: ${props => props.alt ? 'red' : 'green'};
color: white;
font: inherit;
border: 1px solid blue;
padding: 8px;
cursor: pointer;
:hover {
background-color:${props => props.alt ? 'salmon' : 'green'};
color:black;
}
}`;
...
<StyledButton
alt={this.state.showPersons} // <-- use alt prop
onClick={this.togglePersonsHandler}
>
Toggle Persons
</StyledButton>
Demo
I'm using styled-components library in my react app and I've come across an interesting problem I wasn't able to find an elegant solution to online. What I want to achieve is to have a reusable piece of code, maybe similar to sass mixins, that would allow me to extend all my buttons with code that animates background darken on hover.
const DarkenHover = css<{ active?: boolean; normalColor: string; activeColor: string }>`
background-color: ${p => (p.active ? p.normalColor : p.activeColor)};
&:hover {
background-color: ${p => darken(0.1)(p.active ? p.normalColor : p.activeColor)};
}
transition: background-color .1s ease-in;
`;
const FooButton = styled.div<{ active?: boolean }>`
${p => DarkenHover({
active: p.active,
normalColor: "red",
activeColor: "blue",
})}
`;
const FooButton = styled.div<{ active?: boolean }>`
${p => DarkenHover({
active: p.active,
normalColor: "white",
activeColor: "green",
})}
`;
This obviously is not valid syntax but it demonstrates my use case. How can I use this DarkenHover css object with attributes?
You can save the styles in a var and reuse later.
const animation = css`
background-color: ${p => p.active ? ThemeColors.backgroundDark : "white"};
&:hover {
background-color: ${p => darken(0.1)(p.active ? p.normalColor : p.activeColor)};
}
transition: background-color .1s ease-in;
}
`;
The when you use it in another component, it should be able to access its props:
const FooButton = styled.div`
${animation};
`
Also to be able to have separate props per each styled components, those can be passed via attrs method:
const FooButton = styled.div.attrs({normalColor: '#000000' })`
${animation}
`;
<FooterLight transparent={true}/>
Is it possible to have a nested rule in definition of FooterLight for which the props value transparent is evaluated. Then it assigns 'color: white' to its children ChangelogVersion and CopyRight?
Next two questions:
Since color: white !important is the same for ChangelogVersion and CopyRight. Can these be merged together in one statement?
Does &&& work to not use !important?
export const FooterLight = styled(Navbar).attrs({fixed: 'bottom'})`
background-color: ${props => props.transparent
? 'transparent'
: 'white'};
${props => props.transparent && ChangelogVersion} {
color: white !important;
}
${props => props.transparent && CopyRight} {
color: white !important;
}
`
export const ChangelogVersion = styled(NavLink)`
&&& {
font-size: 14px !important;
padding-right: .5rem;
}
`
export const CopyRight = styled.div `
padding: .5rem 0;
color: '#777777';
font-size: 14px;
}
Sure can... You could do something like this:
export const FooterLight = styled(Navbar).attrs({fixed: 'bottom'})`
background-color: ${props => props.transparent
? 'transparent'
: 'white'};
${ChangelogVersion}, ${CopyRight} {
${props => props.transparent && "color: white !important;"}
}
`
As for your second statement, &&& might work but you're better off structuring the CSS better so it doesn't need to be !important in the first place... In you're example there's no reason for any of the importants to be there, so it's hard to offer a suggestion.
Here I want to use two style in one line css. but i got error how i add two style object in style tag reactjs.
here is my code:
const style = {
color:"black",
fontSize:16,
borderRadius:4,
border: "1px solid grey",
lineHeight: "28px",
background: "white",
padding: 3,
margin:3
}
const hoverStyle = {
color:"black",
fontSize:16,
borderRadius:4,
border: "1px solid grey",
lineHeight: "28px",
background: "yellow",
padding: 3,
margin:3
}
const highlightStyle = {
color:"black",
fontSize:16,
border: "1px solid grey",
background:"lightblue",
borderRadius:4,
lineHeight: "25px",
padding: 3,
margin:5
}
onHover(){
console.log("mouse enter")
// this.setState({hover:!this.state.hover})
}
<span id={this.props.atId} className = {this.props.classword}
style={this.state.color_black ? style: highlightStyle,this.state.hover ? hoverStyle: ''}
onClick={this.changeColor}
onMouseEnter={() => {this.onHover()}}
onMouseLeave={() => {this.onUnHover()}}
//
>
{item}
</span>
so what should i do add two style object in one line.
here i am using ternary operator. if my condition is true then print true part.
can anyone tell me how i add two style object.
help will be appreciated.
thank you
change on applying styles :
style={Object.assign({},
this.state.color_black ? style : highlightStyle,
this.state.hover && hoverStyle)}
onMouseOver={this.hoverOn}
onMouseLeave={this.hoverOff}
Working demo below :
working demo
style={{...highlightStyle , ...hoverStyle}}
This would display both styles from highlightStyle and hoverStyle.
The ... operator is called spread operator in es6. More on spread
style={this.state.color_black ? highlightStyle : (this.state.hover ? hoverStyle: '')}
I'm trying to load Radium (which is a javascript library for inline css) following instructions here.
In app.browserify.js: Radium = require("radium");.
In package.json: "radium": "0.13.4"
However when I try to use Radium in js in the app, the inline css doesn't work. Chrome dev tool indicates that Radium = module.exports(ComposedComponent)..
I'm assuming this should be an object, considering that ReactPIXI that I loaded the same way, works just fine, and the dev tool says ReactPIXI = Object {factories: Object}.
Here is my code:
AppBody = React.createClass({
mixins: [ReactMeteorData, Navigation, State, Radium.StyleResolverMixin,
Radium.BrowserStateMixin],
render: function() {
var self = this;
var styles = {
base: {
color: this.state.fontColor,
background: 'red',
states: [
{hover: {background: 'blue', color: 'red'}},
{focus: {background: 'pink', outline: 'none', color: 'yellow'}}
]
//also tried
//':hover': {background: 'blue', color: 'red'},
//':focus': {background: 'pink', outline: 'none', color: 'yellow'}
},
primary: {
background: 'green'
},
warning: {
background: 'purple'
}
};
var items = this.state.items.map(function(item, i) {
return (
<div>
<div style= {[styles.base, styles['warning']]} key={item}>
// also tried <div style = {this.buildStyles(styles)} key={item}>
{item}
</div>
<button style = {[styles.base, styles['warning']]} onClick={update} >Remove</button>
</div>
);
}.bind(this));
return (
{items}
)
The issue was resolved by wrapping the React.createComponent with Radium as instructed in the Radium documentation. Instead of using the mixins, the code now looks like this and it works as intended.
AppBody = Radium(React.createClass({
mixins: [ReactMeteorData, Navigation, State],
render: function() {
var self = this;
var styles = {
base: {
color: this.state.fontColor,
background: 'red',
':hover': {background: 'blue', color: 'red'},
':focus': {background: 'pink', outline: 'none', color: 'yellow'}
},
primary: {
background: 'green'
},
warning: {
background: 'purple'
}
};
var items = this.state.items.map(function(item, i) {
return (
<div>
<div style= {[styles.base, styles['warning']]} key={item}>
{item}
</div>
<button style = {[styles.base, styles['warning']]} onClick={update} >Remove</button>
</div>
);
}.bind(this));
return (
{items}
)
)}));