Classnames mismatch using Material-UI and NextJS - material-ui

Using Intersection Observer API I'm trying to render a Material-UI Component by visibility on the viewport.
export default function Index() {
const [onScreen, theRef] = useOnScreen({
rootMargin: "-300px",
ssr: true
});
const classes = useStyles();
return (
<Container maxWidth="sm">
<DummyContainer />
<div
ref={theRef}
style={{
height: "100vh",
padding: "20px",
backgroundColor: "green",
transition: "all .5s ease-in"
}}
>
{onScreen && (
<Box className={classes.rootBox} my={16}>
<Typography variant="h2" gutterBottom>
Content Lazy using Intersection Observer
</Typography>
<Copyright />
</Box>
)}
</div>
<Box className={classes.rootBox} my={4}>
<Typography variant="h2" gutterBottom>
Content no lazy, why this Box loses margin?
</Typography>
<Typography gutterBottom>
If you request this page with JavaScript disabled, you will notice
that has been properly rendered in SSR
</Typography>
</Box>
</Container>
);
}
Basic stuff, onScreen is a toggled boolean using Intersection Observer
In order to be "SEO friendly" I'm using NextJS and I wanted this component to always be visible in SSR and conditional visible in CSR.
The problem arises during rehydration in CSR, it's seems that some classnames after the lazy component are recreated and I'm losing styling in second Box component.
I've created this CodeSandbox to have a look : https://codesandbox.io/s/nextjsmaterialuiclassnamemismatch-1j4oi
Is this a bug in MaterialUI, JSS? Or most probably I'm doing something wrong?

Related

like in mui components make an asterisk before the text?

like in mui components make an asterisk before the text?
The documentation doesn't say anything about it.
https://mui.com/material-ui/react-text-field/
The documentation makes it very clear under Input Adornments. You can put whatever you want in the beginning or end of the text field using input adornments.
Sample code:
import * as React from 'react';
import Box from '#mui/material/Box';
import InputAdornment from '#mui/material/InputAdornment';
import TextField from '#mui/material/TextField';
export default function InputAdornments() {
return (
<Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
<div>
<TextField
id="outlined-start-adornment"
sx={{ m: 1, width: '25ch' }}
InputProps={{
startAdornment: <InputAdornment position="start">*</InputAdornment>,
}}
/>
</div>
</Box>
);
}

Can't add an icon in MenuItem MUI

I am trying to create a Dropdown which will have Menu items which would be, on hovered, deletable. I would like to insert an Icon as a children of my Menu Items, but when trying to render it with Storybook, I am getting an error : "Couldn't find story matching 'components-forms-buttons-newdropdown--new-dropdown'."
If I simply comment the Icon component, it's working fine.
Example :
<Box sx={sx} style={{ display: 'inline-block', position: 'relative' }}>
<Box
sx={{
cursor: disabled ? 'not-allowed' : undefined,
display: 'inline-block',
borderRadius: '15px',
}}
>
<StyledMuiButton
variant="outlined"
isdisabled={isdisabled}
onClick={handleClick}
endIcon={<KeyboardArrowDownIcon />}
>
<Typography variant="body1">
{defaultValue ? `${label} :` : label}
</Typography>
<Typography variant="h4">{activeOption}</Typography>
</StyledMuiButton>
</Box>
<StyledMenuContainer
isClicked={isClicked ? 1 : 0}
maxHeight={maxHeight}
>
{options?.map(option => {
return (
<StyledMenuItem
key={option.label}
value={option.value}
divider={option.divider}
disabled={option.disabled}
className={option.className}
onClick={() => handleOptionClick(option)}
>
<ListItemIcon>
{/* When uncommenting this, storybook trhows an error */}
{/* <Delete /> */}
</ListItemIcon>
<ListItemText
sx={{ color: 'grey.160' }}
primary={option.label}
/>
</StyledMenuItem>
);
})}
</StyledMenuContainer>
</Box>
I imported the Icon from MUI.
I do not get why it's not working, as I took inspiration from the documentation.
I upgraded my dependencies so it should not be related to MUI version.
storybook render

How to use a button to control material ui v5 datepicker dialog open/close?

