Styling react-toolbox elements with className - javascript

I seem to be having some issues in regards to styling the components without using a theme. I just want to change a couple of colors without needing to create a new theme per element.
In this case, I just want to change the color of the bar to a brownish color and right now I have an input class as follows:
import style from './style.scss'
const TextInput = (props) => {
<Input className={style.textInput} {...props} />
}
And in my style.scss file:
.textInput {
.bar {
background-color: #663300;
}
}
Any help would be appreciated.

ClassName doesn't work like that.
You can't pass a Css style to a className, that is wrong.
Either pass the class names you want to apply as a string (in your case I guess it would be className="textInput bar") or you can create a className with classNames library (in any case the final result will be a string).
Just make sure you're styles are included in the page that the component is going to render and react will be smart enough to render the correct css class for each component.
As you can check in here ClassName is a string

Related

next js className haven't been set

I've just started playing with next js. so I want to use css as module and setup classname for nav, but in rendered DOM this classname doesn't exist. I can see generated styles by webpack in "head" tag, but I dont see classname on my nav tag.
import React from "react";
import styles from './NavigationContainer.module.scss';
type Props = {};
const NavigationContainer: React.FC<Props> = ({children}) => {
return <nav className={styles.mainNavigationContainer}>{children}</nav>
};
export default NavigationContainer;
In JS, we cannot use - as a variable name it is considered as a minus to do the math.
It is a good idea to rename the CSS selector to .mainNavigationContainer so that the Next Js can get the correct CSS styles.
The JS part will remain the same.
https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css

Design system: styles override using TailwindCSS

