How to properly overwrite existing className with emotionJS - css

I'm trying to use emotion to overwrite the styling of an existing React component from a 3rd party library.
I try my best to simplified the problem in this codesandbox
The ExternalLib simulates a 3rd party component I'm using which I should not change the code.
As you can see it accepts a "prefix" props for css namespace and uses className in static string.(the original one has it as sass variable also)
I first try to get the base className hash with css function, then I try to compose those in emotion way of composition, and I get the expected visual result.
const baseStyle = css`
background-color: blue;
width: 200px;
height: 200px;
`;
const getItemStyle = ({ disabled }) => {
return `
height: 50px;
margin: 4px;
background-color: ${disabled ? "gray" : "yellow"};
`;
};
const getTextStyle = ({ color }) => {
return `
color: ${color}
`;
};
const StyledExternalLib = styled(ExternalLib)`
.${baseStyle}-track {
${getItemStyle};
}
.${baseStyle}-text {
${getTextStyle};
}
`;
however inspecting the style tags, I got many duplicated styles, what am I doing wrong?
you can see there are twice the yellow background

Here what i found, use css prop to the parent tag
css={{
"& .class__youwant--overwrite": {
margin: 80
}
}}
Worked in my case

Related

Styled-components - Over 200 classes were generated, but cant get :hover to work

I came across the error in styled-components :
Over 200 classes were generated for component......
and did the suggested fix from console, and that did the trick, but when I have a container component "Card" that when hovered should change text color of another component "Number" (which has that suggested fix applied, then I cant change the color (i assume because style overrides the hover change, because it works fine with opacity)
the mentioned components are in src/ProgressPieCard (first 2 components)
anyone got any got suggestions, thanks in advance :)
( sorry styling/position is a bit off )
CodeSandBox
const Number = styled.p.attrs<ColorProps>((props) => ({
style: {
color: props.color,
},
}))`
position: absolute;
span {
font-size: 1.5rem;
}
`;
const Card = styled.div.attrs<ColorProps>((props) => ({
style: {
background: props.color,
},
}))`
position: relative;
&:hover {
${Number} {
opacity: 0.5;
// color: red; <-- this dont work
}
}
`;
Values ​​from props were pass as inline styles. They have higher priority. I suggest passing values ​​from props differently. The example below will now work as you wanted.
const Number = styled.p<ColorProps>`
position: absolute;
color: ${p => p.color};
span {
font-size: 1.5rem;
}
`;
const Card = styled.div<ColorProps>`
position: relative;
background: ${p => p.color};
&:hover ${Number} {
opacity: 0.5;
color: red; <-- this WILL work :)
}
`;

Material-ui makeStyles with both before and after

I'm working on a project which requires the following CSS code.
.hexagon, .hexagon::before, .hexagon::after {
width: 67px;
height: 116px;
border-radius: 18%/5%;
}
Is there a way to implement the above style using Material-UI makeStyles without separate use of before and after selectors?
You can use the below code, '&' means the generated class name that will be passed to the component
const useStyles = makeStyles({
root: {
"&, &:before, &:after": {
// your styles
}
}
});
<div className={classes.root}>

How to conditionally render using object properties in styled-components?

