diff --git a/.editorconfig b/.editorconfig
index ebe51d3..95405c1 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -9,4 +9,4 @@ indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
-insert_final_newline = false
\ No newline at end of file
+insert_final_newline = false
diff --git a/.prettierrc.json b/.prettierrc.json
index 937375d..81d0180 100644
--- a/.prettierrc.json
+++ b/.prettierrc.json
@@ -1,4 +1,5 @@
{
"semi": true,
- "singleQuote": true
+ "singleQuote": true,
+ "editorconfig": true
}
diff --git a/Dockerfile b/Dockerfile
index fa56e14..dc5ee33 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -58,4 +58,4 @@ EXPOSE 3000
ENV PORT 3000
-CMD ["node", "server.js"]
\ No newline at end of file
+CMD ["node", "server.js"]
diff --git a/components/NavBar.tsx b/components/NavBar.tsx
index 27041c6..c09cdf3 100644
--- a/components/NavBar.tsx
+++ b/components/NavBar.tsx
@@ -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',
},
diff --git a/components/RUA/tab/index.tsx b/components/RUA/tab/index.tsx
index 7a10210..9dd2110 100644
--- a/components/RUA/tab/index.tsx
+++ b/components/RUA/tab/index.tsx
@@ -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 (
diff --git a/components/mdx/Pre.tsx b/components/mdx/Pre.tsx
index 270ad05..57ff559 100644
--- a/components/mdx/Pre.tsx
+++ b/components/mdx/Pre.tsx
@@ -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}
-
-
-
+
>
);
diff --git a/components/pages/ProjectCard.tsx b/components/pages/ProjectCard.tsx
new file mode 100644
index 0000000..e88efc6
--- /dev/null
+++ b/components/pages/ProjectCard.tsx
@@ -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 (
+ <>
+
+ >
+ );
+};
+
+export default ProjectCard;
diff --git a/pages/about.tsx b/pages/about.tsx
index 706ac82..aa9601a 100644
--- a/pages/about.tsx
+++ b/pages/about.tsx
@@ -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'
)}
>
diff --git a/pages/p/[slug].tsx b/pages/p/[slug].tsx
index 31c2fdf..e87f8e9 100644
--- a/pages/p/[slug].tsx
+++ b/pages/p/[slug].tsx
@@ -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'));
diff --git a/pages/projects.tsx b/pages/projects.tsx
new file mode 100644
index 0000000..3543e85
--- /dev/null
+++ b/pages/projects.tsx
@@ -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) => {
+ return (
+ <>
+
+
+ {/* Git projects */}
+
+
Projects
+
+
+ {projects.map((item) => (
+
+ ))}
+
+
+
+
+
+
Seft Hosts
+
+
+ {selfHosts.map((item) => (
+
} key={item.id} project={item} />
+ ))}
+
+
+
+ >
+ );
+};
+
+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 {page};
+};
+
+export default Projects;