I am trying to create a Design System using ReactJS and TailwindCSS.
I created a default Button component with basic styling as follow:
import React from "react";
import classNames from "classnames";
const Button = React.forwardRef(
({ children, className = "", onClick }, ref) => {
const buttonClasses = classNames(
className,
"w-24 py-3 bg-red-500 text-white font-bold rounded-full"
);
const commonProps = {
className: buttonClasses,
onClick,
ref
};
return React.createElement(
"button",
{ ...commonProps, type: "button" },
children
);
}
);
export default Button;
I then use the Button in my page like:
import Button from "../src/components/Button";
export default function IndexPage() {
return (
<div>
<Button onClick={() => console.log("TODO")}>Vanilla Button</Button>
<div className="h-2" />
<Button
className="w-6 py-2 bg-blue-500 rounded-sm"
onClick={() => console.log("TODO")}
>
Custom Button
</Button>
</div>
);
}
This is what is displayed:
Some attributes are overridden like the background-color but some aren't (the rest).
The reason is the classes provided by TailwindCSS are written in an order where bg-blue-500 is placed after bg-red-500, therefore overriding it. On the other hand, the other classes provided in the custom button are written before the classes on the base button, therefore not overriding the styles.
This behavior is happening with TailwindCSS but might occurs with any other styling approach as far as the class order can produce this scenario.
Do you have any workaround / solution to enable this kind of customisation?
Here is a full CodeSanbox if needed.
One approach is to extract classes from your component using Tailwind's #apply in your components layer.
/* main.css */
#layer components {
.base-button {
#apply w-24 py-3 bg-red-500 text-white font-bold rounded-full;
}
}
// Button.js
const Button = React.forwardRef(({ children, className = "", onClick }, ref) => {
const buttonClasses = classNames("base-button", className);
// ...
);
This will extract the styles into the new base-button class, meaning they can easily be overwritten by the utility classes you pass to the Button component.
Another approach to create reusable React components using Tailwind is as follows..
Read this gist
https://gist.github.com/RobinMalfait/490a0560a7cfde985d435ad93f8094c5
for an excellent example.
Avoid using className as a prop. Otherwise, it'd be difficult for you to know what state your component is in. If you want to add an extra class, you can easily extend.
You need a helper for combining classname strings conditionally. Robert, the writer of this gist, shared the helper function also with us:
export function classNames(...classes: (false | null | undefined | string)[]) {
return classes.filter(Boolean).join(" ");
}
To have Tailwind CSS override material theming (or something else for that matter) one could apply !important to all tailwind utilities with configuration to module.exports.
The important option lets you control whether or not Tailwind’s utilities should be marked with !important. This can be really useful when using Tailwind with existing CSS that has high specificity selectors.
To generate utilities as !important, set the important key in your configuration options to true:
tailwind.config.js
module.exports = {
important: true
}
https://tailwindcss.com/docs/configuration#important
To solve, I recommend doing what Bootstrap does. Use a default class for your default button like:
.button {
width: 2rem;
background-color: red;
border-radius: 0.25rem;
}
Then when customizing a button you should apply classes that either come after the button class in your CSS file, or come in a different CSS file that is called after your default CSS file, or use the !important declaration.
Old answer
Use your browser developer tools to observe how your browser is loading CSS styles on an element. For example, in Chrome, right-click on the custom button and select "Inspect". A DevTools window will open and the element will be highlighted in the DOM.
On the right, you should have a Styles pane. There, you'll see a list of all the CSS styles being applied to the element. Styles with strikethroughs are being overridden by styles called by other CSS classes or inline styles.
In your case, the custom button has both the "CommonProps" classes and the classes you're adding in IndexPage. For example, both class w-6 and class w-24.
Class w-24 is overriding class w-6 because of CSS precedence. Read more about CSS precedence here. Check out rule #3 in the accepted answer. I think that's what's happening to you.
To solve, you may want to remove some classes from commonProps. Or use the !important declaration on some classes. This is the part of your design system that you need to think through. Look at how other systems like Bootstrap have done it.

Change id of multiple item of array React

I'm using React JSX with Hooks, and I have a problem. I'd like to change a p id of all the vector items when I click on one of them.
In particular:
I have a vector and for every item of this vector I call a component:
cards.map((item, index) => (<Card key={index} card={item} index={index} hover={hover} /> ))}
Inside the Card componet I have the div tag with onClick event: <div onClick={TitleTransition}>
The TitleTransition function changes a state of click: function TitleTransition() { setClick(true);}
This is the p tag inside the Card component: <p id={click ? "titleTransition" : ""}>{props.card.p1}</p>
Hence, when I click in one of these item (I have called them card) I'd like to change the p id for all the items (cards).
Anyone could help me? Thank you!
this is more a guess answer than anything else, but i'm unable to comment before 50 reputation.
If i had to guess, I'd say you are trying to change the styling onClick on a Card component and maybe additionally reset the styling of the other cards.
In that case you should try to use instead of the id prop of the p tag either the style or the className prop. I imagine you have a css file with something similar to
#titleTransition {
/* Your styling if element is clicked */
}
If you use the className prop, which is the React equivalent of the html class attribute, you have to change your css line to something like
.titleTransition {
/* Your styling if element is clicked */
}
or
:global(.titleTransition) {
/* Your styling if element is clicked */
}
or whatever way of styling you prefer in react, there are so many.
If you want to change all Card elements, onClick you will probably have to save the dataset for the cards in a state in their parent component (where the .map(...) is used to add the elements) and add an attribute to that data, such as 'isClicked'. Then define a function that takes the index of the and add the function to the props of the Card, like () and call that function in the Card by adding it in the . Then use it in the :
<div onClick={() => props.onChildClickChangeDataState(props.index)} />
This will trigger the function in the parent, where you can iterate over the dataset and change the isClicked attribute to the value you like.
To change the styling you then can use
<p className={props.item.isClicked ? 'titleTransition' : '' />
This an approach that helps you changing all at once as well as avoiding the invalid HTML #CertainPerformance mentioned.
I hope i guessed right and it helps you on the right track. It is hard to help you more at the moment. Maybe you could share the Code of you Card Parent Component, Card, your CSS file, and why you would like to change all id's at once. Then somebody might be able to help you a bit better.

Is there a way to increase specificity by adding the element with Emotion?

We have a styled component that and when it compiles it adds a class name such as this:
<div class="app">
<a class="css-hash">link</a>
</div>
This is all good, except for instances where someone has CSS declared similar to the following:
.app a { color: red }
The .css-hash is no longer picked up if it has a color rule. This could be resolved if we could have emotion create the CSS in a manner like "a.css-hash". In that case whatever we have as part of emotion's .css-hash would be applied over other styles that are declared elsewhere in the page.
It's possible that we're approaching this incorrectly. I tried searching for a solution in various places, but with no luck.
You can use the & selector more than once to increase specificity:
import { css } from '#emotion/css'
const myClassName = css({
// Using `&` twice to increase specificity
'&&': {
backgroundColor: 'red'
}
})
const MyComponent = () => {
return <div className={myClassName}>hello</div>
}
& will simply copy your classname, so if your class name is .css-hash, then && will become .css-hash.css-hash. You can use more & to further increase specificity.
See Sass Ampersand docs.

Dynamic CSS via prop using CSSModules with React component

I'm learning how to use css modules with react, below is a working example of a checkbox here's what it looks like (pure HTML + CSS fiddle) without react.
import React from 'react'
import CSSModules from 'react-css-modules'
import styles from './checkbox.css'
export function Checkbox (props) {
return <div styleName="checkbox--container">
<input styleName="checkbox" type="checkbox" {...props}/>
<span styleName="checkbox--styled"></span>
</div>
}
export default CSSModules(Checkbox, styles)
This is great and all, but let's say my client comes back and wants me to change the checkbox color. Fine, seems easy enough? That fiddle above shows that there is a couple of hex-codes (#479ccf) for border and within the SVG background image. Ideally I'd be able to pass along a react prop that allows you to do something like this <Checkbox color="#666333"/> and blam! However I can't find any documentation / way to get information from the component to the CSS file.
What does this mean?
I know what the react community is going to say, that particular set of CSS isn't ideal. It can be written in javascript within the component and from there you can set the inline styles of the pieces of the checkbox to the prop color. I'm pretty sure this is possible. Is this necessary? I'd have to refactor the ::after code, question about that.
I started on making the SVG functions.
function SVGDash (color) {
return `data:image/svg+xml;charset=US-ASCII,<svg%20xmlns%3D"http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg"%20viewBox%3D"0%200%2012%2012"%20enable-background%3D"new%200%200%2012%2012"><style%20type%3D"text%2Fcss">circle%2Cellipse%2Cline%2Cpath%2Cpolygon%2Cpolyline%2Crect%2Ctext%7Bfill%3A%23${color}%20%21important%3B%20%7D<%2Fstyle><path%20d%3D"M6%200"%2F><path%20d%3D"M.8%207C.3%207%200%206.7%200%206.2v-.4c0-.5.3-.8.8-.8h10.5c.4%200%20.7.3.7.8v.5c0%20.4-.3.7-.8.7H.8z"%2F><%2Fsvg>`
}
function SVGCheck (color) {
return `data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20enable-background%3D%22new%200%200%2024%2024%22%3E%3Cstyle%20type%3D%22text%2Fcss%22%3Ecircle%2Cellipse%2Cline%2Cpath%2Cpolygon%2Cpolyline%2Crect%2Ctext%7Bfill%3A%23${color}%20%21important%3B%20%7D%3C%2Fstyle%3E%3Cpath%20d%3D%22M23.6%205L22%203.4c-.5-.4-1.2-.4-1.7%200L8.5%2015l-4.8-4.7c-.5-.4-1.2-.4-1.7%200L.3%2011.9c-.5.4-.5%201.2%200%201.6l7.3%207.1c.5.4%201.2.4%201.7%200l14.3-14c.5-.4.5-1.1%200-1.6z%22%2F%3E%3C%2Fsvg%3E`
}
You could create a different class composing the class you want to change the color:
.checkbox--styled-red {
composes: checkbox--styled;
background-image: url("data:image .... FF0000 ....");
}
And set it in the component when you get the matching props.color:
import React from 'react'
import CSSModules from 'react-css-modules'
import styles from './checkbox.css'
function getStyleNameForColor(color) {
colorToStyleName = {
red: 'checkbox--styled-red'
};
return colorToStyleName[color] || 'checkbox--styled';
}
export function Checkbox (props) {
return <div styleName="checkbox--container">
<input styleName="checkbox" type="checkbox" {...props}/>
<span styleName={getStyleNameForColor(props.color)}></span>
</div>
}
export default CSSModules(Checkbox, styles)
Better yet, use classnames instead of getStyleNameFor(color).

Categories