How to pass custom class name on react and use scss? - reactjs

I am trying to create a react component that has the class name as props being passed,
I have managed sending the props part successfully, however when I try to set the scss for the updated class name, I could not find a way to fix that, all of your input is appreciated.
Code of the component
Code of injecting the custom style class
Styles of the Variation
Output
Output of the Variation Class
Output of the Stylesheet
not sure what I am missing to connect all of them.
Thanks in advance.

As mentioned by Phil, your SCSS should be using &.secondary as the selector.
As for the difference in your scss class IDs and them not matching when you pass ${variant} to the className, your issue is that you are passing a raw string as the variant to the className and are using CSS modules for your SCSS (this is what handles namespacing them/adding the unique characters). To fix this, you need to use the imported style rather than a raw string for the className.
The way I usually address this is with an enum as the prop for different variants, or if there are only two a boolean, and then apply the imported style accordingly. A quick example of this, using your code would be:
const SectionTitle: FC<SectionTitleProps> = ({ title, isSecondary = false }) => (
<h3
className={`${styles.SectionTitle}${isSecondary ? styles.secondary : ''}`}
...
>
...
</h3>
);
I also find the classnames library helpful for this. It allows you to achieve the above with something I find a bit more readable, such as:
<h3
className={classNames(styles.SectionTitle, { [styles.secondary]: isSecondary } )}
...
>
...
</h3>
EDIT: Also including an example using classnames with an enum for different variants:
enum TitleVarient {
Default,
Secondary,
Accent,
}
const SectionTitle: FC<SectionTitleProps> = ({
title,
variant = TitleVarient.Default,
}) => (
<h3
className={classNames(styles.SectionTitle, {
[styles.secondary]: variant === TitleVarient.Secondary,
[styles.accent]: variant === TitleVarient.Accent,
})}
...
>
...
</h3>
);

Related

How do you use Tailwind animate classes with React Hooks?

For example - add animate-ping upon new message from a web-socket.
Tailwind just-in-time is likely to be the reason why you can't do that.
Basically, if animate-ping is not scraped in your files, adding it through Javascript or any other way later will simply not work, as the CSS file generated will not include animate-ping.
You should likely make your very own class in your CSS, even if it means using #apply directive of Tailwind. Adding Tailwind class later on in the DOM that were never parsed at build time will simply.. not works.
To conditionally show a class would be something like this:
function Notification() {
const [isNotification, setIsNotification] = useState(false);
return (
<div className={` ${isNotification ? "animate-ping" : null} h-2 w-2 m-5 bg-sky-400 rounded-full`}></div>
);
}

How can i dynamically change images as Background in TailwindCSS?

I want to make a carousel, where the background is changing, i don't want to use the <img/> tag! I set the value as described in the documentation: https://tailwindcss.com/docs/background-image#arbitrary-values
My Code:
import React from 'react';
type CarouselProps = {
img: string;
};
const Carousel = ({ img }: CarouselProps) => {
return (
<div
className={`col-span-full bg-[url(${img})] bg-cover grid grid-cols-12 gap-6`}
> ...
</div>
);
};
When i set the String i pass to the Component hardcoded it works but when i use curly Braces and $ it doesn't. In addition i don't want to define my Background-Images in the tailwind.conf.js
The Error:
ERROR in ./src/index.css (./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5]
.use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[1].oneOf[5].use[2]!
./node_modules/source-map-loader/dist/cjs.js!./src/index.css) 9:36-70
i don't want to define my Background-Images in the tailwind.conf.js
Well you have to. What you're trying to do isn't supported.
The way Tailwind scans your source code for classes is intentionally
very simple — we don’t actually parse or execute any of your code in
the language it’s written in, we just use regular expressions to
extract every string that could possibly be a class name.
so tailwind has no idea what your React code actually means. So it's simply not going to work.
Tailwind does not support dynamic class names:
Don't construct class names dynamically
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
you should customise your theme to include the image url:
You can add your own background images by editing the
theme.backgroundImage section of your tailwind.config.js file:
tailwind.config.js
module.exports = {
theme: {
extend: {
backgroundImage: {
'hero-pattern': "url('/img/hero-pattern.svg')",
'footer-texture': "url('/img/footer-texture.png')",
}
}
}
}
The solution is to use the style attribute. Thanks for helping :)
<div
className="col-span-full bg- bg-cover grid grid-cols-12 gap-6"
style={{
backgroundImage: `url(${img})`,
}}
>

