Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[material-ui][docs] Open Material UI template with CodeSandbox/StackBlitz #43604

Merged
merged 43 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
b48eb9e
poc AppTheme + TemplateFrame
siriwatknp Sep 4, 2024
c982bbf
add codesandbox button
siriwatknp Sep 4, 2024
033443d
move AppTheme to
siriwatknp Sep 5, 2024
0e236e1
update TemplateFrame to use button
siriwatknp Sep 5, 2024
52ee07e
fix dark mode flicker issue
siriwatknp Sep 5, 2024
f2ef7f2
switch back to TemplateName
siriwatknp Sep 5, 2024
63baeff
use branding theme
siriwatknp Sep 5, 2024
e6eb4a1
replace file with module
siriwatknp Sep 5, 2024
b12cbf6
run docs:format
siriwatknp Sep 5, 2024
411a832
Merge branch 'master' of https://github.com/mui/material-ui into poc/…
siriwatknp Sep 6, 2024
8b59da7
add StackBlitz
siriwatknp Sep 6, 2024
0e98e5c
move ToggleColorMode to shared-theme
siriwatknp Sep 6, 2024
39ed005
fix tests
siriwatknp Sep 6, 2024
fa891f7
fix typo
siriwatknp Sep 6, 2024
eefecad
remove updateTemplates check
siriwatknp Sep 6, 2024
7b8a931
fix dark mode flicker at the toolbar
siriwatknp Sep 6, 2024
20cfc8e
remove unnecessary comment
siriwatknp Sep 6, 2024
bfc116a
Merge branch 'master' of https://github.com/mui/material-ui into poc/…
siriwatknp Sep 9, 2024
1c377a9
fix the toolbar
siriwatknp Sep 9, 2024
ad00393
comment commitRef
siriwatknp Sep 9, 2024
0385f86
make Dashboard work with new structure
siriwatknp Sep 9, 2024
16b2e23
remove unused files
siriwatknp Sep 9, 2024
2d0ce45
add contributing guide
siriwatknp Sep 9, 2024
cb7823e
typescript format
siriwatknp Sep 9, 2024
d080e3f
fix experiment dashboard
siriwatknp Sep 9, 2024
a269533
fix non-breaking space
siriwatknp Sep 9, 2024
bb3e39f
Merge branch 'master' of https://github.com/mui/material-ui into poc/…
siriwatknp Sep 9, 2024
494bc92
Add visual separator between items
zanivan Sep 9, 2024
f3a1537
Fix layout shift
zanivan Sep 9, 2024
8dd2969
wip
siriwatknp Sep 10, 2024
3cb513f
Merge branch 'master' of https://github.com/mui/material-ui into poc/…
siriwatknp Sep 10, 2024
469338c
make the generateTemplate works with the new structure
siriwatknp Sep 10, 2024
eac95f9
Merge branch 'poc/template-theme' of github.com:siriwatknp/material-u…
siriwatknp Sep 10, 2024
63778ad
switch back to headless mode
siriwatknp Sep 10, 2024
185cbfd
move contributing to faq
siriwatknp Sep 10, 2024
f4e1ae9
Merge branch 'master' of https://github.com/mui/material-ui into poc/…
siriwatknp Sep 10, 2024
046339e
add disableTransitionOnChange
siriwatknp Sep 10, 2024
5f501ea
docs:ts format
siriwatknp Sep 10, 2024
3361f4a
Add link to contribution guide
zanivan Sep 10, 2024
dd74af9
Merge branch 'poc/template-theme' of https://github.com/siriwatknp/ma…
zanivan Sep 10, 2024
b01d202
Tweaks to the text
zanivan Sep 10, 2024
9dd82c4
fix non-breaking space
siriwatknp Sep 11, 2024
8c64407
fix data-screenshot="toggle-mode"
siriwatknp Sep 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -299,12 +299,6 @@ jobs:
command: |
pnpm docs:link-check
git add -A && git diff --exit-code --staged
- run:
name: Update the templates shared themes
command: pnpm template:update-theme
- run:
name: '`pnpm template:update-theme` changes committed?'
command: git add -A && git diff --exit-code --staged
Comment on lines -302 to -307
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer need to run the script. The shared theme is the source of truth and it will be bundled with the template when users open CodeSandbox or StackBlitz.

