How to add style on a particular image when hovering in ReactJS? - css

The problem is that I wanted to add a border to the image and display a Card that contains information when hovering but instead it displays to all the images.
After fetching data from a movie API, I stored the response in the state:
const [movies, setMovies] = useState([])
useEffect(() => {
/**side-effects**/
setMovies(response.data)
},[])
then
let style = {
display: 'none'
};
let imgStyle = {};
if(hover){
style = {
display: 'block'
}
imgStyle = {
border: 1px solid white
}
}
if(movies.length > 1) {
display = (
<div className="MovieContainer">
<h2>Trending this week</h2>
<Carousel>
{movies.map((movie) => {
return (
<>
<img
style={imgStyle}
onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}
className="Images"
key={movie.id}
src={movie.image}
alt={movie.title}
/>
<Card style={style}>{movie.title}</Card>
</>
);
})}
</Carousel>
</div>
);
}
but instead of adding a style to the *hovered* image, it also adds the style to all images.
I also tried using css for the border and it works the way I wanted but I couldn't think of any way for the Cards to show up when hovering

Why do not you do this modification directly in css file, you can just add to your css
img:hover { "2px solid black" }
instead of doing inline styling and using onMouseEnter onMouseLeave

Related

How to give padding to items from parent in react

I'm using css-module to style react , i have a css file like this
.button-style {
flex-direction: row;
padding: 10px;
}
And an simple react file like this
import React from "react"
import { useEffect, useState, useCallback, useMemo } from "react"
import style from "./styleHook.module.css"
export default function TestEffect() {
const [count, setCount] = useState(1)
const [color, setColor] = useState("black")
const increaseCount = () => setCount(count + 1)
const double = (count: number) => count * 2
const changeColor = (color: string) => {
console.log("uh oh,this will re-render")
color === "black" ? setColor("blue") : setColor("black")
}
useEffect(() => {
console.log("hey count just change and i show up")
}, [count])
return (
<div>
<h1>Value of double count : {count}</h1>
<h2 style={{ color: color }}>This text have {color} color!</h2>
<div className={style['button-style']}>
<button
onClick={() => {
setCount(count + 1)
}}
>
Change value
</button>
<button
onClick={() => {
changeColor(color)
}}
>
Change color
</button>
<button onClick={increaseCount}>Increase count by 1</button>
</div>
</div>
)
}
Now i want to give some space between button, but don't know how but it give padding for parent instead of child, come from react-native and i feel like it not work like react-native
Please help, here is the codesandbox demo
Demo
add margin to buttons
button {
margin: 0 5px;
}
You can put these buttons into a div and apply grid property on that div.
Like this
<div style={{display:'grid', gridTemplateColumns:'repeat( auto-fit,minmax(250px, 1fr)', gap:'10px'}}>
<button1>1</button1>
<button2>2</button1>
<button3>3</button1>
</div>
Now they are responsive as well.

Transition css animation works only once

I have a problem with css animation in react app triggering by useState. Animation between width changes works only once on one component. (I have array of tags on upper level)
...
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
console.log(isMounted);
setIsMounted(true);
// setIsMounted(false);
return () => {
console.log('There is');
setIsMounted(false);
}
}, []);
...
<div
id={item.label}
onKeyDown={onKeyDown}
className={isMounted ? 'i-tag' : 'no-tag' }
> {`some text`}
</div>
and scss here
.i-tag {
width: 100px;
position: relative;
max-width: max-content;
transition: width 1s ease-in;
}
.no-tag {
#extend .i-tag;
width: 0;
}
You can use TransitionGroup with CSSTransition for animating array of components.
Actually there are 2 ways to achieve animation of array of components in React,
By your own code which is bit trickier to do it perfectly
use some packages like 'react-transition-group' which is much easier to integrate
If you would like to use the package 'react-transition-group', here is the codesandbox on how to use it
<TransitionGroup component="ul">
{todos.map((todo) => (
<CSSTransition key={todo} timeout={700} classNames="item">
<li>
{todo}{" "}
<button
onClick={() => {
setTodos(todos.filter((t) => t !== todo));
}}
>
Delete
</button>
</li>
</CSSTransition>
))}
</TransitionGroup>
Courtesy: https://typeofnan.dev/how-to-animate-items-out-of-an-array-in-react/

