Style child element by id prop using styled-component - css

I'm creating AccordionSections for every element I get from my backend this way
<AccordionSection
defaultOpen={activePackage}
headingLevel="h3"
id={
activePackage
? `active-${packageObj.type}-${key.toString()}`
: `${packageObj.type}-${key.toString()}`
}
label={label}
key={`${key.toString()}-${packageObj.type}`}
>
I'm wrapping this Accordion sections in a styled Accordion component:
<Wrapper spaceStackEnd="s">{content}</Wrapper>;
I want to show the label with the green colour only for the AccordionSection that start with active in the id:
const Wrapper = styled(Accordion)`
span > {
&:first-child {
${(properties) =>
properties.id?.startsWith('active') &&
css`
color: green;
`};
}
}
`;
Span is because the generated elements are spans. Nothing is happening. am I missing something ?

You can pass a parameter active to your component. If you have children I assume that you have multiple components. So in order to render multiple components developers usually use the map() function. The second argument of the map() function is the place of the component you want to render based on the array of data you have. you can simply do this:
<YourComponent {...yourProps} active={index === 0? "green" :
"black(default color you set)"} />
and then pass that active prop to your styled-components.
if you want know more about this you can visit this link.

Related

Styled Component: hover style passed in props

I have a StyledButton, and I use it like this:
const StyledButton = styled.div<{
hoverStyle?: CSSProperties
}>`
color: black;
background: blue;
// What can I do here to apply the hoverStyle?
`
<StyledButton
hoverStyle={{
backgroundColor: 'red',
color: 'white',
}}
>
My button
</StyledButton>
Are there any ways to do that?
Usually we provide individual values in extra styling props, but it is still definitely possible to provide a set of CSS rules (a CSSObject).
First you need to use an interpolation function to adapt the style based on runtime props:
const StyledButton = styled.div<{
hoverStyle?: CSSProperties
}>`
color: black;
background: blue;
// What can I do here to apply the hoverStyle?
${(props) => props.hoverStyle && inlineRules(props.hoverStyle)}
`
Here I used an inlineRules function to convert the CSSObject into a list of rules:
function inlineRules(rulesObj: CSSProperties) {
return Object.entries(rulesObj).map(([property, value]) => `${property}: ${value};`).join('');
}
Then, based on the "hoverStyle" name of your styling prop, it sounds like these rules should be applied only on :hover, rather than being directly merged with the root styles of your <div>. In that case, you need to place them in a nested block, for which you can use the & ampersand keyword to refer to the self style:
& a single ampersand refers to all instances of the component; it is used for applying broad overrides
&:hover {
${(props) => props.hoverStyle && inlineRules(props.hoverStyle)}
}
Live demo on CodeSandbox: https://codesandbox.io/s/sleepy-brook-h515v7?file=/src/App.tsx
Note: CSS rules in styled-components actually use the normal "kebab-case" notation, whereas CSSProperties are defined in camelCase ("background-color" v.s. "backgroundColor" in your example). In the above demo, I used a template literal conversion type to convert them into kebab-case, based on TypeScript add kebab case types form actual camel case keys

filter icon in material-ui's v5 DataGrid

The default behavior for the new DataGrid is to hide a filter icon unless you hover over the column header (and have a filter applied). In the previous version the icon remained visible.
Codesandbox https://codesandbox.io/s/mui-datagrid-filter-icon-7rbrk
When a filter is applied it adds a new iconButtonContainer div. The classes are: MuiDataGrid-iconButtonContainer css-ltf0zy-MuiDataGrid-iconButtonContainer
Is there a way to override this behavior? All I'd like to do is set visibility to always be visible when that div is generated by the library.
The answer here was to create a separate styled component of the data grid and use the global classnames imported from mui to reference the correct one for the style you wish to override. In my case it was something like:
const MyStyledGrid = styled(DataGrid, () => ({
[`& .${gridClasses.iconButtonContainer}`] : {
visibility: "visible",
width: "auto"
}
}))
function MyComponent() {
return (
<MyStyledDataGrid {...props} />
)
}

How should I write Jest Test cases for styled component and spy on css to verify if the styles?

