Prevent React from rendering inline styles - javascript

const Component = () => <CustomButton color="highlight">Click me</CustomButton>;
const colors = { highlight: "#123456" };
export const CustomButton = styled(Button)`
${({ props }) =>
color: ${colors[props.color]}};
`;
How can I prevent React form rendering "color="highlight" as an inline style in line 1?
I sometimes use CSS named properties to use them within my CSS in JS library as props (styled components in this case).
React renders this HTML, though:
color="highlight" is not valid HTML and displays no color.
Since color="highlight is rendered as an inline style, my styled components stylesheets are not working anymore and the styles are broken.
The correct output should be
// no inline styles applied
<button class="sc-crzoAe dV0xyD sc-cTJkRt jDcPXG" />
// corresponding style sheet class
.sc-crzoAe {
color: #123456;
}
Keep in mind that React handles some CSS properties like width, height as a shortcut to style={{ width: "100%", height: "50%" }}. That's where the behaviour comes from I think.
One idea I had was to just rename the prop, but it would be nice to have a prop called color to take care of the color.

The correct way to set color is this:
export const CustomButton = styled(Button)`
color: => ${(props) => colors[props.color]};
`
An example can be shown here

Related

Overriding antd component style for just one component

Working with antd components, if you have an Alert component, inside there is a tooltip that is given the styling through ​ant-alert-icon​ class. So, if we need to override the Tooltip color, you can have in your stylesheet a class to override the values. For example:
ant-alert-info {
.ant-alert-icon {
color: #3d6de7 !important;
}
}
However, this will apply the color #3d6de7 to all Alerts type Info. How can I apply a different color to just one specific Alert type Info while keeping the styling above for the remaining Alert type Info components? Is this possible? What are the alternatives to doing something similar?
I am able to change the background of the Alert using the style field as follows:
<Alert
description={}
type="info"
showIcon
style={!props.alert ? { backgroundColor: "#F4F0F0"} : { backgroundColor: "#fff2f0", border: "#ffccc7" }}
/>
However, I have not been able to change the Tooltip color.
Thanks!
You can set an additional className like ant-alert-info-custom this way:
<Alert
description={}
type="info"
showIcon
className="ant-alert-info-custom ant-alert-info-custom-with-red-icon"
/>
And use it like this:
.ant-alert-info.ant-alert-info-custom {
// some shared styles by all custom alerts
.ant-alert-icon {
color: #3d6de7 !important;
}
// specific style for red icon
&.ant-alert-info-custom-with-red-icon{
.ant-alert-icon {
color: red!important;
}
}
}
As you can see you can do this:
<ConfigProvider csp={{ nonce: 'YourNonceCode' }}>
<Button>My Button</Button>
</ConfigProvider>
I think you can use ConfigProvider to overwrite Antdesign styles. Check out the link for more info:
ConfigProvider.

Create dynamic tags with Styled Components

Is there a way to create a dynamic tag using styled-components?
For example:
const MyComponent = styled(CustomTag)``;
<MyComponent element="h1" />
You can use as prop by default on components created with styled-components. If in your example CustomTag is also a styled-component that styles a native element (e.g.:)
const CustomTag = styled.h1`
color: red;
`;
then you can do
const MyComponent = styled(CustomTag)`
font-size: 64px;
`;
<MyComponent as="span">Something</MyComponent>
and you'll end up with a <span> tag with font-size of 64px and red text color. Of course you can also use as prop on CustomTag so you don't necessarily need MyComponent.
Maybe this will help you:
Add you code in your typescript
class Test extends HTMLElement {
connectedCallback() {
this.innerHTML = `<h1>Hello World...</h1>`;
this.style.color = "red";
}
}
customElements.define('test', Test);
after compiling refer the js file in you HTML and you can use it like <test></test>

How do I use the useState hook to change the color of my react icons to blue?

I want to use a useState hook to change the color of my react icons to blue in my sidebar upon clicking one of them. I tried this
const [changeColor, setChangeColor] = useState('blue');
and then in the return
<IconOuter onClick={() => setChangeColor(changeColor)}>
{item.icon}
I would like to know what I am doing wrong? Any help would be greatly appreciated. Thank you.
Upon further inspection, I styled using component styles, so this is my css for the icon. It looks like theres a span surounding the icons which may be easier to style.
const IconOuter = styled.span`
background-color: white;
border-radius: 5px;
padding: 10px;
width: 44px;
height: 44px;
left: 8px;
top: 8px;
`;
When using the useState hook you create a variable and a method, the variable is used to store the state and the method to change the value of the variable. The variables initial value is gained from the value inside the useState hook and you can change that value latter by using the method you defined from the useState hook
This is the basic form of the useState hook:
const [state, setState] = UseState(<initial state>)
So your code should be :
const [myColor, setmyColor] = useState('white'); //the color is currently white
<IconOuter onClick={() => setColor('blue')} />
const IconOuter = styled.span`
background-color: ${ myColor };
border-radius: 5px;
padding: 10px;
width: 44px;
height: 44px;
left: 8px;
top: 8px;
`;
I can see that the default value for this state is blue and in your code, you just call setChangeColor and pass 'blue' again so if you click on it again and aging, still state is blue since you just pass 'blue' to your changeColor state method(setChangeColor()).
So I can just see that the state gets the same value as the default value all the time.
You haven't put the rest of the code but in this small piece of code that you have shared here, I can see that you are not using this state value anywhere.
You can try inline CSS as
<IconOuter onClick={()=>setChangeColor('blue')} style={{color:changeColor}}/>
If you want component style try using color instead of background-color in CSS.
Here is an example that can be helpful. In this case, I want to update the colour of my heart IonIcon when a user clicks on it once, so I first wrapped it in touchableOpacity to get that blink effect. If you don't want to wrap it, you simply put the onPress function inside the icon.
function MyComponent= () => {
const [defaultcolor, setNewColor] = useState('white')
return (
<View>
<TouchableOpacity style={styles.MyRoundButtonStyle} onPress={() =>
setColor('green')} >
<Ionicons name="heart" size={50} color={defaultcolor} />
</TouchableOpacity>
</View>
)};
export default MyComponent;
Note that in the IonIcons I did not make color='green' etc, I rather used the name of the initial state of the state hook (defaultcolor).
Note that it is just a name that you can set to anything like 'mycolor' etc. You may be familiar with the naming convention that is something like [state, setState], it is just a choice.
Do let me know if you need more clarity with this.

