Does anyone know how to map a function to react-spring-3d-carousel? This is the code I have but nothing seems to be working. My data structure for portfolioItems is fine and ImageMedia renders one card only instead of mapping each card to its respective place.
It seems I am only able to render one car successfully, but not sure what's wrong here. Maybe if someone can look at the mapping function they'll be able to see where I'm screwing up.
import React, { useState, useEffect } from "react";
import styled from "styled-components";
import Carousel from "react-spring-3d-carousel";
import { config } from "react-spring";
function Rotate(props) {
const table = props.cards.map((element, index) => {
return { ...element, onClick: () => setGoToSlide(index) };
});
const [offsetRadius, setOffsetRadius] = useState(0);
const [showArrows, setShowArrows] = useState(false);
const [goToSlide, setGoToSlide] = useState(null);
const [cards] = useState(table);
useEffect(() => {
setOffsetRadius(props.offset);
setShowArrows(props.showArrows);
}, [props.offset, props.showArrows]);
return (
<CarouselWrapper>
<Carousel
slides={cards}
currentSlide={goToSlide}
offsetRadius={offsetRadius}
showNavigation={showArrows}
animationConfig={config.gentle}
/>
</CarouselWrapper>
);
}
export default Rotate;
const CarouselWrapper = styled.div`
width: (${(props) => props.width});
height: (${(props) => props.height});
margin: (${(props) => props.margin});
`;
import React from "react";
import styled from "styled-components";
import Rotate from "./props/Rotate";
import portfolioItems from "./data/portfolioItems";
import ImageMediaCard from "./ImageMediaCard";
import { v4 as uuidv4 } from "uuid";
function Portfolio() {
let cards = [
{
key: uuidv4(),
content: <ImageMediaCard alt="1" />,
},
{
key: uuidv4(),
content: <ImageMediaCard alt="2" />,
},
{
key: uuidv4(),
content: <ImageMediaCard alt="3" />,
},
{
key: uuidv4(),
content: <ImageMediaCard alt="4" />,
},
];
return (
<PortfolioWrapper id="portfolio">
<PortfolioHeading>Portfolio</PortfolioHeading>
<Rotate
cards={
{key: uuidv(),
content: {portfolioItems.map((portfolioItem) => (
<ImageMediaCard
key={portfolioItem.id}
image={portfolioItem.image}
alt={portfolioItem.alt}
title={portfolioItem.title}
description={portfolioItem.description}
website={portfolioItem.website}
source={portfolioItem.source}
/>
))}}}
height="500px"
width="80%"
margin="10px"
offset={2}
showArrows={false}
/>
</PortfolioWrapper>
);
}
export default Portfolio;
const PortfolioWrapper = styled.div`
max-width: 100vw;
padding-bottom: 120px;
background-color: lightgreen;
height: 900px;
#media (max-width: 768px) {
display: block;
display: inline-block;
}
`;
const PortfolioHeading = styled.h2`
font-size: 60px;
display: flex;
justify-content: center;
`;
const RowWrap = styled.div`
padding-top: 20px;
`;
const Row = styled.div`
display: flex;
justify-content: space-around;
padding-bottom: 30px;
margin-left: 30px;
margin-right: 30px;
#media (max-width: 768px) {
flex-direction: column;
}
`;
const Cards = styled(Card)`
/* display: flex; */
/* justify-content: space-around; */
`;
Any help would be greatly appreciated!
Related
I am working on an app that fetches current weather for a specified location.
I want to display current time but i have to use "slice()" method to get rid of the first part of the string that looks like this: "localtime: '2022-05-12 13:39' ".
The problem is with useEffect() and states in the context file.
import axios from "axios";
import { createContext, useEffect, useState } from "react";
const Context = createContext({
weather: {},
place: {},
});
export const ContextProvider = ({ children }) => {
const [weather, setWeather] = useState({});
const [place, setPlace] = useState({});
useEffect(() => {
const getWeatherData = async () => {
try {
const request = await axios.get(
"http://api.weatherstack.com/current"
);
const currentWeather = request.data.current;
const currentPlace = request.data.location;
setWeather(currentWeather);
setPlace(currentPlace);
} catch (err) {
console.log(err);
}
};
getWeatherData();
}, []);
console.log(weather);
console.log(place);
const context = {
weather,
place,
};
return <Context.Provider value={context}>{children}</Context.Provider>;
};
export default Context;
When i console.log my states (lines 33 & 34 in context file) i get this result:
result
So on the first render they're undefined but then useEffect runs and update them.
I assume that this is why my "splice()" method does not work properly.
import styled from "styled-components";
import IconWind from "../icons/icon-wind";
import IconWindDirection from "../icons/icon-wind-direction";
// import IconHumidity from "../icons/icon-humidity";
import { useContext } from "react";
import Context from "../../store/context";
const WeatherDisplay = () => {
const current = useContext(Context);
const currentDay = new Date(current.place.localtime).toLocaleString("en-us", {
weekday: "long",
});
const currentTime = current.place.localtime.slice(10);
return (
<Wrapper>
<div>
<PrimaryInfo>
<h1>{current.place.name},</h1>
<h2>{current.weather.temperature}°</h2>
<p>
{currentDay}, {currentTime}
</p>
</PrimaryInfo>
<AdditionalInfo>
<p>
<IconWind /> Wind Speed: {current.weather.wind_speed}
</p>
<p>
<IconWindDirection /> Wind Direction: {current.weather.wind_dir}
</p>
<p>Atmospheric pressure: {current.weather.pressure}</p>
<p>Humidity: {current.weather.humidity}</p>
</AdditionalInfo>
</div>
</Wrapper>
);
};
const Wrapper = styled.section`
width: 50%;
border-radius: 10px 0 0 10px;
& > div {
height: 100%;
padding-left: 4rem;
display: flex;
justify-content: center;
flex-direction: column;
}
`;
const PrimaryInfo = styled.section`
margin-bottom: 10rem;
h1 {
font-size: 5rem;
}
h2 {
font-size: 4rem;
margin: 1rem 0rem;
}
p {
font-size: 2.4rem;
}
`;
const AdditionalInfo = styled.div`
p {
margin: 1rem 0rem;
font-size: 1.2rem;
display: flex;
align-items: center;
}
`;
export default WeatherDisplay;
splice logs
I tried to check if they already have content but still didnt work:
import styled from "styled-components";
import IconWind from "../icons/icon-wind";
import IconWindDirection from "../icons/icon-wind-direction";
// import IconHumidity from "../icons/icon-humidity";
import { useContext } from "react";
import Context from "../../store/context";
const WeatherDisplay = () => {
const current = useContext(Context);
let currentDay;
let currentTime;
if (current.place.length > 0 && current.weather.length > 0) {
currentDay = new Date(current.place.localtime).toLocaleString("en-us", {
weekday: "long",
});
currentTime = current.place.localtime.slice(10);
}
console.log( currentDay);
console.log( currentTime);
return (
<Wrapper>
<div>
<PrimaryInfo>
<h1>{current.place.name},</h1>
<h2>{current.weather.temperature}°</h2>
<p>
{currentDay}, {currentTime}
</p>
</PrimaryInfo>
<AdditionalInfo>
<p>
<IconWind /> Wind Speed: {current.weather.wind_speed}
</p>
<p>
<IconWindDirection /> Wind Direction: {current.weather.wind_dir}
</p>
<p>Atmospheric pressure: {current.weather.pressure}</p>
<p>Humidity: {current.weather.humidity}</p>
</AdditionalInfo>
</div>
</Wrapper>
);
};
const Wrapper = styled.section`
width: 50%;
border-radius: 10px 0 0 10px;
& > div {
height: 100%;
padding-left: 4rem;
display: flex;
justify-content: center;
flex-direction: column;
}
`;
const PrimaryInfo = styled.section`
margin-bottom: 10rem;
h1 {
font-size: 5rem;
}
h2 {
font-size: 4rem;
margin: 1rem 0rem;
}
p {
font-size: 2.4rem;
}
`;
const AdditionalInfo = styled.div`
p {
margin: 1rem 0rem;
font-size: 1.2rem;
display: flex;
align-items: center;
}
`;
export default WeatherDisplay;
It just displays currentDay and currentTime as undefined.
What am I doing wrong?
I'm building a tic-tac-toe app. I haven't added functionality between the X's and O's, right now, I'm stuck on rending ONE image via the onClick. I've set the state to make the onClick - at least I think - and I've written out my conditional, but its rendering X images for each square. How do I render an image for only ONE square instead of them all? Here is my code:
Xs.js
import React from 'react'
import styled from 'styled-components'
import X1 from './images/X1.jpg'
import X2 from './images/X2.jpg'
import X3 from './images/X3.jpg'
const Image = styled.img`
width: 175px;
height: 175px;
`
const Xs = () => {
const X = [X1, X2, X3]
const randomXImg = Math.floor(Math.random() * X.length)
return (
<Image src={X[randomXImg]} />
)
}
export default Xs
Cell.js - this is just a div to show for the actual square
import React from 'react'
import styled from 'styled-components'
const CellBlock = styled.div`
display: flex;
align-items: center;
justify-content;
border: 1px solid white;
width: 200px;
height: 200px;
background-color: white;
`
const Container = styled.div`
display: flex;
flex-wrap: nowrap;
flex-direction: column;
align-items: center;
box-sizing: border-box;
`
const Board = styled.div`
display: grid;
grid-template-columns: 210px 210px 202px;
grid-template-rows: 210px 210px 202px;
background-color: darkgreen;
`
const Cell = ({ onClick, isTurn, children }) => {
let squares = []
squares = Array.from(Array(9).fill(''))
return (
<Container>
<Board>
{
squares.map((box, id) => (
<CellBlock
key={id}
id={id}
onClick={onClick}
isTurn={isTurn}
>
{children}
</CellBlock>
))
}
</Board>
</Container>
)
}
export default Cell
Here is the gameboard which is the parent component of both Xs.js and Cell.js
Gameboard.js
import React, { useState } from 'react'
import Cell from './Cell'
import Xs from './Xs'
const Gameboard = () => {
const [ player, setPlayer ] = useState('X')
const [ isNotOccupied, setIsNotOccupied ] = useState(false)
return (
<>
<Cell
onClick={() => setIsNotOccupied(!isNotOccupied)}
isTurn={player}
>
{ isNotOccupied && player === 'X' && <Xs />}
</Cell>
</>
)
}
export default Gameboard
Any help would be greatly appreciated.
I am using create-react-app, and im using a Data.js file where i have object with properties which i spread as props in a tag. But when i run npm start, or deploy my image wont show, and it looks like the compiler puts my video and images in a static/media directory. i tried webpack, file-loader en url-loader but no luck.
home.js
import React, { useState } from 'react'
import Sidebar from '../components/SideBar'
import NavBar from '../components/NavBar'
import HeroSection from '../components/HeroSection'
import InfoSection from '../components/InfoSection'
import { homeObjOne, homeObjTwo, homeObjThree } from '../components/InfoSection/Data'
//set sidebar navbar toggle states
//default state toggle is
const Home = () => {
const [isOpen, setIsOpen] = useState(false)
const toggle = () => {
setIsOpen(!isOpen)
}
return (
<>
<Sidebar isOpen={isOpen} toggle={toggle} />
<NavBar toggle={toggle} />
<HeroSection />
<InfoSection {...homeObjOne} />
<InfoSection {...homeObjTwo} />
<InfoSection {...homeObjThree} />
</>
)
}
export default Home
Data.js
import reactImage from '../assets/images/react.svg'
import reactImg2 from '../assets/images/draw_and_publish.png'
export const homeObjOne = {
id: 'about',
lightBg: false,
lightText: false,
lightTextDescription: true,
topLine: 'Create SVGs for your configurators easily',
headLine: 'With the Map Tool',
description: 'Quickly and easily draw available lot using the drawing tool',
buttonLabel: 'Try it for free >',
imgStart: false,
img: require('../assets/images/react.svg'),
alt: 'Drawing',
dark: true,
primary: true,
darkText: false,
}
export const homeObjTwo = {
id: 'usage',
lightBg: true,
lightText: false,
lightTextDescription: false,
topLine: 'Usage is very easy, use these four steps to ',
headLine: 'create your first project',
description: 'Get to know the app easily in these 4 simple steps',
buttonLabel: 'Try it for free >',
imgStart: true,
img: {reactImage},
alt: 'Steps',
dark: true,
primary: true,
darkText: false,
}
export const homeObjThree = {
id: 'publish',
lightBg: false,
lightText: false,
lightTextDescription: true,
topLine: 'Publish your drawings',
headLine: 'as SVG or as an Iframe',
description: 'and import it into your projects',
buttonLabel: 'Try it for free >',
imgStart: false,
img: {reactImg2},
alt: 'Publish',
dark: true,
primary: true,
darkText: false,
}
Index.js
import React from 'react'
import { InfoContainer, InfoWrapper, InfoRow, Column1, Column2, TextWrapper, TopLine, Heading, Subtitle, BtnWrap, ImgWrap, Img } from './InfoElements'
import { Button } from '../ButtonElement'
// import reactImage from '../assets/images/react.svg'
//n
const InfoSection = ({ lightBg, id, imgStart, topLine, lightText, lightTextDescription, darkText, headLine, description, buttonLabel, img, alt, primary, dark, dark2 }) => {
return (
<>
<InfoContainer lightBg={lightBg} id={id}>
<InfoWrapper>
<InfoRow imgStart={imgStart}>
<Column1>
<TextWrapper>
<TopLine>
{/* Create SVGs for your configurators easily */}
{topLine}
</TopLine>
<Heading lightText={lightText}>
{/* With the Map Tool */}
{headLine}
</Heading>
<Subtitle darkText={darkText} lightTextDescription={lightTextDescription}>
{/* Quickly and easily draw available lot using the drawing tool */}
{description}
</Subtitle>
<BtnWrap>
<Button to='signup'
smooth={true}
duration={500}
spy={true}
exact="true"
offset={-80}
primary={primary ? 1 : 0}
dark={dark ? 1 : 0}
dark2={dark2 ? 1 : 0}>
{/* Try it for free */}
{buttonLabel}
</Button>
</BtnWrap>
</TextWrapper>
</Column1>
<Column2>
<ImgWrap>
<Img src={img} alt={alt} />
</ImgWrap>
</Column2>
</InfoRow>
</InfoWrapper>
</InfoContainer>
</>
)
}
export default InfoSection
InfoElements (styled components)
import styled from 'styled-components'
// import { homeObjOne } from './Data'
//$ variables dependant on Data.js property values
export const InfoContainer = styled.div`
color: #fff;
background: ${({ lightBg }) => (lightBg ? '#f9f9f9' : '#d3d3d3')};
font-family: 'Lato', sans-serif;
#media screen and (max-width: 768px) {
padding: 100px 0;
}
`
export const InfoWrapper = styled.div`
display: grid;
z-index: 1;
height: 860px;
width: 100%;
max-width: 1100px;
margin-right: auto;
margin-left: auto;
padding: 0 24px;
justify-content: center;
`
export const InfoRow = styled.div`
display: grid;
grid-auto-columns: minmax(auto, 1fr);
align-items: center;
grid-template-areas: ${({ imgStart }) => (imgStart ? `'col2 col1'` : `'col1 col2'`)};
#media screen and (max-width: 768px) {
grid-template-areas: ${({ imgStart }) => (imgStart ? `'col1' 'col2'` : `'col1 col1' 'col2 col2'`)};
}
`
export const Column1 = styled.div`
margin-bottom: 15px;
padding: 0 15px;
grid-area: col1;
`
export const Column2 = styled.div`
margin-bottom: 15px;
padding: 0 15px;
grid-area: col2;
`
export const TextWrapper = styled.div`
max-width: 540px;
padding-top: 0;
padding-bottom: 60px;
`
export const TopLine = styled.p`
color: #393939;
font-size: 16px;
line-height: 16px;
font-weight: 700;
letter-spacing: 1.4px;
text-transform: uppercase;
margin-bottom: 16px;
`
export const Heading = styled.h1`
margin-bottom: 24px;
font-size: 48px;
line-height: 1.1;
font-weight: 600;
color: ${({ lightText }) => (lightText ? '#f7f8fa' : '#000000')};
#media screen and (max-width: 480px) {
font-size: 32px;
}
`
export const Subtitle = styled.div`
max-width: 440px;
margin-bottom: 35px;
font-size: 18px;
font-family: 'Lato', sans-serif;
line-height: 24px;
color: ${({ darkText }) => (darkText ? '#ffffff' : '#000000')};
`
export const BtnWrap = styled.div`
display: flex;
justify-content: flex-start;
`
export const ImgWrap = styled.div`
max-width: 555px;
height: 100%;
`
export const Img = styled.div`
width: 100%;
margin: 0 0 10px 0;
padding: 0;
/* background-image: url('../images/react.svg'); */
`
**you img is a img component not a div component so rename its with img not a styled.div **
Live example (images might load slowly): https://suhadolnik-photo.surge.sh/portreti
I'm making a photography site with GatsbyJS and using the following template as a base site that I've been changing: https://github.com/LekoArts/gatsby-starter-portfolio-emilia
Being really new to graphql I've run into a problem displaying images after a user clicks on the card to show the 'Portraits' subpage. The images are all displayed with a fixed width and height which I don't want. I need to display them with their native width and height, just resized to fit into the grid.
I've tried changing the graphql query in the project.js file, where you set the maxWidth: 1600 to no avail, as well as the resize(width: 800) further down the query. Later I found out that changing the margin on gatsby-image-wrapper through dev tools gave me the expected results, but that required changing the core gatsby-image plugin and having to manually change the margin for every image separately which isn't the solution.
project.js
import React from 'react'
import Img from 'gatsby-image'
import PropTypes from 'prop-types'
import { graphql } from 'gatsby'
import styled from 'styled-components'
import { Layout, ProjectHeader, ProjectPagination, SEO } from '../components'
import config from '../../config/site'
const BG = styled.div`
background-color: ${props => props.theme.colors.bg};
position: relative;
padding: 2rem 0 0 0;
`
const OuterWrapper = styled.div`
padding: 0 ${props => props.theme.contentPadding};
margin: -10rem auto 0 auto;
`
const InnerWrapper = styled.div`
position: relative;
max-width: ${props => `${props.theme.maxWidths.project}px`};
margin: 0 auto;
`
const Grid = styled.div`
display: grid;
grid-template-columns: repeat(${props => props.theme.gridColumnsProject}, 1fr);
grid-gap: 20px;
#media (max-width: 768px) {
grid-template-columns: 1fr;
}
`
const Project = ({ pageContext: { slug, prev, next }, data: { project: postNode, images } }) => {
const project = postNode.frontmatter
return (
<Layout customSEO>
<SEO postPath={slug} postNode={postNode} postSEO />
<ProjectHeader
name={config.name}
date={project.date}
title={project.title}
areas={project.areas}
text={postNode.body}
/>
<BG>
<OuterWrapper>
<InnerWrapper>
<Grid>
{images.nodes.map(image => (
<Img
alt={image.name}
key={image.childImageSharp.fluid.src}
fluid={image.childImageSharp.fluid}
style={{ margin: '2rem 0' }}
/>
))}
</Grid>
</InnerWrapper>
<ProjectPagination next={next} prev={prev} />
</OuterWrapper>
</BG>
</Layout>
)
}
export default Project
Project.propTypes = {
pageContext: PropTypes.shape({
slug: PropTypes.string.isRequired,
next: PropTypes.object,
prev: PropTypes.object,
}),
data: PropTypes.shape({
project: PropTypes.object.isRequired,
images: PropTypes.object.isRequired,
}).isRequired,
}
Project.defaultProps = {
pageContext: PropTypes.shape({
next: null,
prev: null,
}),
}
export const pageQuery = graphql`
query($slug: String!, $absolutePathRegex: String!) {
images: allFile(
filter: {
absolutePath: { regex: $absolutePathRegex }
extension: { regex: "/(jpg)|(png)|(tif)|(tiff)|(webp)|(jpeg)/" }
}
sort: { fields: name, order: ASC }
) {
nodes {
name
childImageSharp {
fluid(maxWidth: 1600, quality: 90) {
...GatsbyImageSharpFluid_withWebp
}
}
}
}
project: mdx(fields: { slug: { eq: $slug } }) {
body
excerpt
parent {
... on File {
mtime
birthtime
}
}
frontmatter {
cover {
childImageSharp {
resize(width: 800) {
src
}
}
}
date(formatString: "DD.MM.YYYY")
title
areas
}
}
}
`
Card.js the parent component:
import React from 'react'
import styled from 'styled-components'
import PropTypes from 'prop-types'
import { useSpring, animated, config } from 'react-spring'
import { rgba } from 'polished'
import Img from 'gatsby-image'
import { Link } from 'gatsby'
const CardItem = styled(Link)`
min-height: 500px;
position: relative;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.2);
display: flex;
flex-direction: column;
justify-content: flex-end;
color: ${props => props.theme.colors.color};
transition: all 0.3s ease-in-out;
&:hover {
color: white;
transform: translateY(-6px);
}
#media (max-width: ${props => props.theme.breakpoints.s}) {
min-height: 300px;
}
`
const Cover = styled.div`
width: 100%;
height: 100%;
position: absolute;
`
const Content = styled.div`
padding: 1rem;
position: relative;
transition: all 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
opacity: 0;
background: ${props => rgba(props.theme.colors.link, 0.65)};
height: 0;
${CardItem}:hover & {
opacity: 1;
height: 120px;
}
`
const Bottom = styled.div`
margin-top: 0.5rem;
display: flex;
align-items: center;
font-size: 0.85rem;
div:first-child {
margin-right: 1rem;
}
`
const Name = styled.h2`
margin-bottom: 0;
margin-top: 0;
`
const Card = ({ path, cover, date, areas, title, delay }) => {
const springProps = useSpring({
config: config.slow,
delay: 200 * delay,
from: { opacity: 0, transform: 'translate3d(0, 30px, 0)' },
to: { opacity: 1, transform: 'translate3d(0, 0, 0)' },
})
return (
<animated.div style={springProps}>
<CardItem to={path}>
<Cover>
<Img fluid={cover} />
</Cover>
<Content>
<Name>{title}</Name>
<Bottom>
<div>{date}</div>
<div>
{areas.map((area, index) => (
<React.Fragment key={area}>
{index > 0 && ', '}
{area}
</React.Fragment>
))}
</div>
</Bottom>
</Content>
</CardItem>
</animated.div>
)
}
export default Card
Card.propTypes = {
path: PropTypes.string.isRequired,
cover: PropTypes.object.isRequired,
date: PropTypes.string.isRequired,
areas: PropTypes.array.isRequired,
title: PropTypes.string.isRequired,
delay: PropTypes.number.isRequired,
}
I expect the images to show in their native width and height, but resized to fit the grid. Providing visual representation below on how it looks now and what the expected result is.
Current result and expected result
Cheers!
Remove height:100% and position:absolute from your cover component on the homepage.
const Cover = styled.div`
width: 100%;
`
Also, in case you weren't aware, you can pass style and imgStyle props to Gatsby image to change it's css.
| style | object | Spread into the default styles of the wrapper element |
| imgStyle | object | Spread into the default styles of the actual img element |
| placeholderStyle | object | Spread into the default styles of the placeholder img element |
So in your project template you can change the object fit style like this:
<Img
alt={image.name}
key={image.childImageSharp.fluid.src}
fluid={image.childImageSharp.fluid}
imgStyle={{ objectFit: 'contain' }}
/>
I'm creating a DropDown List box and each item in the list has a remove (X) button to remove the item from the list. How is it possible to show the remove button "only" when the item is hovered over?
The current code shows the clear button each each item but I only want it to show when the item is hovered over
Sorry, here is the code
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
const ListWrapper = styled.div`
position: absolute;
width: 16rem;
z-index: 1;
background: white;
&:hover {
cursor: pointer;
}
`;
const ListMenu = styled.div`
position: absolute;
width: 100%;
z-index: 1;
background: white;
overflow-x: hidden;
`;
const ListMenuHeader = styled.div`
display: flex;
flex-direction: row;
justify-content: flex-end;
`;
const DropdownText = Text.Link.extend`
padding-top: 3rem;
`;
const DropdownButton = styled.div`
padding: 1 rem 0.75rem;
`;
const ListMenuItem = styled.div`
display: flex;
background-color: grey)};
color: grey};
>[name~=icon] {
right: 0rem;
border-radius: 0;
background: none;
align-items: right;
justify-content: right;
&:hover {
background-color: grey)};
}
&:focus {
outline: none;
}
`;
class ListListMenu extends React.Component {
static propTypes = {
id: PropTypes.string.isRequired,
text: PropTypes.node.isRequired,
items: PropTypes.arrayOf(PropTypes.any).isRequired,
component: PropTypes.func.isRequired,
selectedItem: PropTypes.any,
getItemProps: PropTypes.func.isRequired,
highlightedIndex: PropTypes.number,
closeListMenu: PropTypes.func.isRequired,
};
static defaultProps = {
selectedItem: null,
highlightedIndex: null,
}
onClearClick = (items,item1) => (item) => {
const index = items.indexOf(item1);
if (index > -1) {
items.splice(index, 1);
}
}
render() {
const {
id, text, items, component, selectedItem, getItemProps,
highlightedIndex, closeListMenu,
} = this.props;
return (
<ListWrapper id={id} >
<ListMenuHeader onClick={closeListMenu}>
<DropdownText>{text}</DropdownText>
<DropdownButton
id={`${id}-button`}
>
<Icon type="caret-up" appearance="neutral" />
</DropdownButton>
</ListMenuHeader>
<ListMenu>
{selectedItems.map((item, index) => (
<ListMenuItem
{...getItemProps({
item,
isActive: highlightedIndex === index,
isSelected: _.isEqual(selectedItem, item),
})}
key={index}
>
{React.createElement(component, { item })}
<Button // CLEAR BUTTON
name={item}
id={item}
icon="remove"
onClick={this.onClearClick(items, item)}
circle
display="flat"
appearance="disabled"
id="clear-search-button"
/>
</ListMenuItem>
))}
</ListMenu>
</ListWrapper>
);
}
}
export default ListListMenu;
Here is one way you could probably just have that "x" appear on hover.
Instead of looking for a "hover" event, what about looking for an "onmouseenter" event combined with "onmouseleave"?
Like so...
class Example extends React.Component {
onHover() {
this.refs.deleteX.style.display = "block";
}
onExit() {
this.refs.deleteX.style.display = "none";
}
render() {
return (
<div>
<input onmouseenter={ this.onHover } onmouseleave={ this.onExit } />
<p ref="deleteX">x</p>
</div>
)
}
}
Kind of like this post