test_types:
<<: *default-job
resource_class: 'medium+'
Expand Down
75 changes: 75 additions & 0 deletions docs/data/material/getting-started/faq/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,81 @@

If you are getting the error: `TypeError: Cannot convert a Symbol value to a string`, take a look at the [styled()](/system/styled/#how-to-use-components-selector-api) docs page for instructions on how you can fix this.

## How can I contribute to the free templates?

Check warning on line 264 in docs/data/material/getting-started/faq/faq.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.FirstPerson] Avoid first-person pronouns such as ' I '. Raw Output: {"message": "[Google.FirstPerson] Avoid first-person pronouns such as ' I '.", "location": {"path": "docs/data/material/getting-started/faq/faq.md", "range": {"start": {"line": 264, "column": 11}}}, "severity": "WARNING"}

The templates are built using a [shared theme](https://github.com/mui/material-ui/tree/v6.0.2/docs/data/material/getting-started/templates/shared-theme). Below are the structure to create a new template:

### Template page

Create a new page in the `docs/pages/material-ui/getting-started/templates/<name>.js` directory with the following code:

```js
import * as React from 'react';
import AppTheme from 'docs/src/modules/components/AppTheme';
import TemplateFrame from 'docs/src/modules/components/TemplateFrame';
import Template from 'docs/data/material/getting-started/templates/<name>/<Template>';

export default function Page() {
return (
<AppTheme>
<TemplateFrame>
<Template />
</TemplateFrame>
</AppTheme>
);
}
```

Then create a template file at `docs/data/material/getting-started/templates/<name>/<Template>.tsx` (add more files if needed):

> Note: The `<Template>` must be a pascal case string of the `<name>` folder.

### Shared theme

The template must use `AppTheme` from `../shared-theme/AppTheme` to ensure a consistent look and feel across all templates.

If the template includes custom-themed components, such as the dashboard template with MUI X themed components, pass them to the `AppTheme`'s `themedComponents` prop:

```js
import AppTheme from '../shared-theme/AppTheme';

const xThemeComponents = {
...chartsCustomizations,
...dataGridCustomizations,
...datePickersCustomizations,
...treeViewCustomizations,
};

export default function Dashboard(props: { disableCustomTheme?: boolean }) {
return (
<AppTheme {...props} themeComponents={xThemeComponents}>...</AppTheme>
)
}
```

### Color mode toggle

The shared theme provides 2 appearance of the color mode toggle, `ColorModeSelect` and `ColorModeIconDropdown`.
You can use either of them in your template, it will be hidden within the `TemplateFrame` but will be visible in the Code Sandbox and Stackblitz.

Check warning on line 319 in docs/data/material/getting-started/faq/faq.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.Will] Avoid using 'will'. Raw Output: {"message": "[Google.Will] Avoid using 'will'.", "location": {"path": "docs/data/material/getting-started/faq/faq.md", "range": {"start": {"line": 319, "column": 49}}}, "severity": "WARNING"}

Check warning on line 319 in docs/data/material/getting-started/faq/faq.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.Will] Avoid using 'will'. Raw Output: {"message": "[Google.Will] Avoid using 'will'.", "location": {"path": "docs/data/material/getting-started/faq/faq.md", "range": {"start": {"line": 319, "column": 95}}}, "severity": "WARNING"}

### Template frame

If the template has a sidebar or a header that needs to stick to the top, refer to the CSS variable `--template-frame-height` to adjust.

For example, the dashboard template has a fixed header that needs to be accounted for the template frame height:

```js
<AppBar
position="fixed"
sx={{
top: 'var(--template-frame-height, 0px)',
// ...other styles
}}
>
```

This will make the `AppBar` stay below the `TemplateFrame` in a preview mode but stick to the top in the CodeSandbox and Stackblitz.

