React Sematic-UI Dropdown renderLabel popup / tooltip on mouse hover - reactjs

I'm making a react Sematic-UI Dropdown with multiselect and custom renderLabel function, I want to add tooltip / popup to these labels which show additional details of the item that the label represents. I have some rough idea how I might be able to do this, but I'm asking here first if someone has already done this or something similar and wants to share the knowledge.
http://react.semantic-ui.com/modules/dropdown/
currently I have this code:
renderLabel = (label) => {
return({
color: 'teal',
content: `${label.value}`,
icon: 'user'
})}
and it looks like:
I imagine I would need to do something like:
renderLabel = (label) => {
return({
color: 'teal',
content: `${label.value}`,
icon: 'user'
description: 'this is tooltip text...'
})}
and make an oldschool css tooltip of the description prop, something like:
[description] {position: -ms-device-fixed;}
[description]:before {
content:'';
/* hides the tooltip when not hovered */
display:none;
content:'';
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid #fff;
position:absolute;
top:30px;
left:35px;
z-index: 2;
font-size:0;
line-height:0;
width: .71428571em;
height: .71428571em;}
[description]:after {
display:none;
content:attr(description);
position:absolute;
top:35px;
left:0px;
padding:5px 10px;
background: #fff;
color: rgba(0,0,0,.87);
z-index:9;
font-size: 14px;
line-height: 1.4285em;
white-space:nowrap;
word-wrap:normal;
-webkit-transform-origin: left bottom;
-ms-transform-origin: left bottom;
transform-origin: left bottom;}
[description]:hover:before,[description]:hover:after {
display:block;}
but this is unpractical and hard coded, sematic-ui has popup module already in it, but I can't figure how to implement that here.

renderLabel={(a, b, c) => {
return (
<Popup
content={<div>Whatever i want here</div>}
eventsEnabled={true}
on="click"
onClose={() => setOpen(false)}
onOpen={() => setOpen(true)}
open={open}
trigger={<Label content={a.text} {...c} />}
/>
);
}}
You will need to improve setOpen method to just open the popop you want to be opened, maybe passing some id

Related

onClick doesn't work on Button Style Component in Mobil View

