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

3
examples/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
package-lock.json
pnpm-lock.yaml
yarn.lock

27
examples/joy-ui-cra-ts/.gitignore vendored Normal file
View File

@@ -0,0 +1,27 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# IDEs and editors
/.idea
/.vscode
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@@ -0,0 +1,36 @@
# Joy UI - Create React App example in TypeScript
`@mui/joy` is still in early development and is not recommended for use in production.
## 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/joy-ui-cra-ts
cd joy-ui-cra-ts
```
Install it and run:
```bash
npm install
npm start
```
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/joy-ui-cra-ts)
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/github/mui/material-ui/tree/master/examples/joy-ui-cra-ts)
## What's next?
<!-- #host-reference -->
You now have a working example project.
You can head back to the documentation and continue by browsing the [templates](https://mui.com/joy-ui/getting-started/templates/) section.

View File

@@ -0,0 +1,33 @@
{
"name": "joy-ui-cra-ts",
"private": true,
"dependencies": {
"@emotion/react": "latest",
"@emotion/styled": "latest",
"@mui/joy": "next",
"@types/react": "latest",
"@types/react-dom": "latest",
"react": "latest",
"react-dom": "latest",
"react-scripts": "latest",
"typescript": "latest"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,20 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="initial-scale=1, width=device-width" />
<title>CRA + Joy UI + TS</title>
<!-- Fonts to support Joy Design -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap"
/>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

View File

@@ -0,0 +1,15 @@
{
"short_name": "Your Orders",
"name": "Your Orders",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@@ -0,0 +1,11 @@
import * as React from 'react';
import { CssVarsProvider } from '@mui/joy/styles';
import Button from '@mui/joy/Button';
export default function App() {
return (
<CssVarsProvider>
<Button>Button</Button>
</CssVarsProvider>
);
}

View File

@@ -0,0 +1,8 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import App from './App';
const rootElement = document.getElementById('root');
const root = ReactDOM.createRoot(rootElement!);
root.render(<App />);

View File

@@ -0,0 +1 @@
/// <reference types="react-scripts" />

View File

@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": ["src"]
}

35
examples/joy-ui-nextjs-ts/.gitignore vendored Normal file
View File

@@ -0,0 +1,35 @@
# 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
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

View File

@@ -0,0 +1,45 @@
# Joy UI - Next.js App Router with TypeScript
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/HEAD/packages/create-next-app).
## 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/joy-ui-nextjs-ts
cd joy-ui-nextjs-ts
```
Install it and run:
```bash
npm install
npm run dev
```
Open [http://localhost:3000](http://localhost:3000) with your web browser to see the result.
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/joy-ui-nextjs-ts)
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/github/mui/material-ui/tree/master/examples/joy-ui-nextjs-ts)
## Learn more
To learn more about this example:
- [Next.js documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Customizing Joy UI](https://mui.com/joy-ui/customization/approaches/) - approaches to customizing Joy UI.
## What's next?
<!-- #host-reference -->
You now have a working example project.
You can head back to the documentation and continue by browsing the [templates](https://mui.com/joy-ui/getting-started/templates/) section.

View File

@@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default nextConfig;

View File

@@ -0,0 +1,29 @@
{
"name": "joy-ui-nextjs-ts",
"version": "5.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"post-update": "echo \"codesandbox preview only, need an update\" && pnpm update --latest"
},
"dependencies": {
"@emotion/cache": "latest",
"@emotion/react": "latest",
"@emotion/styled": "latest",
"@mui/joy": "next",
"next": "latest",
"react": "latest",
"react-dom": "latest"
},
"devDependencies": {
"@types/node": "latest",
"@types/react": "latest",
"@types/react-dom": "latest",
"eslint": "latest",
"eslint-config-next": "latest",
"typescript": "latest"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,17 @@
import * as React from 'react';
import ThemeRegistry from '@/components/ThemeRegistry/ThemeRegistry';
export const metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
};
export default function RootLayout(props: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<ThemeRegistry>{props.children}</ThemeRegistry>
</body>
</html>
);
}

View File

@@ -0,0 +1,63 @@
import * as React from 'react';
import Sheet from '@mui/joy/Sheet';
import Typography from '@mui/joy/Typography';
import FormControl from '@mui/joy/FormControl';
import FormLabel from '@mui/joy/FormLabel';
import Input from '@mui/joy/Input';
import Button from '@mui/joy/Button';
import Link from '@mui/joy/Link';
export default function Home() {
return (
<Sheet
sx={{
display: 'flex',
flexFlow: 'row nowrap',
justifyContent: 'center',
alignItems: 'center',
minHeight: '100vh',
}}
>
<Sheet
sx={{
width: 300,
mx: 'auto',
my: 4,
py: 3,
px: 2,
display: 'flex',
flexDirection: 'column',
gap: 2,
borderRadius: 'sm',
boxShadow: 'md',
}}
variant="outlined"
>
<div>
<Typography level="h4" component="h1">
<strong>Welcome back 👋</strong>
</Typography>
<Typography level="body-sm">Sign in to continue.</Typography>
</div>
<FormControl id="email">
<FormLabel>Email</FormLabel>
<Input name="email" type="email" placeholder="johndoe@email.com" />
</FormControl>
<FormControl id="password">
<FormLabel>Password</FormLabel>
<Input name="password" type="password" placeholder="password" />
</FormControl>
<Button sx={{ mt: 1 }}>Log in</Button>
<Typography
endDecorator={<Link href="/sign-up">Sign up</Link>}
sx={{
fontSize: 'sm',
alignSelf: 'center',
}}
>
Don&apos;t have an account?
</Typography>
</Sheet>
</Sheet>
);
}

View File

@@ -0,0 +1,64 @@
import * as React from 'react';
import Sheet from '@mui/joy/Sheet';
import Typography from '@mui/joy/Typography';
import FormControl from '@mui/joy/FormControl';
import FormLabel from '@mui/joy/FormLabel';
import Input from '@mui/joy/Input';
import Button from '@mui/joy/Button';
import Link from '@mui/joy/Link';
export default function SignUp() {
return (
<Sheet
sx={{
display: 'flex',
flexFlow: 'row nowrap',
justifyContent: 'center',
alignItems: 'center',
minHeight: '100vh',
}}
>
<Sheet
sx={{
width: 300,
mx: 'auto',
my: 4,
py: 3,
px: 2,
display: 'flex',
flexDirection: 'column',
gap: 2,
borderRadius: 'sm',
boxShadow: 'md',
}}
variant="outlined"
>
<div>
<Typography level="h4" component="h1">
<strong>Welcome 👋</strong>
</Typography>
<Typography level="body-sm">Sign up for an account.</Typography>
</div>
<FormControl>
<FormLabel>Email</FormLabel>
<Input name="email" type="email" placeholder="johndoe@email.com" />
</FormControl>
<FormControl>
<FormLabel>Password</FormLabel>
<Input name="password" type="password" placeholder="password" />
</FormControl>
<Button sx={{ mt: 1 }}>Create account</Button>
<Typography
endDecorator={<Link href="/">Log in</Link>}
sx={{
fontSize: 'sm',
alignSelf: 'center',
}}
>
Already have an account?
</Typography>
</Sheet>
</Sheet>
);
}

View File

@@ -0,0 +1,91 @@
'use client';
import * as React from 'react';
import createCache from '@emotion/cache';
import { useServerInsertedHTML } from 'next/navigation';
import { CacheProvider as DefaultCacheProvider } from '@emotion/react';
import type { EmotionCache, Options as OptionsOfCreateCache } from '@emotion/cache';
export type NextAppDirEmotionCacheProviderProps = {
/** This is the options passed to createCache() from 'import createCache from "@emotion/cache"' */
options: Omit<OptionsOfCreateCache, 'insertionPoint'>;
/** By default <CacheProvider /> from 'import { CacheProvider } from "@emotion/react"' */
CacheProvider?: React.ElementType<{ value: EmotionCache }>;
children: React.ReactNode;
};
// Adapted from https://github.com/garronej/tss-react/blob/main/src/next/appDir.tsx
export default function NextAppDirEmotionCacheProvider(props: NextAppDirEmotionCacheProviderProps) {
const { options, CacheProvider = DefaultCacheProvider, children } = props;
const [registry] = React.useState(() => {
const cache = createCache(options);
cache.compat = true;
const prevInsert = cache.insert;
let inserted: { name: string; isGlobal: boolean }[] = [];
cache.insert = (...args) => {
const [selector, serialized] = args;
if (cache.inserted[serialized.name] === undefined) {
inserted.push({
name: serialized.name,
isGlobal: !selector,
});
}
return prevInsert(...args);
};
const flush = () => {
const prevInserted = inserted;
inserted = [];
return prevInserted;
};
return { cache, flush };
});
useServerInsertedHTML(() => {
const inserted = registry.flush();
if (inserted.length === 0) {
return null;
}
let styles = '';
let dataEmotionAttribute = registry.cache.key;
const globals: {
name: string;
style: string;
}[] = [];
inserted.forEach(({ name, isGlobal }) => {
const style = registry.cache.inserted[name];
if (typeof style !== 'boolean') {
if (isGlobal) {
globals.push({ name, style });
} else {
styles += style;
dataEmotionAttribute += ` ${name}`;
}
}
});
return (
<React.Fragment>
{globals.map(({ name, style }) => (
<style
key={name}
data-emotion={`${registry.cache.key}-global ${name}`}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: style }}
/>
))}
{styles && (
<style
data-emotion={dataEmotionAttribute}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: styles }}
/>
)}
</React.Fragment>
);
});
return <CacheProvider value={registry.cache}>{children}</CacheProvider>;
}

