import * as React from 'react'; import { InferGetStaticPropsType } from 'next'; import { useRouter } from 'next/router'; import Avatar from '@mui/material/Avatar'; import AvatarGroup from '@mui/material/AvatarGroup'; import Box from '@mui/material/Box'; import Container from '@mui/material/Container'; import Divider from '@mui/material/Divider'; import Typography from '@mui/material/Typography'; import Paper from '@mui/material/Paper'; import Pagination from '@mui/material/Pagination'; import Button from '@mui/material/Button'; import KeyboardArrowRightRoundedIcon from '@mui/icons-material/KeyboardArrowRightRounded'; import Chip from '@mui/material/Chip'; import XIcon from '@mui/icons-material/X'; import GitHubIcon from '@mui/icons-material/GitHub'; import LinkedInIcon from '@mui/icons-material/LinkedIn'; import YouTubeIcon from '@mui/icons-material/YouTube'; import DiscordIcon from 'docs/src/icons/DiscordIcon'; import Head from 'docs/src/modules/components/Head'; import AppHeader from 'docs/src/layouts/AppHeader'; import AppFooter from 'docs/src/layouts/AppFooter'; import GradientText from 'docs/src/components/typography/GradientText'; import BrandingCssVarsProvider from 'docs/src/BrandingCssVarsProvider'; import { authors as AUTHORS } from 'docs/src/modules/components/TopLayoutBlog'; import HeroEnd from 'docs/src/components/home/HeroEnd'; import { Link } from '@mui/docs/Link'; import generateRssFeed from 'docs/scripts/generateRSSFeed'; import Section from 'docs/src/layouts/Section'; import SectionHeadline from 'docs/src/components/typography/SectionHeadline'; import { getAllBlogPosts, BlogPost } from 'docs/lib/sourcing'; export const getStaticProps = () => { const data = getAllBlogPosts(); generateRssFeed(data.allBlogPosts); return { props: data, }; }; function PostPreview(props: BlogPost) { return ( {props.tags.map((tag) => ( ({ height: 22, fontWeight: 'medium', fontSize: theme.typography.pxToRem(13), '& .MuiChip-label': { px: '6px', }, ...theme.applyDarkStyles({ color: (theme.vars || theme).palette.grey[200], }), })} /> ))} {props.title} {props.description} {props.authors && ( ({ mt: 2, mb: 1, alignSelf: 'flex-start', '& .MuiAvatar-circular': { width: 28, height: 28, fontSize: theme.typography.pxToRem(13), fontWeight: theme.typography.fontWeightSemiBold, color: (theme.vars || theme).palette.text.primary, border: `1px solid ${(theme.vars || theme).palette.divider}`, outline: '3px solid', outlineColor: '#FFF', backgroundColor: (theme.vars || theme).palette.grey[100], }, ...theme.applyDarkStyles({ '& .MuiAvatar-circular': { outlineColor: (theme.vars || theme).palette.primaryDark[900], backgroundColor: (theme.vars || theme).palette.primaryDark[700], }, }), })} > {(props.authors as Array).map((author) => ( ))} )} {props.authors && ( {props.authors .slice(0, 3) .map((userId) => { const name = AUTHORS[userId as keyof typeof AUTHORS]?.name; if (name) { if (props.authors && props.authors.length > 1) { // display only firstName return name.split(' ')[0]; } return name; } return userId; }) .join(', ')} {props.authors.length > 2 && ', and more.'} )} {props.date && ( {new Date(props.date).toDateString()} )} ); } const PAGE_SIZE = 7; export default function Blog(props: InferGetStaticPropsType) { const router = useRouter(); const postListRef = React.useRef(null); const [page, setPage] = React.useState(0); const [selectedTags, setSelectedTags] = React.useState>({}); const { allBlogPosts, tagInfo: rawTagInfo } = props; const [firstPost, secondPost, ...otherPosts] = allBlogPosts; const tagInfo = { ...rawTagInfo }; [firstPost, secondPost].forEach((post) => { post.tags.forEach((tag) => { if (tagInfo[tag]) { tagInfo[tag]! -= 1; } }); }); Object.entries(tagInfo).forEach(([tagName, tagCount]) => { if (tagCount === 0) { delete tagInfo[tagName]; } }); const filteredPosts = otherPosts.filter((post) => { if (Object.keys(selectedTags).length === 0) { return true; } return post.tags.some((tag) => { return Object.keys(selectedTags).includes(tag); }); }); const pageStart = page * PAGE_SIZE; const totalPage = Math.ceil(filteredPosts.length / PAGE_SIZE); const displayedPosts = filteredPosts.slice(pageStart, pageStart + PAGE_SIZE); const getTags = React.useCallback(() => { const { tags = '' } = router.query; return (typeof tags === 'string' ? tags.split(',') : tags || []) .map((str) => str.trim()) .filter((tag) => !!tag); }, [router.query]); React.useEffect(() => { const arrayTags = getTags(); const finalTags: Record = {}; arrayTags.forEach((tag) => { finalTags[tag] = true; }); setSelectedTags(finalTags); setPage(0); }, [getTags]); const removeTag = (tag: string) => { router.push( { query: { ...router.query, tags: getTags().filter((value) => value !== tag), }, }, undefined, { shallow: true }, ); }; return (
Stay in the loop with
the latest about MUI's products } />
{[firstPost, secondPost].map((post) => ( ({ p: 2, display: 'flex', flexDirection: 'column', backgroundImage: (theme.vars || theme).palette.gradients.radioSubtle, boxShadow: '0 4px 12px rgba(170, 180, 190, 0.2)', ...theme.applyDarkStyles({ background: (theme.vars || theme).palette.primaryDark[900], backgroundImage: (theme.vars || theme).palette.gradients.radioSubtle, boxShadow: '0 4px 12px rgba(0, 0, 0, 0.4)', }), })} > {post.image && ( )} ))} Posts{' '} {Object.keys(selectedTags).length ? ( tagged as{' '} "{Object.keys(selectedTags)[0]}" ) : ( '' )} Filter posts by tag {Object.keys(tagInfo).map((tag) => { const selected = !!selectedTags[tag]; return ( { postListRef.current?.scrollIntoView(); removeTag(tag); }, } : { label: tag, onClick: () => { postListRef.current?.scrollIntoView(); router.push( { query: { ...router.query, tags: tag, }, }, undefined, { shallow: true }, ); }, })} size="small" /> ); })} Want to hear more from us? Get up to date with everything MUI-related through our social media: svg': { mr: 1 } }}> GitHub X Discord LinkedIn Youtube
{displayedPosts.map((post) => ( ))} { setPage(value - 1); postListRef.current?.scrollIntoView(); }} sx={{ mt: 1, mb: 4 }} />
); }