mirror of
https://github.com/DefectingCat/DefectingCat.github.io
synced 2025-07-16 01:01:38 +00:00
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:
@ -9,4 +9,4 @@ indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = false
|
||||
insert_final_newline = false
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"semi": true,
|
||||
"singleQuote": true
|
||||
"singleQuote": true,
|
||||
"editorconfig": true
|
||||
}
|
||||
|
@ -58,4 +58,4 @@ EXPOSE 3000
|
||||
|
||||
ENV PORT 3000
|
||||
|
||||
CMD ["node", "server.js"]
|
||||
CMD ["node", "server.js"]
|
||||
|
@ -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',
|
||||
},
|
||||
|
@ -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 (
|
||||
|
@ -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>
|
||||
</>
|
||||
);
|
||||
|
54
components/pages/ProjectCard.tsx
Normal file
54
components/pages/ProjectCard.tsx
Normal 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;
|
@ -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'
|
||||
)}
|
||||
>
|
||||
|
@ -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
94
pages/projects.tsx
Normal 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;
|
Reference in New Issue
Block a user