React.js + CSS: Splash Screen Animation to FadeOut - css

"leaflet": "^1.9.2",
"react": "^18.2.0",
I've built a web app using React frontend and Leaflet. The amount of data (over 3,000 objects) means the app has a 3-6 second lag when loading the page. To combat this my idea was to build a "splash screen".
.css
animation: fadeOut 1s linear forwards;
animation-delay: 5s;
width: 101%;
height: 101vh;
background-color: #428bca;
color: whitesmoke;
z-index: 99999999;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
#keyframes fadeOut {
0% {
opacity: 1;
visibility:visible;
}
100% {
opacity: 0;
visibility:hidden;
}
}
App.js
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Splash from "./components/Splash";
import Footer from "./components/Footer";
import Navbar from "./components/Nav";
import MapPage from "./pages/MapPage";
import Admin from "./pages/Admin";
import "./index.css";
import "./App.css";
import "./styles/splash.css";
import logoimg from "./img/logo.png";
function App() {
// function will move to a component once it's complete and working.
function splash() {
return (
<main id="splash-bck">
<article id="splash-container">
<img
src={logoimg}
style={{
width: "35%",
}}
/>
<p id="splash-tagline">
<em>Input your location to find warm spaces near you</em>
</p>
<div id="splash-search">
<input
type="text"
placeholder="ex: Sheffield"
style={{
border: "3px solid #428bca",
borderWidth: "2px",
borderStyle: "solid",
borderColor: "#428bca",
borderRadius: "1.5rem",
color: "grey",
padding: ".5rem",
fontSize: "1.3rem",
textAlign: "center",
}}
/>
</div>
</article>
</main>
);
}
return (
<>
<Router>
{splash()}
{/* <Splash /> */}
<div className="overlay">
<Navbar />
</div>
<Routes>
<Route index element={<MapPage />} />
<Route path="/admin" element={<Admin />} />
</Routes>
<Footer />
</Router>
</>
);
}
export default App;
I've tried different transition types and 'display: none; / visibility: hidden' where both give the same results. The idea is to show a component for 6s before it transitions (fade-out) to show the map underneath. What i currently get is the transition fades out to a white/blank page.

Related

organize Css menu-bars

i had create a menu-bars hamburger inside the app.js file to show it when I click on the 3bars alls is good but I had a problem related to CSS so when I click on icons-bar the menubar display very well but the other menu navbar on the right of it disappear.to be honest with you I'm not hero in CSS.this is my code :
app.js file:
import {useState} from "react";
import {BrowserRouter, Routes, Route, Link} from "react-router-dom";
import {useSelector} from "react-redux";
import HomePage from "./Pages/HomePage";
import ProductPage from "./Pages/ProductPage";
import CartPage from "./Pages/CartPage"
function App() {
const cart = useSelector(state=> state.cart);
const productsList = useSelector(state=> state.productsList);
const { products } = productsList;
const categories = products?.length
? products.map(({category})=> category)
: [];
const [open, setOpen] = useState(false);
const allCategories = categories.filter((element, index, categories)=> element !== categories[index + 1]);
console.log(allCategories)
const { cartProducts } = cart;
const menuBar = () => {
return (
<div className={open ?"bars": "bars-close"} >
{allCategories.map((category, index)=> <div key={index} className="bar" >{category}</div>
)}
</div>
)
}
console.log(open)
return (
<BrowserRouter>
<div className="grid-container" >
<header className="row">
<div>
<Link className="brand" to="/">My shop</Link>
<span className ="menu-bar">
<i onClick={()=> setOpen(!open)} className="fa fa-bars"></i>
</span>
{menuBar()}
</div>
<div>
<Link to="/cart/:id">Cart
{cartProducts.length > 0 && (
<span className="badge" >{cartProducts.length}</span>
)}
</Link>
<Link to="/signin">Sign In</Link>
</div>
</header>
<main>
<Routes>
<Route path="/cart/:id" element={<CartPage />} ></Route>
<Route path="/product/:id" element={<ProductPage />} exact ></Route>
<Route path="/" element={<HomePage />} ></Route>
</Routes>
</main>
<footer className="row center" >All right reserved</footer>
</div>
</BrowserRouter>
);
}
export default App;
index.css file just the part of menu-bars:
.bars {
display: block;
width: 20rem;
background-color: #101010;
height: 80px;
transition-delay: 400ms;
z-index: 2;
position: relative;
left: 5rem;
}
.bars-close {
display: none;
transition-delay: 500ms;
}
.bars .bar {
font-size: 2rem;
color: #fff;
text-decoration: underline;
margin: 0.2rem 0;
text-align: center;
}
.menu-bar {
color: #ffffff;
}
.menu-bar i {
margin-left: 2rem;
font-size: 3rem;
cursor: pointer;
}