Hide nav button in react-material-ui-carousel

I've just implemented the react material ui carousel, and it was pretty straightforward, the only thing i didn't catch, is how to hide buttons and show them only on over.
I noticed the props navButtonsAlwaysVisible and set it to false but it isn't enough.
Should i implement my own logic for that, or maybe I'm just missing something?
here's the component code:
import styles from '../../styles/Testimonial.module.scss'
import Image from 'next/image'
import Carousel from 'react-material-ui-carousel'
const Testimonial = _ => {
const items = [
{
imageUrl: "/png/image0.webp",
feedback: "feedback0",
name: "name0",
location: "location0"
},
{
imageUrl: "/png/image1.jpeg",
feedback: "feedback1",
name: "name1",
location: "location1"
}
]
return (
<div id="customers" className={`section ${styles.testimonial}`}>
<h2 className={`title ${styles.title}`}>Clientes Felizes</h2>
<span className={"separator"}> </span>
<Carousel
className={styles.carousel}
autoPlay={true}
stopAutoPlayOnHover={true}
interval={5000}
animation={"slide"}
swipe={true}
navButtonsAlwaysVisible={false}
navButtonsProps={{
style: {
backgroundColor: "#8f34eb",
opacity: 0.4
}
}}
>
{
items.map( (item, i) => <Item key={i} item={item} /> )
}
</Carousel>
</div>
)
}
function Item(props)
{
return (
<article className={styles.testimonial__card}>
<div className={styles.testimonial__photo_container}>
<Image
className={styles.testimonial__photo}
src={props.item.imageUrl}
alt="Testimonial"
width={312}
height={300}
/>
</div>
<p className={styles.testimonial__copy}>{props.item.feedback}</p>
<span className={styles.testimonial__name}>{props.item.name}</span>
<span className={styles.testimonial__city}>{props.item.location}</span>
</article>
)
}
export default Testimonial;
there's a prop called navButtonsAlwaysInvisible
navButtonsAlwaysInvisible={true}
You can try using Custom CSS for your purpose. Based on the current rendered markup,
.jss6 {
opacity: 0;
transition: all ease 1000ms; /* So that it does not disappear quickly */
}
You can define the hover for the parent so that it displays only when the parent container is hovered on:
.jss1.Testimonial_carousel__3rny3:hover .jss6 {
opacity: 1;
}
This is how it works now:

Adding image to button using Emotion css

I want to style two buttons: Up and Down with an image using emotion css but unable to do so. Currently, I am normally styling my elements within a function. How can I achieve this using emotion css?
I followed https://emotion.sh/docs/introduction but I am unable to implement it the right way.
import up from "../img/up.png";
function PostButton(props) {
let style = {
backgroundRepeat: 'no-repeat',
background: `url(${up})`,
paddingRight: 24,
paddingTop: 26,
paddingLeft: 26,
paddingBottom: 26.6
};
return (
<button style={style} onClick={() => props.handleClick()}>{props.background}</button>
);
}
//I have written similar code for PostButton2
function Post(props) {
return (
<div>
<Up >
<PostButton src={"../images/up.png"} handleClick= .
{props.incrementScore} />
</Up> >
<Down >
<PostButton2 src={"../images/down.png"}
handleClick{props.decrementScore} />
</Down>
</Col>
</Row>
</Container>
</div>
);
}
Assuming that src property holds the background image, I think you need to update background to use the prop like so:
background: `url(${props.src})`,
Use src prop as path to image.
// First way, with css from emotion/react
/** #jsx jsx */
import { jsx, css } from '#emotion/react'
const PostButton = ({ background, handleClick, src }) => (
<button css={css`
background: ${`no-repeat url(${src})`};
padding: 26px 24px 26.6px 26px;
`}
onClick={handleClick}>{background}</button>
)
// Second way, with css from emotion/css
import React from 'react'
import { css } from '#emotion/css'
const PostButton = ({ background, handleClick, src }) => (
<button className={css`
background: ${`no-repeat url(${src})`};
padding: 26px 24px 26.6px 26px;
`}
onClick={handleClick}>{background}</button>
)
// Third way, with css from emotion/css, but pass styles as object
import React from 'react'
import { css } from '#emotion/css'
const PostButton = ({ background, handleClick, src }) => (
<button className={css({
background: `no-repeat url(${src})`,
padding: '26px 24px 26.6px 26px'
})}
onClick={handleClick}>{background}</button>
)

