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

[WIP][docs] Move blog to app #35060

Closed
wants to merge 13 commits into from
4 changes: 4 additions & 0 deletions docs/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"typescript.tsdk": "./node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
8 changes: 8 additions & 0 deletions docs/app/Box.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use client';

import * as React from 'react';
import MuiBox from '@mui/material/Box';

export default function Box(props) {
return <MuiBox {...props} />;
}
8 changes: 8 additions & 0 deletions docs/app/BrandingProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use client';

import * as React from 'react';
import DocsBrandingProvider from 'docs/src/BrandingProvider';

export default function BrandingProvider(props) {
return <DocsBrandingProvider {...props} />;
}
8 changes: 8 additions & 0 deletions docs/app/Divider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use client';

import * as React from 'react';
import MuiDivider from '@mui/material/Divider';

export default function Divider(props) {
return <MuiDivider {...props} />;
}
61 changes: 61 additions & 0 deletions docs/app/EmotionRootStyleRegistry.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use client';
import * as React from 'react';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import { useServerInsertedHTML } from 'next/navigation';
import { useState } from 'react';
import BrandingProvider from './BrandingProvider';
// import { ThemeProvider, createTheme } from '@mui/material/styles';
// import { green, deepPurple } from '@mui/material/colors';

// const theme = createTheme({
// palette: {
// primary: green,
// secondary: deepPurple
// }
// });

export default function RootStyleRegistry({ children }: { children: JSX.Element }) {
const [{ cache, flush }] = useState(() => {
const cache = createCache({ key: 'my' });
cache.compat = true;
const prevInsert = cache.insert;
let inserted: string[] = [];
cache.insert = (...args) => {
const serialized = args[1];
if (cache.inserted[serialized.name] === undefined) {
inserted.push(serialized.name);
}
return prevInsert(...args);
};
const flush = () => {
const prevInserted = inserted;
inserted = [];
return prevInserted;
};
return { cache, flush };
});

useServerInsertedHTML(() => {
const names = flush();
if (names.length === 0) return null;
let styles = '';
for (const name of names) {
styles += cache.inserted[name];
}
return (
<style
data-emotion={`${cache.key} ${names.join(' ')}`}
dangerouslySetInnerHTML={{
__html: styles,
}}
/>
);
});

return (
<CacheProvider value={cache}>
<BrandingProvider>{children}</BrandingProvider>
</CacheProvider>
);
}
8 changes: 8 additions & 0 deletions docs/app/GradientText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use client';

import * as React from 'react';
import DocsGradientText from 'docs/src/components/typography/GradientText';

export default function GradientText(props) {
return <DocsGradientText {...props} />;
}
8 changes: 8 additions & 0 deletions docs/app/Paper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use client';

import * as React from 'react';
import MuiPaper from '@mui/material/Paper';

export default function Paper(props) {
return <MuiPaper {...props} />;
}
8 changes: 8 additions & 0 deletions docs/app/Section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use client';

import * as React from 'react';
import DocsSection from 'docs/src/layouts/Section';

export default function Section(props) {
return <DocsSection {...props} />;
}
8 changes: 8 additions & 0 deletions docs/app/blog/AppFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use client';

import * as React from 'react';
import DocsAppFooter from 'docs/src/layouts/AppFooter';

export default function AppFooter(props) {
return <DocsAppFooter {...props} />;
}
8 changes: 8 additions & 0 deletions docs/app/blog/AppHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use client';

import * as React from 'react';
import DocsAppHeader from 'docs/src/layouts/AppHeader';

export default function AppHeader(props) {
return <DocsAppHeader {...props} />;
}
12 changes: 12 additions & 0 deletions docs/app/blog/ClientComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use client';
import * as React from 'react';
import Button, { ButtonProps } from '@mui/material/Button';

export default function ClientComponent() {
const [color, setColor] = React.useState<ButtonProps['color']>('primary');
return (
<Button color={color} onClick={() => setColor(color === 'primary' ? 'secondary' : 'primary')}>
ClientComponent
</Button>
);
}
61 changes: 61 additions & 0 deletions docs/app/blog/Head.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use client';

import * as React from 'react';
import NextHead from 'next/head';
import { useUserLanguage, useTranslate } from 'docs/src/modules/utils/i18n';

// #major-version-switch
const HOST = 'https://mui.com';

interface HeadProps {
card?: string;
children?: React.ReactNode;
description: string;
disableAlternateLocale?: boolean;
largeCard?: boolean;
title: string;
type?: string;
}

