2

I am implementing a custom color theme module. Simply the user selects two separate colors (a primary and secondary that are ANY hex value) and save the value in state. I use these colors to set custom dynamic styles to components in my application such as:

<Link style={{backgroundColor: this.props.myprofile.primaryColor}} to={href} />

This was working fine except for 2 issues.

  1. It takes forever adding the logic to each component. I would rather be able to set a className and call the logic on every element with that className.

  2. Psuedo Classes. Psuedo Classes such as :hover and :focus do not mix well with inline styling. I know about and have used Radium, but I would prefer to find a different solution.

Sequential
  • 1,455
  • 2
  • 17
  • 27
  • What is preventing you from setting a value in `className`, exactly? ES6 allows you to use [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals), which you can fill in with a ternary expression at runtime for `className`. e.g. ``` – Akshat Mahajan May 08 '17 at 22:35
  • Hmmm, haven't tried this. Let me try and implement. @AkshatMahajan – Sequential May 08 '17 at 22:41
  • @AkshatMahajan This will limit me to certain values if I'm not mistaken. I would like to let the user set their own value of any Hex color, save it in state, and then use that value. Wouldn't this make it so I have to create a class for every color I want the user to have access to? – Sequential May 08 '17 at 22:47
  • Well, yes. I presumed when you said "I would rather be able to set a `className` and call the logic on every element with that `className`." that that was an acceptable option. – Akshat Mahajan May 08 '17 at 22:56
  • @AkshatMahajan apologies I have defined that issue and Updated the question. – Sequential May 08 '17 at 22:57

2 Answers2

0

React doesn't have any special control over CSS classes, it's the same as vanilla javascript. So you won't be able to manipulate pseudo elements for the same reason.

1) You can use React's state to set a classname conditionally, inside the render method. In this example I'm using a module called classnames but you can handle this logic however you like.

render() {
 const isActive = this.state.isActive
 const styles = classNames({
  button: true,
  'is-active': isActive
 })

 return (
  <div className={styles}></div>
  
 )

}
/* evaluates to

<div className="button is-active"></div>

*/

2) There's no real solution for javascript with pseudo classes. The best you can do is add classes you've defined in your CSS files that have pseudo selectors already.

  • So I can not let the user select any Hex color he or she wants. It has to be a predefined set of values defined in classes? – Sequential May 08 '17 at 22:52
  • 1
    You definitely can do that, if you apply the values to the element's `style` property. But you won't have access to :before and :after selectors. –  May 08 '17 at 22:54
  • So exactly what I was doing? a trade-off. I don't like these situations :/ Thank you for your help. – Sequential May 08 '17 at 22:58
  • No problem. You'll just have to find a solution that doesn't involve pseudo elements. –  May 08 '17 at 22:59
  • Actually, if you use Radium, it works. As much as I wanted to avoid it. I'll post the solution, Using Radium – Sequential May 08 '17 at 23:05
0

So it seems the best solution I could personally find was still using my style method, but I was also forced to use Radium.

The dynamic of what I am trying to do makes using inline styles a necessity it seems because a CSS stylesheet can not be set by state dynamically unless there is a class for every case on the hexadecimal chart (which is what I want as options for my Users).

NOTE: Is important to understand when viewing this that the main reason for this decision is because the options I want for the user is every value the hex color chart can yield.

This is a dreadful way of doing this needing apply a style attribute containing the logic, but for the sake of the feature must be done to every component. This beats writing a class for every hex value.

To solve the issue with Psuedo classes I am using Radium for use of :hover and :focus. Not the solution I wanted from my original question, but the best I've got at the moment.

So the code if using Psuedo Classes looks something like this...

import Radium from 'radium'

<div key={i} style={{backgroundColor: primaryColor, ':hover': {backgroundColor: 'yellow'}}} />

const radMyComponent = Radium(MyComponent)

export default connect(mapStateToProps, mapDispatchToProps)(radMyComponent)

If anyone has a better solution. Please post. I would love to see.

Sequential
  • 1,455
  • 2
  • 17
  • 27