#tippy.js/react allowHTML

In react Tippy I cannot make work some properties of tippy. I want allowHTML in Tippy.
Here is my code:
<Tippy
// content={<div dangerouslySetInnerHTML={{__html: tooltip}} />}
content={tooltip}
delay={100}
hideOnClick={false}
allowHTML={true}
>
...some other code here
</Tippy>
The commented code does what I would like to see. If the content contains html then it renders the content properly. I have found the solution here: https://github.com/atomiks/tippyjs-react/issues/94#issuecomment-498100958
However, I would like to use the own properties of tippy.
allowHTML does not work while delay and hideOnClick work.
It seems like the properties with "R" (see attached picture) do not seem to work and I cannot figure out how to use them in react and could not find in documentation either.
Tippy properties V6.x
Source: https://atomiks.github.io/tippyjs/v6/all-props/
My main issue with dangerouslySetInnerHTML was XSS vulnerability. That's why I wanted to use own property of tippyjs, the innerHTML. Because I though it handles XSS vulnerability but after reading the documentation again, more carefully, I realized it requires sanitizing data as well.
So I just go with dangerouslySetInnerHTML and sanitize my data before using it.
Here is my code:
import Tippy from '#tippy.js/react';
import dompurify from 'dompurify';
import React from 'react';
const PropertyLabel = ({ label, tooltip }) => {
const sanitizedTooltip = dompurify.sanitize(tooltip);
return (
<Tippy
content={<div dangerouslySetInnerHTML={{ __html: sanitizedTooltip }} />}
delay={100}
>
...some other code here
</Tippy>
);
};
Here are the sources that I used to implement dompurify:
https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part2.html
https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml:~:text=class%20attribute%20instead.-,dangerouslySetInnerHTML,-dangerouslySetInnerHTML%20is%20React%E2%80%99s
https://www.npmjs.com/package/dompurify
I know it does not solve the problem of using properties of Tippy marked with an "R" in React, but this single solution works instead of "allowHTML" property.

Convert imported CSS module class for style attribute

I want to import a style from CSS module file and assign it to style attribute, instead of writing it directly as inline style. The following code:
import styles from "./Calculator.module.css"
const Calculator = () => {
return (
// ...
<Card style={styles.darkmode} />
// ...
);
};
Gives a The style prop expects a mapping from style properties to values, not a string error, because styles.darkmode is just a name, not a JSON object. How could I convert the class name to a valid JSON object?
I've also read this question, but in that case, he got the JSON object itself, not just the name.
CSS modules return unique class names. You should be using className, instead of style:
<Card className={styles.darkmode} />

Is string comparison the right way to do dynamic styling for variants in React-JSS?

I have a Sandbox here:
https://codesandbox.io/s/p2wy9pp8lx
I have some dynamic styling like this:
const styles = {
fooDisplay: props => ({
display: props.variant === "foo" ? "block" : "none"
}),
}
For a class like:
const Something = ({ classes, children, variant }) => {
return (
<div className={classes.someThing}>
<div> variant is : {variant}</div>
<div className={classes.fooDisplay}>I only display if variant is foo</div>
</div>
);
};
This does what I want.
Is using string comparison the right way to achieve this though? Or would this be bad for performance?
Best practice in my opinion is to export variant constants on each element that you can reference whenever you import the element, an example would look like:
<Button variant={Button.Variant.PRIMARY}> This is a primary button </Button>
And on Button you can do a check using the same constants this.props.variant === Variant.Primary
There's no real performance issue with string comparison, it's just a weakly typed way of getting to the same solution, and looks a little bit messier. This method means there's no room for error and it's very clear what the intent is.
If you need a bit more code to understand what I mean let me know

Resources