Styled Components & React: Click event - reactjs

I am trying to create an onClick for a Styled Components Component, but it is not working. It is not logging hello in the console.
<Component onClick={this.handleClick} />
The handleClick:
handleClick(e) {
console.log("hello");
}
This is also in the constructor:
this.handleClick = this.handleClick.bind(this);
The component:
const Component = styled.span`
/* Regular CSS */
${css};
`;
Thanks in advance!
EDIT:
The component is nested in a Button component. When I add the onClick to the Button Component hello is shown in the console. However I want the child to have this function not the parent.
EDIT 2:
Ok so when I change the CSS it works. I have no idea why. This is my css:
top: 0;
left: 0;
width: 10px;
height: 10px;
display: block;
z-index: 0;
position: absolute;
overflow: hidden;
border-radius: inherit;

We probably need more code. Anyway the cleanest way to bind is by arrow functions:
handleClick = () => console.log('click')
If your Button is INSIDE you have to use another props as onClick is binded to onClick event.
Try
// In Parent
<Parent action={this.handleClick} />
// In Child
<Child onClick={this.props.action} />

Your span is rendered with a css value of display: inline. If there is no actual content in it to expand, it will be 0 pixels in width, and therefore you are not actually clicking on it.
I ran into the same issues and in Styled Components I couldn't make it work with a forced display: block. You should use a clickable item, like styled.button...

You might want to try this:
handleClick = e => {
console.log('hello');
}
...
<Component onClick={(e) => this.handleClick(e)} />
or
<Component onClick={this.handleClick.bind(e)}/>

Related

How to change other element when hover by using 'styled'

I'm new to Mui and trying to apply animation to components.
What I want to do is, I have four same component and each has its own image.
<MyComponent>some images...</MyComponent>
<MyComponent>some images...</MyComponent>
<MyComponent>some images...</MyComponent>
<MyComponent>some images...</MyComponent>
const MyComponent = styled("div")((theme) => ({
//... some styles.
// scale up when hovered
'&:hover': {
transform: "scale(1.2)",
marginRight: "20px",
}
}));
If I hover a <MyComponent>, I want to scale up hovered one, and scale down others.
Is there any ways to defined such action by using styled???
I would set a state then use a conditional to change styles .. IE
const [hoverState, setHoverState] = useState(false);
<MyComponent
onMouseOver={setHoverState(true)}
onMouseOut={setHoverState(false)}
style={hoverState ? {transform: "scale(1.2)",marginRight: "20px",} : ''}
>
some images...
</MyComponent>
You can do this with css and styled-components.
Note that the styled function is not meant to be called directly, but passed a template literal. Inside the template literal, you can write regular css expressions.
codesandbox
const MyComponent = styled.div`
transform: scale(1);
margin-right: 0px;
:hover {
transform: scale(1.2);
margin-right: 20px;
}
`;

React styled component specificity issue for modal calling custom styled modal

I am working with styled component in React. I want to style a modal with the following style inside my component,
const StyledModal = styled(Modal)`
.modal-container-header {
display: none;
}
.modal-container-footer {
display: none ;
}
.modal-container-close {
display: none;
}
`;
That is, I want to omit the global footer, header for my custom modal. It is working fine for one case but not working for another.
Here is the entire component,
interface LoaderInterface {
loading: boolean;
loadingText?: string;
}
const StyledModal = styled(Modal)`
.modal-container-header {
display: none;
}
.modal-container-footer {
display: none ;
}
.modal-container-close {
display: none;
}
`;
const Loader: FC<LoaderInterface> = ({ loading, loadingText }) => {
console.log("this modal is working");
return (
<StyledModal onClose={() => loading === false} open={loading}>
<div>
<Loading size="large" />
<Heading type="h4">{loadingText}</Heading>
</div>
</StyledModal>
);
};
export default Loader;
It is working when a general React functional component is calling the custom styled modal
but it is not working when a modal calling this custom modal. When the modal is triggering the custom modal then the style of the calling modal is getting effected. But I closed the calling modal before calling this custom modal.
In DEV tool I'm always seeing, for example, for footer,
.hPyTDi modal-container-footer {
border-top: 1px solid rgba(0,0,0,0.06);
padding: 16px 24px;
text-align: right;
}
That is the global style. Not my custom style. when I apply display: none inside the above code in the dev tool obviously it is working.
But this issue doesn't persist when my custom modal is called by a React functional component. Only this issue appears when a modal (which is also a React component) calls this custom modal.
I also tried '&' to increase specificity but it doesn't work.
I did,
&.modal-container-footer {
display: none;
}
It doesn't work. If I move the custom modal style in a global place it works. But I don't want that as then this is applied for all modal where I want the header/footer to be visible.
Really struggling with this. Any help is much appreciated.
I've run into so many issues with the way Styled Components selectors, and come to realise that it's always 'safer' to pass props into them. This is because of the way SC dynamically assigns class names. Might this help?
const StyledModal = styled(Modal)`
${ ({ hidden }) => hidden && `
.modal-container-header, .modal-container-footer, .modal-container-close {
display: none;
}
`}
`;
const Example = () => (
<StyledModal hidden={()=>someFunction} />
)
For TypeScript, the syntax is similar:
const StyledModal = styled.div<{hidden: boolean}>(...)

