Styling different values of an array in React.js - css

I have an array that is getting data from an API, but I want to style each button differently so that the background colours differ. I am also using Material UI... Here is my code -
{options.map((data, id) => (
<Button className='p-3 md:w-[25wh] md:h-[25vh]' onClick={handleClickAnswer} fullWidth variant="contained">{decode(data)}</Button>
))}
Please tell me how to style them

There are several ways in which you can assign different styles to different buttons. It can be done majorly using string literals.
Few examples,
If you are using bootstrap/tailwind and your styling will majorly consist of that, then you can something like
{options.map((data, id) => (
<Button
className=`p-${id} md:w-[25wh] md:h-[25vh]`
onClick={handleClickAnswer}
fullWidth
variant="contained">
{decode(data)}
</Button>
))}
Notice p-${id} would get modified for each particular element in the array
Even if bootstrap isn't being used, you can use the above method, create custom classNames to assign styles to each button separately.
If you need to specifically assign a style to the first/last element, you can use first child selector (or) last child selector.

Related

Add Inline style with css variable in next.js

Doing components for app. For section want to add ability to pass some optional accent color to get output like:
<section style="--mycolor:red">
... //contents
</section>
where "red" can be passed in backend during page build as color name, #hex, "rgba()" or "hsla()" strings. It gives opportunity to use that color to children elements of this section - for border colors, first letters, markers, backgrounds etc.
Simple code^:
<section style={`--mycolor:{color}`};>
does not work because next expects mappable code, but looks like css variables names aren't parse-able in inline syntax.
I can also inject it with <style jsx> statement:
<style jsx>{`
section{
--mycolor: ${ color != '' ? color : 'var(--default-color)'};
}
`}
</style>
but this soluition looks "dirty" for such simple task - adds tons of unnecessary code just to serve one css rule.
I think it can be achieved with something like
<section styles={myStyle}>
where myStyle is jsx style object, but i don't understand how to manually create it (in examples its only imported prop w/o details where did it get from).
So is there a way to achieve simple output like <section style="--mycolor:red"> ?
#juliomalves, thanks for help, final solution is like
style={{ '--mycolor': color }}>
where:
'--mycolor' = css variable name quoted as string (css properties are not quoted !)
color = prop of an element
If using TypeScript with Nextjs, there is very simple solution as blow
{{ ['your css variable name' as any] : your value}}
e.g.
['--rating' as any]: 2.5,
['--star-color' as any]: '#b3b3b3',
incase if you want to insert inline styling using style tag in next.js , you have to insert an object inside the style={} tag as all of the style and classNames in next are considered as object . For example you want to insert the background colour of your div using the insline styling than do the followings
<div style={{ ["background-color" as any]: "#ffc107" }}></div>
do make sure that You use semicolons to insert style properties

How to get rid off default classes applied by ngbootstrap

I use ngbootstrap for popovers, but I want to override all the default styles it comes with. I have a form that should be displayed as a popover on a button click which has its own styles.
When I use [ngbPopover] it renders an element with the default class of 'popover' applied, instead of overriding each of its properties to align with my expectation, is it possible to remove it all together while rendering on the page and then I could use a custom class with popoverClass property.
<ng-template #popContent><user-form></user-form></ng-template>
<button type="button" class="btn btn-outline-secondary" [ngbPopover]="popContent">
I've got markup and bindings in my popover!
</button>
Looking into the popover source code I see lots of classes nailed without a chance to change them. I suppose the only promising approach would be exclude the css for the popover component from the import.
How to do it depends on how you import the Bootstrap css

How can I set a different backgroundImage in <div> element in a .map() function?

I want to give each CategoryCard div a different background-image.
How can I solve this problems with styled components? I use React and Typescript.
{this.MainChannels.map(item => {
return (
<CategoryCard key={item._id} onClick={() => this.handleChannel(item.name)}>
{item.name}
</CategoryCard>)
})}
the URL's of the images are locally it means my pictures are stored on my computer
I solved it with importing of each image and inline styling of the CategoryCard.
then i pushed the imports in an array. And every item in the .map() function gets the own background through the array.

How to apply conditional css?

I have a component item that represents a card with the data about the item. Since all the cards have the same structure (price/color/size/photo categories are shown on each card, nothing more and nothing less), I would like to apply a conditional CSS, but I don't know how, since the cards' style differ (slightly) based on:
price (for example, the card is bigger if the price is lower)
if the user has marked it as favorite
whether they are a part of this or that component (the URL can be the same). For example, in a single view there is the first component with a X card's style and the second component with a Y card's style - but the cards have the same data.
I'd really appriciate any suggestion!
<div [className]="'example-class'"></div>
This allows us to add classes based on a condition:
<div [className]="condition ? 'example-class' : 'other-class'"></div>
Or we could build the class name at runtime:
<div [className]="'class' + someValue"></div>
we can easily toggle CSS classes like so:
<div [class.example-class]="condition"></div>
we can assign a variable class name :
<div [ngClass]="seleted-class"></div>
NgClass can also assign multiple static class names all at once:
We can also use ngClass to assign multiple CSS classes based on multiple conditions.
<div
[ngClass]="{
'example-class': condition,
'other-class': !condition
}"
></div>
<div [ngClass]="['example-class', 'other-class']"></div>
source : https://malcoded.com/posts/angular-ngclass/
You can use NgClass to add conditional classes. For more info, refer the documentation - https://angular.io/api/common/NgClass

Custom elements and accessibility

I'd like to implement a listbox widget using the current web components specs. Moreover, the resulting listbox should conform to the ARIA standard. Instantiating the listbox widget should be as simple as:
<x-listbox>
<x-option>Option 1</x-option>
<x-option>Option 2</x-option>
</x-listbox>
For purposes of cleanliness and encapsulation, everything else should be rendered in shadow dom. To implement this widget, two custom elements, <x-listbox> and <x-option> are registered. The top-level element of the shadow dom of <x-listbox> is a <div> that carries the role=listbox and the aria-activedescendent attributes for accessibility (I don't want these attributes on the <x-listbox> element because they are implementation details.)
In order for aria-activedescendent to work, one needs ids on the option elements. Putting ids directly on the <x-option> elements won't work out of two reasons: Firstly, it would pollute the id namespace of the document that uses the listbox widget. Secondly and even more importantly, ids do not work across shadow boundaries (which is one purpose of the shadow dom), so the ids of the options have to live in the same shadow dom as the <div> with the aria-activedescendent attribute.
A solution for this would be to surround each <x-option> that is rendered as content inside the shadow dom of <x-listbox> with another <div> (belonging to that shadow dom), on which an id can be put.
My question is: Is this the right way to go and how to implement this using the custom element and shadow dom web apis?
Your probably should better implement this by creating an select element (using JavaScript). This should ensure screen readers recognize this correctly as an input for selecting a value/values from a list.
Add an select element like this below your <x-listbox> element:
<select class="only-screenreader">
<option>Option 1</option>
<option>Option 2</option>
</select>
Then add aria-hidden="true" to your custom <x-listbox> element.
Finally apply CSS to make the screenreader select element invisible.
.only-screenreader {
position:absolute;
left:-10000px;
top:auto;
width:1px;
height:1px;
overflow:hidden;
}
That's my approach but maybe there's a better one.
In the markup provided, x-option is in the light DOM, not the shadow DOM, so it can be referred to by id. To avoid polluting the id namespace, I generate a random id, which is set when the component loads but can be replaced. This way I can refer to the element by id whether or not the component user has set an id on it.
Wrapping each option in a div seems unnecessary and likely to cause issues. Also, if the options are in a <slot />, it's simply not possible.

Resources