init project
Some checks failed
No response / noResponse (push) Has been cancelled
CI / Continuous releases (push) Has been cancelled
CI / test-dev (macos-latest) (push) Has been cancelled
CI / test-dev (ubuntu-latest) (push) Has been cancelled
CI / test-dev (windows-latest) (push) Has been cancelled
Maintenance / main (push) Has been cancelled
Scorecards supply-chain security / Scorecards analysis (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled

This commit is contained in:
how2ice
2025-12-12 14:26:25 +09:00
commit 005cf56baf
43188 changed files with 1079531 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,44 @@
# Material UI and Next.js example with @mui/styles (in TypeScript)
## How to use
Download the example [or clone the repo](https://github.com/mui/material-ui):
<!-- #target-branch-reference -->
```bash
curl https://codeload.github.com/mui/material-ui/tar.gz/master | tar -xz --strip=2 material-ui-master/examples/material-ui-nextjs-ts-v4-v5-migration
cd material-ui-nextjs-ts-v4-v5-migration
```
Install it and run:
```bash
npm install
npm run dev
```
or:
<!-- #target-branch-reference -->
[![Edit on StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/mui/material-ui/tree/master/examples/material-ui-nextjs-ts-v4-v5-migration)
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/github/mui/material-ui/tree/master/examples/material-ui-nextjs-ts-v4-v5-migration)
## The idea behind the example
The project uses [Next.js](https://github.com/vercel/next.js), which is a framework for server-rendered React apps.
It includes `@mui/material` and its peer dependencies, including [Emotion](https://emotion.sh/docs/introduction), the default style engine in Material UI.
If you prefer, you can [use styled-components instead](https://mui.com/material-ui/integrations/interoperability/#styled-components).
It also includes `@mui/styles`, the legacy styling solution that uses JSS as an engine.
It provides all the necessary config for working with both Emotion and JSS for server-side rendering.
The project is intended as a basic starter for migrating your application from v4 to v5, as it lets the JSS style overrides take precedence over the default styles passed to the components by Emotion.
It demonstrates what results after handling v5's breaking changes to the [theme](https://mui.com/material-ui/migration/v5-style-changes/) and [components](https://mui.com/material-ui/migration/v5-component-changes/).
## The Link component
Next.js Pages Router has [a custom Link component](https://nextjs.org/docs/pages/api-reference/components/link).
The example folder provides adapters for usage with Material UI.
You can find more information [in the documentation](https://mui.com/material-ui/integrations/routing/#next-js-pages-router).

View File

@@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
export default {
reactStrictMode: true,
};

View File

@@ -0,0 +1,35 @@
{
"name": "material-ui-nextjs-ts-v4-v5-migration",
"version": "7.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"post-update": "echo \"codesandbox preview only, need an update\" && pnpm update --latest"
},
"dependencies": {
"@emotion/cache": "latest",
"@emotion/react": "latest",
"@emotion/server": "latest",
"@emotion/styled": "latest",
"@mui/icons-material": "latest",
"@mui/material": "latest",
"@mui/material-nextjs": "latest",
"@mui/styles": "latest",
"autoprefixer": "latest",
"clean-css": "latest",
"clsx": "latest",
"next": "latest",
"postcss": "latest",
"react": "latest",
"react-dom": "latest"
},
"devDependencies": {
"@types/node": "latest",
"@types/react": "latest",
"eslint": "latest",
"eslint-config-next": "latest",
"typescript": "latest"
}
}

View File

@@ -0,0 +1,32 @@
import * as React from 'react';
import Head from 'next/head';
import { AppProps } from 'next/app';
import { AppCacheProvider } from '@mui/material-nextjs/v14-pagesRouter';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import theme from '../src/theme';
export default function MyApp(props: AppProps) {
const { Component, pageProps } = props;
React.useEffect(() => {
// Remove the server-side injected CSS.
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles?.parentElement?.removeChild(jssStyles);
}
}, []);
return (
<AppCacheProvider {...props}>
<Head>
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</AppCacheProvider>
);
}

View File

@@ -0,0 +1,96 @@
import * as React from 'react';
import {
Html,
Head,
Main,
NextScript,
DocumentProps,
DocumentInitialProps,
DocumentContext,
} from 'next/document';
import { AppProps } from 'next/app';
import {
DocumentHeadTags,
DocumentHeadTagsProps,
documentGetInitialProps,
} from '@mui/material-nextjs/v14-pagesRouter';
import { ServerStyleSheets as JSSServerStyleSheets } from '@mui/styles';
import theme from '../src/theme';
export default function MyDocument(props: DocumentProps & DocumentHeadTagsProps) {
return (
<Html lang="en">
<Head>
{/* PWA primary color */}
<meta name="theme-color" content={theme.palette.primary.main} />
<link rel="icon" href="/favicon.ico" />
<DocumentHeadTags {...props} />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
// You can find a benchmark of the available CSS minifiers under
// https://github.com/GoalSmashers/css-minification-benchmark
// We have found that clean-css is faster than cssnano but the output is larger.
// Waiting for https://github.com/cssinjs/jss/issues/279
// 4% slower but 12% smaller output than doing it in a single step.
//
// It's using .browserslistrc
let prefixer: any;
let cleanCSS: any;
if (process.env.NODE_ENV === 'production') {
/* eslint-disable global-require */
const postcss = require('postcss');
const autoprefixer = require('autoprefixer');
const CleanCSS = require('clean-css');
/* eslint-enable global-require */
prefixer = postcss([autoprefixer]);
cleanCSS = new CleanCSS();
}
MyDocument.getInitialProps = async (ctx: DocumentContext) => {
const jssSheets = new JSSServerStyleSheets();
const finalProps = await documentGetInitialProps(ctx, {
plugins: [
{
enhanceApp: (App: React.ComponentType<AppProps>) =>
function EnhanceApp(props: AppProps) {
return jssSheets.collect(<App {...props} />);
},
resolveProps: async (initialProps: DocumentInitialProps) => {
// Generate the css string for the styles coming from jss
let css = jssSheets.toString();
// It might be undefined, for example after an error.
if (css && process.env.NODE_ENV === 'production') {
const result1 = await prefixer.process(css, { from: undefined });
css = result1.css;
css = cleanCSS.minify(css).styles;
}
return {
...initialProps,
styles: [
...(Array.isArray(initialProps.styles) ? initialProps.styles : [initialProps.styles]),
<style
id="jss-server-side"
key="jss-server-side"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: css }}
/>,
...React.Children.toArray(initialProps.styles),
],
};
},
},
],
});
return finalProps;
};

View File

@@ -0,0 +1,40 @@
import * as React from 'react';
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import { makeStyles } from '@mui/styles';
import { Link } from '../src/Link';
import ProTip from '../src/ProTip';
import Copyright from '../src/Copyright';
const useStyles = makeStyles((theme) => ({
main: {
marginTop: theme.spacing(4),
marginBottom: theme.spacing(4),
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
}));
export default function About() {
const classes = useStyles();
return (
<Container maxWidth="lg">
<div className={classes.main}>
<Typography variant="h4" component="h1" sx={{ mb: 2 }}>
Material UI - Next.js example in TypeScript with legacy @mui/styles
</Typography>
<Box sx={{ maxWidth: 'sm' }}>
<Button variant="contained" component={Link} noLinkStyle href="/">
Go to the home page
</Button>
</Box>
<ProTip />
<Copyright />
</div>
</Container>
);
}

View File

@@ -0,0 +1,37 @@
import * as React from 'react';
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
import { makeStyles } from '@mui/styles';
import { Link } from '../src/Link';
import ProTip from '../src/ProTip';
import Copyright from '../src/Copyright';
const useStyles = makeStyles((theme) => ({
main: {
marginTop: theme.spacing(4),
marginBottom: theme.spacing(4),
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
}));
export default function Home() {
const classes = useStyles();
return (
<Container maxWidth="lg">
<div className={classes.main}>
<Typography variant="h4" component="h1" sx={{ mb: 2 }}>
Material UI - Next.js example in TypeScript with legacy @mui/styles
</Typography>
<Link href="/about" color="secondary">
Go to the about page
</Link>
<ProTip />
<Copyright />
</div>
</Container>
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,21 @@
import * as React from 'react';
import Typography from '@mui/material/Typography';
import MuiLink from '@mui/material/Link';
export default function Copyright() {
return (
<Typography
variant="body2"
align="center"
sx={{
color: 'text.secondary',
}}
>
{'Copyright © '}
<MuiLink color="inherit" href="https://mui.com/">
Your Website
</MuiLink>{' '}
{new Date().getFullYear()}.
</Typography>
);
}

View File

@@ -0,0 +1,70 @@
import * as React from 'react';
import clsx from 'clsx';
import { useRouter } from 'next/router';
import NextLink, { LinkProps as NextLinkProps } from 'next/link';
import MuiLink, { LinkProps as MuiLinkProps } from '@mui/material/Link';
interface NextLinkComposedProps
extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'>,
Omit<NextLinkProps, 'href' | 'as' | 'passHref' | 'onMouseEnter' | 'onClick' | 'onTouchStart'> {
to: NextLinkProps['href'];
linkAs?: NextLinkProps['as'];
}
export const NextLinkComposed = React.forwardRef<HTMLAnchorElement, NextLinkComposedProps>(
function NextLinkComposed(props, ref) {
const { to, linkAs, ...other } = props;
return <NextLink href={to} as={linkAs} ref={ref} {...other} />;
},
);
export type LinkProps = {
activeClassName?: string;
as?: NextLinkProps['as'];
href: NextLinkProps['href'];
linkAs?: NextLinkProps['as']; // Useful when the as prop is shallow by styled().
noLinkStyle?: boolean;
} & Omit<NextLinkComposedProps, 'to' | 'linkAs' | 'href'> &
Omit<MuiLinkProps, 'href'>;
// A styled version of the Next.js Link component:
// https://nextjs.org/docs/pages/api-reference/components/link
export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(function Link(props, ref) {
const {
activeClassName = 'active',
as,
className: classNameProps,
href,
linkAs: linkAsProp,
noLinkStyle,
...other
} = props;
const router = useRouter();
const pathname = typeof href === 'string' ? href : href?.pathname;
const className = clsx(classNameProps, {
[activeClassName]: router.pathname === pathname && activeClassName,
});
const linkAs = linkAsProp || as || (href as string);
const nextjsProps = {
to: href,
linkAs,
};
if (noLinkStyle) {
return <NextLinkComposed className={className} ref={ref} {...nextjsProps} {...other} />;
}
return (
<MuiLink
component={NextLinkComposed}
className={className}
ref={ref}
{...nextjsProps}
{...other}
/>
);
});

View File

@@ -0,0 +1,38 @@
import * as React from 'react';
import Link from '@mui/material/Link';
import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon';
import Typography from '@mui/material/Typography';
import { makeStyles } from '@mui/styles';
function LightBulbIcon(props: SvgIconProps) {
return (
<SvgIcon {...props}>
<path d="M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6C7.8 12.16 7 10.63 7 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z" />
</SvgIcon>
);
}
const useStyles = makeStyles((theme) => ({
typography: {
marginTop: theme.spacing(6),
marginBottom: theme.spacing(3),
},
}));
export default function ProTip() {
const classes = useStyles();
return (
<Typography
className={classes.typography}
sx={{
color: 'text.secondary',
}}
>
<LightBulbIcon sx={{ mr: 1, verticalAlign: 'middle' }} />
{'Pro tip: See more '}
<Link href="https://mui.com/material-ui/getting-started/templates/">templates</Link>in the
{' in the Material UI documentation.'}
</Typography>
);
}

View File

@@ -0,0 +1,30 @@
import { Roboto } from 'next/font/google';
import { createTheme } from '@mui/material/styles';
import { red } from '@mui/material/colors';
const roboto = Roboto({
weight: ['300', '400', '500', '700'],
subsets: ['latin'],
display: 'swap',
});
// Create a theme instance.
const theme = createTheme({
cssVariables: true,
palette: {
primary: {
main: '#556cd6',
},
secondary: {
main: '#19857b',
},
error: {
main: red.A400,
},
},
typography: {
fontFamily: roboto.style.fontFamily,
},
});
export default theme;

View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"jsxImportSource": "@emotion/react",
"incremental": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}

View File

@@ -0,0 +1,5 @@
import { Theme } from '@mui/material/styles';
declare module '@mui/styles' {
interface DefaultTheme extends Theme {}
}