CSSTransition to make a slide out drawer in css grid layout

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

I want the sidebar to appear on all interfaces

I am creating a site for the sake of monitoring employees, and there are six interfaces on the site, as the first interface is for the Sine-Up, the second for logging, and the third interface is for creating a project, the fourth interface is for displaying projects, the fifth is for creating TASK and the sixth In order to view the tasks.
And I created a sidebar in a separate interface, which is the image shown in the screen, and my problem now is that I want the sidebar to appear in all interfaces except for the signup and the log.
This is the application file from which router-view is used.
App.vue:
<template>
<v-app>
<router-view></router-view>
</v-app>
</template>
<script>
export default {
components:{
}
}
</script>
And in this file, the sidebar was created, which I want to appear in all the interfaces.
navbar.vue:
<template>
<v-app>
<div class="main-sidebar-container">
<div class="main-sidebar-container_content">
<v-navigation-drawer class="deep-purple accent-4" dark permanent>
<div class="main-sidebar-container_content_header">
<img class="logo" src="../../../src/assets/logo_base.png" />
</div>
<v-divider></v-divider>
<div class="sidebar-search">
<div class="cu2-search_simple-layout cu2-search">
<div class="cu2-search__inner ">
<div class="cu2-search__icon icon">
<svg class="ng-star-inserted">
<use
xlink:href="https://app.clickup.com/map.e7a227c29e2316abeae1.svg#svg-sprite-
cu3-search"
></use>
</svg>
</div>
</div>
</div>
</div>
<div class="cu2-search__text"> Search </div>
<v-list>
<v-list-item v-for="item in items" :key="item.title" class="twoSection" link>
<v-list-item-icon>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
<template v-slot:append>
<div class="pa-2">
<v-btn block>
Logout
</v-btn>
</div>
</template>
</v-navigation-drawer>
</div>
</div>
</v-app>
</template>
<script>
export default {
data() {
return {
drawer: true,
items: [
{ title: "Home", icon: "mdi-home-city" },
{ title: "Notifications", icon: "mdi-account" },
{ title: "Pulse", icon: "mdi-account-group-outline" },
{ title: "Goals", icon: "mdi-account" },
{ title: "Show less", icon: "mdi-account-group-outline" }
],
mini: true,
};
},
};
</script>
<style scoped>
.main-sidebar-container {
left: 0;
top: 0;
bottom: 0;
height: 100%;
width: 60%;
position: fixed;
z-index: 1;
top: 0;
overflow-x: hidden;
}
.main-sidebar-container_content {
width: 50%;
height: 100%;
}
.main-sidebar-container_content_header {
display: flex;
justify-content: center;
align-items: center;
width: 50%;
height: 10%;
padding-left: 1rem;
}
.logo {
display: flex;
width: 50%;
z-index: 1;
position: fixed;
}
.sidebar-search {
display: flex;
align-items: center;
height: 32px;
flex-shrink: 0;
margin: 0 8px 10px;
}
.cu2-search_simple-layout {
width: auto;
height: 100%;
flex-grow: 1;
border-radius: 4px;
background: #f6f7f9;
}
.cu2-search {
transition: background-color 0.2s cubic-bezier(0.785, 0.135, 0.15, 0.86) 0s;
display: flex;
align-items: center;
justify-content: center;
position: relative;
width: 30px;
height: 30px;
border-radius: 3px;
overflow: hidden;
flex-shrink: 0;
}
.cu2-search__inner {
display: flex;
align-items: center;
cursor: pointer;
width: 100%;
height: 100%;
}
.cu2-search__icon {
transition: fill 0.2s cubic-bezier(0.785, 0.135, 0.15, 0.86) 0s;
}
.icon {
display: flex;
align-items: center;
justify-content: center;
flex-grow: 0;
flex-shrink: 0;
}
.icon svg {
display: block;
}
.cu2-search__text{
display: block;
font: 400 12px/1 Gotham Pro,Proxima Nova,arial,serif;
color: rgba(124,130,141,.5);
transition: color .2s cubic-bezier(.785,.135,.15,.86) 0s;
cursor: pointer;
display: none;
}
.twoSection{
display: flex;
justify-content: center;
align-items: center;
height: 10%;
}
</style>
main.js:
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify';
import VueRouter from "vue-router";
import { routes } from "./router";
import axios from "axios";
import { store } from './store/index';
import Vuelidate from "vuelidate";
import 'material-design-icons-iconfont/dist/material-design-icons.css'
Vue.config.productionTip = false
Vue.use(VueRouter);
Vue.use(Vuelidate);
axios.defaults.baseURL = "localhost:4000/api/services";
axios.defaults.headers.common["Authorization"] =
"Bearer " + localStorage.getItem("accessToken") || null;
axios.defaults.headers.get["Accepts"] = "application/json";
const router = new VueRouter({
routes,
mode: "history",
});
new Vue({
vuetify,
router,
store,
render: h => h(App)
}).$mount('#app')
you can add your navbar component to App .vue
like
<template>
<v-app>
<div>
<div class="flex w-full overflow-auto h-screen bg-page">
<navbar class="w-full flex-1 max-w-72"/>
<div class="px-4 flex-1 max-h-screen overflow-auto">
<div class="pb-16">
<router-view></router-view>
</div>
</div>
</div>
</v-app>
</template>
<script>
import navbar from './navbar'
export default {
components:{
navbar
}
}
</script>
but you should handle login and signup views to make sidebar disappears.
to do this you have several options.
For it to appear in every page, you need to import the navigation component in every page.
So for instance, let's say your navigation file is called TheNavigation.vue, then on every interface you need to do something as following in the template where you want that component to appear-->
<div style="text-align: center;">
<TheNavigation />
<transition name="fade" mode="out-in">
<router-view :key="$route.path" />
</transition>
</div>
Then, in the script, you need to import the component like below
<script>
import TheNavigation from '../components/TheNavigation.vue';
import axios from "axios";
export default {
components: {
TheNavigation
},
data() {
}
}
</script>
Let me know if this worked! Or if you need me to go deeper into this! Make sure to put your relative path when importing the navigation component in the script!
The way I used to do this in React.js was, I used to make a Menu Component then use that component with every MenuItem component.
Like in your case Home MenuItem or others component you can call Menu component in that MenuItem Component
Something like this
const Menu = () => {
return <div>{...Menu}</div>
}
const HomeMenuItem = () => {
return (
<div>
<Menu />
<div>
{...this menu content in here!}
</div>
</div>
)
}
and the same goes for every other menuItem, it's somewhat of a hack but it works.

