How to positioning tooltip always above the children - css

I am making tooltip with antd library. I wanted to change the basic styles, so I needed to override styles. Here is the code:
import * as Styled from './Tooltip.styles';
type Props = {
title: string;
children: React.ReactNode;
};
export const CustomTooltip = ({ title, children }: Props) => (
<Styled.Tooltip
visible
title={title}
getPopupContainer={(triggerNode) => triggerNode}>
{children}
</Styled.Tooltip>
);
import styled from 'styled-components';
import { Tooltip as TooltipAnt } from 'antd';
export const Tooltip = styled(TooltipAnt)`
.ant-tooltip-content {
position: relative;
overflow-x: hidden;
overflow-y: visible;
padding-bottom: 20px;
display: inline-block;
left: -35px;
top: 25px;
}
.ant-tooltip-arrow {
display: none;
}
.ant-tooltip-inner {
padding: 10px 15px;
background: white;
display: inline-block;
border-radius: 10px;
border: 3px solid #D04A02;
border-bottom-right-radius: 0;
z-index: 2;
max-width: 200px;
color: #000;
box-shadow: none;
}
.ant-tooltip-content:before {
content: '';
position: absolute;
width: 25px;
height: 25px;
background: white;
bottom: 14px;
right: -8px;
transform: rotate(25deg);
border-bottom: 3px solid #D04A02;
}
.ant-tooltip-content:after {
content: '';
width: 3px;
background: #D04A02;
height: 50%;
position: absolute;
right: -0.5px;
bottom: 12px;
}
`;
And component where I would like to call this Tooltip:
import { CustomTooltip } from 'components/Tooltip/Tooltip';
export const SomeComponent = () => {
return (
<div>
<CustomTooltip title="Home">
<p>Home</p>
</CustomTooltip>
</div>
);
};
The problem is, the tooltip is not above the children. How can I fix this?
Codesanbox: https://codesandbox.io/s/stupefied-cohen-sgxr3s?file=/src/App.tsx

Related

Search bar won't stay at top with CSS position: sticky property