In my react app, I would like to control open/close of a material ui v5 Datepicker by clicking an icon button:
function handleShowCalendar() {
setState({ showCalendar: true })
}
<TextField
{...params}
autoFocus={props.autoFocus}
fullWidth
placeholder="Enter a task..."
variant="outlined"
size="small"
InputProps={{
...params.InputProps,
onKeyUp: handleKeyUp,
endAdornment: addTodo.isLoading ? (
<Box position="absolute" top={10} right={10}>
<CircularProgress size={16} />
</Box>
) : (
<Box position="absolute" top={-4} right={0}>
<IconButton
onClick={handleShowCalendar}
disabled={state.text.length <= 0}
>
<CalendarToday />
</IconButton>
</Box>
),
}}
/>
...
<DatePicker
open={state.showCalendar}
value={state.due}
onChange={handleChangeDate}
onClose={() => setState({ showCalendar: false })}
disableHighlightToday
// DialogProps={{ sx: { postition: "inline" } }}
renderInput={(params) => <Fragment {...params} />}
showToolbar={true}
ToolbarComponent={() => (
<AppBar position="static">
<Toolbar>
<Typography variant="h6">Due Date</Typography>
</Toolbar>
</AppBar>
)}
/>
</Fragment>
The problem is the position of the Datepicker is always at the top left corner. Can anyone help why the Datepicker won't show like inline, what I am missing in above code? Thanks.
As an answer to the question in the title, it seems that the code you have posted does open and close the DatePicker.
It sounds like the second question is the one that needs answering, whether it will show "inline".
It seems that the "absolute" position of the Box surrounding the IconButton and the hardcoded top and right values are preventing the borders of the DatePicker from being inside of the TextField.
Here's a Code Sandbox illustrating a DatePicker within a TextField.
If you would like to clarify the positioning you prefer, please do so.

MUI V5, how to minify class names in production build

How is possible to there is no option to minify the prod class names? It is a a big step back. Please say me that I am not right.
In Material v4 can be achieved with 3 simple rules:
Only one theme provider is used (No theme nesting)
The style sheet has a name that starts with Mui (all Material-UI components).
The disableGlobal option of the class name generator is false (the default).
In v5.5 in my experiment I don`t use any custom styles, just default provided from MUI components.
"react": "^18.0.0",
"react-dom": "^18.0.0",
"#emotion/react": "^11.8.1",
"#mui/material": "^5.5.2"
import { ThemeProvider, createTheme } from '#mui/material/styles'
<ThemeProvider theme={theme}>
<CssBaseline />
<Component {...this.props} />
</ThemeProvider>
import { Paper, Grid, Typography, Box } from '#mui/material'
<Grid container component={'main'}>
<Grid item xs={false} sm={4} md={8} />
<Grid item xs={12} sm={8} md={4} component={Paper} elevation={6} square>
<Typography component={'h1'} variant={'h4'} align={'center'}>
<Box fontWeight={'fontWeightLight'} m={1}>
{'MY ACCOUNT'}
</Box>
</Typography>
</Grid>
</Grid>
In production build I expect to be something like this:
jss1 jss2 jss3 jss4 jss5 jss6 and etc...
but the result is:
MuiGrid-root MuiGrid-container css-1d3bbye
MuiGrid-root MuiGrid-item MuiGrid-grid-sm-4 MuiGrid-grid-md-8 css-18mwvdj
I think i found it
https://v5-0-6.mui.com/guides/classname-generator/
Converts from
<button
class="MuiButton-root MuiButton-text MuiButton-textPrimary MuiButton-sizeMedium MuiButton-textSizeMedium MuiButtonBase-root css-1ujsas3"
>
Button
</button>
to
<button
class="foo-bar-MuiButton-root foo-bar-MuiButton-text foo-bar-MuiButton-textPrimary foo-bar-MuiButton-sizeMedium foo-bar-MuiButton-textSizeMedium foo-bar-MuiButtonBase-root css-1ujsas3"
>
Button
</button>
I have just tried it with latest MUIv5 and works great.

How to make something like this in material ui react?

How can i make this in material ui react?
The main problem i have is i don't know how to make the right part with the refresh icon.
This question is kinds an amateur question. But I can give you little insights how you can start with little basics and you can later make it stateful component.
const styles = theme => ({
margin: {
margin: theme.spacing.unit,
},
roundBorder : {
borderRadius: '25px',
borderColor: '#80bdff',
border: '1px solid #ced4da',
}
});
function App(props) {
const { classes } = props;
return (
<div>
<div className={classes.margin}>
<Grid container spacing={8} alignItems="flex-end">
<Grid item>
<TextField className={classes.roundBorder} id="input-with-icon-grid" label="With a grid" />
</Grid>
<Grid item>
<AccountCircle />
</Grid>
</Grid>
</div>
</div>
);
}
This will create something like this:
Check this sample which has searching with icon, just align icon to the right:
https://codesandbox.io/s/material-demo-jhy9f