Applying the class name through json not working, same works if hardcoded - reactjs

It's my json:
export const initialInitialPropsSchema: InitialProps[] = [
{ className: 'text-secondary text-5xl font-semibold', label: 'B' },
{ className: 'text-white text-5xl font-semibold', label: 'M' },
{ className: 'text-tertiary text-5xl font-semibold', label: 'A' },
];
my header: where I apply my class names on loop:
export const Header: FC<{ initials: InitialProps[] }> = ({ initials }) => {
return (
<div className="p-5 bg-primary flex justify-between">
{initials.length &&
initials.map((initial) => (
<h1 key={initial.label} className={initial.className}>
{initial.label}
</h1>
))}
</div>
);
};
But in the browser I see all class names are applied. But no property update with element. If I hard code the classNames, instead of assign from json it works fine. I am using Nx workspace with vite for react app. the header placed under the header library.
in browser I see this:
UPDATE
In my header part, I simply added all classes what it's used in json like this: ( apart from loop as static )
<h1 className="text-secondary text-tertiary text-white text-5xl font-semibold"></h1>
then all look classes as well works. what would be the issue? how to solve this?

This is most likely due to the Tailwind compiler not including those classes in the generated CSS. As stated in the documentation, here and here
Tailwind doesn’t include any sort of client-side runtime, so class names need to be statically extractable at build-time, and can’t depend on any sort of arbitrary dynamic values that change on the client.
This is because Tailwind tries to optimize your bundle size by removing unused classes and it needs to be able to determine which of those to keep at build time which it seems is not possible in this case due to classes being assigned to variables.

Related

How to use a dynamic background image URL with Tailwind CSS and React

In React, I'm unable to use a URL string in my Tailwind background image class:
1: Not working, getting error "can't resolve ${link}"
const link = "https://cdn.test.net/test.jpg";
<div className={`px-4 py-1 h-[22rem] lg:h-[28vw] bg-cover bg-center bg-[url('${link}')]`}></div
2: Working, but I need to use a variable inside my bg- class.
const link = "bg-[url('https://cdn.test.net/test.jpg')]";
<div className={`px-4 py-1 h-[22rem] lg:h-[28vw] bg-cover bg-center ${link}`}></div>
I still need to be able to use ${link} inside bg-[url('${link}')].
Here is how it looks for me
The given example should be working fine.
Working fine for me.
The CSS file generated by Tailwind will only include classes that it recognizes when it scans your code, which means that dynamically generated classes (e.g. bg-[url('${link}')]) will not be included.
If you only have a few different background images, you could add them to your tailwind.config.js and switch between them:
module.exports = {
theme: {
extend: {
backgroundImage: {
'first': "url('/img/first.jpg')",
'second': "url('/img/second.jpg')",
}
}
}
}
<div className={`bg-cover bg-center ${useFirst ? 'bg-first' : 'bg-second'}`}></div>
This would work, as long as you use the full utility class name, e.g. bg-first, in the code for Tailwind to find and include in the generated CSS.
If you need to reference completely arbitrary URL values, you can always use a style attribute instead of Tailwind classes. For example:
<div className="bg-cover bg-center" style={{backgroundImage: `url('${link}')`}}></div>

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

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>
);

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})`,
}}
>

Unable to resolve an image in an array in React JS

I'm attempting to import images into an array in React JS. My intention is to be able to map through the array and have the images appear one as a time. However, my images are not being properly resolved. I'm fairly certain it is a syntax error of my doing, but I'm just not able to solve this. I'm currently a student who is just learning react, so any and all help is much appreciated!
import universe from "./images/universespider.jpeg"
let content = [
{
title: "Universe",
image: universe,
author: "Alex",
date: "09/09/8099",
blog: "Spider-Man is in different universes.",
},
]
import "./blogs.css"
import content from "../../content"
export default function blogs() {
return (
content.map((blog, i) => (
<div key={i}>
<div className="blogBox">
{blog.title}
{blog.image}
{blog.author}
{blog.date}
{blog.blog}
</div>
</div>
)
))
}
Error Message
You can't use imported images directly, in your case you should use element and pass your image as a source.
Instead of
{blog.image}
try this
import universe from "./images/universespider.jpeg"
...
<img src={universe} alt="universe"/>
More information about this assuming that your app was created with CRA.

Render CSS Classes w/ No Styles Using Webpack Extract Plugin

We use the Extract Text plugin with Webpack 3 and it works great but we recently hired a QA automation engineer who works in Selenium.
We are discussing ways to make selecting elements with Selenium easier but on the front end side. That would involve us writing CSS that we don't use in order to get a class to render on a component. The opposite of what the plugin does essentially.
Is there any way to accomplish this with the plugin? Also open to suggestions if you've worked in Selenium. Maybe even a hack. 😱
Example:
{ vehicleOptions.map((option, index) => {
let [label, value] = option
if (label && value) {
return (
<li
className={ [styles.option, styles[label]].join(' ') }
key={ `${ label }_${ index }` }>
<img
className={ styles.icon }
src={ `/images/icon-${ label }#2x.png` }
/>
<p className={ styles.value }>
{ typeof value === 'number'
? formatDistance(value, ',', 'mi')
: value
}
</p>
</li>
)
} else {
return null
}
In this line className={ [styles.option, styles[label]].join(' ') }, the label for only one of the mapped items applies it's label as a class because it has corresponding CSS. The others do not otherwise based on how Extract Text works.
This is where it becomes difficult for the QA engineer to query the HTML for a particular element.
I had a thought of being able to run testing mode but rendering things differently for tests sort of defeats the purpose of testing against real world code that will go to prod.
Similar experience doing this, one thing we ended up doing was adding data-id="foo", then using xpath selectors in our selenium tests.
Then in selenuim you can do things like:
'//*[#data-id="foo"]'
or test in chrome with
$x('//*[#data-id="foo"]')

Resources