I have a component in React-redux, which has a PagedGrid component (basically a table which renders data row-wise).
<UsersContainer>
<Title>{t('users')}</Title>
<PagedGrid
data-auto-container="user:table"
pageData={user.data}
columns={this.column}
/>
</UsersContainer>
I have created a function for the custom styled component which applies css to the rows of the table inside PagedGrid
const UsersContainer = styled.div`
> table > tbody {
${props => customcss(props)};
}
`;
function customcss({ data = [] }) {
let styles = '';
if (data.length > 0) {
data.forEach((value, index) => {
if (value.mycondition) {
const rowStyle = `& > tr:nth-child(${index + 1}) {
background-color: ${LIGHT_BLUE}
}`;
}
});
}
return css` ${rowStyle} `;
}
Now I want to create a test case using jest to spy on the css of this table and check if the styles are getting applied or not. Can anyone help me on creating a test case for this.
Assuming that you use the #testing-library/react library, you could test your component's style by getting it directly from the html document, and see precisely what style is used for your specific element.
In your example, you can do something like below (assuming that the ${LIGHT_BLUE} value is blue):
import React from 'react';
import { render } from '#testing-library/react';
import UsersContainer from '../UsersContainer';
it('should have the background color set to blue', () => {
const { container, getAllByTestId } = render(
<UsersContainer />
);
// Replace <YOUR_CSS_SELECTOR> by your component's css selector (that can be found in the inspector panel)
let contentDiv = document.querySelector('<YOUR_CSS_SELECTOR>');
let style = window.getComputedStyle(contentDiv[0]);
expect(style.color).toBe('blue');
}
Here, to get the style of your element, I am using the element's CSS Selector. However, it could also work with the element's className, or id directly if it has one, respectively using the methods document.getElementByClassName('YOUR_DIV_CLASS_NAME'), document.getElementId('YOUR_DIV_ID') instead of document.querySelector('<YOUR_CSS_SELECTOR>'). Note that the given name here should be unique, either with the id technique, or the className.

How to get access to the children's css values from a styled component?

I am using a REACT BIG CALENDAR and I want to get access to the css values in one of my functions.
I created a style component and override the library
const StyledCalendar = styled(Calendar);
Now for example there is a div inside of the Calendar with the class = "hello",
How would I access the css values of "hello" in a function? Similar to property lookup say in stylus.
I have tried window.getComputedStyle(elem, null).getPropertyValue("width") but this gives the css of the parent component.
If you know the class name, you should be able to select that and give that element to getComputedStyle instead of giving it StyledCalendar. Something like:
const childElement = document.getElementsByClassName('hello')[0];
const childWidth = getComputedStyle(childElement).getPropertyValue('width');
(this assumes that there's only one element with the class 'hello' on the page, otherwise you'll have to figure out where the one you want is in the node list that's returned by getElementsByClassName)
You can do it using simple string interpolation, just need to be sure that className is being passed to Calendar's root element.
Like this:
const StyledCalendar = styled(Calendar)`
.hello {
color: red;
}
`
Calendar component
const Calendar = props => (
// I don't know exact how this library is structured
// but need to have this root element to be with className from props
// if it's possible to pass it like this then you can do it in this way
<div className={props.className}>
...
<span className="hello"> Hello </span>
...
</div>
)
See more here.

How to dynamically change css selector property value in react js code?

I need to dynamically change the color in the react component for specific selector.
In scss (use sass) i have the following rule:
foo.bar.var * {
color: blue;
}
I want to change it in react code, to be yellow, red or something else.
I cant use style property for element, cause i need the selector to
apply for all subchilds !=)
Is there any native ways? Or should i use Radium? Or is there any similar libs for this? Maybe css-next some hove can help with this?
I have color picker, i cant write class styles for every color =(
For some answerers NOTE:
So i have selector in some scss file, that imported in some root js file with .class * {color: $somecolor} and i need change the $somecolor in that selector, during picking colors in color picker
Maybe i can somehow set selector for all nested inside style property? or there is the way how to recursively apply css style for every nested items from the style prop?
What about
class MyComponent extends React.Component {
render() {
const yellow = true // Your condition
return(
<div className={`foo bar var ${yellow && 'yellow'}`}
My item
</div>
)
}
}
.foo.bar.var {
& * {
color: blue;
}
&.yellow * {
color: yellow;
}
}
You could define a custom CSS property (CSS variables) using the style attribute of the element and assign the value to a prop, state etc.
<div className='foo bar var' style={{ "--my-color": props.color }}></div>
The custom property would work for any selector that apply to that component or children. So you could use it like that:
foo.bar.var * {
color: var(--my-color);
}
See a snippet with similar code here
this may sound stupid . but does this work ?
import myCss from './mydesign.css';
myCss.foo.bar.var = "your color"

Resources