Skip to content

Commit

Permalink
[Snackbar][Material You] apply md3 designs
Browse files Browse the repository at this point in the history
  • Loading branch information
Best-Sardar committed Nov 3, 2023
1 parent 2f18792 commit 65d4200
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 138 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as React from 'react';
import { Stack } from '@mui/material';
import { Button, SnackbarContent } from '@mui/material-next';
import MaterialYouUsageDemo from 'docs/src/modules/components/MaterialYouUsageDemo';

export default function SnackbarMaterialYouPlayground() {
const actions = (
<Button
size="small"
color="secondary"
sx={{ color: (p) => p.sys.color.inversePrimary }}
>
Action
</Button>
);

const codeBlock = `
<Snackbar
open={open}
onClose={handleClose}
message="..."
action={action}
/>
`;

const multilineMessage = (
<span>
I love candy. I love cookies.
<br />I love candy. I love cookies.
<br />I love candy. I love cookies.
</span>
);

const longMessage =
'I love candy. I love cookies. I love cupcakes. \
I love candy. I love cookies. I love cupcakes. \
I love candy. I love cookies. I love cupcakes. ';

return (
<MaterialYouUsageDemo
getCodeBlock={() => codeBlock}
componentName="Snackbar"
renderDemo={() => {
return (
<Stack spacing={2} sx={{ maxWidth: 600 }}>
<SnackbarContent message="I love snacks." />
<SnackbarContent message="I love snacks." action={actions} />

<SnackbarContent message={multilineMessage} />
<SnackbarContent message={multilineMessage} action={actions} />

<SnackbarContent message={longMessage} />
<SnackbarContent message={longMessage} action={actions} />
</Stack>
);
}}
/>
);
}
13 changes: 13 additions & 0 deletions docs/data/material/components/snackbars/snackbars.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,16 @@ export default function MyComponent() {
);
}
```

## Experimental APIs

### Material You version

The default Material UI Snackbar component follows the Material Design 2 specs.
To get the Material You ([Material Design 3](https://m3.material.io/)) version, use the new experimental `@mui/material-next` package:

```js
import Snackbar from '@mui/material-next/Snackbar';
```

{{"demo": "SnackbarMaterialYouPlayground.js"}}
2 changes: 1 addition & 1 deletion docs/pages/base-ui/api/snackbar.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"onClose": {
"type": { "name": "func" },
"signature": {
"type": "function(event: React.SyntheticEvent<any> | Event, reason: string) => void",
"type": "function(event: React.SyntheticEvent<any> | Event | null, reason: string) => void",
"describedArgs": ["event", "reason"]
}
},
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/joy-ui/api/snackbar.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"onClose": {
"type": { "name": "func" },
"signature": {
"type": "function(event: React.SyntheticEvent<any> | Event, reason: string) => void",
"type": "function(event: React.SyntheticEvent<any> | Event | null, reason: string) => void",
"describedArgs": ["event", "reason"]
}
},
Expand Down
249 changes: 126 additions & 123 deletions docs/src/modules/components/MaterialYouUsageDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ interface MaterialYouUsageDemoProps<ComponentProps> {
/**
* Configuration
*/
data: Array<{
data?: Array<{
/**
* Name of the prop, e.g. 'children'
*/
Expand Down Expand Up @@ -170,7 +170,7 @@ interface MaterialYouUsageDemoProps<ComponentProps> {
export default function MaterialYouUsageDemo<T extends { [k: string]: any } = {}>({
componentName,
childrenAccepted = false,
data,
data = [],
renderDemo,
getCodeBlock = defaultGetCodeBlock,
}: MaterialYouUsageDemoProps<T>) {
Expand Down Expand Up @@ -240,138 +240,141 @@ export default function MaterialYouUsageDemo<T extends { [k: string]: any } = {}
/>
</BrandingProvider>
</Box>
<Box
sx={(theme) => ({
flexShrink: 0,
gap: 2,
borderLeft: '1px solid',
borderColor: theme.palette.grey[200],
background: alpha(theme.palette.grey[50], 0.5),
minWidth: '250px',
[`:where(${theme.vars ? '[data-mui-color-scheme="dark"]' : '.mode-dark'}) &`]: {
borderColor: alpha(theme.palette.grey[900], 0.8),
backgroundColor: alpha(theme.palette.grey[900], 0.3),
},
})}
>

{data.length > 0 && (
<Box
sx={{
px: 3,
py: 2,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
sx={(theme) => ({
flexShrink: 0,
gap: 2,
borderLeft: '1px solid',
borderColor: theme.palette.grey[200],
background: alpha(theme.palette.grey[50], 0.5),
minWidth: '250px',
[`:where(${theme.vars ? '[data-mui-color-scheme="dark"]' : '.mode-dark'}) &`]: {
borderColor: alpha(theme.palette.grey[900], 0.8),
backgroundColor: alpha(theme.palette.grey[900], 0.3),
},
})}
>
<Typography
id="usage-props"
component="h3"
fontWeight="600"
sx={{ scrollMarginTop: 160, fontFamily: 'General Sans' }}
<Box
sx={{
px: 3,
py: 2,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
Playground
</Typography>
<IconButton
aria-label="Reset all"
size="small"
onClick={() => setProps(initialProps as T)}
<Typography
id="usage-props"
component="h3"
fontWeight="600"
sx={{ scrollMarginTop: 160, fontFamily: 'General Sans' }}
>
Playground
</Typography>
<IconButton
aria-label="Reset all"
size="small"
onClick={() => setProps(initialProps as T)}
sx={{
visibility: !shallowEqual(props, initialProps) ? 'visible' : 'hidden',
}}
>
<ReplayRoundedIcon />
</IconButton>
</Box>
<Divider sx={{ opacity: 0.5 }} />
<Box
sx={{
visibility: !shallowEqual(props, initialProps) ? 'visible' : 'hidden',
p: 3,
display: 'flex',
flexDirection: 'column',
gap: 2,
[`& .${formLabelClasses.root}`]: {
fontWeight: 'lg',
},
}}
>
<ReplayRoundedIcon />
</IconButton>
</Box>
<Divider sx={{ opacity: 0.5 }} />
<Box
sx={{
p: 3,
display: 'flex',
flexDirection: 'column',
gap: 2,
[`& .${formLabelClasses.root}`]: {
fontWeight: 'lg',
},
}}
>
{data.map(({ propName, knob, options = [], defaultValue, onChange }) => {
const resolvedValue = props[propName] ?? defaultValue;
if (!knob) {
return null;
}
if (knob === 'switch') {
return (
<FormControl
key={propName}
size="small"
sx={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<FormLabel
sx={{
textTransform: 'capitalize',
fontWeight: 'medium',
fontSize: '0.875rem',
color: 'text.secondary',
}}
>
{propName}
</FormLabel>
<Switch
{data.map(({ propName, knob, options = [], defaultValue, onChange }) => {
const resolvedValue = props[propName] ?? defaultValue;
if (!knob) {
return null;
}
if (knob === 'switch') {
return (
<FormControl
key={propName}
size="small"
checked={Boolean(resolvedValue)}
onChange={(event) => {
setProps((latestProps) => ({
...latestProps,
[propName]: event.target.checked,
}));
onChange?.(event);
}}
/>
</FormControl>
);
}
if (knob === 'select') {
return (
<FormControl key={propName} size="small">
<FormLabel
sx={{
textTransform: 'capitalize',
fontWeight: 'medium',
fontSize: '0.875rem',
mb: 0.5,
}}
>
{propName}
</FormLabel>
<Select
placeholder="Select a variant..."
value={(resolvedValue || 'none') as string}
onChange={(event) => {
setProps((latestProps) => ({
...latestProps,
[propName]: event.target.value,
}));
onChange?.(event as React.SyntheticEvent);
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
{options.map((value) => (
<MenuItem key={value} value={value}>
{value}
</MenuItem>
))}
</Select>
</FormControl>
);
}
return null;
})}
<FormLabel
sx={{
textTransform: 'capitalize',
fontWeight: 'medium',
fontSize: '0.875rem',
color: 'text.secondary',
}}
>
{propName}
</FormLabel>
<Switch
size="small"
checked={Boolean(resolvedValue)}
onChange={(event) => {
setProps((latestProps) => ({
...latestProps,
[propName]: event.target.checked,
}));
onChange?.(event);
}}
/>
</FormControl>
);
}
if (knob === 'select') {
return (
<FormControl key={propName} size="small">
<FormLabel
sx={{
textTransform: 'capitalize',
fontWeight: 'medium',
fontSize: '0.875rem',
mb: 0.5,
}}
>
{propName}
</FormLabel>
<Select
placeholder="Select a variant..."
value={(resolvedValue || 'none') as string}
onChange={(event) => {
setProps((latestProps) => ({
...latestProps,
[propName]: event.target.value,
}));
onChange?.(event as React.SyntheticEvent);
}}
>
{options.map((value) => (
<MenuItem key={value} value={value}>
{value}
</MenuItem>
))}
</Select>
</FormControl>
);
}
return null;
})}
</Box>
</Box>
</Box>
)}
</Box>
);
}
3 changes: 3 additions & 0 deletions packages/mui-material-next/src/Snackbar/Snackbar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { spy } from 'sinon';
import { describeConformance, act, createRenderer, fireEvent } from '@mui-internal/test-utils';
import Snackbar, { snackbarClasses as classes } from '@mui/material-next/Snackbar';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import { CssVarsProvider, extendTheme } from '@mui/material-next/styles';

describe('<Snackbar />', () => {
const { clock, render: clientRender } = createRenderer({ clock: 'fake' });
Expand All @@ -26,6 +27,8 @@ describe('<Snackbar />', () => {
describeConformance(<Snackbar open message="message" />, () => ({
classes,
inheritComponent: 'div',
ThemeProvider: CssVarsProvider,
createTheme: extendTheme,
render,
refInstanceof: window.HTMLDivElement,
muiName: 'MuiSnackbar',
Expand Down
Loading

0 comments on commit 65d4200

Please sign in to comment.