I have a styled.button that works perfectly on desktop view, but when on my desktop I toggle to mobile view it doesn't work at all.
Button:
const DateElement = styled.button`
background-color: ${(props) => (props.primary ? '#DEE2FF' : '#696B86')};
color: ${(props) => (props.primary ? 'black' : '#dedee4')};
box-shadow: none;
padding: 9px;
width: 90px;
text-align: center;
height: 90px;
user-select: none;
border: 1px solid rgba(20, 79, 118, 0.2);
& :hover {
cursor: pointer;
}
& :focus {
display: none;
}
${(theme) => theme.theme.breakpoints.down('sm')} {
padding: 3px;
width: 70px;
text-align: center;
height: 70px;
}
`;
render:
return (
<DateElement
key={date.getTime()}
primary={isSelected}
onClick={() => handleClick(date)}
className={clsx({
[classes.crossed]: date.getTime() + endTimeMilli < today.getTime(),
[classes.containerWidth]: dates.length > 4,
})}
>
<Typography className={classes.date}>{getWeekDay(date)}</Typography>
<Typography className={classes.month}>{getMonth(date)}</Typography>
<Typography className={classes.day}>{date.getDate()}</Typography>
</DateElement>
);
What is the issue?
How can I fix this?
I end up fixing it changing the styled component from button to div, I just changed it and it work, I still don't understand why or how but it worked.
const DateElement = styled.div`
Is it because you are using theme.theme?
${(theme) => theme.theme.breakpoints.down('sm')} {..
I could be wrong but not how it usually looks according to the docs: https://mui.com/customization/breakpoints/

Radio Input As Cards - React + Antd

I wanted to create Radio Input Buttons styled Cards.
I am using react js and ant design.
Tried to create my own native component using good old input type="radio".
Connecting them to antd forms wasen't smooth sailing, then I had another idea.
Using antd react Radio component and just passing a card component. That's the working result!
Usage.tsx
// Other Code
<Radio.Group onChange={onChange} value={value} className="cards-container">
<Radio value={FOCUS_LEVEL.Regular} className="radio-input-card-container">
<InputCard
title="First Card"
checked={value === CONSTANT1}
imgPath="../../assets/icon1.svg"
points={["This is a point explain why this card is the best!", "Wow this is also a great point"]} />
</Radio>
<Radio value={FOCUS_LEVEL.DeepFocus} className="radio-input-card-container">
<InputCard
title="Second Card"
checked={value === CONSTANT2}
imgPath="../../assets/icon2.svg"
points={["This point explains why this card is way better", "The other card as shitty points!"]} />
</Radio>
</Radio.Group>
// Other Code
Usage.scss
.cards-container {
display: flex;
justify-content: space-between;
margin-left: 20px;
}
InputCard.tsx
import React from "react"
import Title from "antd/lib/typography/Title";
import "./InputCard.scss"
export function InputCard({ title, checked, imgPath, points }): JSX.Element {
return (
<div className={checked ? "card checked" : "card"}>
<div className="header-container">
<Title className="card-title">{title}</Title>
<img src={imgPath} alt="regular focus"></img>
</div>
<ul>
{points.map((point) =>
<li key={point.toString()}>{point}</li>
)}
</ul>
</div >
);
}
InputCard.scss
.card {
height: 420px !important;
width: 360px !important;
position: relative !important;
left: -45px; // A work around. Placing the card under the native radio button
-webkit-appearance: none;
appearance: none;
border: 2px solid rgba(2,28,53,0.08);
border-radius: 14px;
box-shadow: 7px 7px 15px rgba(2,28,53,0.08);
cursor: pointer;
outline: none;
.header-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
ul {
padding: 0em 1em 0em 2.5em !important;
}
img {
margin: 0.5em 0em 1em 0em;
}
}
.card-title {
font-size: 20px !important;
margin-top: 16px !important;
}
.checked {
transition: border 0.5s ease;
border: 2px solid rgba(255,0,0,0.6);
}
The antd component creates a radio input circle right before the card childe. Moving the card to the left (left: -45px) so the card will include the radio circle is a workaround. I don't want to change too much in the parent component for me to use this InputCard component, and this is my try to do it within the component.

How to prevent button from losing focus when clicking elsewhere on screen?

I am fairly new to React and I am using styled-components.
const Button = styled.button`
height: 35px;
width: 85px;
color: #0288d1;
border: 1px solid #0288d1;
background: white;
border-radius: 1px;
&:hover {
cursor: pointer;
background: #cfe8ef;
}
&:focus {
background: #0288d1;
color: white;
}
`;
I would like to prevent the button from losing focus when the user clicks somewhere else on the screen. Would I need to add additional JavaScript code to do this or is there a CSS property that can help me with this issue?
Try below:
const setFocus = e => {
e.target && e.target.focus();
};
return (
<button
onBlur={e => {
setFocus(e);
}}
>
My Button
</button>
);
You can add :active in global stylesheet.
button:active {
border: 2px solid #000;
}
So any time, button tags receive this style in active mode.

Design Bootstrap dynamic nav tabs component

I want to design a dynamic nav tabs component. when the card is clicked relevant tab is shown, with the connection arrow and border-color green.
sample code or a suggestion would be much helpful
.
You can use accordion by bootstrap. Use css flexbox to horizontally align the tabs next to each other and bind a javascript method that changes css color properties (arrow, green color) on clicking.
Here is the link - https://getbootstrap.com/docs/4.0/components/collapse/
Here is how you can do :
.js :
import React, { Component } from "react";
import { render } from "react-dom";
import "./style.css";
const App = () => {
const selectBlock = (e) => {
e.target.classList.toggle('selected');
}
return (
<div className="block" onClick={(e) => {selectBlock(e)}}>
<div>Here is the block</div>
<div className="arrow">
<FakeArrow />
</div>
</div>
);
};
const FakeArrow = () => {
return (
<div>
<span className="arrow-down-border" />
<span className="arrow-down" />
</div>
);
};
render(<App />, document.getElementById("root"));
.css :
.block {
position: relative;
width: 150px;
height: 50px;
text-align: center;
border: 2px solid black;
}
.arrow {
display: none;
}
.block.selected {
border: 2px solid #99d32c;
}
.block.selected .arrow {
display: block;
}
/* You need to fake the arrow border with another arrow behind */
.arrow-down-border {
position: absolute;
bottom: -20px;
left: 55px; /* 150px (main block) / 2 -20px (size of the triangle)*/
width: 0;
height: 0;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-top: 20px solid #99d32c;
}
.arrow-down{
position: absolute;
bottom: -17px;
left: 58px; /* 150px (main block) / 2 -17px (size of the triangle)*/
width: 0;
height: 0;
border-left: 17px solid transparent;
border-right: 17px solid transparent;
border-top: 17px solid #ffffff;
}
Here is the repro on Stackblitz.
Of course this is just an example, you have to set a color for the arrows so my advice would be to do it with constants or props. Same thing for the position and others functionality you can add to the FakeArrow component.
Now, it would be waaaayy easier to manage it with an image if you really need a border (this is the tricky part in your requirement), or a simple arrow without border.
You can take a look at this post, it's the same question actually, i used a slightly different way to do it with css, but the result seems to be the same.

react-modal not closing when clicking the overlay

I'm using react-modal
The documentation mentions that the modal should close when you click the overlay by default. Even if I set the shouldCloseOnOverlayClick prop to true, this still does not work.
I'm not aware of anything that might prevent that event from occurring.
In case this is relevant/indicative of anything (and I haven't figured out why this is showing), I noticed in Chrome Developer Tools that my modal's overlay and content nodes both have an undefined class. All the CSS classes I have used are defined and working as they should.
Here's the relevant JSX and CSS, please let me know if more context is required.
JSX:
return (
<div className="Modal">
<Modal
className={{
base: 'Modal-content' + ' Modal-InputError-videoURL'
}}
overlayClassName={{
base: 'Modal-overlay'
}}
isOpen={true}
contentLabel="Modal"
>
{props.message}
<br />
<br />
<br />
<button
className="Modal-button"
onClick={events.handleCloseModal}
>
Close
</button>
</Modal>
</div>
)
CSS classes:
.Modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.35);
z-index: 9998;
}
.Modal-content {
display: relative;
position: absolute;
top: 50%;
left: 50%;
border: 1px solid #ccc;
background: rgb(38,38,38);
border: 1.5px solid rgb(45,45,45);
overflow: auto;
border-radius: 1px;
outline: none;
z-index: 9999;
width: 400px;
margin-left: -150px;
margin-right: -150px;
padding: 24px;
line-height: 16px;
}
.Modal-InputError-videoURL {
height: 134px;
margin-bottom: -67px;
margin-top: -67px;
}
.Modal-button {
display: inline-block;
padding: 4px;
margin: 0;
}
I solved this problem by using onRequestClose (per the docs). It seems that react-modal doesn't store isOpen in its local state, so I provided a callback to onRequestClose that updates the state in the parent component, which is subsequently passed down to the modal as a prop.
http://reactcommunity.org/react-modal/examples/on_request_close.html
isOpen property is statically set to true. You should control its value by keeping isOpen value in your state.
isOpen = {this.state.isModelOpen}
And in handleCloseModal method you can set its value to false.
this.setState({isModelOpen: false})
I tried to use the modal in a certain component but the click overlay close was not working. Then, I moved the modal to the previous component parent, and it started work.
I guess it have to do with z-index, but I am not sure. Sorry for missing details.
Hope it helps you guys!

Resources