View File

@@ -0,0 +1,17 @@
'use client';
import * as React from 'react';
import { CssVarsProvider } from '@mui/joy/styles';
import CssBaseline from '@mui/joy/CssBaseline';
import NextAppDirEmotionCacheProvider from './EmotionCache';
import theme from './theme';
export default function ThemeRegistry({ children }: { children: React.ReactNode }) {
return (
<NextAppDirEmotionCacheProvider options={{ key: 'joy' }}>
<CssVarsProvider theme={theme}>
<CssBaseline />
{children}
</CssVarsProvider>
</NextAppDirEmotionCacheProvider>
);
}

View File

@@ -0,0 +1,47 @@
import { extendTheme } from '@mui/joy/styles';
import { Inter, Source_Code_Pro } from 'next/font/google';
const inter = Inter({
subsets: ['latin'],
adjustFontFallback: false, // prevent NextJS from adding its own fallback font
fallback: ['var(--joy-fontFamily-fallback)'], // use Joy UI's fallback font
display: 'swap',
});
const sourceCodePro = Source_Code_Pro({
subsets: ['latin'],
adjustFontFallback: false, // prevent NextJS from adding its own fallback font
fallback: [
// the default theme's fallback for monospace fonts
'ui-monospace',
'SFMono-Regular',
'Menlo',
'Monaco',
'Consolas',
'Liberation Mono',
'Courier New',
'monospace',
],
display: 'swap',
});
const theme = extendTheme({
fontFamily: {
body: inter.style.fontFamily,
display: inter.style.fontFamily,
code: sourceCodePro.style.fontFamily,
},
components: {
JoyButton: {
styleOverrides: {
root: ({ ownerState }) => ({
...(ownerState.color === 'primary' && {
backgroundColor: '#4338ca',
}),
}),
},
},
},
});
export default theme;