I am trying to conditonally render in styled-components. This code seems to work in this case.
background-color: ${props => (props.active ? 'Black' : 'Green')};
I want to rather use object properties from a JSON file and provide 2 colours to the above condition. Something similar to these below instead of Black and Green.
${colors['Brand/PrimaryBlack']}
${colors['Brand/PrimaryGreen']}
colored.json
{
"colors": {
"Brand/PrimaryBlack": "#424449",
"Brand/PrimaryGreen": "#8ED6C9",
}
}
styles.js
import styled from 'styled-components'
import { colors } from './colored.json'
const Tabs = styled.button`
background-color: ${props => (props.active ? 'Black' : 'Green')};
`
How can I achieve this?
The ternary works exactly the same as your previous code, but just references the keys in your colors JSON, i.e. background-color: ${props => colors[props.active ? "Brand/PrimaryBlack" : "Brand/PrimaryGreen"]};.
{
"colors": {
"Brand/PrimaryBlack": "#424449",
"Brand/PrimaryGreen": "#8ED6C9",
}
}
import styled from 'styled-components'
import { colors } from './colored.json'
const Tabs = styled.button`
background-color: ${props => colors[props.active ? "Brand/PrimaryBlack" : "Brand/PrimaryGreen"]};
`;
You can do what you desire using styled components in the following way:
background-color: ${(props) =>
props.active ? colors["Brand/PrimaryGreen"] : colors["Brand/PrimaryBlack"]};
Find the working CodeSandBox here
Inside of Template literal you pass any valid JavaScript code inside of ${} expression even call to function so if you have an object which you want to access some keys you can just access those keys as you would do in a normal JavaScript code. so if you have an object colors with some properties you can access it inside of you Styled Component like this
const colors = {
"Brand/PrimaryGreen": "green",
"Brand/PrimaryBlack": "black"
};
const Comp = styled.div`
background: ${props => props.active? colors["Brand/PrimaryBlack"] : colors["Brand/PrimaryGreen"]};
color: #fff;
`;
You can simply do this
<TagName active={this.state.active}>Test</TagName>
And in your styles something like this:
const TagName = styled.button`
width: 100%;
outline: 0;
border: 0;
height: 100%;
justify-content: center;
align-items: center;
line-height: 0.2;
${({ active }) => active && `
background: blue;
`}
`;

Increase size of Twemoji in REACT

My REACT component's code is like this
import React from 'react';
import { Twemoji } from 'react-emoji-render';
import emoji.css;
const emoji = () => {
return ( <Twemoji className="Twemoji" text=":+1:"/> );
}
export default emoji;
My css file (emoji.css) has the following code
.Twemoji {
width: 20em;
height: 20em;
}
but the size of the emoji doesn't change.
if I inspect the element and modify the inline style in the page html that works
Please can you help me understand how I can increase the emoji size via CSS
Twemoji Component does not take a prop className (see here), instead you will have to use the options prop in order to pass a custom css classname
const options = { className: "Twemoji" };
const emoji = () => {
return ( <Twemoji text=":+1:" options={options} /> );
}
EDIT:
you would also have to add !important to width and height in the css class to take precedence over the element style (see css precedence)
.Twemoji {
width: 4em !important;
height: 4em !important;
}

Use props to switch width using styled components mixins

Tech used - Styled components and react
I have a mixin to make my app responsive
import { css } from 'styled-components';
export default {
smallScreen: (...args: any) => css`
#media (max-width: 600px) {
${css(...args)}
}
`,
}
In another react component, I want to use the above defined method to write css that applied on small screens.
const SideNavWrapper = styled.article`
background: red; // this works
width: ${props => props.expanded ? '260px' : '80px'}; // this works
${media.smallScreen({
background: 'yellow', // this works
width: `${props => props.expanded ? '100%' : '20px'}`, // this doesn't work. props is undefined.
})}
`;
Depending on props.expanded, I want to switch the width of SideNavWrapper. However it doesn't work on smaller screens.
Background color changes as expected but not the width. On debugging, I realized that props is undefined. Any ideas what am I missing? Thank you so much!
Another way which you could use and in my opinion would be much cleaner to read and thus maintainable is the following:
const getCorrectWidth = ({ expanded }) => (
expanded
? 260
: 80
);
const getCorrectSmallWidth = ({ expanded }) => (
expanded
? '100%'
: '20px'
);
const SideNavWrapper = styled.article`
background: red;
width: ${getCorrectWidth}px;
${media.smallScreen`
background: yellow;
width: ${getCorrectSmallWidth}
`}
`;
The above has clear functions which tell the developer what they are doing. Syntax looks clean, also.
Would you try:
${props => {
return (media.smallScreen({
background: 'yellow',
width: `${props.expanded ? '100%' : '20px'}`,
}))
}}

Resources