Styled-Components Pass Props For Condition

I am trying to make a conditional icon with styled-components. But I need to pass props like function params. Because I need to change the icon with the condition.
export const RadioCheck = ({checked}) => styled(checked ? FaCheckCircle : FaRegCircle)`
display: flex;
align-self: center;
margin: 0 2em;
font-size: 1em;
color: ${props => props.checked ? primary : `transparent`}
`
Is there any way for this or I need to create two different components and use them?
Seems to me like you should use the condition where you return the icon to decide which component to use.
Something like
return(
<div>
{checked ?
<FaCheckCircle
//... your props
/>
:
<FaRegCircle
//... props
/>
}
</div>
)
If it's helpful to you, it is possible to style a styled component, such as
const FirstComponent = styled.div`
//some styling
`
const SecondComponent = styled(FirstComponent)`
//some more styling
`

styled-components with custom React components: passing props

I have a custom component that takes in a property icon and sets the button's inner image to the corresponding icon as follows:
<custom-button-icon ref={showIcon} slot="right" icon="tier1:visibility-show" onClick={() => isPasswordVisible(false)} />
I would like to apply custom styling to a couple of instances of this component using styled-components. How can I pass the icon prop in so that it still functions (gets passed in as a pop of custom-button-icon)? This is what I have so far but it returns an empty button (with no icon):
export const d2lButtonIcon = ({ icon }) => {
const buttonIcon = styled(`d2l-button-icon`)`
display: flex;
align-items: center;
justify-content: center;
padding: 100px;
margin: 1px;
`
return <buttonIcon icon={icon} />
}
Thanks!
This is a really unusually case because this d2l-button-icon that you are dealing with a custom HTML element rather than a React component.
styled-components can style any React component and any built-in DOM element (a, div, etc.), but I don't think it knows how to deal with a custom DOM element because that's just not the way that we build things in React.
At first I tried passing the style to the d2l-button-icon element, and I got the icon prop to pass through but the style was ignored.
The way that I got this to work is to apply the styles to a div around the element and pass the other props to the d2l-button-icon element itself.
// function component adds styles around the icon button
const UnstyledD2L = ({ className, ...props }) => {
return (
<div className={className}>
<d2l-button-icon {...props} />
</div>
);
};
// can use styled-component to style this wrapper component
const StyledButtonIcon = styled(UnstyledD2L)`
display: flex;
align-items: center;
justify-content: center;
padding: 100px;
margin: 1px;
`;
// example usage with props
export default () => <StyledButtonIcon text="My Button" icon="tier1:gear" />;
However if you aren't super attached to this Brightspace package, I would recommend switching to a UI library that is designed for React.

how to style a nested react component

I have a component that has another nested component inside it. On a particular page I want that component to have a different background color, but it doesn't work. I'm using LESS and importing styles from styles.module.less. What am I doing wrong?
<ParentComponent className={styles.parent}>
<ChildComponent className={styles.child} />
</ParentComponent>
.parent {
.child {
background-color: black;
}
}
Did you try to set style like this?
.parent .child {
background-color: black;
}
Hope it helps.
By the way, you can set style in line like this:
<ChildComponent style={{backgroundColor: 'black'}} className={styles.child} />

Resources