export default function Head(props: HeadProps) {
const t = useTranslate();
const {
card = '/static/social-previews/default-preview.jpg',
children,
description = t('strapline'),
disableAlternateLocale = false,
largeCard = true,
title = t('headTitle'),
type = 'website',
} = props;
const userLanguage = useUserLanguage();
const preview = card.startsWith('http') ? card : `${HOST}${card}`;

return (
<NextHead>
<title>{title}</title>
<meta name="description" content={description} />
{/* Twitter */}
<meta name="twitter:card" content={largeCard ? 'summary_large_image' : 'summary'} />
{/* https://twitter.com/MUI_hq */}
<meta name="twitter:site" content="@MUI_hq" />
{/* #major-version-switch */}
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={preview} />
{/* Facebook */}
<meta property="og:type" content={type} />
<meta property="og:title" content={title} />
{/* #major-version-switch */}
<meta property="og:url" content={`${HOST}`} />
<meta property="og:description" content={description} />
<meta property="og:image" content={preview} />
<meta property="og:ttl" content="604800" />
{/* Algolia */}
<meta name="docsearch:language" content={userLanguage} />
{/* #major-version-switch */}
<meta name="docsearch:version" content="master" />
{children}
</NextHead>
);
}
8 changes: 8 additions & 0 deletions docs/app/blog/HeroEnd.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use client';

import * as React from 'react';
import DocsHeroEnd from 'docs/src/components/home/HeroEnd';

export default function HeroEnd(props) {
return <DocsHeroEnd {...props} />;
}
145 changes: 145 additions & 0 deletions docs/app/blog/Link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import * as React from 'react';
import clsx from 'clsx';
import NextLink, { LinkProps as NextLinkProps } from 'next/link';
import { usePathname } from 'next/navigation';
import MuiLink, { LinkProps as MuiLinkProps } from '@mui/material/Link';
import { styled } from '@mui/material/styles';
import { useUserLanguage } from 'docs/src/modules/utils/i18n';
import { LANGUAGES_IGNORE_PAGES } from 'docs/src/modules/constants';

/**
* File to keep in sync with:
*
* - /docs/src/modules/components/Link.tsx
* - /examples/nextjs/src/Link.js
* - /examples/nextjs-with-typescript/src/Link.tsx
*/

// Add support for the sx prop for consistency with the other branches.
const Anchor = styled('a')({});

interface NextLinkComposedProps
extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'>,
Omit<NextLinkProps, 'href' | 'as' | 'passHref' | 'onMouseEnter' | 'onClick' | 'onTouchStart'> {
to: NextLinkProps['href'];
linkAs?: NextLinkProps['as'];
}

const NextLinkComposed = React.forwardRef<HTMLAnchorElement, NextLinkComposedProps>(
function NextLinkComposed(props, ref) {
const {
to,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior = true,
locale,
...other
} = props;

return (
<NextLink
href={to}
prefetch={prefetch}
as={linkAs}
replace={replace}
scroll={scroll}
shallow={shallow}
passHref
locale={locale}
legacyBehavior={legacyBehavior}
>
<Anchor data-no-markdown-link="true" ref={ref} {...other} />
</NextLink>
);
},
);

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/api-reference/next/link
const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(function Link(props, ref) {
const {
activeClassName = 'active',
as,
className: classNameProps,
href,
legacyBehavior,
linkAs: linkAsProp,
locale,
noLinkStyle,
prefetch,
replace,
role, // Link don't have roles.
scroll,
shallow,
...other
} = props;

const nextPathname = usePathname();

const pathname = typeof href === 'string' ? href : href.pathname;
const className = clsx(classNameProps, {
[activeClassName]: nextPathname && nextPathname === pathname && activeClassName,
});

const isExternal =
typeof href === 'string' && (href.indexOf('http') === 0 || href.indexOf('mailto:') === 0);
const userLanguage = useUserLanguage();

if (isExternal) {
if (noLinkStyle) {
return <Anchor className={className} href={href} ref={ref} {...other} />;
}

return <MuiLink className={className} href={href} ref={ref} {...other} />;
}

let linkAs = linkAsProp || as || (href as string);
if (
userLanguage !== 'en' &&
pathname &&
pathname.indexOf('/') === 0 &&
!LANGUAGES_IGNORE_PAGES(pathname) &&
!pathname.startsWith(`/${userLanguage}/`)
) {
linkAs = `/${userLanguage}${linkAs}`;
}

const nextjsProps = {
to: href,
linkAs,
replace,
scroll,
shallow,
legacyBehavior,
prefetch,
locale,
};

if (noLinkStyle) {
return <NextLinkComposed className={className} ref={ref} {...nextjsProps} {...other} />;
}

return (
<MuiLink
component={NextLinkComposed}
className={className}
ref={ref}
{...nextjsProps}
{...other}
/>
);
});

export default Link;
Loading