Combining CSS and custom CSS properties inline on a react component

I need to pass custom CSS properties inline to a React component (Google Model Viewer in this instance),combined with more run-of-the-mill styles (background width, height etc.). There's quite a lot of questions on using custom properties inline with react, but I couldn't see one for specifically combing the properties with other styles.
I have the styles here, with the commented out style being an example of the custom property.
const styles = {
width: "100%",
height: "100%",
background: this.props.background,
// "--progress-bar-height": this.props.progressBarHeight
};
The const gets passed into rendering the component:
return (
<model-viewer
style={styles}
</model-viewer>
How do I combine the usual inline styles with the custom properties to add inline?
I tried adding it as a variable (as seen elsewhere on SO):
const progressBarHeight={ "--progress-bar-height": this.props.progressBarHeight };
But wasn't sure how to combine that with the {styles} . I tried longhand declaring each style and adding the variable to the list, but that didnt work either:
style={{ background: styles.background, width: styles.width, height: styles.height, progressBarHeight }}
Any tips?
You can simply use object spreading for this
style={{...styles, ...progressBarHeight }} // progressBarHeight = { "--customrvar" : '1px'}
Here's a working demo
Shouldn't a simple object map work?
Here is a sample code -
const styles = {
width: "100%",
height: "100%",
background: "this.props.background",
//"--progress-bar-height": "black"
};
const props = {
"--progress-bar-height": "white"
}
for(let i in props)
{
styles[i] = props[i];
}
for(let i in styles)
{
console.log(styles[i]);
}
And then the resulting combined style goes into props of your component.

How can I pass props to base component in styled-component?

As an example, let's say I've a component that can take in props like this:
const testComponent = (props: {isBold: boolean}) => {
if(props.isBold)
return <strong><div>hello</div></strong>
return <div>hello</div>
}
In this case, my example component that can take in props and the result depends on the props given to it.
Now, if I extend this component in styled-components, how can I pass my props into the base component? The idea is something like this:
const styledTestComponent = styled(testComponent({isBold: true}))`
width: 100%;
opacity: 0.5
/* etc etc... */
`
Well, obviously not going to work. This part will fail: styled(testComponent({isBold: true}))
But the idea is that what I want to do is to use CSS to style a particular instance of a component. So in that case, I will need to pass a pre-defined props to the base component, testComponent.
How can I achieve this?
Update:
I've come up with a quick example to illustrate the issue. The code below attempts to style a react component MyCustomImage as a styled-component StyledMyCustomImage. When this is run, you can see that StyledMyCustomImage does render itself as MyCustomImage. However, the CSS styles are not applied.
const MyCustomImage = props => (
<img
src={`https://dummyimage.com/${props.width}x${props.height}/619639/000000`}
/>
);
const StyledMyCustomImage = styled(MyCustomImage)`
border: 2px dotted red;
`;
function App() {
return (
<div className="App">
<h3>Test passing props from styled component to base component</h3>
<StyledMyCustomImage width="600" height="400" />
</div>
);
}
I've created a sandbox for this demo: https://codesandbox.io/s/k21462vjr5
Update 2:
Oh! Thanks to #SteveHolgado's answer, I've gotten it to work! I didn't know styled component will pass the CSS as a prop to its base component! Here's the code after adding in the class name for future reference:
const MyCustomImage = props => (
<img
src={`https://dummyimage.com/${props.width}x${props.height}/619639/000000`}
className={props.className}
/>
);
const StyledMyCustomImage = styled(MyCustomImage)`
border: 2px dotted red;
`;
The sadnbox of the working demo: https://codesandbox.io/s/j4mk0n8xkw
Try this, it should work
const StyledTestComponent = styled(testComponent)`
width: 100%;
opacity: 0.5
/* etc etc... */
`
and pass the prop to instance in this way.
<StyledTestComponent isBold />
Feedbacks are welcome. I have not checked it working, but feels it will work
Note: I checked and it's working. Should work for you.
When you use the styled function like that, your wrapped component will get passed a prop called className, which you need to apply to the element that you want the styles to affect:
const testComponent = (props) => {
return <div className={props.className}>hello</div>
}
You will have access to all props in your styles, which you can use like this:
const styledTestComponent = styled(testComponent)`
width: 100%;
opacity: 0.5;
font-weight: ${props => props.isBold ? "bold" : "normal"};
/* etc etc... */
`

Categories