View File

@@ -0,0 +1,28 @@
{
"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",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}

24
examples/joy-ui-vite-ts/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1,43 @@
# Joy UI - Vite.js in TypeScript example
[Joy UI](https://mui.com/joy-ui/getting-started/) is a library of beautifully designed React UI components built to spark joy in the development process.
[Vite](https://vite.dev/) is a build tool that aims to provide a faster and leaner development experience for modern web projects, consisting of a dev server and a build command.
## 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/joy-ui-vite-ts
cd joy-ui-vite-ts
```
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/joy-ui-vite-ts)
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/github/mui/material-ui/tree/master/examples/joy-ui-vite-ts)
## The idea behind the example
This example uses [Vite.js](https://github.com/vitejs/vite).
It includes `@mui/joy` and it's peer dependencies.
## What's next?
<!-- #host-reference -->
You now have a working example project.
You can head back to the documentation and continue by browsing the [templates](https://mui.com/joy-ui/getting-started/templates/) section.

View File

@@ -0,0 +1,20 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="initial-scale=1, width=device-width" />
<title>Vite + Joy UI + TS</title>
<!-- Fonts to support Joy Design -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap"
/>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

View File

@@ -0,0 +1,26 @@
{
"name": "joy-ui-vite-ts",
"version": "5.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@emotion/react": "latest",
"@emotion/styled": "latest",
"@mui/joy": "next",
"react": "latest",
"react-dom": "latest"
},
"devDependencies": {
"@types/react": "latest",
"@types/react-dom": "latest",
"@vitejs/plugin-react": "latest",
"typescript": "latest",
"vite": "latest"
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,44 @@
import * as React from 'react';
import Container from '@mui/joy/Container';
import Typography from '@mui/joy/Typography';
import Card from '@mui/joy/Card';
import Button from '@mui/joy/Button';
import Link from '@mui/joy/Link';
import SvgIcon from '@mui/joy/SvgIcon';
function Copyright() {
return (
<Typography level="body-md" color="neutral" sx={{ textAlign: 'center' }}>
{'Copyright © '}
<Link href="https://mui.com/">Your Website</Link> {new Date().getFullYear()}.
</Typography>
);
}
function Arrow() {
return (
<SvgIcon>
<path d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z" />
</SvgIcon>
);
}
export default function App() {
return (
<Container maxWidth="md">
<Card variant="outlined">
<Typography level="h2">Joy UI Vite.js example in TypeScript</Typography>
<Button
sx={{ mt: 6, mb: 3 }}
variant="soft"
component="a"
href="https://mui.com/joy-ui/getting-started/templates/"
endDecorator={<Arrow />}
>
See more examples
</Button>
<Copyright />
</Card>
</Container>
);
}

View File

@@ -0,0 +1,9 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import App from './App';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
);

View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View File

@@ -0,0 +1,9 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -0,0 +1,7 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
});

View File

@@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}

View File

@@ -0,0 +1,18 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@@ -0,0 +1,39 @@
import * as React from 'react';
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import Link from '@mui/material/Link';
import ProTip from './ProTip';
function Copyright() {
return (
<Typography
variant="body2"
align="center"
sx={{
color: 'text.secondary',
}}
>
{'Copyright © '}
<Link color="inherit" href="https://mui.com/">
Your Website
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
export default function App() {
return (
<Container maxWidth="sm">
<Box sx={{ my: 4 }}>
<Typography variant="h4" component="h1" sx={{ mb: 2 }}>
Material UI Express.js server-rendered example
</Typography>
<ProTip />
<Copyright />
</Box>
</Container>
);
}

View File

@@ -0,0 +1,23 @@
import * as React from 'react';
import Link from '@mui/material/Link';
import SvgIcon from '@mui/material/SvgIcon';
import Typography from '@mui/material/Typography';
function LightBulbIcon(props) {
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>
);
}
export default function ProTip() {
return (
<Typography sx={{ mt: 6, mb: 3, 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 Material UI documentation.'}
</Typography>
);
}

View File

@@ -0,0 +1,43 @@
# Material UI - Server-side-rendered example
## 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-express-ssr
cd material-ui-express-ssr
```
Install it and run:
```bash
npm install
npm run start
```
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-express-ssr)
[![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-express-ssr)
## The idea behind the example
<!-- #host-reference -->
This is the reference implementation of the [Server Rendering tutorial](https://mui.com/material-ui/guides/server-rendering/).
The example project 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).
## What's next?
<!-- #host-reference -->
You now have a working example project.
You can head back to the documentation and continue by browsing the [templates](https://mui.com/material-ui/getting-started/templates/) section.

View File

@@ -0,0 +1,24 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import CssBaseline from '@mui/material/CssBaseline';
import { ThemeProvider } from '@mui/material/styles';
import { CacheProvider } from '@emotion/react';
import App from './App';
import theme from './theme';
import createEmotionCache from './createEmotionCache';
const cache = createEmotionCache();
function Main() {
return (
<CacheProvider value={cache}>
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<App />
</ThemeProvider>
</CacheProvider>
);
}
ReactDOM.hydrateRoot(document.querySelector('#root'), <Main />);

View File

@@ -0,0 +1,17 @@
import createCache from '@emotion/cache';
const isBrowser = typeof document !== 'undefined';
// On the client side, Create a meta tag at the top of the <head> and set it as insertionPoint.
// This assures that Material UI styles are loaded first.
// It allows developers to easily override Material UI styles with other styling solutions, like CSS modules.
export default function createEmotionCache() {
let insertionPoint;
if (isBrowser) {
const emotionInsertionPoint = document.querySelector('meta[name="emotion-insertion-point"]');
insertionPoint = emotionInsertionPoint ?? undefined;
}
return createCache({ key: 'mui-style', insertionPoint });
}

View File

@@ -0,0 +1,36 @@
{
"name": "material-ui-express-ssr",
"version": "7.0.0",
"private": true,
"browserslist": [
">0.25%",
"not dead"
],
"dependencies": {
"@babel/core": "latest",
"@babel/node": "latest",
"@babel/preset-env": "latest",
"@babel/preset-react": "latest",
"@emotion/cache": "latest",
"@emotion/react": "latest",
"@emotion/styled": "latest",
"@emotion/server": "latest",
"@mui/material": "latest",
"babel-loader": "latest",
"cross-env": "latest",
"express": "latest",
"nodemon": "latest",
"npm-run-all": "latest",
"react": "latest",
"react-dom": "latest",
"webpack": "latest",
"webpack-cli": "latest"
},
"scripts": {
"start": "npm-run-all -p build serve",
"build": "webpack -w",
"serve": "nodemon --ignore ./build --exec babel-node -- server.js",
"production": "cross-env NODE_ENV=production npm start",
"post-update": "echo \"codesandbox preview only, need an update\" && pnpm update --latest"
}
}

View File

@@ -0,0 +1,70 @@
import express from 'express';
import * as React from 'react';
import * as ReactDOMServer from 'react-dom/server';
import CssBaseline from '@mui/material/CssBaseline';
import { ThemeProvider } from '@mui/material/styles';
import { CacheProvider } from '@emotion/react';
import createEmotionServer from '@emotion/server/create-instance';
import createEmotionCache from './createEmotionCache';
import App from './App';
import theme from './theme';
function renderFullPage(html, css) {
return `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My page</title>
<meta name="viewport" content="initial-scale=1, width=device-width" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
/>
<meta name="emotion-insertion-point" content="" />
${css}
</head>
<body>
<script async src="build/bundle.js"></script>
<div id="root">${html}</div>
</body>
</html>
`;
}
function handleRender(req, res) {
const cache = createEmotionCache();
const { extractCriticalToChunks, constructStyleTagsFromChunks } = createEmotionServer(cache);
// Render the component to a string.
const html = ReactDOMServer.renderToString(
<CacheProvider value={cache}>
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<App />
</ThemeProvider>
</CacheProvider>,
);
// Grab the CSS from emotion
const emotionChunks = extractCriticalToChunks(html);
const emotionCss = constructStyleTagsFromChunks(emotionChunks);
// Send the rendered page back to the client.
res.send(renderFullPage(html, emotionCss));
}
const app = express();
app.use('/build', express.static('build'));
// This is fired every time the server-side receives a request.
app.use(handleRender);
const port = 3000;
app.listen(port, () => {
console.log(`Listening on ${port}`);
});

View File

@@ -0,0 +1,20 @@
import { createTheme } from '@mui/material/styles';
import { red } from '@mui/material/colors';
// Create a theme instance.
const theme = createTheme({
cssVariables: true,
palette: {
primary: {
main: '#556cd6',
},
secondary: {
main: '#19857b',
},
error: {
main: red.A400,
},
},
});
export default theme;

View File

@@ -0,0 +1,20 @@
const path = require('path');
module.exports = {
entry: './client.js',
mode: process.env.NODE_ENV || 'development',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.js',
publicPath: '/',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
],
},
};

19
examples/material-ui-gatsby/.gitignore vendored Normal file
View File

@@ -0,0 +1,19 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Gatsby.js
/public
/.cache

View File

@@ -0,0 +1,34 @@
# Material UI - Gatsby example
## 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-gatsby
cd material-ui-gatsby
```
Install it and run:
```bash
npm install
npm run develop
```
## The idea behind the example
<!-- #host-reference -->
The project uses [Gatsby](https://github.com/gatsbyjs/gatsby), which is a static site generator for React.
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).
## What's next?
<!-- #host-reference -->
You now have a working example project.
You can head back to the documentation and continue by browsing the [templates](https://mui.com/material-ui/getting-started/templates/) section.

View File

@@ -0,0 +1,26 @@
{
"name": "material-ui-gatsby",
"version": "7.0.0",
"private": true,
"browserslist": [
">0.25%",
"not dead"
],
"dependencies": {
"@emotion/react": "latest",
"@emotion/server": "latest",
"@emotion/styled": "latest",
"@mui/material": "latest",
"gatsby": "latest",
"gatsby-plugin-react-helmet": "latest",
"react": "latest",
"react-dom": "latest",
"react-helmet": "latest"
},
"scripts": {
"develop": "gatsby develop",
"build": "gatsby build",
"serve": "gatsby serve",
"post-update": "echo \"codesandbox preview only, need an update\" && pnpm update --latest"
}
}

View File

@@ -0,0 +1,22 @@
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,9 @@
import * as React from 'react';
import MuiLink from '@mui/material/Link';
import { Link as GatsbyLink } from 'gatsby';
const Link = React.forwardRef(function Link(props, ref) {
return <MuiLink component={GatsbyLink} ref={ref} {...props} />;
});
export default Link;

View File

@@ -0,0 +1,23 @@
import * as React from 'react';
import Link from '@mui/material/Link';
import SvgIcon from '@mui/material/SvgIcon';
import Typography from '@mui/material/Typography';
function LightBulbIcon(props) {
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>
);
}
export default function ProTip() {
return (
<Typography sx={{ mt: 6, mb: 3, 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 Material UI documentation.'}
</Typography>
);
}

View File

@@ -0,0 +1,22 @@
import * as React from 'react';
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import ProTip from '../components/ProTip';
import Link from '../components/Link';
import Copyright from '../components/Copyright';
export default function About() {
return (
<Container maxWidth="sm">
<Box sx={{ my: 4 }}>
<Typography variant="h4" component="h1" sx={{ mb: 2 }}>
Material UI Gatsby example
</Typography>
<Link to="/">Go to the main page</Link>
<ProTip />
<Copyright />
</Box>
</Container>
);
}

View File

@@ -0,0 +1,24 @@
import * as React from 'react';
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import ProTip from '../components/ProTip';
import Link from '../components/Link';
import Copyright from '../components/Copyright';
export default function Index() {
return (
<Container maxWidth="sm">
<Box sx={{ my: 4 }}>
<Typography variant="h4" component="h1" sx={{ mb: 2 }}>
Material UI Gatsby example
</Typography>
<Link to="/about" color="secondary">
Go to the about page
</Link>
<ProTip />
<Copyright />
</Box>
</Container>
);
}

View File

@@ -0,0 +1,20 @@
import { red } from '@mui/material/colors';
import { createTheme } from '@mui/material/styles';
// A custom theme for this app
const theme = createTheme({
cssVariables: true,
palette: {
primary: {
main: '#556cd6',
},
secondary: {
main: '#19857b',
},
error: {
main: red.A400,
},
},
});
export default theme;

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,54 @@
# Material UI - Next.js Pages Router example 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-pages-router-ts
cd material-ui-nextjs-pages-router-ts
```
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-pages-router-ts)
[![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-pages-router-ts)
## The idea behind the example
**Note:** This example is set up to use the Next.js Pages Router.
As of Next.js 13.4, the newer App Router pattern is stable.
We recommend starting new projects with the [Material UI with Next.js (App Router) example](https://github.com/mui/material-ui/tree/master/examples/material-ui-nextjs-ts) unless you need (or prefer) the Pages Router.
<!-- #host-reference -->
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).
## The link component
<!-- #target-branch-reference -->
<!-- #host-reference -->
The [example folder](https://github.com/mui/material-ui/tree/HEAD/examples/material-ui-nextjs-pages-router-ts) provides an adapter for the use of [Next.js's Link component](https://nextjs.org/docs/pages/api-reference/components/link) with Material UI.
More information [in the documentation](https://mui.com/material-ui/integrations/routing/#next-js-pages-router).
## What's next?
<!-- #host-reference -->
You now have a working example project.
You can head back to the documentation and continue by browsing the [templates](https://mui.com/material-ui/getting-started/templates/) section.

View File

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

View File

@@ -0,0 +1,31 @@
{
"name": "material-ui-nextjs-pages-router-ts",
"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",
"clsx": "latest",
"next": "^15.0.5",
"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,23 @@
import * as React from 'react';
import Head from 'next/head';
import { AppProps } from 'next/app';
import { AppCacheProvider } from '@mui/material-nextjs/v15-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;
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,31 @@
import * as React from 'react';
import { Html, Head, Main, NextScript, DocumentProps, DocumentContext } from 'next/document';
import {
DocumentHeadTags,
DocumentHeadTagsProps,
documentGetInitialProps,
} from '@mui/material-nextjs/v15-pagesRouter';
import theme, { roboto } from '../src/theme';
export default function MyDocument(props: DocumentProps & DocumentHeadTagsProps) {
return (
<Html lang="en" className={roboto.className}>
<Head>
{/* PWA primary color */}
<meta name="theme-color" content={theme.palette.primary.main} />
<link rel="icon" href="/favicon.ico" />
<meta name="emotion-insertion-point" content="" />
<DocumentHeadTags {...props} />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
MyDocument.getInitialProps = async (ctx: DocumentContext) => {
const finalProps = await documentGetInitialProps(ctx);
return finalProps;
};

View File

@@ -0,0 +1,35 @@
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 { Link } from '../src/Link';
import ProTip from '../src/ProTip';
import Copyright from '../src/Copyright';
export default function About() {
return (
<Container maxWidth="lg">
<Box
sx={{
my: 4,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Typography variant="h4" component="h1" sx={{ mb: 2 }}>
Material UI - Next.js example in TypeScript
</Typography>
<Box sx={{ maxWidth: 'sm' }}>
<Button variant="contained" component={Link} noLinkStyle href="/">
Go to the home page
</Button>
</Box>
<ProTip />
<Copyright />
</Box>
</Container>
);
}

View File

@@ -0,0 +1,32 @@
import * as React from 'react';
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import { Link } from '../src/Link';
import ProTip from '../src/ProTip';
import Copyright from '../src/Copyright';
export default function Home() {
return (
<Container maxWidth="lg">
<Box
sx={{
my: 4,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Typography variant="h4" component="h1" sx={{ mb: 2 }}>
Material UI - Next.js example in TypeScript
</Typography>
<Link href="/about" color="secondary">
Go to the about page
</Link>
<ProTip />
<Copyright />
</Box>
</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,23 @@
import * as React from 'react';
import Link from '@mui/material/Link';
import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon';
import Typography from '@mui/material/Typography';
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>
);
}
export default function ProTip() {
return (
<Typography sx={{ mt: 6, mb: 3, 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 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';
export 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,18 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Next.js
/.next

View File

@@ -0,0 +1,54 @@
# Material UI - Next.js Pages Router example
## 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-pages-router
cd material-ui-nextjs-pages-router
```
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-pages-router)
[![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-pages-router)
## The idea behind the example
**Note:** This example is set up to use the Next.js Pages Router.
As of Next.js 13.4, the newer App Router pattern is stable.
We recommend starting new projects with the [Material UI with Next.js (App Router) example](https://github.com/mui/material-ui/tree/master/examples/material-ui-nextjs) unless you need (or prefer) the Pages Router.
<!-- #host-reference -->
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).
## The Link component
<!-- #target-branch-reference -->
<!-- #host-reference -->
The [example folder](https://github.com/mui/material-ui/tree/HEAD/examples/material-ui-nextjs-pages-router) provides an adapter for the use of [Next.js's Link component](https://nextjs.org/docs/pages/api-reference/components/link) with Material UI.
More information [in the documentation](https://mui.com/material-ui/integrations/routing/#next-js-pages-router).
## What's next?
<!-- #host-reference -->
You now have a working example project.
You can head back to the documentation and continue by browsing the [templates](https://mui.com/material-ui/getting-started/templates/) section.

View File

@@ -0,0 +1,3 @@
export default {
reactStrictMode: true,
};

View File

@@ -0,0 +1,28 @@
{
"name": "material-ui-nextjs-pages-router",
"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",
"clsx": "latest",
"next": "^15.0.5",
"react": "latest",
"react-dom": "latest"
},
"devDependencies": {
"eslint": "latest",
"eslint-config-next": "latest"
}
}

View File

@@ -0,0 +1,23 @@
import * as React from 'react';
import Head from 'next/head';
import { AppCacheProvider } from '@mui/material-nextjs/v15-pagesRouter';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import theme from '../src/theme';
export default function MyApp(props) {
const { Component, pageProps } = props;
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,27 @@
import * as React from 'react';
import { Html, Head, Main, NextScript } from 'next/document';
import { DocumentHeadTags, documentGetInitialProps } from '@mui/material-nextjs/v15-pagesRouter';
import theme from '../src/theme';
export default function MyDocument(props) {
return (
<Html lang="en">
<Head>
{/* PWA primary color */}
<meta name="theme-color" content={theme.palette.primary.main} />
<link rel="icon" href="/favicon.ico" />
<meta name="emotion-insertion-point" content="" />
<DocumentHeadTags {...props} />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
MyDocument.getInitialProps = async (ctx) => {
const finalProps = await documentGetInitialProps(ctx);
return finalProps;
};

View File

@@ -0,0 +1,25 @@
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 ProTip from '../src/ProTip';
import { Link } from '../src/Link';
import Copyright from '../src/Copyright';
export default function About() {
return (
<Container maxWidth="sm">
<Box sx={{ my: 4 }}>
<Typography variant="h4" component="h1" sx={{ mb: 2 }}>
Material UI - Next.js example
</Typography>
<Button variant="contained" component={Link} noLinkStyle href="/">
Go to the main page
</Button>
<ProTip />
<Copyright />
</Box>
</Container>
);
}

View File

@@ -0,0 +1,24 @@
import * as React from 'react';
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import ProTip from '../src/ProTip';
import { Link } from '../src/Link';
import Copyright from '../src/Copyright';
export default function Index() {
return (
<Container maxWidth="sm">
<Box sx={{ my: 4 }}>
<Typography variant="h4" component="h1" sx={{ mb: 2 }}>
Material UI - Next.js example
</Typography>
<Link href="/about" color="secondary">
Go to the about page
</Link>
<ProTip />
<Copyright />
</Box>
</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,52 @@
import * as React from 'react';
import clsx from 'clsx';
import { useRouter } from 'next/router';
import NextLink from 'next/link';
import MuiLink from '@mui/material/Link';
export const NextLinkComposed = React.forwardRef(function NextLinkComposed(props, ref) {
const { to, linkAs, ...other } = props;
return <NextLink href={to} as={linkAs} ref={ref} {...other} />;
});
// A styled version of the Next.js Link component:
// https://nextjs.org/docs/pages/api-reference/components/link
export const Link = React.forwardRef(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;
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,23 @@
import * as React from 'react';
import Link from '@mui/material/Link';
import SvgIcon from '@mui/material/SvgIcon';
import Typography from '@mui/material/Typography';
function LightBulbIcon(props) {
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>
);
}
export default function ProTip() {
return (
<Typography sx={{ mt: 6, mb: 3, 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 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,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 {}
}

View File

@@ -0,0 +1,36 @@
# 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*
.pnpm-debug.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
# next-env.d.ts

View File

@@ -0,0 +1,47 @@
# Material UI - Next.js App Router example in TypeScript
This is a [Next.js](https://nextjs.org/) project bootstrapped using [`create-next-app`](https://github.com/vercel/next.js/tree/HEAD/packages/create-next-app) with Material UI installed.
## 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
cd material-ui-nextjs-ts
```
Install it and run:
```bash
npm install
npm run dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
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)
[![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)
## Learn more
To learn more about this example:
<!-- #host-reference -->
- [Next.js documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Customizing Material UI](https://mui.com/material-ui/customization/how-to-customize/) - approaches to customizing Material UI.
## What's next?
<!-- #host-reference -->
You now have a working example project.
You can head back to the documentation and continue by browsing the [templates](https://mui.com/material-ui/getting-started/templates/) section.

View File

@@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default nextConfig;

Some files were not shown because too many files have changed in this diff Show More