I am using Material-UI React Drawer. Is there a way I can have the drawer confined to a specific section of my page instead of occupying the entire window? I have tried giving the root component an absolute position instead of fixed but this does not change the placement of the drawer.
<div className="confirmation-drawer">
<Drawer
anchor="top"
open={state.top}
onClose={toggleDrawer('top', false)}>
<!-- Drawer content goes here -->
</Drawer>
</div>
I need the drawer inside the .confirmation-drawer div and not the entire page. Any help would be highly appreciated.
The code below worked for me. It uses the preferred one-off styling method in the MUI docs. Transitions work without any additional tweaks. Of course make sure you have a 'relative' element up in the DOM tree.
<Drawer
sx={{
'& .MuiDrawer-root': {
position: 'absolute'
},
'& .MuiPaper-root': {
position: 'absolute'
},
}}
>
</Drawer>
what #Jon Deavers said is true, though there is a workaround. you can find the z-index of the drawer overlay (1300 in may case) and set a higher z-index to the component you wish to be on top. then just set paddings inside the drawer so all it's content is visible.
as i said its merely a workaround but i hope it helps somebody.
try this:
import {styled, Drawer as MuiDrawer} from '#mui/material'
const Drawer = styled(MuiDrawer)({
position: "relative", //imp
width: 240, //drawer width
"& .MuiDrawer-paper": {
width: 240, //drawer width
position: "absolute", //imp
transition: "none !important"
}
})
If you want transitions then use collapse.
<Collapse orientation='horizontal' in={open} >
<Box> ... </Box>
</Collapse>
The Drawer component is a nav menu component that is designed to overlay the application and not to be nested inside a container. It will always appear over your other content.
If you are looking to have a dynamic element in which you can hide information and other interactive components you may want to take a look at the Accordion component from MUI.
https://material-ui.com/api/accordion/
That will allow you to have a small "drawer"-like element that other components can be hidden inside of.
Related
I am using a <TextareaAutosize> component from the Material UI Library in my React app, as such:
<TextareaAutosize
minRows="2"
style={{resize: "vertical"}}
/>
This creates a textarea that autosizes based on the size of the content. I have styled it so that the user is only able to manually expand vertically.
The current behavior is that, when the user shrinks the textbox, there is no way to view the content out of sight. My goal is to bring up the scroll bar when the user shrinks the text area.
View CodeSandbox to test.
Simply add overflow: 'auto' to the style attribute.
<TextareaAutosize
minRows="2"
style={{ width: '50%', resize: 'vertical', overflow: 'auto' }}
/>
Codesandbox
Here is codesandbox. I am trying to have the ability to sort by the first name and last name The default Datagrid only shows the sort icon when hovering. Is there a way I can set it to be always visible? Thanks for the help!
you can use .MuiDataGrid-iconButtonContainer. however Material-UI doesn't provided default icon for unsorted list. I have forked your demo and updated it. added icon for unsorted list too. please check codesandbox
This is what I did:
const StyledDataGrid = styled(DataGrid)(() => ({
'& .MuiDataGrid-iconButtonContainer': {
marginLeft: '2px',
visibility: 'visible !important',
width: 'auto !important',
},
}))
I created a styled component which adds some custom styling to DataGrid. Specifically to always show the icon and take up width for it. Using !important is not recommended, but doesn't harm in this case.
I must add, this only works with using custom sort icons, like so:
<StyledDataGrid
components={{
ColumnSortedAscendingIcon,
ColumnSortedDescendingIcon,
ColumnUnsortedIcon,
}}
/>
If you don't want to use custom icons, I'm sure it's doable, you just need to play with CSS bit more.
Add the below code in .scss file. (.MuiDataGrid-sortIcon is pre-defined class of Mui Datagrid). Hope it helps!
.MuiDataGrid-sortIcon {
opacity: inherit !important;
}
You can use the sx prop in DataGrid like so:
<DataGrid
sx={{
'.MuiDataGrid-iconButtonContainer': {
visibility: 'visible',
},
'.MuiDataGrid-sortIcon': {
opacity: 'inherit !important',
},
}}
In my case, I had to style both the iconButtonContainer and sortIcon make sure it's always visible.
Solution:
#the_previ answer worked, but I needed some more CSS to be how I wanted.
This would be my CSS that was added with makeStyles from materialUI (It can be an external CSS file too).
dropdownIcon: {
background: "url(/images/down-chevron.png) no-repeat",
backgroundSize: "20px",
backgroundPosition: "left",
paddingLeft: "30px",
},
This would be the result:
I know menus, are a really common problem, but I couldn't find a way to do it.
I have a component, with the lib react-multilevel-dropdown, that actually does exactly what I want to.
<Dropdown position="right" title="Todos os departamentos">
<Dropdown.Item>Item 1</Dropdown.Item>
<Dropdown.Item>
Item 2
<Dropdown.Submenu position="right">
<Dropdown.Item>Subitem 1</Dropdown.Item>
<Dropdown.Item>Subitem 2</Dropdown.Item>
</Dropdown.Submenu>
</Dropdown.Item>
<Dropdown.Item>Item 3</Dropdown.Item>
</Dropdown>
This would be my component right now, and I need to add an Icon on the beginning of the title, title prop only accepts strings. (it's not mandatory to be this lib, anything functioning just like it but with an icon would be great)
A possible solution using this library is to add the icon with CSS as a background image like this:
.dropdown-main {
background: url("your-icon.svg") no-repeat;
}
I'm building a login Component in React, and trying to add the brand image. When I do this, I'm getting a huge amount of white space underneath it.
I've been working on this for a bit now, and I've discovered that, when I look in the dev tools, I can make headway by modifying this mysterious div that seems to be created by Material-UI, the front-end framework I'm using.
When I look into this in the dev tools, I find that there's a div with the attribute padding-top: calc(100%) which, when modified to something like padding-top: calc(30%), reduces the size of this whitespace underneath the image.
I've also tried some of the basic layout solutions suggested in many of the answers to similar questions here on SO, but none of them make a difference. It seems that this padding issue is at the heart of the problem.
The Problem
Because I don't know what's creating this div, I'm not able to override the padding to work towards a solution. I've tried modifying paddingTop and padding with the !important tag in the styling of both the image, and the parent element of the image.
Code Sample
<Paper variant='outlined' style={{ width: '380px' }}>
<Box m={4}>
<Image
src='../static/images/TextLogo.svg'
imageStyle={{
height: 'auto',
width: '100%',
}}
/>
</Box>
...
Stack
"#material-ui/core": "^4.0.0-alpha.8",
"material-ui-image": "^3.2.3",
"next": "^8.1.0",
"react": "^16.8.6",
"react-dom": "^16.8.6"
Thanks. I'd appreciate your help!
The <div> with the padding-top and other styles is coming from the Image component that you are using from material-ui-image.
Below is the overall structure rendered by that Image component:
<div
style={styles.root}
onClick={onClick}
>
{image.src && <img
{...image}
style={styles.image}
onLoad={this.handleLoadImage}
onError={this.handleImageError}
/>}
<div style={styles.iconContainer}>
{!disableSpinner && !this.state.imageLoaded && !this.state.imageError && loading}
{!disableError && this.state.imageError && errorIcon}
</div>
</div>
padding-top is part of the styles in styles.root.
styles.root:
const styles = {
root: {
backgroundColor: color,
paddingTop: `calc(1 / ${aspectRatio} * 100%)`,
position: 'relative',
...style
},
When padding-top is a percentage, it is a percentage of the width, so it is important to control the width of the container in order to have predictable behavior.
You can modify the padding-top by either explicitly overriding it via the style prop or by specifying the appropriate value in the aspectRatio prop. By default, this Image component is assuming square images (aspectRatio: 1).
Here is a working example demonstrating both ways of controlling padding-top:
import React from "react";
import Image from "material-ui-image";
import Box from "#material-ui/core/Box";
export default function App() {
return (
<>
<Box m={4} width={200}>
<Image
aspectRatio={1.5}
src="https://www.publicdomainpictures.net/pictures/10000/velka/black-monkey-11280155875i3QV.jpg"
/>
Something under image 1
</Box>
<Box m={4} width={200}>
<Image
style={{
paddingTop: "calc(66.7%)"
}}
src="https://www.publicdomainpictures.net/pictures/10000/velka/black-monkey-11280155875i3QV.jpg"
/>
Something under image 2
</Box>
</>
);
}
Slightly related answer (with regard to the use of padding-top): A good way to handle #material-ui Skeleton scaling within a variable height grid row?
Try as I might, I cannot wrap my head around the description given here.
The Box component serves as a wrapper component for most of the CSS utility needs.
What are 'the' CSS utility needs?
What is the use case for this component? What problem does it solve? How do you use it?
I find the MUI docs very limited and hard to understand. I have googled, but generally only found fairly lightweight blog posts on how to use material UI. In addition to help understanding this component, I would really appreciate any good resources (something like a better version of their own documentation, if such a thing exists).
(Background, I generally understand React, JS, CSS, HTML etc, with less strength in the latter two).
EDIT: This was written in the MUI v4 days. In MUI v5, all MUI components allow you to define CSS styles via the sx prop, not just Box; but Box also accepts styling props at top-level, as well as within sx.
The other answers don't really explain the motivation for using Box.
Box renders a <div> you can apply CSS styles to directly via React props, for the sake of convenience, since alternatives like separate CSS files, CSS-in-JS, or inline styles can be more typing and hassle to use.
For example, consider this component that uses JSS:
import * as React from 'react'
import { makeStyles } from '#material-ui/styles'
const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
padding: theme.spacing(1),
}
}))
const Example = ({children, ...props}) => {
const classes = useStyles(props);
return (
<div className={classes.root}>
{children}
</div>
)
}
It's much shorter to do this with Box by passing the props you want to it:
import * as React from 'react'
import Box from '#material-ui/core/Box'
const Example = ({children}) => (
<Box display="flex" flexDirection="column" alignItems="stretch" padding={1}>
{children}
</Box>
)
Notice also how padding={1} is a shorthand for theme.spacing(1). Box provides various conveniences for working with Material-UI themes like this.
In larger files it can be more of a hassle to jump back and forth from the rendered elements to the styles than if the styles are right there on the element.
Cases where you wouldn't want to use Box (MUI v4):
You want the enclosing component to be able to override styles by passing classes (makeStyles enables this. <Example classNames={{ root: 'alert' }} /> would work in the makeStyles example, but not the Box example.)
You need to use nontrivial selectors (example JSS selectors: $root > li > a, $root .third-party-class-name)
A Box is basically a div* on steroid. Box allows you to apply dynamic styles to an otherwise normal div very quickly like inline styles (but it's not inline styles). Besides that, it also has a first-class integration with MUI theme:
<Box
sx={{
bgcolor: 'primary.main',
color: 'text.secondary',
border: 4,
borderRadius: 2,
px: 2,
fontWeight: 'fontWeightBold',
zIndex: 'tooltip',
boxShadow: 8,
}}
>
Box
</Box>
If you need to do the above with a normal div, you have to get the theme object using useTheme hook and create an inline styles which is not a good practice if abused everywhere:
<div
style={{
backgroundColor: theme.palette.primary.main,
color: theme.palette.text.secondary,
border: '4px solid black',
borderRadius: theme.shape.borderRadius * 2,
padding: `0 ${theme.spacing(2)}`,
fontWeight: theme.typography.fontWeightBold,
zIndex: theme.zIndex.tooltip,
boxShadow: theme.shadows[8],
}}
>
div
</div>
Box among other components like Typography or Stack also supports system properties that lets you pass the style values to the top-level props, which resulted in even shorter code. Internally, the system properties are gathered and merged with the sx prop so they are the same thing (See this answer for more detail)
<Box
bgcolor="primary.main"
color="text.secondary"
border={4}
borderRadius={2}
px={2}
fontWeight="fontWeightBold"
zIndex="tooltip"
boxShadow={8}
>
Box
</Box>
Because Box leverages sx prop, you can also use sx features like adding responsive values:
<Box
display={{
xs: 'none',
sm: 'block',
}}
width={{
sm: 30,
md: 50,
lg: 100,
}}
>
Or creating nested styles:
<Box
display='flex'
sx={{
'& > :not(:last-child)': {
mr: 2 // maginRight: theme.spacing(2)
},
':hover': {
bgcolor: 'green'
}
}}
>
When to use Box?
When you want to create a styled div quickly when prototyping.
When you want to create a one-off inline styles that is not really reusable anywhere else. This is convenient when you want to fix something that is a bit off in a specific part of your layout.
When you want to add dynamic or responsive styles and make your code easier to understand at the same time because everything is defined in one place, plus the fact that sx syntax is highly compact.
When you want to reference multiple MUI theme properties because many sx properties are theme-aware out-of-the-box.
When not to use Box?
When you don't need to styles anything. Just use a normal div then.
When you are using it in a highly reusable components like list item, grid item or table cell. This is because sx prop has the slowest performance (2x slower than the second slowest approach)
When you're using other MUI components. In v5, all components from MUI has sx support so using Box as a wrapper or root component is unnecessary if you just want to style other MUI components.
*: By default a Box is a div, but you can override the root component of it. For example: <Box component='span'>
A Box is just that, a box. It's an element wrapped around its content which by itself contains no styling rules nor has any default effects on the visual output. But it's a place to put styling rules as needed. It doesn't offer any real functionality, just a placeholder for controlling the styles in the hierarchical markup structure.
Structurally it results in a <div>.
I often think of it as semantically similar to the JSX empty element:
<>
Some elements here
</>
In that it's used to group things. But it results in a <div> and can include some Material UI capabilities:
<Box className={classes.someStyling}>
Some elements here
</Box>
The Box component in Material UI it has a lot of useful stuff
The most important thing is that box element has been built in with material-ui/system functionalities by default that mean you can apply system functionalities to what you need if you use it as wrapper
Like this example:
<Box bgcolor="primary.main" color="primary.contrastText" p={2}>
primary.main
</Box>
and of course you can add css class to it as you like or not
the other good useful thing that it offer it can be warp in other components and be very helpful to apply system functionalities to it
Like this example:
<Typography component="div" variant="body1">
<Box color="primary.main">primary.main</Box>
</Typography>
Both of examples above i took them from documentation
you can find them in this link :here
and you can find what i mean by material ui system functionalities:here
Note: you can add any of material ui system functionalities to any component like docs here but i recommend you to warp what u need with box component it make life a lot easier