I have a modal window / Cookies dialog that I want to be launched when I open my application, without having to press any buttons, before showing my Dashboard.
this is my dashboard:
import { getDocument } from '../actions/documentAction';
//
import Grid from '#mui/material/Grid';
import { ThemeProvider } from '#mui/material'
//
import theme from '../styles/theme'
import '../styles/styles.css'
//
import HeaderBar from './header-bar/HeaderBar'
import BodyGrid from './body-grid/BodyGrid';
import BottomBar from './botton-bar/BottonBar';
// -----------------------------------------------------------
export const Dashboard = () => {
const dispatch = useDispatch();
dispatch( getDocument( 'EIT5850', {} ) );
//dispatch( getPrintCenter( 'EIT5850' ) );
return (
<>
<ThemeProvider theme={theme}>
<div>
<HeaderBar/>
<Grid container xs={12}>
<BodyGrid/>
</Grid>
<Grid container xs={12} pt={4}>
<BottomBar/>
</Grid>
</div>
</ThemeProvider>
</>
)
}
This is my Cookies modal:
import * as React from 'react';
import Backdrop from '#mui/material/Backdrop';
import Box from '#mui/material/Box';
import Modal from '#mui/material/Modal';
import Fade from '#mui/material/Fade';
import Button from '#mui/material/Button';
import Typography from '#mui/material/Typography';
import {Stack, ThemeProvider } from '#mui/material'
import Tab from '#mui/material/Tab';
import TabContext from '#mui/lab/TabContext';
import TabList from '#mui/lab/TabList';
import TabPanel from '#mui/lab/TabPanel';
import { FormControlLabel, IconButton } from '#mui/material';
import CloseIcon from '#mui/icons-material/Close';
import PropTypes from 'prop-types';
import { styled } from '#mui/material/styles';
import Dialog from '#mui/material/Dialog';
import DialogTitle from '#mui/material/DialogTitle';
import DialogContent from '#mui/material/DialogContent';
import DialogActions from '#mui/material/DialogActions';
import theme from '../../styles/theme'
import '../../styles/styles.css'
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 1800,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};
const BootstrapDialog = styled(Dialog)(({ theme }) => ({
'& .MuiDialogContent-root': {
padding: theme.spacing(2),
},
'& .MuiDialogActions-root': {
padding: theme.spacing(1),
},
}));
const BootstrapDialogTitle = (props) => {
const { children, onClose, ...other } = props;
return (
<DialogTitle sx={{ m: 0, p: 2 }} {...other}>
{children}
{onClose ? (
<IconButton
aria-label="close"
onClick={onClose}
sx={{
position: 'absolute',
right: 8,
top: 8,
color: (theme) => theme.palette.grey[500],
}}
>
<CloseIcon />
</IconButton>
) : null}
</DialogTitle>
);
};
BootstrapDialogTitle.propTypes = {
children: PropTypes.node,
onClose: PropTypes.func.isRequired,
};
export default function ModalNonDocs() {
const handleOpen = () => setOpen(true);
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const handleNotClose = (event, reason) => {
if (reason && reason == "backdropClick")
return;
}
const [value, setValue] = React.useState('1');
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<ThemeProvider theme={theme}>
<div>
<Fade in={open}>
<Box>
<BootstrapDialog
onClose={handleNotClose}
aria-labelledby="customized-dialog-title"
open={open}
closeAfterTransition
BackdropComponent={Backdrop}
BackdropProps={{
timeout: 500,
}}
>
<BootstrapDialogTitle id="customized-dialog-title" onClose={handleClose}>
</BootstrapDialogTitle>
<TabContext value={value}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<TabList onChange={handleChange} aria-label="lab API tabs example">
<Tab
label="Consentimiento"
value="1" />
<Tab
label="PolĂtica de Cookies"
value="2" />
<Tab
label="Acerca de las Cookies"
value="3" />
</TabList>
</Box>
<TabPanel value="1">
<p>Opcion 1</p>
</TabPanel>
<TabPanel value="2">
<p>Opcion 2</p>
</TabPanel>
<TabPanel value="3">
<p>Opcion 3</p>
</TabPanel>
</TabContext>
<Button
onClick={handleClose}
variant="contained"
color="secondary"
style={
{ borderRadius: 0 ,
fontFamily: 'Source Sans Pro'}
}
>
Aceptar
</Button>
</BootstrapDialog>
</Box>
</Fade>
</div>
</ThemeProvider>
);
}
and this is where I call my dashboard to launch it
import { Routes, Route, BrowserRouter } from 'react-router-dom';
import { Dashboard } from '../components/Dashboard';
import { PrivateRoute } from './PrivateRoute';
export const AppRouter = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/*" element={
<PrivateRoute>
<Dashboard />
</PrivateRoute>
} />
</Routes>
</BrowserRouter>
)
}
Until now I launched my cookie modal through an informative button, but now I need it to be shown automatically when the application starts.
I can't find a way to do it without a button
Related
Im trying to implement dark/light mode in my project but i have problems to put the IconButton with its functionalities inside the Navbar component? The IconButton component is rendered with an onClick function that toggles the color mode between 'light' and 'dark' when it is clicked.
import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { Box } from "#mui/material";
import IconButton from "#mui/material/IconButton";
import {
Navbar,
Feed,
VideoDetail,
ChannelDetail,
SearchFeed,
} from "./components";
import { useTheme, ThemeProvider, createTheme } from "#mui/material/styles";
import Brightness4Icon from "#mui/icons-material/Brightness4";
import Brightness7Icon from "#mui/icons-material/Brightness7";
const ColorModeContext = React.createContext({ toggleColorMode: () => {} });
const App = () => {
const theme = useTheme();
const colorMode = React.useContext(ColorModeContext);
return (
<BrowserRouter>
<Box sx={{ bgcolor: "background.default", color: "text.primary" }}>
<Navbar />
<IconButton
sx={{ ml: 2, position: "sticky" }}
onClick={colorMode.toggleColorMode}
color="inherit"
>
{theme.palette.mode === "dark" ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
<Routes>
<Route exact path="/" element={<Feed />} />
<Route path="/video/:id" element={<VideoDetail />} />
<Route path="/channel/:id" element={<ChannelDetail />} />
<Route path="/search/:searchTerm" element={<SearchFeed />} />
</Routes>
</Box>
</BrowserRouter>
);
};
export default function ToggleColorMode() {
const [mode, setMode] = React.useState("light");
const colorMode = React.useMemo(
() => ({
toggleColorMode: () => {
setMode((prevMode) => (prevMode === "light" ? "dark" : "light"));
},
}),
[]
);
const theme = React.useMemo(
() =>
createTheme({
palette: {
mode,
},
}),
[mode]
);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</ColorModeContext.Provider>
);
}
Navbar
import React from "react";
import { IconButton, Stack } from "#mui/material";
import { Link } from "react-router-dom";
import { logo } from "../utils/constants";
import SearchBar from "./SearchBar";
const Navbar = () => {
return (
<Stack
direction="row"
alignItems="center"
p={2}
sx={{
position: "sticky",
bgcolor: "background.default",
color: "text.primary",
top: 0,
justifyContent: "space-between",
}}
>
<Link to="/" style={{ display: "flex", alignItems: "center" }}>
<img src={logo} alt="logo" height={45} />
</Link>
<SearchBar />
</Stack>
);
};
export default Navbar;
The IconButton component is rendered with an onClick function that toggles the color mode between 'light' and 'dark' when it is clicked.
I am trying to build a hamburger menu using Material UI List on Next.js similar to Nested List example on Material UI docs. However, I am keep getting error if I use "collapse" on my code. If I remove collapse then the other parts of the code works fine.
Can anyone tell me what am I doing wrong?
screenshot of an error message
I am trying to build similar to this
import * as React from "react";
import { useState } from "react";
import IconButton from "#mui/material/IconButton";
import ListSubheader from "#mui/material/ListSubheader";
import { Drawer } from "#mui/material";
import List from "#mui/material/List";
import ListItem from "#mui/material/ListItem";
import ListItemButton from "#mui/material/ListItemButton";
import ListItemIcon from "#mui/material/ListItemIcon";
import ListItemText from "#mui/material/ListItemText";
import MenuIcon from "#mui/icons-material/Menu";
import { ExpandLess, ExpandMore } from "#mui/icons-material";
import Collapse from "#mui/material";
const myMenu = [
{
title: "about",
},
{
title: "services",
submenu: [{ title: "Digital Marketing" }, { title: "Promotion" }],
},
{
title: "blog",
},
{
title: "contact",
},
];
const ResponsiveAppBar = () => {
const [openDrawer, setOpenDrawer] = useState(false);
const [open, setOpen] = React.useState(false);
const handleClick = () => {
setOpen(!open);
};
return (
<React.Fragment>
<Drawer
anchor="right"
open={openDrawer}
onClose={() => setOpenDrawer(false)}
>
<List
sx={{ width: "100%", maxWidth: 360, bgcolor: "background.paper" }}
component="nav"
aria-labelledby="nested-list-subheader"
subheader={
<ListSubheader component="div" id="nested-list-subheader">
Navigation
</ListSubheader>
}
>
{myMenu.map((page, index) =>
page.submenu ? (
<div>
<ListItemButton key={index} onClick={handleClick}>
<ListItemText>{page.title}</ListItemText>
{open ? <ExpandLess /> : <ExpandMore />}
</ListItemButton>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{page.submenu.map((sub, index) => {
return (
<ListItemButton key={index}>
<ListItem key={index}>
<ListItemText>{sub.title}</ListItemText>
</ListItem>
</ListItemButton>
);
})}
</List>
</Collapse>
</div>
) : (
<ListItemButton key={index}>
<ListItemIcon>
<ListItemText>{page.title}</ListItemText>
</ListItemIcon>
</ListItemButton>
)
)}
</List>
</Drawer>
<IconButton
sx={{ color: "black", marginLeft: "auto" }}
onClick={() => setOpenDrawer(!openDrawer)}
>
<MenuIcon color="white" />
</IconButton>
</React.Fragment>
);
};
export default ResponsiveAppBar;
The culprit is an incorrect import of Collapse:
import Collapse from "#mui/material";
Since Collapse is a named import, you must import it in one of these two ways:
import { Collapse } from "#mui/material";
// Alternatively
import Collapse from "#mui/material/Collapse";
I am trying to write out a website with responsive-based app bar with a drawer tagged onto it. I am using this design found at https://medium.com/#tsubasakondo_36683/create-responsive-drawer-menu-with-react-material-ui-617a42764b69 and modifying it accordingly. But unfortunately, I am getting this issue, in which the drawer covers the portion of the content trying to be displayed. Please know that I have seen similar questions on this site, but I couldn't figure out how to solve them or the answers were kind of vague. Any help would be much appreciated, please let me know if I need to clarify anything further. All of this is using Material UI components.
Here is my code:
Material UI App-Bar
//Used code: https://medium.com/#tsubasakondo_36683/create-responsive-drawer-menu-with-react-material-ui-617a42764b69
//Picture/Icon Imports
import home from "../Icons/home.png";
import about from "../Icons/about.png";
import contact from "../Icons/contact.png";
import resume from "../Icons/resume.png";
import minecraft from "../Icons/minecraft.png";
import github from "../Icons/github.png"
import React from 'react';
import PropTypes from 'prop-types';
import AppBar from '#material-ui/core/AppBar';
import CssBaseline from '#material-ui/core/CssBaseline';
import Drawer from '#material-ui/core/Drawer';
import Hidden from '#material-ui/core/Hidden';
import IconButton from '#material-ui/core/IconButton';
import List from '#material-ui/core/List';
import ListItem from '#material-ui/core/ListItem';
import ListItemText from '#material-ui/core/ListItemText';
import MenuIcon from '#material-ui/icons/Menu';
import CloseIcon from '#material-ui/icons/Close';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import { makeStyles, useTheme } from '#material-ui/core/styles';
import {Link} from "react-router-dom";
const drawerWidth = 240;
const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
},
drawer: {
[theme.breakpoints.up('sm')]: {
width: drawerWidth,
flexShrink: 0,
},
},
appBar: {
zIndex: theme.zIndex.drawer + 1,
},
menuButton: {
marginRight: theme.spacing(2),
[theme.breakpoints.up('sm')]: {
display: 'none',
},
},
toolbar: theme.mixins.toolbar,
drawerPaper: {
width: drawerWidth
},
content: {
flexGrow: 1,
padding: theme.spacing(0),
},
closeMenuButton: {
marginRight: 'auto',
marginLeft: 0,
},
}));
function NavBar() {
const DifferentPages = [
{Text: "Home", location: "/", Image: home},
{Text: "About", location: "/about", Image: about},
{Text: "Contact", location: "/contact", Image: contact},
{Text: "Resume", location: "/resume", Image: resume},
{Text: "Minecraft", location: "/minecraft", Image: minecraft},
]
const classes = useStyles();
const theme = useTheme();
const [mobileOpen, setMobileOpen] = React.useState(false);
function handleDrawerToggle() {
setMobileOpen(!mobileOpen)
}
const drawer = (
<div>
<List>
{DifferentPages.map((Text) => (
<ListItem button component={Link} to={Text.location}>
<img src={Text.Image} width={"25"} height={"25"}/>
<ListItemText primary={Text.Text} />
</ListItem>
))}
<ListItem button href={"example.com"}>
<img src={github} width={"25"} height={"25"}/>
<ListItemText>
Github
</ListItemText>
</ListItem>
</List>
</div>
);
return (
<div className={classes.root}>
<CssBaseline />
<AppBar position="fixed" className={classes.appBar}>
<Toolbar>
<IconButton
color="inherit"
aria-label="Open drawer"
edge="start"
onClick={handleDrawerToggle}
className={classes.menuButton}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap>
Responsive drawer
</Typography>
</Toolbar>
</AppBar>
<nav className={classes.drawer}>
<Hidden smUp implementation="css">
<Drawer
variant="temporary"
anchor={theme.direction === 'rtl' ? 'right' : 'left'}
open={mobileOpen}
onClose={handleDrawerToggle}
classes={{
paper: classes.drawerPaper,
}}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
>
<IconButton onClick={handleDrawerToggle} className={classes.closeMenuButton}>
<CloseIcon/>
</IconButton>
{drawer}
</Drawer>
</Hidden>
<Hidden xsDown implementation="css">
<Drawer
className={classes.drawer}
variant="permanent"
classes={{
paper: classes.drawerPaper,
}}
>
<div className={classes.toolbar} />
{drawer}
</Drawer>
</Hidden>
</nav>
<div className={classes.content}>
<div className={classes.toolbar} />
</div>
</div>
);
}
NavBar.propTypes = {
container: PropTypes.object,
};
export default NavBar;
App.js: NOTE** in App.js, I can add style={{paddingleft:240}} to the div before routes and it kind of remedy this issue, however, once the screen is small enough (i.e.like mobile) view and the drawer is hidden, 240px padding is still there.
(edited down for simplicity - content still the same)
import React from 'react';
import './App.css';
import { HashRouter as Router, Routes, Route} from 'react-router-dom';
//Page Routes
import NavigationAppBar from "./Navigation-Bar/NavigationAppBar";
import Home from './Page-Information/main';
function App() {
return (
<Router>
<NavigationAppBar/>
<div>
<Routes>
<Route exact path='/' exact element={<Home />} />
</Routes>
</div>
</Router>
);
}
export default App;
Home.js: (edited down for simplicity - content still the same)
import React from 'react';
const Home = () => {
return (
<div>
<h3>Example</h3>
</div>
);
};
export default Home;
I have forked the default persistent demo updated it into separate files.
You can add breakpoint for smaller device to remove margin or padding as appropriate.
const Main = styled("main", { shouldForwardProp: (prop) => prop !== "open" })(
({ theme, open }) => ({
flexGrow: 1,
padding: theme.spacing(3),
transition: theme.transitions.create("margin", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
}),
marginLeft: `-${drawerWidth}px`,
...(open && {
transition: theme.transitions.create("margin", {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen
}),
marginLeft: 0
}),
[theme.breakpoints.down('sm')]: {
//add CSS here.
}
})
);
i have inertia progress bar initialized in my app.js
app.js
import React from "react";
import { render } from "react-dom";
import { createInertiaApp } from "#inertiajs/inertia-react";
import { InertiaProgress } from "#inertiajs/progress";
createInertiaApp({
resolve: (name) => require(`./Pages/${name}`),
setup({ el, App, props }) {
render(<App {...props} />, el);
},
});
InertiaProgress.init({
// The color of the progress bar.
color: "red",
// Whether the NProgress spinner will be shown.
showSpinner: true,
});
but the progressbar won't appear every time I render the appbar in the layout, its only the layout file, because if I render without it The progressbar will appear as usual
here is my Layout.tsx
import {
Button,
Container,
ListItem,
ListItemIcon,
ListItemText,
useTheme,
} from "#mui/material";
import React from "react";
import { styled, ThemeProvider } from "#mui/material/styles";
import CssBaseline from "#mui/material/CssBaseline";
import MuiDrawer from "#mui/material/Drawer";
import Box from "#mui/material/Box";
import MuiAppBar, { AppBarProps as MuiAppBarProps } from "#mui/material/AppBar";
import Toolbar from "#mui/material/Toolbar";
import List from "#mui/material/List";
import Typography from "#mui/material/Typography";
import Divider from "#mui/material/Divider";
import IconButton from "#mui/material/IconButton";
import MenuIcon from "#mui/icons-material/Menu";
import ChevronLeftIcon from "#mui/icons-material/ChevronLeft";
import { listItems } from "./ListItems";
import { usePage } from "#inertiajs/inertia-react";
import { Inertia } from "#inertiajs/inertia";
import route from "ziggy-js";
import FlashMessage from "./FlashMessage";
import { withStyles } from "#mui/styles";
const Layout = ({
children,
title,
}: {
children: React.ReactNode;
title: React.ReactNode;
}) => {
const theme = useTheme();
const authUser: any = usePage().props.user;
const drawerWidth: number = 240;
interface AppBarProps extends MuiAppBarProps {
open?: boolean;
}
const [open, setOpen] = React.useState(false);
const toggleDrawer = () => {
setOpen(!open);
};
const handleLogout = () => {
if (confirm("are you sure want to logout?")) {
Inertia.post(route("logout"));
}
};
return (
<ThemeProvider theme={theme}>
<Box sx={{ display: "flex" }}>
<CssBaseline />
<AppBar position="absolute" open={open}>
<Toolbar
sx={{
pr: "24px", // keep right padding when drawer closed
}}
>
<IconButton
edge="start"
color="inherit"
aria-label="open drawer"
onClick={toggleDrawer}
sx={{
marginRight: "36px",
...(open && { display: "none" }),
}}
>
<MenuIcon />
</IconButton>
<Typography
component="h1"
variant="h6"
color="inherit"
noWrap
sx={{ flexGrow: 1, marginLeft: 2 }}
>
{title}
</Typography>
<Button
{...(authUser ? { display: "none" } : { sx: {} })}
variant="text"
color="inherit"
onClick={handleLogout}
>
Logout
</Button>
</Toolbar>
</AppBar>
<Drawer variant="permanent" open={open}>
<Toolbar
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
px: [1],
}}
>
<IconButton onClick={toggleDrawer}>
<ChevronLeftIcon />
</IconButton>
</Toolbar>
<Divider />
<List>{listItems}</List>
</Drawer>
<Box
component="main"
}}
>
<Toolbar />
<FlashMessage />
<Container sx={{ marginTop: "50px" }}>{children}</Container>
</Box>
</Box>
</ThemeProvider>
);
};
export default Layout;
I think my progressbar appears under the appbar, is there any solution to this problem?
Just find out what the zIndex for your AppBar is (1100 by default I think)
console.log(Theme.zIndex.appBar)
Then on your CSS file, add a line to make the zIndex of the progress bar higher:
#nprogress .bar {
z-index: 1101!important;
}
I have parent & its 2 child component
Parent code:
import React from 'react';
import { Grid, CircularProgress } from '#mui/material';
import { useSelector } from 'react-redux';
import Angle from './Angle/Angle';
import CustomSnackbar from '../Snackbar/CustomSnackbar';
import useStyles from './styles';
const Angles = ({ setCurrentId }) => {
const angles = useSelector((state) => state.angles);
const [snackbarOpenProp, setSnackbarOpenProp] = React.useState(false);
const classes = useStyles();
const handleSnackBarCloseAction = () => {
setSnackbarOpenProp(false)
}
const handleAddToCartAction = () => {
console.log('click');
setSnackbarOpenProp(true)
}
return (
!angles.length ? <CircularProgress /> : (
<Grid className={classes.container} container alignItems="stretch" spacing={3}>
{angles.map((angle) => (
<Grid key={angle._id} item xs={12} sm={6} md={6}>
<Angle angle={angle} setCurrentId={setCurrentId} handleAddToCart={handleAddToCartAction}/>
</Grid>
))}
<CustomSnackbar openState={snackbarOpenProp} handleSnackBarCloseProp={handleSnackBarCloseAction}/>
</Grid>
)
);
};
export default Angles;
Child 1 code:
import React from 'react';
import { Card, CardActions, CardContent, CardMedia, Button, Typography } from '#mui/material';
import Add from '#mui/icons-material/Add';
import { useDispatch } from 'react-redux';
import useStyles from './styles';
const Angle = ({ angle, setCurrentId,handleAddToCart }) => {
const dispatch = useDispatch();
const classes = useStyles();
return (
<Card className={classes.card}>
<CardMedia className={classes.media} image={angle.image} />
<div className={classes.overlay}>
<Typography variant="h6">{angle.qualityName}</Typography>
<Typography variant="body2">{angle.colors}</Typography>
</div>
<div className={classes.overlay2}>
<Button onClick={handleAddToCart} style={{ color: 'white' }} size="small" onClick={() => setCurrentId(angle._id)}><Add fontSize="large" /></Button>
</div>
</Card>
);
};
export default Angle;
Child 2 code:
import * as React from 'react';
import Button from '#mui/material/Button';
import Snackbar from '#mui/material/Snackbar';
import IconButton from '#mui/material/IconButton';
import CloseIcon from '#mui/icons-material/Close';
export default function CustomSnackbar(props) {
const action = (
<React.Fragment>
<Button color="secondary" size="small" onClick={props.handleSnackBarCloseProp}>
UNDO
</Button>
<IconButton
size="small"
aria-label="close"
color="inherit"
onClick={props.handleSnackBarCloseProp}
>
<CloseIcon fontSize="small" />
</IconButton>
</React.Fragment>
);
return (
<div>
<Snackbar
open={props.openState}
autoHideDuration={6000}
onClose={props.handleSnackBarCloseProp}
message="Note archived"
action={action}
/>
</div>
);
}
As you can see, I am trying to attach the onClick event which is in Child1 Angle code & based on its click I am trying to change a state value of another child2 CustomSnackbar and sending it as a prop, but on clicking I am not getting a response, How can I do it, also is there any more simple way to achieve this ?
There are two onClick methods on the button component. Please change according below example and try it.
Before:
<Button onClick={handleAddToCart} style={{ color: 'white' }} size="small" onClick={() => setCurrentId(angle._id)}><Add fontSize="large" /></Button>
After:
<Button
style={{ color: 'white' }}
size="small"
onClick={() => {
handleAddToCart();
setCurrentId(angle._id)
}
}>
<Add fontSize="large" />
</Button>