How to removing the padding for card in and design?

I am using ant design to react UI components. I need to remove the padding given for the ant design card.
So I need to remove the padding given for the classes .ant-card-wider-padding and .ant-card-body.I am using JSS for styling the UI components.
cardStyle: {
marginTop: '30px',
boxShadow: '0px 1px 10px rgba(0,1,1,0.15)',
backgroundColor: '#ffffff',
borderStyle: 'solid',
outline: 'none',
width: '100%',
},
i am using cardStyle class to styling ant design card.Now i need to remove the padding in that card.
From the documentation of Ant Design
You need to override the style in bodyStyle not cardStyle
bodyStyle: Inline style to apply to the card content
<Card title="Card title" bodyStyle={{padding: "0"}}>Card content</Card>
use fullWidth props for removing padding..,
<Card.Section fullWidth>
<ResourceList
items={[
{
id: 341,
url: 'customers/341',
name: 'Mae Jemison',
location: 'Decatur, USA',
}
]}
renderItem={
(item) => {
const {id, url, name, location} = item;
const defaultImage = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBkPSJNLS4wMi0uMDFoMTAwdjEwMGgtMTAweiIgZmlsbD0iI2ZmZTBjMyIvPjxwYXRoIGZpbGw9IiNmZjk2N2QiIGQ9Ik0wIDBoNjkuNDF2MTAwSDB6Ii8+PHBhdGggZD0iTTY5LjkyIDB2NDQuMzJMNTEuMzQgNTV2NDVIMTAwVjB6IiBmaWxsPSIjZmZlMGMzIi8+PHBhdGggZmlsbD0iIzMyY2FjNiIgZD0iTTM5LjMyIDc2YTExLjg1IDExLjg1IDAgMCAwIDEyIDExLjYyVjc2Ii8+PHBhdGggZmlsbD0iIzAwOTc5NiIgZD0iTTM5LjMyIDc2YTEyIDEyIDAgMCAxIDEyLTExLjgyVjc2Ii8+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZmZmIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNNDMuNzQgMTkuODNhMTIuODIgMTIuODIgMCAxIDEtMjUuNjQgMCIvPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iNCIgZD0iTTI3LjM5IDMxLjZsLTEuNTggNS45Nm05LjM3LTUuNzJsMi41NSA1LjQ3bTQuMjYtOS44NWwzLjUzIDQuNW0tMjUuNDMtNC41bC0zLjUzIDQuNSIvPjwvc3ZnPgo=" ;
const media = <Thumbnail source={defaultImage} size="small" name={name} />;
return (
<ResourceList.Item id={id} url={url} media={media}>
<Stack alignment="center">
<Stack.Item fill>
<TextStyle>{name}</TextStyle>
</Stack.Item>
<Stack.Item>
<TextStyle>Last changed</TextStyle>
</Stack.Item>
<Stack.Item>
<Button>Edit Giffy</Button>
</Stack.Item>
</Stack>
</ResourceList.Item>
);
}
}
/>
</Card.Section>
very simple just add bodyStyle in Card Component
<Card bodyStyle={{ padding: "0"}}>
You can use this:
.cardStyle {
padding: 0;
}
If didn't work, use this:
.cardStyle {
padding: 0 !important;
}
I'm not too familiar with JSS but if your other styles are being applied then I assume the issue is not with that.
I was able to remove the padding from the card with the following code.
//style.less
.panelcard { ... }
.panelcard .ant-card-body {
padding: 0;
}
// panelCard.js
import { Card } from 'antd';
require('./style.less');
const PanelCard = ({ children }) => {
return (
<Card className='panelcard'>
{children} // <p>Some Child Component(s)</p>
</Card>
);
}
// invocation
<PanelCard label='Panel Title'>
<p>Some Child Component(s)</p>
</PanelCard>
This gave me the following output (card is the white box):
I am not sure if this is the preferred way of customizing antd's components but I didn't really find too much on antd's website about overriding styles, only on extending components.
Try using :global in you scss/less
div { // or any parent element/class
:global {
.ant-card-body {
passing: <number>px; // number can be 0 onwards
}
}
}

Resources