In the case I have on toggle button that will bring this "mini drawer" that has some chips,
After pressing the Button
The issue in this case is that this chips just POP on the screen and I need to add some animation like this Drawer http://www.material-ui.com/#/components/drawer, I tried to add the transition and transform on CSS but It wont work
JS Part:
renderChip() {
console.log("1.30");
return this.state.listChip.map( (i, index) => (
<Chip className="chips">
{i.nome}
</Chip>
));
}
toggleList() {
this.setState({
visivel: !this.state.visivel,
});
// (this.state.visivel) ? document.getElementById("push").style.width = "0" : document.getElementById("push").style.width = "10px"};
}
render()
{
return (
<MuiThemeProvider>
<div >
<div className="anchor">
<RaisedButton
label="Label before"
labelPosition="before"
primary={true}
onClick = {this.toggleList}
/>
</div>
<div id="push" className="anchorz" style={(this.state.visivel) ? styles.wrapper : styles.closed} >
{this.renderChip()}
</div>
</div>
</MuiThemeProvider>
);
}
CSS part:
position: fixed;
display: flex;
right: 0;
bottom: 110px;
margin-right: 0;
margin-bottom: 0;
margin-left: 10px;
z-index: 900;
transition: transform 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms;*/
overflow-x: hidden;
transition: 0.5s;
Related
I am making an Airbnb clone. I am unable to make this locations filter carousel work. The carousel either takes up more space in the x-axis or if I use overflow: hidden, I am unable to make the hidden icons display on scrolling. Please find the code below.
function LocationFilter() {
const slide = (e) => {
console.log(e);
let handle = e.target.className.baseVal;
let leftHandle = document.querySelector(".left-handle");
console.log(handle);
let locations = document.querySelector(".locations");
let cs = getComputedStyle(locations);
let locationsIndex = parseInt(cs.getPropertyValue("--locations-index"));
if(handle == "right-handle") {
locations.style.setProperty("--locations-index", locationsIndex + 5);
} else {
if(locationsIndex - 5 > 0) {
locations.style.setProperty("--locations-index", locationsIndex - 5);
}
}
// console.log("locationsIndex: ", locationsIndex);
if(locationsIndex > 0) {
leftHandle.style.setProperty("display", "flex");
}
}
return (
<div className='location-filter-container'>
<RiArrowLeftSLine className="left-handle" onClick={(e) => slide(e)} />
<div className="locations snaps-inline">
{
locationData.map((data, index) => (
<button id={index} className="btn">
<img src={data.link} />
<span>{data.desc}</span>
</button>
))
}
</div>
<RiArrowRightSLine className="right-handle" onClick={(e) => slide(e)} />
<div className="location-filters-flex">
<div className="location-filters">
<RiEqualizerLine />
<span>Filters</span>
</div>
</div>
</div>
)
}
export default LocationFilter;
//CSS
.location-filter-container {
display: flex;
align-items: center;
padding: 10px 20px;
margin: 20px auto;
height: 80px;
column-gap: 10px;
background: whitesmoke;
}
.location-filter-container > .locations {
--locations-index: 0;
width: 100%;
max-width: 100%;
display: flex;
flex: 1;
column-gap: 50px;
align-items: center;
justify-content: space-between;
overflow-x: hidden;
overscroll-behavior-inline: contain;
transform: translateX(calc(var(--locations-index) * -10%));
transition: transform .5s ease-in-out;
}
Please find the screenshot below.
enter image description here
I am trying to make a slide out drawer utilizing the npm package react-transition-group. For whatever reason, I cannot seem to get the drawer to slide out from left to right on clicking the additional criteria button. If you can solve this issue without using the package, that is ok too!
Here is the code I am trying to get to work as a React component:
{/* DeveloperSearch.js */}
<CSSTransition
in={sidebarClicked}
appear
timeout={1000}
classNames="drawer"
mountOnEnter
unmountOnExit
>
<div className="DevSearch__additional-search-criteria">
Additional Search Criteria
<div className="DevSearch__additional-search-criteria-individual">
<div
style={{
fontSize: '0.8rem',
marginBottom: '5px',
fontWeight: 'bold',
}}
>
Only show people who match more than {criteriaMatch}% of all
search criteria
</div>
<input
className="form-control"
type="number"
value={criteriaMatch}
onChange={(e) => setCriteriaMatch(e.target.value)}
min={0}
max={100}
step={5}
/>
</div>
</div>
</CSSTransition>
I also have a css file that is specifically for the CSS Transition component called DeveloperSearch.css:
.drawer-exit {
width: 250px;
}
.drawer-exit.drawer-exit-active {
width: 250px;
transition: width 1000ms ease-in;
}
.drawer-exit-done {
width: 0px;
}
.drawer-enter {
width: 250px;
}
.drawer-enter.drawer-enter-active {
width: 250px;
transition: all 1000ms ease-in;
}
Unfortunately, my results are no where near what I was wanting, as the drawer does not seem to slide out at all...
I also have replicated this issue in a codesandbox that can be found by clicking here. Thanks for your help!
Here is a pure css based solution but this is a bit hacky
Markup
const Drawer = ({ transitionExit, handleExit }) => (
<div
onClick={handleExit}
className={`drawer ${transitionExit ? "exit" : ""}`}
>
<p>Home</p>
<p>About</p>
<p>Contact</p>
<p>Close Drawer</p>
</div>
);
export default function App() {
const [isOpen, setIsOpen] = useState(false);
const [transitionExit, setTransitionExit] = useState(false);
const handleExit = () => {
setTransitionExit(true);
setTimeout(() => {
setIsOpen(false);
setTransitionExit(false);
// timeout should be less than animation time otherwise state might still be true
// after animation ends and drawer appears for few milliseconds
}, 450);
};
return (
<div className="App">
<div className="wrapper">
<div className="sidebar_container">
<button onClick={() => setIsOpen(true)}>open</button>
</div>
{isOpen && (
<div className={`container ${transitionExit ? "exit" : ""}`}>
<Drawer handleExit={handleExit} transitionExit={transitionExit} />
</div>
)}
</div>
</div>
);
}
CSS
.wrapper {
height: 90vh;
max-width: 60vw;
display: grid;
grid-template-columns: 30% 70%;
overflow: hidden;
margin: 40px;
}
.sidebar_container {
width: 100px;
height: 100%;
background-color: rgb(250, 207, 213);
padding: 30px;
position: relative;
z-index: 30;
}
#keyframes containerTransitionEnter {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes drawerTransitionEnter {
0% {
opacity: 0;
left: -10vw;
}
100% {
opacity: 1;
left: 0vw;
}
}
#keyframes containerTransitionExit {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes drawerTransitionExit {
0% {
opacity: 1;
left: 0vw;
}
100% {
opacity: 0;
left: -10vw;
}
}
.container {
position: relative;
z-index: 10;
height: 90vh;
animation: containerTransitionEnter 0.5s;
}
.drawer {
box-sizing: border-box;
position: relative;
height: 90vh;
width: 25vw;
padding: 20px;
background-color: rgb(4, 118, 156);
border-right: 1px solid rgba(0, 0, 0, 0.3);
animation: drawerTransitionEnter 0.5s;
}
p {
margin-bottom: 10px;
color: white;
}
.container.exit {
animation: containerTransitionExit 0.5s;
}
.drawer.exit {
animation: drawerTransitionExit 0.5s;
}
Here is the link to codesandbox
Since you are using react you can use Material UI for this Here
and you can try this in your case
<Drawer
className={classes.drawer}
variant=''
anchor='left'
open={open}
classes={{
paper: classes.drawerPaper,
}}>
<div className={classes.drawerHeader}>
<IconButton onClick={handleDrawerClose}>
{theme.direction === 'ltr' ? (
<ChevronLeftIcon />
) : (
<ChevronRightIcon />
)}
</IconButton>
</div>
<Divider />
<List>
{arr.map((text, index) => (
<ListItem
button
key={text}
onClick={
text === 'Home'
? goToHome
: text === 'About'
? handleOpenAbout
: text === 'Contact'
? goToContact
: text == 'Team'
? goToMyTea,
: goToDashboard
}>
<ListItemIcon>
{text === 'Home' ? (
<HomeIcon />
) : text === 'About' ? (
<NoteAddIcon />
) : text === 'About' || text === 'Contact' ? (
<ListAltIcon />
) : text === 'Dashboard' ? (
<DashboardIcon />
) : (
<></>
)}
</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</Drawer>
You should not delete div that has class="DevSearch__additional-search-criteria drawer-enter-done" from the DOM. In this case, Transition will not work. If you want to delete it, you must use css animation.
In this way, after adding div to the DOM, put animation on it to enter as a slider
This is the grid that I have
Once a square has been clicked, the color changes to red. - This is done using active class
I would like the change to the background color of the div tag to remain permanent after the square has been clicked.
Code
Board.js
{board.map((row, rowIdx) => (
<div key={rowIdx} className="row">
{row.map((cell, cellIdx) => (
<div key={cellIdx} className="cell"></div>
))}
</div>
))}
Board.css
.row {
height: 30px;
margin: 10px;
transition: transform 0.1s;
}
.cell:hover {
transform: scale(1.4);
}
.cell {
width: 30px;
height: 30px;
outline: 1px solid rgb(134, 154, 189);
display: inline-block;
background-color: seagreen;
margin: 5px;
transition: transform 0.2s;
}
.row :active {
background-color: red;
}
.cell :active { // Does not do anything
background-color: blue;
}
Once another square is clicked, the previosly clicked one does not remain active, you can do this by adding another class with your desired style, and using state to track the squares that have been clicked.
const [boardIndeces, setBoardIndeces] = useState(initArray(board));
const initArray = arr => {
let rows = [];
for (let i = 0; i < arr.length; i++) {
let row = [];
const currBoard = arr[i];
for (let z = 0; z < currBoard.length; z++) {
row[z] = false;
}
rows[i] = row;
}
return rows;
};
const onCellClick = (rowIdx, cellIdx) => {
if (!(boardIndeces[rowIdx] && boardIndeces[rowIdx][cellIdx])) {
boardIndeces[rowIdx][cellIdx] = true;
setBoardIndeces([...boardIndeces]);
}
};
{
board.map((row, rowIdx) => (
<div key={rowIdx}>
{row.map((cell, cellIdx) => (
<div
key={cellIdx}
className={
boardIndeces[rowIdx].includes(cellIdx)
? 'your_active_class'
: 'your_inactive_class'
}
onClick={() => onCellClick(rowIdx, cellIdx)}
></div>
))}
</div>
));
}
You can use a checkbox if you don't want to use React
HTML
<input type="checkbox" id="color" name="color">
<label id="color-div" for="color">
<!-- the div you want to change color -->
</label>
CSS
#color {
display: none
}
#color:checked + #color-div { /* + in CSS is the sibling combinator */
background-color: #fffff /* your background color */
}
What you're basically doing is making an invisible checkbox and toggling it with the label, when it's toggled you do the changes to the CSS
Remember the CSS combinators only work in elements after the HTML element it's being applied to
I have spent countless hours trying to figure out why my dropdown that is opened/closed by a burger menu icon click is sitting in front of the navbar even though I have specified z-indexes, overflows and positions. This issue is only happening on the MobileNav component below. MobileNav consists of a burger icon and the actual dropdown. Once the burger icon is clicked, the dropdown will either close or open. Currently It is displaying above the nav component and I am having a very hard time figuring out why. Any help will be much appreciated.
Vid to see the dropdown's behavior: https://www.youtube.com/watch?v=zOBnb6r_RN4&ab_channel=TylerOreskey
The dropdown is supposed to come out from the bottom of the navbar and close up into the bottom of the navbar.
Navbar Component: Renders MobileNav component
const Navbar = (props) => {
const [showDropdown, setShowDropdown] = useState(false);
const dropdownToggleHandler = () => setShowDropdown(!showDropdown);
const dropdownClosedHandler = () => setShowDropdown(false);
return (
<header
className={classes.Navbar}
style={{
position: props.passedNavbar ? "fixed" : "relative",
}}
>
<nav className={classes.MobileNav}>
<MobileNav
allNavigationRefs={props.allNavigationRefs}
scrollToDiv={props.scrollToDiv}
open={showDropdown}
closed={dropdownClosedHandler}
dropdownToggleHandler={dropdownToggleHandler}
/>
</nav>
</header>
);
};
export default memo(Navbar);
CSS file for Navbar component: z-index is not working in here.
.Navbar {
top: 0;
height: 50px;
background-color: hsl(213, 27%, 15%);
border-bottom: #00bfff 3px solid;
width: 100%;
z-index: 500;
}
#media (max-width: 500px) {
.DesktopNav {
display: none;
}
}
#media (min-width: 500px) {
.MobileNav {
display: none;
}
}
MobileNav component
const MobileNav = (props) => {
return (
<div className={classes.MobileNav}>
<DropdownToggle clicked={props.dropdownToggleHandler} />
<Dropdown open={props.open} allNavigationRefs={props.allNavigationRefs} />
</div>
);
};
export default MobileNav;
CSS file for MobileNav component
.MobileNav {
overflow: hidden;
}
Dropdown component: (This is displayed above the Navbar component and I cannot get it to be behind the navbar component).
const Dropdown = (props) => {
let attachedClasses = [classes.Dropdown, classes.Close];
if (props.open) {
attachedClasses = [classes.Dropdown, classes.Open];
}
return (
<div className={attachedClasses.join(" ")}>
<NavigationItems allNavigationRefs={props.allNavigationRefs} />
</div>
);
};
export default Dropdown;
CSS file for Dropdown component: z-index is not working in here.
.Dropdown {
background: hsl(212, 87%, 3%);
height: 200px;
transition: transform 0.3s ease-out;
z-index: 400;
display: block;
}
.Open {
transform: translate(0, 25%);
}
.Close {
transform: translate(0, -75%);
}
You are confused on how z-index works.
Consider each level in your tree as a layer.
lets say that Navbar is layer 0, MobileNav is then layer 1, and its children are on layer 2.
By default z-index is calculated among children of the same layer. This is true when the position attribute is on default static. When you alter this to relative you can instruct which layers are going to interuct with each other in a more immediate way.
Having 500 z-index on Navbar will make no sense to MobileNav. It is not his sibling, it's his child.
Here is a possible solution if you can alter the DOM tree
<header
className={classes.Navbar}
style={{
position: props.passedNavbar ? "fixed" : "relative"
}}
>
<nav className={classes.Navbar}>
<DropdownToggle clicked={props.dropdownToggleHandler} />
</nav>
<MobileNav
className={classes.MobileNav}
allNavigationRefs={props.allNavigationRefs}
scrollToDiv={props.scrollToDiv}
open={showDropdown}
closed={dropdownClosedHandler}
/>
</header>
and here is an answer if you can alter the CSS
.Navbar {
top: 0;
height: 50px;
background-color: hsl(213, 27%, 15%);
border-bottom: #00bfff 3px solid;
width: 100%;
position: relative;
}
...
.Dropdown {
background: hsl(212, 87%, 3%);
height: 200px;
transition: transform 0.3s ease-out;
display: block;
position: relative;
z-index: -1;
}
I am trying to use transitions to change the way a modal I created is shown on the screen. I need the modal to slide in from the left but the code doesn't seem to work. The app is in React.
The JSX code
const Modal = (props)=>{
let ModalClasses = [Styles.Modal];
if(props.show){
ModalClasses = [Styles.Modal, Styles.Open]
}
return(
<div className={ModalClasses.join(' ')}>
<div className={Styles.ModalNav} onClick={props.clicked}>
<div></div>
<div></div>
</div>
</div>
)
}
CSS
.Modal{
background-color: white;
position: absolute;
top: 0;
left: 25%;
width: 50vw;
height: 100vh;
z-index: 2;
transform: translateX(-100%);
transition: transform 500ms ease-out;
}
.Modal.Open{
transform: translateX(0);
}
.ModalNav div{
height: 3px;
width: 20px;
background-color: black;
margin: 5px;
position: absolute;
top: 10px;
right: 0;
cursor: pointer;
}
.ModalNav div:first-of-type{
transform: rotate(45deg);
}
.ModalNav div:last-of-type{
transform: rotate(-45deg);
}
JSX code for the component I am receiving props from
class App extends Component{
state={
showModal: false,
}
showModalHandler = ()=>{
this.setState({showModal:!this.state.showModal})
}
render(){
return (
<div className="App">
{ this.state.showModal ?
<Modal
show={this.state.showModal}
clicked={this.showModalHandler}/> : null}
{ this.state.showModal ?
<Backdrop
clicked={this.showModalHandler}/> : null}
<Table clicked={this.showModalHandler}/>
</div>
);
}
}
export default App;
My goal is to get the modal to slide in but it just pops right in.
https://salesruby.netlify.app/ can be viewed here.
Here's an alternative answer that is more in line with OP's original approach of using CSS transition instead of animating. This also let's you slide the menu back in so it slides both ways.
OP's problem is returning null in the App component if the modal is in a hidden state (which it starts with). So react will not render the modal, until you change the isOpen flag to true - at that point it renders directly in the open state (popping in), and the CSS transition has no effect. Subsequently when you close the modal, it is removed from the DOM, again without time for a transition so it "pops out".
The solution below is to render the modal in its starting state, and use the IsOpen flag to toggle the state of the element, rather than pulling it in and out of the DOM.
Here is a modified sandbox from Cyrus' answer that shows this - isModalOpen flag is used by the Modal to toggle the "open" class. The rest is basically the same as what OP started with.
https://codesandbox.io/s/bold-architecture-9t50w?file=/src/Components/Modal/Modal.js
App (Notice Modal is always returned, no : null - and isModalOpen is bound)
import React, { useState } from "react";
import "./styles.css";
import Modal from "./Components/Modal/Modal";
const App = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={() => setIsModalOpen(true)}>Open modal </button>
<Modal isModalOpen={isModalOpen} closeModal={setIsModalOpen} />
</div>
);
};
export default App;
Modal (Notice className={isModalOpen ? "open" : ""} to toggle class)
import React from "react";
import "./modal.css";
const Modal = ({ closeModal, isModalOpen }) => {
return (
<div id="modal" className={isModalOpen ? "open" : ""}>
Modal here <button onClick={() => closeModal(false)}> open modal</button>
</div>
);
};
export default Modal;
CSS (simple transform and transition effect)
#modal {
background-color: #000000cc;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
transform: translateX(-100%);
transition: transform 0.5s ease-in-out;
width: 30%;
height: 100%;
}
#modal.open {
transform: translateX(0);
}
so I made this really fast. This is just a demo on how to make the animation slide in from left to right. If you look at the css you can see that I have left : -600px and that is the width of the modal. You can make it dynamic so that it will only take some % of the screen, but don't forget to add a max-width.
here is a link to codesandbox
//app.js
import React, { useState } from "react";
import "./styles.css";
import Modal from "./Components/Modal/Modal";
const App = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={() => setIsModalOpen(true)}>Open modal </button>
{isModalOpen ? <Modal closeModal={setIsModalOpen} /> : null}
</div>
);
};
export default App;
//Modal.js
import React, { useEffect } from "react";
import "./modal.css";
const Modal = ({ closeModal }) => {
return (
<div id="modal">
Modal here <button onClick={() => closeModal(false)}> open modal</button>
</div>
);
};
export default Modal;
//modal.css
#modal {
background-color: #000000cc;
position: absolute;
top: 0;
left: 100px;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
transition: top 2s;
animation: slideIn 1s;
width: 600px;
height: 600px;
}
#keyframes slideIn {
0% {
left: -600px;
}
100% {
left: 100px;
}
}