Check warning on line 337 in docs/data/material/getting-started/faq/faq.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.Will] Avoid using 'will'. Raw Output: {"message": "[Google.Will] Avoid using 'will'.", "location": {"path": "docs/data/material/getting-started/faq/faq.md", "range": {"start": {"line": 337, "column": 6}}}, "severity": "WARNING"}

## [legacy] I have several instances of styles on the page

If you are seeing a warning message in the console like the one below, you probably have several instances of `@mui/styles` initialized on the page.
Expand Down
111 changes: 45 additions & 66 deletions docs/data/material/getting-started/templates/dashboard/Dashboard.js
Original file line number Diff line number Diff line change
@@ -1,81 +1,60 @@
import * as React from 'react';
import { createTheme, ThemeProvider, alpha } from '@mui/material/styles';

import { alpha } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import Box from '@mui/material/Box';
import Stack from '@mui/material/Stack';
import getDashboardTheme from './theme/getDashboardTheme';
import AppNavbar from './components/AppNavbar';
import Header from './components/Header';
import MainGrid from './components/MainGrid';
import SideMenu from './components/SideMenu';
import TemplateFrame from './TemplateFrame';

export default function Dashboard() {
const [mode, setMode] = React.useState('light');
const [showCustomTheme, setShowCustomTheme] = React.useState(true);
const dashboardTheme = createTheme(getDashboardTheme(mode));
const defaultTheme = createTheme({ palette: { mode } });
// This code only runs on the client side, to determine the system color preference
React.useEffect(() => {
// Check if there is a preferred mode in localStorage
const savedMode = localStorage.getItem('themeMode');
if (savedMode) {
setMode(savedMode);
} else {
// If no preference is found, it uses system preference
const systemPrefersDark = window.matchMedia(
'(prefers-color-scheme: dark)',
).matches;
setMode(systemPrefersDark ? 'dark' : 'light');
}
}, []);

const toggleColorMode = () => {
const newMode = mode === 'dark' ? 'light' : 'dark';
setMode(newMode);
localStorage.setItem('themeMode', newMode); // Save the selected mode to localStorage
};
import AppTheme from '../shared-theme/AppTheme';
import {
chartsCustomizations,
dataGridCustomizations,
datePickersCustomizations,
treeViewCustomizations,
} from './theme/customizations';

const toggleCustomTheme = () => {
setShowCustomTheme((prev) => !prev);
};
const xThemeComponents = {
...chartsCustomizations,
...dataGridCustomizations,
...datePickersCustomizations,
...treeViewCustomizations,
};

export default function Dashboard(props) {
return (
<TemplateFrame
toggleCustomTheme={toggleCustomTheme}
showCustomTheme={showCustomTheme}
mode={mode}
toggleColorMode={toggleColorMode}
>
<ThemeProvider theme={showCustomTheme ? dashboardTheme : defaultTheme}>
<CssBaseline enableColorScheme />
<Box sx={{ display: 'flex' }}>
<SideMenu />
<AppNavbar />
{/* Main content */}
<Box
component="main"
sx={(theme) => ({
flexGrow: 1,
backgroundColor: alpha(theme.palette.background.default, 1),
overflow: 'auto',
})}
<AppTheme {...props} themeComponents={xThemeComponents}>
<CssBaseline enableColorScheme />
<Box sx={{ display: 'flex' }}>
<SideMenu />
<AppNavbar />
{/* Main content */}
<Box
component="main"
sx={(theme) => ({
flexGrow: 1,
backgroundColor: theme.vars
? `rgba(${theme.vars.palette.background.defaultChannel} / 1)`
: alpha(theme.palette.background.default, 1),
overflow: 'auto',
})}
>
<Stack
spacing={2}
sx={{
alignItems: 'center',
mx: 3,
pb: 10,
mt: { xs: 8, md: 0 },
}}
>
<Stack
spacing={2}
sx={{
alignItems: 'center',
mx: 3,
pb: 10,
mt: { xs: 8, md: 0 },
}}
>
<Header />
<MainGrid />
</Stack>
</Box>
<Header />
<MainGrid />
</Stack>
</Box>
</ThemeProvider>
</TemplateFrame>
</Box>
</AppTheme>
);
}
119 changes: 48 additions & 71 deletions docs/data/material/getting-started/templates/dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,86 +1,63 @@
import * as React from 'react';
import {
PaletteMode,
createTheme,
ThemeProvider,
alpha,
} from '@mui/material/styles';
import type {} from '@mui/x-date-pickers/themeAugmentation';
import type {} from '@mui/x-charts/themeAugmentation';
import type {} from '@mui/x-data-grid/themeAugmentation';
import type {} from '@mui/x-tree-view/themeAugmentation';
import { alpha } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import Box from '@mui/material/Box';
import Stack from '@mui/material/Stack';
import getDashboardTheme from './theme/getDashboardTheme';
import AppNavbar from './components/AppNavbar';
import Header from './components/Header';
import MainGrid from './components/MainGrid';
import SideMenu from './components/SideMenu';
import TemplateFrame from './TemplateFrame';

export default function Dashboard() {
const [mode, setMode] = React.useState<PaletteMode>('light');
const [showCustomTheme, setShowCustomTheme] = React.useState(true);
const dashboardTheme = createTheme(getDashboardTheme(mode));
const defaultTheme = createTheme({ palette: { mode } });
// This code only runs on the client side, to determine the system color preference
React.useEffect(() => {
// Check if there is a preferred mode in localStorage
const savedMode = localStorage.getItem('themeMode') as PaletteMode | null;
if (savedMode) {
setMode(savedMode);
} else {
// If no preference is found, it uses system preference
const systemPrefersDark = window.matchMedia(
'(prefers-color-scheme: dark)',
).matches;
setMode(systemPrefersDark ? 'dark' : 'light');
}
}, []);

const toggleColorMode = () => {
const newMode = mode === 'dark' ? 'light' : 'dark';
setMode(newMode);
localStorage.setItem('themeMode', newMode); // Save the selected mode to localStorage
};
import AppTheme from '../shared-theme/AppTheme';
import {
chartsCustomizations,
dataGridCustomizations,
datePickersCustomizations,
treeViewCustomizations,
} from './theme/customizations';

const toggleCustomTheme = () => {
setShowCustomTheme((prev) => !prev);
};
const xThemeComponents = {
...chartsCustomizations,
...dataGridCustomizations,
...datePickersCustomizations,
...treeViewCustomizations,
};

export default function Dashboard(props: { disableCustomTheme?: boolean }) {
return (
<TemplateFrame
toggleCustomTheme={toggleCustomTheme}
showCustomTheme={showCustomTheme}
mode={mode}
toggleColorMode={toggleColorMode}
>
<ThemeProvider theme={showCustomTheme ? dashboardTheme : defaultTheme}>
<CssBaseline enableColorScheme />
<Box sx={{ display: 'flex' }}>
<SideMenu />
<AppNavbar />
{/* Main content */}
<Box
component="main"
sx={(theme) => ({
flexGrow: 1,
backgroundColor: alpha(theme.palette.background.default, 1),
overflow: 'auto',
})}
<AppTheme {...props} themeComponents={xThemeComponents}>
<CssBaseline enableColorScheme />
<Box sx={{ display: 'flex' }}>
<SideMenu />
<AppNavbar />
{/* Main content */}
<Box
component="main"
sx={(theme) => ({
flexGrow: 1,
backgroundColor: theme.vars
? `rgba(${theme.vars.palette.background.defaultChannel} / 1)`
: alpha(theme.palette.background.default, 1),
overflow: 'auto',
})}
>
<Stack
spacing={2}
sx={{
alignItems: 'center',
mx: 3,
pb: 10,
mt: { xs: 8, md: 0 },
}}
>
<Stack
spacing={2}
sx={{
alignItems: 'center',
mx: 3,
pb: 10,
mt: { xs: 8, md: 0 },
}}
>
<Header />
<MainGrid />
</Stack>
</Box>
<Header />
<MainGrid />
</Stack>
</Box>
</ThemeProvider>
</TemplateFrame>
</Box>
</AppTheme>
);
}
Loading
Loading