I am trying to make a search bar stay at the top of a div with position: sticky but the property doesnt seem to work. Googling it, I see that overflow: hidden and overflow: hidden on a parent element can make it unresponsive if there is no height specified but I have a height specified so I don't think that's it. Here is the relevant CSS:
.container {
background-color: white;
box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
border-radius: 1rem;
height: 85vh;
width: 60vw;
overflow-y: scroll;
overflow-x: hidden;
margin: auto;
}
.search-bar {
position: sticky;
top: 0;
margin: 1rem 1rem;
padding: 0.5rem;
font-size: 20px;
width: 100%;
display: block;
outline: 0;
border-width: 0 0 2px;
}
Note that .search-bar is a child element of .container. If needed, here is the JSX file (it's a react app):
import React, { useState, useEffect } from 'react';
import { average } from './utils/util.js';
import Card from './components/Card/Card';
import './App.css';
function App() {
const [loading, setLoading] = useState(true);
const [query, setQuery] = useState({ name: '', tag: '' });
const [users, setUsers] = useState([]);
const [filteredUsers, setFilteredUsers] = useState([]);
return (
<div className='container'>
<input
className='search-bar'
placeholder='Search by name'
onChange={(e) => {
setQuery({ ...query, name: e.target.value });
}}
/>
<input
className='search-bar'
placeholder='Search by tag'
onChange={(e) => {
setQuery({ ...query, tag: e.target.value });
}}
/>
{filteredUsers.map((user) => (
<Card
id={user.id}
pic={user.pic}
name={`${user.firstName} ${user.lastName}`}
email={user.email}
company={user.company}
skill={user.skill}
average={average(user.grades)}
grades={user.grades}
tags={user.tags}
onTagChange={tagChange}
/>
))}
</div>
);
}
export default App;
I tried to reproduce your issue here,
https://codesandbox.io/s/winter-breeze-5spod8?file=/src/styles.css
but it seems to work fine with your code. The only thing I changed was to add two .search-bar classes and height into it, because you have two input elements which you want sticky and they start to overlap on each other when we start scrolling.
.container {
background-color: white;
box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
border-radius: 1rem;
height: 85vh;
width: 60vw;
overflow-y: scroll;
overflow-x: hidden;
margin: auto;
}
.search-bar1 {
position: sticky;
top: 0;
margin: 1rem 1rem;
padding: 0.5rem;
font-size: 20px;
width: 100%;
height: 3%;
display: block;
outline: 0;
border-width: 0 0 2px;
}
.search-bar2 {
position: sticky;
top: 5.8%;
margin: 1rem 1rem;
padding: 0.5rem;
font-size: 20px;
width: 100%;
height: 3%;
display: block;
outline: 0;
border-width: 0 0 2px;
}

How to make close effect after clicking on close in Styled-components?

I'm trying to make an in and out animation for my comment -
import {
Popup,
Overlay,
NavBarPopupHeader,
NavBarPopupContainer,
NavBarPopupImg,
NavBarPopupClose,
NavBarPopupContent,
NavBarPopupTitle,
NavBarPopupInfo,
NavBarPopupContentImg,
NavBarPopupFooter,
NavBarPopupSignOut,
} from "./styled.js";
function NavBarPopup(props) {
const { isPopupOpen } = props;
return (
<Overlay>
<Popup active={false}>
<NavBarPopupHeader>
<NavBarPopupClose
src="./popup_close.svg"
alt="close"
onClick={() => isPopupOpen(false)}
active={true}
/>
<NavBarPopupContainer>
<NavBarPopupImg />
</NavBarPopupContainer>
</NavBarPopupHeader>
<NavBarPopupContent>
<NavBarPopupTitle>You are logged as</NavBarPopupTitle>
<NavBarPopupInfo>'UserName'</NavBarPopupInfo>
<NavBarPopupInfo>'Email'</NavBarPopupInfo>
<NavBarPopupContentImg src="./popup_img.png" />
</NavBarPopupContent>
<NavBarPopupFooter>
<NavBarPopupSignOut>Sign Out...</NavBarPopupSignOut>
</NavBarPopupFooter>
</Popup>
</Overlay>
);
}
export default NavBarPopup;
I am using styled-components :
import styled, { keyframes, css } from "styled-components";
import { fadeIn, bounceInRight, bounceInLeft } from 'react-animations';
const fader = keyframes`${fadeIn}`;
const bounceIn = keyframes`${bounceInRight}`;
const bounceOut = keyframes`${bounceInLeft}`;
const Popup = styled.div`
position: fixed;
top: 0;
right: 0;
height: 100vh;
width: 400px;
background-color: #ffffff;
transition: ${(active) =>
active
? css`
${bounceIn} 0.5s linear
`
: css`${bounceOut} 0.5s`};
`;
const Overlay = styled.div`
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(0, 0, 0, 0.8);
animation: 0.2s ${fader};
`;
const NavBarPopupHeader = styled.div`
width: 100%;
height: 15%;
background-color: #000000;
`;
const NavBarPopupContainer = styled.p`
text-align: center;
margin: 0;
padding: 30px 0 0 0;
`;
const NavBarPopupImg = styled.img`
width: 80px;
height: 80px;
border-radius: 50px;
border: none;
background-color: white;
color: black;
font-size: 25px;
`;
const NavBarPopupClose = styled.img`
position: absolute;
top: 5px;
left: 5px;
cursor: pointer;
`;
const NavBarPopupContent = styled.div`
height: 75%;
`;
const NavBarPopupTitle = styled.h3`
margin:0;
padding: 10px 0 10px 0;
text-align: center;
font-size: 30px;
`
const NavBarPopupInfo = styled.h4`
width: 80%;
margin: 10px auto;
padding:5px;
text-align: center;
font-size: 25px;
background-color: black;
color:white;
border-radius: 15px;
`
const NavBarPopupContentImg = styled.img`
width:100%;
margin-top:90px;
`
const NavBarPopupFooter = styled.div`
width: 100%;
height: 10%;
background-color: #000000;
`;
const NavBarPopupSignOut = styled.p`
width:200px;
text-align: center;
margin: 0 auto;
padding: 15px 0 0 0;
font-weight: 700;
font-size: 32px;
color: white;
text-decoration: underline;
cursor: pointer;
`;
export {
Popup,
Overlay,
NavBarPopupHeader,
NavBarPopupContainer,
NavBarPopupImg,
NavBarPopupClose,
NavBarPopupContent,
NavBarPopupTitle,
NavBarPopupInfo,
NavBarPopupContentImg,
NavBarPopupFooter,
NavBarPopupSignOut
};
I want my popup to be animated with $bounceIn when it appears, and disappear with $bounceOut when it closes. I tried to do it by passing an attribute to styled-components but now it only works when my Popup appears. Perhaps I chose the wrong approach, in which case please guide me in the right direction.

Using CSS attr() with styled components in react Hooks

I am trying to use attribute of SkillPer component pers={80} in css content attr function like so:
content: attr(pers) "%";
But content: attr() cannot get the attributes of <SkillPer pers={80}></SkillPer>
Am I missing something there? please help!
<SkillBar className="skill-bar">
<SkillPer
className="skill-per"
pers={80}
style={{ maxWidth: "80%" }}
></SkillPer>
</SkillBar>
export const SkillPer = styled.div`
height: 12px;
border-radius: 8px;
background-color: var(--color-green);
animation: ${fillBars} 2.5s 1;
position: relative;
&::before {
content: attr(pers) "%"; // here
position: absolute;
padding: 4px 6px;
background-color: #333;
color: var(--color-white);
font-size: 15px;
right: 0;
transform: translateX(200%);
}
`;
pers is a prop, so you can access the props in the style body. I believe this should work for you.
export const SkillPer = styled.div`
height: 12px;
border-radius: 8px;
background-color: var(--color-green);
animation: ${fillBars} 2.5s 1;
position: relative;
&::before {
content: ${({ pers }) => `"${pers} %"`};
position: absolute;
padding: 4px 6px;
background-color: #333;
color: var(--color-white);
font-size: 15px;
right: 0;
transform: translateX(200%);
}
`;

Trying to get my expanded list to push other elements upwards?

I've built a section that will eventually become a product filter. I already have the functionality that when the parent option is clicked, the list expands to reveal the sub-options. Only problem is that I need the parent option and styled span to be pushed upwards, with the bottom of the sub-options being where the parent option and span used to sit, at the bottom of that line, if that makes sense...
React :
import React, {Component} from "react";
import "./LeftMenuBar.js.css";
class LeftMenuBar extends Component {
constructor (props) {
super(props);
this.state = {
isHidden: true
}
}
handleToggle(e){
console.log(e);
this.setState({
isHidden: !this.state.isHidden
})
}
render() {
console.log(this.state.isHidden);
return (
<div className="LeftMenu">
<div className="filterList">
<ul className="ul-style">
<li id="filterOption"><a onClick={(e) => this.handleToggle(e)} href="#"><span className="dot"/>Option 1</a>
<ul className={`list ${this.state.isHidden ? 'is-hidden' : ''}`}>
<li className="expanded">Sub</li>
<li className="expanded">Sub</li>
<li className="expanded">Sub</li>
</ul>
</li>
</ul>
</div>
<div className="filterLine">
</div>
</div>
);
}
}
export default LeftMenuBar;
And here's the CSS :
.LeftMenu {
position: absolute;
left: 0;
width: 200px;
height: 400px;
z-index: 3;
}
.filterLine {
position: absolute;
width: 1px;
left: 75px;
top: 180px;
background-color: black;
height: 100%;
}
.LeftMenu.logo {
width: 50px;
height: 50px;
}
.filterList {
position: absolute;
top: 200px;
left: 75px;
}
#filterOption {
position: relative;
list-style: none;
display: inline-block;
left: 0;
}
#filterOption a {
display: inline-block;
color: black;
padding-top: 0;
margin-top: 0;
}
.dot {
z-index: 3;
position: relative;
border: 5px solid #e9e9e9;
height: 20px;
width: 20px;
background-color: black;
border-radius: 50%;
display: inline-block;
left: -20px;
}
.ul-style {
position: absolute;
padding: 0;
list-style-type: none;
top: 360px;
width: 95px;
}
.list.is-hidden {
display: none;
}
li a {
color: black;
}
.expanded {
display: block;
left: 0;
list-style-type: none;
margin: 0;
padding: 0;
}
I need the parent option and styled span to be pushed upwards, with the bottom of the sub-options being where the parent option and span used to sit.
Replace your CSS with the following to see how a few lines of flexbox can handle this:
.LeftMenu {
width: 200px;
height: 400px;
}
.filterList {
display: flex;
align-items: flex-end;
height: 100%;
}
.is-hidden {
display: none;
}
Here is a demo sandbox: https://codesandbox.io/s/xr47k1wqlq

