Add projects page

Update project item styles

Update project page layout

Fix about page loading backgourd color wrong in dark mode

Add project page
This commit is contained in:
DefectingCat
2022-10-24 17:49:54 +08:00
parent 076d386abd
commit 112dcc73b4
10 changed files with 176 additions and 33 deletions

View File

@ -1,4 +1,5 @@
{
"semi": true,
"singleQuote": true
"singleQuote": true,
"editorconfig": true
}

View File

@ -21,11 +21,16 @@ const txtMenu = [
},
{
id: 2,
name: 'Projects',
path: '/projects',
},
{
id: 3,
name: 'Gists',
path: '/gists',
},
{
id: 3,
id: 4,
name: 'About',
path: '/about',
},

View File

@ -15,12 +15,10 @@ const Tab = ({ defaultValue, children }: Props) => {
// Pass current selected state to child
const childrenWithProps = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, {
showContent: child.props.value === currentValue,
});
}
return child;
if (!React.isValidElement(child)) return child;
return React.cloneElement(child, {
showContent: child.props.value === currentValue,
});
});
return (

View File

@ -1,12 +1,6 @@
import classNames from 'classnames';
import useCopyToClipboard from 'lib/hooks/useCopyToClipboard';
import {
DetailedHTMLProps,
HTMLAttributes,
lazy,
Suspense,
useRef,
} from 'react';
import { DetailedHTMLProps, HTMLAttributes, lazy, useRef } from 'react';
const CopyButton = lazy(() => import('components/post/CopyButton'));
@ -34,9 +28,7 @@ const Pre = ({ ...rest }: Props) => {
{...props}
>
{children}
<Suspense fallback>
<CopyButton onCopy={handleCopy} />
</Suspense>
<CopyButton onCopy={handleCopy} />
</pre>
</>
);

View File

@ -0,0 +1,54 @@
import classNames from 'classnames';
import { Project } from 'pages/projects';
import { Children, cloneElement, isValidElement } from 'react';
import { VscGithubInverted } from 'react-icons/vsc';
type ProjectCardProps = {
project: Project;
icon?: React.ReactElement<{ className?: string }>;
};
const ProjectCard = ({ project, icon }: ProjectCardProps) => {
const Icon = Children.map(icon, (child) => {
if (!isValidElement(child)) return child;
return cloneElement(child, {
className: 'w-8 h-8',
});
});
return (
<>
<div
className={classNames(
'py-3 px-4 rounded-lg bg-slate-100',
'hover:bg-slate-200',
'transition-all duration-300',
'flex items-center cursor-pointer',
'justify-between'
)}
>
{Icon ? Icon : <VscGithubInverted className="w-8 h-8" />}
<a
href={project.url}
className="w-[calc(100%_-_40px)]"
target="_blank"
rel="noreferrer"
>
<h2 className="text-xl">{project.name}</h2>
<span
className={classNames(
'overflow-hidden break-keep text-ellipsis',
'whitespace-nowrap inline-block',
'w-[inherit]'
)}
>
{project.description}
</span>
</a>
</div>
</>
);
};
export default ProjectCard;

View File

@ -10,12 +10,11 @@ import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader';
import { NextPageWithLayout } from 'types';
const Loading = dynamic(() => import('components/RUA/loading/RUALoading'));
const MainLayout = dynamic(() => import('layouts/MainLayout'));
const rotationY = 0.4;
const rotationX = 0.2;
const MainLayout = dynamic(() => import('layouts/MainLayout'));
const About: NextPageWithLayout = () => {
const [loading, setLoading] = useState(true);
const [showLoading, setShowLoading] = useState(true);
@ -174,7 +173,7 @@ const About: NextPageWithLayout = () => {
'absolute top-0 left-0',
'items-center flex justify-center',
'w-full h-full transition-all duration-500',
'bg-white',
'bg-white dark:bg-rua-gray-900',
loading ? 'opacity-1' : 'opacity-0'
)}
>

View File

@ -1,15 +1,15 @@
import { allPostsPath, readSinglePost } from 'lib/posts';
import { GetStaticPaths, GetStaticProps, InferGetStaticPropsType } from 'next';
import { serialize } from 'next-mdx-remote/serialize';
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote';
import components from 'components/mdx/components';
import data from 'data/mdxData';
import rehypePrism from '@mapbox/rehype-prism';
import remarkGfm from 'remark-gfm';
import rehypeSlug from 'rehype-slug';
import dynamic from 'next/dynamic';
import { generateToc, SingleToc } from 'lib/utils';
import components from 'components/mdx/components';
import PostToc from 'components/post/PostToc';
import data from 'data/mdxData';
import { allPostsPath, readSinglePost } from 'lib/posts';
import { generateToc, SingleToc } from 'lib/utils';
import { GetStaticPaths, GetStaticProps, InferGetStaticPropsType } from 'next';
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote';
import { serialize } from 'next-mdx-remote/serialize';
import dynamic from 'next/dynamic';
import rehypeSlug from 'rehype-slug';
import remarkGfm from 'remark-gfm';
const Footer = dynamic(() => import('components/Footer'));
const HeadBar = dynamic(() => import('components/NavBar'));

94
pages/projects.tsx Normal file
View File

@ -0,0 +1,94 @@
import classNames from 'classnames';
import { GetStaticProps, InferGetStaticPropsType } from 'next';
import dynamic from 'next/dynamic';
import { ReactElement } from 'react';
import { SiGitea } from 'react-icons/si';
const MainLayout = dynamic(() => import('layouts/MainLayout'));
const ProjectCard = dynamic(() => import('components/pages/ProjectCard'));
const Projects = ({
projects,
selfHosts,
}: InferGetStaticPropsType<typeof getStaticProps>) => {
return (
<>
<main className="max-w-4xl px-8 py-8 mx-auto lg:px-0">
<div>
{/* Git projects */}
<div>
<h1 className="mb-4 text-2xl">Projects</h1>
</div>
<div
className={classNames(
'grid grid-cols-1 lg:grid-cols-3',
'md:grid-cols-2 gap-5'
)}
>
{projects.map((item) => (
<ProjectCard key={item.id} project={item} />
))}
</div>
</div>
<div className="mt-6">
<div>
<h1 className="mb-4 text-2xl">Seft Hosts</h1>
</div>
<div
className={classNames(
'grid grid-cols-1 lg:grid-cols-3',
'md:grid-cols-2 gap-5'
)}
>
{selfHosts.map((item) => (
<ProjectCard icon={<SiGitea />} key={item.id} project={item} />
))}
</div>
</div>
</main>
</>
);
};
export type Project = {
id: number;
name: string;
description: string;
url: string;
};
export const getStaticProps: GetStaticProps<{
projects: Project[];
selfHosts: Project[];
}> = async () => {
const projects = [
{
id: 0,
name: '3d-globe',
description: 'A 3d globe made by three.js.',
url: 'https://github.com/DefectingCat/3d-globe',
},
];
const selfHosts = [
{
id: 0,
name: 'Gitea',
description: 'Selfhost git.',
url: 'https://git.rua.plus/',
},
];
return {
props: {
projects,
selfHosts,
},
};
};
Projects.getLayout = function getLayout(page: ReactElement) {
return <MainLayout>{page}</MainLayout>;
};
export default Projects;