Skip to content

Commit

Permalink
[docs] Add Templates listing to examples page (#4449)
Browse files Browse the repository at this point in the history
  • Loading branch information
bharatkashyap authored Nov 22, 2024
1 parent e1378c2 commit 79c6bf2
Show file tree
Hide file tree
Showing 10 changed files with 258 additions and 31 deletions.
8 changes: 7 additions & 1 deletion docs/data/toolpad/core/introduction/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ title: Examples

<!-- #default-branch-switch -->

{{"component": "modules/components/ExamplesGrid/ExamplesGrid.tsx", "examplesFile": "core-examples.ts"}}
## Featured Examples

{{"component": "modules/components/Examples/FeaturedExamples.tsx", "examplesFile": "core-examples.ts"}}

## Other Examples

{{"component": "modules/components/Examples/ExamplesGrid.tsx", "examplesFile": "core-examples.ts", "reverse": true}}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ This collection includes apps that showcase connecting to APIs, adding custom co

If you're interested in how we, at MUI, use Toolpad Studio to build internal apps, check out the [blog post](https://mui.com/blog/toolpad-use-cases/).

{{"component": "modules/components/ExamplesGrid/ExamplesGrid.tsx", "examplesFile": "studio-examples.ts"}}
{{"component": "modules/components/Examples/ExamplesGrid.tsx", "examplesFile": "studio-examples.ts"}}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,11 @@ import IconButton from '@mui/material/IconButton';
import Tooltip from '@mui/material/Tooltip';
import Stack from '@mui/material/Stack';
import SvgIcon from '@mui/material/SvgIcon';
import type { Example } from './types';

interface Example {
title: string;
description: string;
src: string;
srcDark?: string;
href: string;
source: string;
codesandbox?: string;
stackblitz?: string;
}

interface TemplatesProps {
interface ExamplesGridProps {
examplesFile: string;
reverse?: boolean;
}

function StackBlitzIcon() {
Expand All @@ -43,16 +34,23 @@ function CodeSandboxIcon() {
);
}

function Templates({ examplesFile }: TemplatesProps) {
function ExamplesGrid(props: ExamplesGridProps) {
const [examples, setExamples] = React.useState<Example[]>([]);

React.useEffect(() => {
const importExamples = async () => {
const exampleContent = await import(`./${examplesFile}`);
setExamples(exampleContent.default);
let exampleContent = await import(`./${props.examplesFile}`);

exampleContent = exampleContent
.default()
.filter((example: Example) => example.featured !== true);
if (props.reverse) {
setExamples(exampleContent.reverse());
}
setExamples(exampleContent);
};
importExamples();
}, [examplesFile]);
}, [props.examplesFile, props.reverse]);
const docsTheme = useTheme();

return (
Expand Down Expand Up @@ -121,11 +119,11 @@ function Templates({ examplesFile }: TemplatesProps) {
Source
</Button>
<Stack direction="row" spacing={1}>
{example.codesandbox && (
{example.codeSandbox && (
<Tooltip title="Edit in CodeSandbox">
<IconButton
component="a"
href={example.codesandbox}
href={example.codeSandbox}
target="_blank"
rel="noopener noreferrer"
size="small"
Expand All @@ -134,11 +132,11 @@ function Templates({ examplesFile }: TemplatesProps) {
</IconButton>
</Tooltip>
)}
{example.stackblitz && (
{example.stackBlitz && (
<Tooltip title="Edit in StackBlitz">
<IconButton
component="a"
href={example.stackblitz}
href={example.stackBlitz}
target="_blank"
rel="noopener noreferrer"
size="small"
Expand All @@ -157,4 +155,4 @@ function Templates({ examplesFile }: TemplatesProps) {
);
}

export default Templates;
export default ExamplesGrid;
208 changes: 208 additions & 0 deletions docs/src/modules/components/Examples/FeaturedExamples.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Card from '@mui/material/Card';
import CardMedia from '@mui/material/CardMedia';
import Chip from '@mui/material/Chip';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import Link from '@mui/material/Link';
import Tooltip from '@mui/material/Tooltip';
import Skeleton from '@mui/material/Skeleton';
import Typography from '@mui/material/Typography';
import SvgIcon from '@mui/material/SvgIcon';
import Visibility from '@mui/icons-material/Visibility';
import CodeRoundedIcon from '@mui/icons-material/CodeRounded';
import OpenInNewRoundedIcon from '@mui/icons-material/OpenInNewRounded';
import { useTheme } from '@mui/material/styles';
import { sxChip } from 'docs/src/modules/components/AppNavDrawerItem';
import type { Example } from './types';

interface FeaturedExamplesProps {
examplesFile: string;
}

export default function FeaturedExamples(props: FeaturedExamplesProps) {
const [examples, setExamples] = React.useState<Example[]>([]);
const [loading, setLoading] = React.useState(true);

React.useEffect(() => {
const importExamples = async () => {
setLoading(true);
let exampleContent = await import(`./${props.examplesFile}`);
exampleContent = exampleContent
.default()
.filter((example: Example) => example.featured === true);
setExamples(exampleContent);
setLoading(false);
};
importExamples();
}, [props.examplesFile]);
const docsTheme = useTheme();
if (loading) {
return (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 4, mb: 4 }}>
{[1].map((key) => (
<Box key={key} sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Skeleton variant="text" width={200} height={32} />
<Skeleton variant="text" width="100%" height={24} />
<Skeleton
variant="rectangular"
width="100%"
height={400}
sx={{ aspectRatio: '16 / 9', borderRadius: 1 }}
/>
</Box>
))}
</Box>
);
}

return (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 4, mb: 4 }}>
{examples.map((example: Example) => {
const computedSrc =
docsTheme?.palette?.mode === 'dark' && example.srcDark ? example.srcDark : example.src;
return (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }} key={example.title}>
<Typography component="h3" variant="h6" sx={{ fontWeight: 'semiBold' }}>
{example.title}
{example.new && <Chip label="NEW" sx={sxChip('success')} />}
</Typography>
<Typography variant="body2" sx={{ color: 'text.secondary', mb: 2 }}>
{example.description}
</Typography>
<Card
variant="outlined"
sx={{
height: '100%',
display: 'flex',
flexDirection: 'column',
borderColor: 'divider',
}}
>
<Box
sx={{
position: 'relative',
'&:hover > .MuiCardMedia-root': {
filter: 'blur(4px)',
},
'&:hover > .MuiButtonBase-root': {
opacity: 1,
},
}}
>
<CardMedia
component="img"
image={computedSrc}
title={example.title}
sx={{
aspectRatio: '16 / 9',
objectPosition: 'top',
transition: 'filter 0.3s',
}}
/>
<Button
variant="text"
endIcon={<OpenInNewRoundedIcon />}
component={Link}
href={example.href}
target="_blank"
data-ga-event-category="toolpad-core-template"
data-ga-event-label={example.title}
data-ga-event-action="preview-img"
sx={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
opacity: 0,
transition: 'opacity 0.5s ease',
backgroundColor: 'background.paper',
'&:hover': {
backgroundColor: 'background.default',
},
}}
>
See live preview
</Button>
</Box>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
p: 2,
borderTop: '1px solid',
borderColor: 'divider',
}}
>
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: 1,
}}
>
{example.stackBlitz ? (
<Tooltip title="Edit in StackBlitz">
<IconButton
color="primary"
size="small"
aria-label="StackBlitz playground"
data-ga-event-category="toolpad-core-template"
data-ga-event-action="stackblitz"
onClick={() => {
window.open(example.stackBlitz, '_blank', 'noopener,noreferrer');
}}
>
<SvgIcon viewBox="0 0 19 28">
<path d="M8.13378 16.1087H0L14.8696 0L10.8662 11.1522L19 11.1522L4.13043 27.2609L8.13378 16.1087Z" />
</SvgIcon>
</IconButton>
</Tooltip>
) : null}
{example.codeSandbox ? (
<Tooltip title="Edit in CodeSandbox">
<IconButton
color="primary"
size="small"
aria-label="CodeSandbox playground"
data-ga-event-category="toolpad-core-template"
data-ga-event-action="codesandbox"
onClick={() => {
window.open(example.codeSandbox, '_blank', 'noopener,noreferrer');
}}
>
<SvgIcon viewBox="0 0 1080 1080">
<path d="M755 140.3l0.5-0.3h0.3L512 0 268.3 140h-0.3l0.8 0.4L68.6 256v512L512 1024l443.4-256V256L755 140.3z m-30 506.4v171.2L548 920.1V534.7L883.4 341v215.7l-158.4 90z m-584.4-90.6V340.8L476 534.4v385.7L300 818.5V646.7l-159.4-90.6zM511.7 280l171.1-98.3 166.3 96-336.9 194.5-337-194.6 165.7-95.7L511.7 280z" />
</SvgIcon>
</IconButton>
</Tooltip>
) : null}
<Tooltip title="See source code">
<IconButton component="a" href={example.source} color="primary" size="small">
<CodeRoundedIcon />
</IconButton>
</Tooltip>
</Box>
<Button
component="a"
href={example.href}
size="small"
variant="outlined"
color="primary"
startIcon={<Visibility sx={{ mr: 0.5 }} />}
data-ga-event-category="toolpad-core-template"
data-ga-event-label={example.title}
data-ga-event-action="preview-img"
sx={{ alignSelf: 'self-start' }}
>
Live preview
</Button>
</Box>
</Card>
</Box>
);
})}
</Box>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,15 @@ export default function examples() {
'https://codesandbox.io/s/github/mui/toolpad/tree/master/examples/core/auth-vite',
},
{
title: 'Custom theme with Auth.js and Next.js App router',
title: 'Functional Dashboard',
description:
'This app shows you how to get started using Toolpad Core with Next.js, Auth.js and customize the Material UI theme',
src: '/static/toolpad/docs/core/auth-next-themed.png',
srcDark: '/static/toolpad/docs/core/auth-next-themed-dark.png',
'This example shows you how to get started building a dashboard with Toolpad Core, Next.js app router, Auth.js and Material UI components in a customized theme',
src: '/static/toolpad/docs/core/functional-dashboard.png',
href: 'https://deploy-preview-4415--mui-toolpad-docs.netlify.app/toolpad/core/templates/nextjs-dashboard',
srcDark: '/static/toolpad/docs/core/functional-dashboard-dark.png',
source: 'https://github.com/mui/toolpad/tree/master/examples/core/auth-nextjs-themed',
featured: true,
new: true,
codesandbox:
'https://codesandbox.io/s/github/mui/toolpad/tree/master/examples/core/auth-nextjs-themed',
},
Expand Down
12 changes: 12 additions & 0 deletions docs/src/modules/components/Examples/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface Example {
title: string;
description: string;
src: string;
srcDark?: string;
href: string;
source: string;
codeSandbox?: string;
stackBlitz?: string;
new?: boolean;
featured?: boolean;
}
8 changes: 4 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 79c6bf2

Please sign in to comment.