I have been trying for some time to figure out a way to position material ui popover under my anchor, and leave it like that always even on smaller screens.
Here is a sandbox example: https://codesandbox.io/s/material-demo-yvcqu?file=/demo.js
This is the best I got, but the scroll is not really on the body at this point its on the popover container div, and that does not help me.
Just to explain I know I can use AnchorElement with position but on smaller screens, the popover will just hide the Anchor, I would like the popover to always be under it, and just make the body scroll, so I can see the full popover content when i scroll down.
import React from "react";
import {makeStyles,MuiThemeProvider,createMuiTheme} from "#material-ui/core/styles";
import Popover from "#material-ui/core/Popover";
import Button from "#material-ui/core/Button";
export default function SimplePopover() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const theme2 = createMuiTheme({
overrides: {
MuiButton: {
root: {
top: 400
}
},
MuiPopover: {
root: {
},
paper: {
height: 500
}
}
}
});
return (
<div>
<MuiThemeProvider theme={theme2}>
<Button
variant="contained"
color="primary"
onClick={handleClick}
>
Open Popover with anchor
</Button>
<Popover
id="popover-with-anchor"
open={Boolean(anchorEl)}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
>
Popover content.
</Popover>
</MuiThemeProvider>
</div>
);
}
Images for example. When popover is bigger than the screen it fits itself in the screen and go overs the anchor
instead of being under the anchor
It's interesting the Popover component doesn't have a property to handle this situation. I ran into a similar issue on a smaller device when I had a long list of data in the popover. To fix this, I just set top myself on the PaperProps property of the Popover component. See below:
<Popover PaperProps={{ style: { top: myAnchor.current ? myAnchor.current.getBoundingClientRect().bottom : 0 } }}></Popover>
Don't do overflow: scroll on root. Instead, do overflowY: auto on paper.
See codesandbox and play around.
Try this:
overrides: {
MuiPopover: {
root: {
// overflow: "scroll"
},
paper: {
left: 50,
top: "500px !important",
height: 50,
overflowY: "auto"
}
}
}
Related
I have a div with a button and another div in it. The button is normally hidden and the inner div has a bunch of graphs and text. In certain circumstances, I want to blur the inner div and have the button float on top in the middle of the blurred out section, kind of like you see on medium or news sites when asking for subscriptions (although I removed the logic for the example). The way I'm doing it is using absolute positioning for the button, but when I do that, all of the hover functionality just flat out isn't working on the button. It doesn't change the background color of the button or change the cursorI'm using material UI and react. Here is a code sample ->
const useStyles = makeStyles((theme) => ({
blur: {
filter: "blur(7px)",
},
relativePos: {
position: "relative",
},
absolutePos: {
position: "absolute",
top: "50%",
left: "50%",
},
floatingBtn: {
"&:hover": {
cursor: "pointer",
backgroundColor: "red",
},
},
});
// some other stuff
<div className={classes.relativePos}>
<Button
variant="contained"
color="primary"
className={`${classes.absolutePos} ${classes.floatingBtn}`}
>
Button Text
</Button>
<div className={classes.blur}>
{/* Blurred Inner Div Stuff */}
</div>
</div>
I'd love suggestions on either 1) how to get this implementation working OR 2) a better implementation NOT using absolute positioning, if there's a better, more modern approach.
There are two solutions:
use zIndex on the button that is greater than the blurred inner div
Move the button under your blurred inner div
I would prefer the 2nd approach as you don't need to know the zIndex of other elements
const useStyles = makeStyles((theme) => ({
blur: {
filter: "blur(7px)"
},
relativePos: {
position: "relative"
},
absolutePos: {
position: "absolute",
top: "50%",
left: "50%"
// zIndex: 1000 <- Add The zIndex here if you want 1st approach
},
floatingBtn: {
"&:hover": {
cursor: "pointer",
backgroundColor: "red"
}
},
// This is temp button to just toggle the absolute button
tempButton: { margin: "30px 0" }
}));
export default function App() {
const classes = useStyles();
const [showButton, setShowButton] = useState(false);
return (
<div className={classes.relativePos}>
{/* Your graphs area */}
<div className={classes.blur}>This is graphs area</div>
{/* Your absolute button with hover effect */}
{/* you can add it at the bottom and then no need to use zIndex */}
{showButton && (
<button className={`${classes.absolutePos} ${classes.floatingBtn}`}>
Button
</button>
)}
{/* Temp button to show/hide the absolute button, you should have ur own logic */}
<button
className={classes.tempButton}
onClick={() => setShowButton(!showButton)}
>
Click me to show/Hide the button
</button>
</div>
);
}
working example: codesandbox
BTW If you remove filter: "blur(7px)" from the blur class then the hover should work without changing anything in your code. I have no idea why (-_-)
I am using Material UI v5, and am trying to make a responsive drawer where for smaller devices it will take up 100% of screen width while for larger devices it should only take 1/3 of screen width. But I have no idea how to access Paper property to modify the actual width and make it responsive.
My code:
import { Drawer, styled } from "#mui/material";
const ResponsiveDrawer = styled(Drawer)(({ theme }) => ({
[theme.breakpoints.up("md")]: {
width: "33%", // THIS ONLY CHANGES DRAWER WIDTH NOT PAPER WIDTH INSIDE THE DRAWER
},
[theme.breakpoints.down("md")]: {
width: "100%",
},
}));
export { ResponsiveDrawer };
How I use it:
import { ResponsiveDrawer } from "./Style";
<ResponsiveDrawer
anchor="right"
open={drawer.state}
onClose={() => drawer.onClick(false)}
>
...
</ResponsiveDrawer>
I figured it out shortly after posting the question. This involves inline styling using useMediaQuery.
const largeScreen = useMediaQuery(theme.breakpoints.up("sm"))
<Drawer
anchor="right"
open={drawer.state}
onClose={() => drawer.onClick(false)}
PaperProps={largeScreen ? {
sx: {
width: 450,
}
} : {
sx: {
width: "100%",
}
}
}
>
<CartContent cart={cart} drawer={drawer}/>
</Drawer>
You can add a div inside the <Drawer> or <SwipeableDrawer> component like so and control the width of the div through CSS (or emotion/styled, if you prefer).
<Drawer ...>
<div className="container">...</div>
</Drawer>
.container {
width: 95vw; // for mobile
... add media queries for rest of the screen sizes here
}
In their docs (expand the code blow) they give an example how to access the paper CSS, where you could add your width settings:
const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open' })(
({ theme, open }) => ({
width: drawerWidth,
flexShrink: 0,
whiteSpace: 'nowrap',
boxSizing: 'border-box',
...(open && {
...openedMixin(theme),
'& .MuiDrawer-paper': openedMixin(theme),
}),
...(!open && {
...closedMixin(theme),
'& .MuiDrawer-paper': closedMixin(theme),
}),
}),
);
They add the same mixin to '& .MuiDrawer-paper' in the main drawer css.
So for your responsive drawer you should add this paper selector to your styled CSS (maybe check with the inspector, if its the right one):
const ResponsiveDrawer = styled(Drawer)(({ theme }) => ({
[theme.breakpoints.up("md")]: {
width: "33%",
'& .MuiDrawer-paper': {
width: "33%",
},
},
[theme.breakpoints.down("md")]: {
width: "100%",
'& .MuiDrawer-paper': {
width: "100%",
},
},
}));
More information about customizing nested elements can be found on https://mui.com/material-ui/customization/how-to-customize/#the-sx-prop.
I want to change the width of the tooltip, but I can't.
How do I do this?
import React, { FunctionComponent } from 'react';
import {Tooltip} from "antd";
import 'antd/dist/antd.css';
export interface Props {
tooltipeText: string
}
const hintWithTooltipeStyle = {
position: 'relative' as 'relative',
left: 5,
top: 1
};
const HintWithTooltipe: FunctionComponent<Props> = ({
tooltipeText
}: Props) => {
return (
<span style={hintWithTooltipeStyle}>
<Tooltip placement="rightTop" title={tooltipeText} style={{width: 700, maxWidth: '500px !important'}}>
<Button>Ant design</Button>
</Tooltip>
</span>
);
};
export default HintWithTooltipe;
Inline styles don't work.
No styles work at all
You can do it like this without css class:
<Tooltip placement="rightTop" title={tooltipeText} overlayStyle={{maxWidth: '500px'}}>
<Button>Ant design</Button>
</Tooltip>
The antd Tooltip can be adapted by overriding values in css class .ant-tooltip-inner.
.ant-tooltip-inner {
color: yellow;
background-color: green;
width: 200px;
}
Here is a working CodeSandBox have a look at the index.css file for changes.
Or you could access overlayInnerStyle property from Tooltip.
<Tooltip overlayInnerStyle={{width: '250px'}} title={`tootltip text`}>
Info Text
</Tooltip>
You should use min-width for changing inside border
overlayStyle={{ maxWidth: '260px' }}
How do you align buttons on the right using Material-UI's makeStyles function?
I have tried using CSS's margin-right: 0 tag, but there is an error using '-' with makeStyles.
I renamed it as 'marginRight' and it still does not work. Also mr: 0 is not valid either. (Using Material-UI's spacing).
The code is trying to make the UI similar to stackOverflow's title layout.
import React from 'react';
import { makeStyles } from "#material-ui/core/styles";
import { Box, Button } from "#material-ui/core";
const style = makeStyles({
titleItemRight: {
color: 'white',
backgroundColor: 'blue',
top: '50%',
height: 30,
align: 'right',
position: 'relative',
transform: 'translateY(-50%)',
}
});
const App = () => {
const classes = style();
return (
<div>
<Box className={classes.titleBar}>
<Button variant='text' className={classes.titleItemRight}>Sign In</Button>
</Box>
</div>
);
};
Change,
align: 'right'
To,
float: 'right'
So the code would look like,
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import { Box, Button } from "#material-ui/core";
const style = makeStyles({
titleItemRight: {
color: "white",
backgroundColor: "blue",
top: "50%",
height: 30,
float: "right",
position: "relative",
transform: "translateY(-50%)"
}
});
const App = () => {
const classes = style();
return (
<div>
<Box className={classes.titleBar}>
<Button variant="text" className={classes.titleItemRight}>
Sign In
</Button>
</Box>
</div>
);
};
Working Codesandbox
I'd suggest using a flexbox for this or just using the AppBar provided already by material ui
https://material-ui.com/components/app-bar/#app-bar
if you'd still like to use Box, just edit the titleBar styles this way and add a spacer element to seperate elements to far right or far left
const style = makeStyles({
titleBar: {
display: 'flex',
width:'100%',
flexFlow: 'row',
},
spacer: {
flex: '1 1 auto'
}
});
and then your component
<Box className={classes.titleBar}>
<LogoHere/>
<div className={classes.spacer}/>
<Button variant="text">
Sign In
</Button>
</Box>
I have my App.js class which renders as
const theme = createMuiTheme({
palette: {
primary: lime,
secondary: {
...grey,
A400: '#00e677'
},
error: red
}
});
class App extends Component {
render() {
const classes = this.props.classes;
return (
<div className={classes.root}>
<MuiThemeProvider theme={theme}>
<MyApp/>
</MuiThemeProvider>
</div>
);
}
}
export default withStyles(styles)(App);
my root class has this style
const styles = theme => ({
root: {
width: '100%',
height: '100%',
marginTop: 0,
zIndex: 1,
overflow: 'hidden',
backgroundColor: theme.palette.background.default,
}
});
I thought that by setting height:'100%' I'd had all my window filled, the problem is that I've got a blank space (wrt the grey background) below the MyApp's div, see attached image.
How can I force the background color to fill 100% of the window?
Instead of using height:100% you may try height:100vh. Using % is relative to the parent height but using vh is relative to the height of the viewport. So making 100vh will ensure that the block fill all the height of the screen.
You can read more about here
This is a version of Temani Afif's answer.
I use Grommet within React.
To fill the whole screen with my theme background (dark!) I styled the style provider HOC thus:
import styled from 'styled-components';
FillGrommet = styled( Grommet )`min-height: 100vh;`;
then, in render() I wrote:
return (
<this.FillGrommet theme={ dark }>
<AppBar /
...
It is recommended to apply the style outside render() for performance reasons.
html {
background-color: *color of your choice*,
}
This changes the whole background past 100vh and 100vw.