How to fit React ant design sidebar height for different screen sizes

I'm using the Sidebar in react ant design and I'm using #media queries for making my application responsive for different screen sizes. However I am unable to make the sidebar fit the length of the screen. Any ideas? Below is my code.
------------App.js--------------
import React, { PropTypes } from "react";
import { Layout, Menu, Icon, Card } from "antd";
import SideBar from "./common/SideBar";
import MainMenu from "./common/MainMenu";
import routes from "./routes";
const { Header, Content } = Layout;
import axios from "axios";
import DashCard from "./common/DashCard";
import Dashboard from "./components/Dashboard";
import Styles from "./styles/styles.less";
import { BrowserRouter as Router, Route, Switch, Link } from "react-router-dom";
import AdminPage from "./components/Admin/AdminPage";
import LoginPage from "./components/Login/LoginPage";
export default class App extends React.Component {
render() {
return (
<Router>
<div id="App" style={{ height: "fit-content" }}>
<Layout style={{ minHeight: "" }}>
<meta name="viewport"
content="width=device-width, initial-scale=0.86, maximum-scale=3.0, minimum-scale=0.86"/>
<Header className="header">
<div className="logo"/>
<MainMenu/>
</Header>
<div className="test">
<Switch>
<Route exact path='/' component={LoginPage}/>
<Route path='/admin' component={AdminPage}/>
<Route path='/home' component={SideBar}/>
</Switch>
</div>
</Layout>
</div>
</Router>
);
}
}
------------Sidebar.js--------------
import React, { Component, PropTypes } from "react";
import ReactDOM from "react-dom";
import { Layout, Menu, Icon, Button } from "antd";
import axios from "axios/index";
import Dashboard from "../components/Dashboard";
import DashCard from "./DashCard";
import App from "../../src/App";
const { Header, Content } = Layout;
const { SubMenu } = Menu;
const { Sider } = Layout;
export default class SideBar extends React.Component {
constructor(props) {
super(props);
this.state = {
envName: "production",
env: {},
servicesArray: [],
groupArray: [],
clickStatus: false
};
this.getServices = this.getServices.bind(this);
this.selectEnv = this.selectEnv.bind(this);
}
selectEnv({ item, key }) {
let that = this;
that.setState({ servicesArray: [] });
that.setState({ clickStatus: true });
this.setState(prevState => {
return ({
envName: key,
servicesArray: [],
selectedValues: []
});
});
this.getServices(key);
}
componentDidMount() {
this.getServices(this.state.envName);
}
getServices(envname) {
let that = this;
this.setState({ servicesArray: [] });
const env = {
envName: envname
};
axios.post("http://localhost:8080/load/serviceList", env)
.then(res => {
res.data.push("Mastering");
this.setState(prevState => {
return ({
servicesArray: res.data
});
});
});
this.setState({ servicesArray: [] });
}
render() {
return (
<Layout>
<Sider width={200} style={{ background: "#fff" }} breakpoint="sm" collapsedWidth="0">
<Menu
className="sidebar"
onClick={this.selectEnv}
mode="inline"
defaultSelectedKeys={["staging"]}
defaultOpenKeys={["sub1"]}
style={{ borderRight: 0, display: "block", backgroundColor: "#6F9B9A", opacity: "0.5" }}
>
<Menu.Item key="ppe" style={{ borderRadius: "0 5px 5px 0" }}>
<span>PPE</span>
</Menu.Item>
<Menu.Item key="production" style={{ borderRadius: "0 5px 5px 0" }}>
<span>Production</span>
</Menu.Item>
<Menu.Item key="staging" style={{ borderRadius: "0 5px 5px 0" }}>
<span>Staging</span>
</Menu.Item>
</Menu>
</Sider>
<Layout style={{}}>
<Content className="appDashCard">
<DashCard title="Card title" status={this.state.clickStatus} env={this.state.servicesArray}
envName={this.state.envName}>Card
content</DashCard>
</Content>
</Layout>
</Layout>
);
}
}
------------styles.less--------------
//For mobile
#media only screen and (max-width: 768px) {
.sidebar{
height: 100%;
}
.imageLogin{
padding: 25%;
opacity: 0.9;
height:100%;
background:#fff;
background-color: #6f9b9a;
}
.loginDiv{
opacity:0.7;
margin: auto;
padding-right: 20px;
padding-top: 40px;
border-radius: 10px ;
border: 2px solid black;
text-align: left;
background-color: rgba(0, 0, 0, 0.28);
}
#btnLogin{
marginTop: 30px;
margin-left: 30px;
width: 10px;
margin-bottom: 20px;
}
.loginBtn{
margin-left: 5px;
background-color: rgba(5, 9, 46, 0.94);
}
#btn {
margin-top:50px;
width: 8%;
align-self: center;
}
.groupDiv{
width: 300px;
position: absolute;
margin-top: 80px;
margin-left: -130%;
}
.hostDiv{
width: 300px;
position: absolute;
margin-top: 160px;
margin-left: -250%;
}
.diciplineDiv{
width: 300px;
position: absolute;
margin-top: 240px;
margin-left: -365%;
}
Button {
width: 1000%;
margin-bottom: 10px;
}
Input {
align-self: center;
width: 250px;
}
h4 {
color: #5400ff;
}
.select{
width: 300px;
}
.appDashCard {
background: #fff;
padding: 10%;
align-content: center;
}
.switch{
margin-top: 320px;
position: relative;
}
}
//For tabs
#media only screen and(max-width: 991px) and (min-width: 768px){
.sidebar{
height: 100%;
}
.imageLogin{
padding: 10%;
opacity: 0.9;
height:100%;
background:#fff;
background-color: #6f9b9a;
}
.loginDiv{
opacity:0.7;
margin: auto;
padding-top: 40px;
border-radius: 10px ;
border: 2px solid black;
text-align: left;
background-color: rgba(0, 0, 0, 0.28);
}
#btnLogin{
marginTop: 30px;
margin-left: 45px;
width: 100px;
margin-bottom: 20px;
}
.loginBtn{
margin-left: 5px;
background-color: rgba(5, 9, 46, 0.94);
}
#btn {
margin-top:350px;
width: 8%;
margin-left: 10px;
align-self: center;
}
.groupDiv{
width: 300px;
position: absolute;
margin-top: 60px;
margin-left: -240%;
}
.serviceDiv{
margin-top: -40%;
margin-left: -45%;
}
.hostDiv{
width: 300px;
position: absolute;
margin-top: 140px;
margin-left: -435%;
}
.diciplineDiv{
width: 300px;
position: absolute;
margin-top: 220px;
margin-left: -635%;
}
Button {
width: 500%;
margin-bottom: 10px;
}
Input {
margin-left: 0px;
width: 250px;
}
h4 {
color: #18ff1b;
}
.select{
width: 300px;
}
.appDashCard {
background: #fff;
padding: 10%;
align-content: center;
}
.switch{
margin-top: -20px;
position: relative;
margin-left: 80%;
}
}
#media only screen and(max-width: 1254px) and (min-width: 992px){
.sidebar{
height: 100%;
}
.imageLogin{
padding: 10%;
opacity: 0.9;
height:100%;
background:#fff;
background-color: #6f9b9a;
}
.loginDiv{
opacity:0.7;
margin: auto;
padding-top: 40px;
border-radius: 10px ;
border: 2px solid black;
text-align: left;
background-color: rgba(0, 0, 0, 0.28);
}
#btnLogin{
marginTop: 30px;
margin-left: 45px;
width: 133px;
margin-bottom: 20px;
}
.loginBtn{
margin-left: 5px;
background-color: rgba(5, 9, 46, 0.94);
}
#btn {
margin-top:350px;
width: 8%;
margin-left: -20px;
align-self: center;
}
.groupDiv{
width: 300px;
position: absolute;
margin-top: 60px;
margin-left: -200%;
}
.serviceDiv{
margin-top: -40%;
margin-left: -45%;
}
.hostDiv{
width: 300px;
position: absolute;
margin-top: 160px;
margin-left: -350%;
}
.diciplineDiv{
width: 300px;
position: absolute;
margin-top: 260px;
margin-left: -500%;
}
Button {
width: 500%;
margin-bottom: 10px;
}
Input {
margin-left: 0px;
width: 250px;
}
h4 {
color: #f814ff;
}
.select{
width: 300px;
}
.appDashCard {
background: #fff;
padding: 10%;
align-content: center;
}
.switch{
margin-top: -40px;
position: relative;
margin-left: 75%;
}
}
//Laptop Screens
#media only screen and(max-width: 1400px) and (min-width: 1255px){
.sidebar {
position:absolute;
height:100%;
top:0;
right:0;
bottom:0;
left:0;
}
.imageLogin{
padding: 8%;
opacity: 0.8;
height:100%;
background:#fff;
background-color: #439b8e;
}
.loginDiv{
opacity:1;
margin: auto;
padding-top: 40px;
border-radius: 10px ;
border: 2px solid black;
text-align: left;
background-color: rgba(252, 252, 254, 0.28);
}
#btnLogin{
marginTop: 30px;
margin-left: 45px;
width: 133px;
margin-bottom: 20px;
}
.loginBtn{
margin-left: 5px;
background-color: rgba(5, 9, 46, 0.97);
}
.hostDiv{
width: 300px;
position: absolute;
margin-left: -40px;
}
.groupDiv{
margin-left:-20px;
margin-top: 0px;
}
.diciplineDiv{
width: 300px;
position: absolute;
margin-left: -60px;
}
.switch{
margin-top: 0px;
position: absolute;
margin-left: 79%;
}
.buttons {
margin-top:150px;
width: 200%;
margin-left: 45px;
}
Button {
width: 100px;
margin-right: 5%;
}
h4 {
color: rgba(255, 35, 62, 0.97);
}
.appDashCard {
height: 100%;
background: #fff;
padding: 20px;
}
.select {
width: 200px;
}
}
//Desktop Screens
#media only screen and(min-width: 1400px){
.sidebar{
height: 255%;
}
.imageLogin{
padding: 10%;
opacity: 0.8;
height:1000px;
background:#fff;
background-color: #6f9b9a;
}
.loginDiv{
opacity:1;
margin: auto;
padding-top: 40px;
border-radius: 10px ;
border: 2px solid black;
text-align: left;
background-color: rgba(0, 0, 0, 0.28);
}
.hostDiv{
width: 300px;
position: absolute;
margin-left: -40px;
}
.groupDiv{
margin-left:-20px;
margin-top: 0px;
}
.diciplineDiv{
width: 300px;
position: absolute;
margin-left: -60px;
}
.switch{
margin-top: 0px;
position: absolute;
margin-left: 78%;
}
.buttons {
margin-top:150px;
width: 200%;
margin-left: 70px;
}
Button {
width: 100px;
margin-right: 5%;
}
#btnLogin{
marginTop: 30px;
margin-left: 45px;
width: 133px;
margin-bottom: 20px;
}
.loginBtn{
margin-left: 5px;
background-color: rgba(5, 9, 46, 0.94);
}
h4 {
color: rgba(5, 9, 46, 0.97);
}
.appDashCard {
background: #fff;
padding: 24px;
}
.select {
width: 200px;
}
}
Below code works for me: Just add height for Layout
<Layout style={{height:"100vh"}}>

Resources