How can I remove the elevation (box shadow) from a material-ui AppBar over one small section?

I'm trying to get rid of the elevation shadow of the navbar over the sidebar.
I'm using Material-UI's AppBar for my NavBar component.
export default function NavBar() {
return (
<div>
<AppBar position="fixed" elevation={4}>
<Toolbar variant="regular">
<IconButton edge="start" color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
</Toolbar>
</AppBar>
</div>
);
}
I am using a custom sidebar component,
.sidebar {
left: 0;
top: 64px;
height: 100vh;
width: 70px;
background-color: #3f50b5;
position: fixed;
}
.sidebar::before{
display: none;
}
I don't want to lose the elevation/shadow of the entire NavBar, just the section on the left where it's over the Sidebar.
Adding this because I spent a lot of timing finding a simple answer to removing the elevation.
The simplest way to remove the shadow is by adding elevation prop to the AppBar.
<AppBar position="fixed" elevation={0}>
you could add a ::after pseudo element to your navbar to do the job. This element would have the width of your sidebar, and would be have a top property accordingly to your navbar.
Given the AppBar itself has some different breakpoints you would need to change top accordingly:
const useStyles = makeStyles((theme) => ({
root: {
"&::after": {
position: "absolute",
content: '""',
width: "70px",
height: "8px",
top: "48px",
backgroundColor: theme.palette.primary.main,
[theme.breakpoints.down("xs")]: {
top: "56px"
},
"#media (orientation: landscape)": {
top: "48px"
},
[theme.breakpoints.up("sm")]: {
top: "64px"
}
}
}
}));
export default function NavBar() {
const classes = useStyles();
return (
<div>
<AppBar classes={{ root: classes.root }} position="fixed" elevation={4}>
<Toolbar variant="regular">
<IconButton edge="start" color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
</Toolbar>
</AppBar>
</div>
);
}
I created a sandbox with only the navbar, and a darker shadow to enhance contrast:

How can I better animate a modal using CSS?

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;
}
}

Resources