feat: update mobile layout, fixes
This commit is contained in:
parent
6d72ac0a56
commit
bf0a411639
@ -1,7 +0,0 @@
|
|||||||
export function BlogWrapper({ children }: React.PropsWithChildren) {
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col items-center">
|
|
||||||
<div className="w-5/6 xl:w-1/2 2xl:w-1/3">{children}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
export function Notbyai() {
|
export function Notbyai() {
|
||||||
return (
|
return (
|
||||||
<div className="fixed m-3 bottom-0 right-0">
|
<div className="flex flex-col items-center">
|
||||||
<a href="https://notbyai.fyi/" target="_blank">
|
<a href="https://notbyai.fyi/" target="_blank">
|
||||||
<img src="https://user-images.githubusercontent.com/62137266/225653923-a69103f5-b318-4e52-9ea1-95b61d388366.svg" />
|
<img src="https://user-images.githubusercontent.com/62137266/225653923-a69103f5-b318-4e52-9ea1-95b61d388366.svg" />
|
||||||
</a>
|
</a>
|
||||||
|
1
app/hooks/index.ts
Normal file
1
app/hooks/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from "./useFormattedDate";
|
4
app/hooks/useFormattedDate.ts
Normal file
4
app/hooks/useFormattedDate.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export function useFormattedDate(_date: string) {
|
||||||
|
const date = new Date(_date)
|
||||||
|
return `${date.getUTCFullYear()}/${date.getUTCMonth()}/${date.getUTCDate()}`
|
||||||
|
}
|
@ -13,7 +13,6 @@ import {
|
|||||||
import stylesheet from "~/tailwind.css?url";
|
import stylesheet from "~/tailwind.css?url";
|
||||||
import { Body } from "./components/Body";
|
import { Body } from "./components/Body";
|
||||||
import { LinkWrapper } from "./components/LinkWrapper";
|
import { LinkWrapper } from "./components/LinkWrapper";
|
||||||
import { Notbyai } from "./components/Notbyai";
|
|
||||||
|
|
||||||
export const links: LinksFunction = () => [
|
export const links: LinksFunction = () => [
|
||||||
{ rel: "stylesheet", href: stylesheet },
|
{ rel: "stylesheet", href: stylesheet },
|
||||||
@ -29,7 +28,7 @@ export const meta: MetaFunction = () => [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
property: "viewport",
|
property: "viewport",
|
||||||
content: "width=device-width,initial-scale=1",
|
content: "width=device-width,initial-scale=1.0",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -42,7 +41,6 @@ export default function App() {
|
|||||||
</head>
|
</head>
|
||||||
<Body>
|
<Body>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
<Notbyai />
|
|
||||||
<ScrollRestoration />
|
<ScrollRestoration />
|
||||||
<Scripts />
|
<Scripts />
|
||||||
</Body>
|
</Body>
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
import { IconContext } from "react-icons/lib";
|
import { IconContext } from "react-icons/lib";
|
||||||
import { MdEmail } from "react-icons/md";
|
import { MdEmail } from "react-icons/md";
|
||||||
import { LinkWrapper } from "~/components/LinkWrapper";
|
import { LinkWrapper } from "~/components/LinkWrapper";
|
||||||
|
import { Notbyai } from "~/components/Notbyai";
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
return (
|
return (
|
||||||
@ -22,6 +23,7 @@ export default function Index() {
|
|||||||
<span className="animate-blink">|</span>
|
<span className="animate-blink">|</span>
|
||||||
</div>
|
</div>
|
||||||
<nav className="pt-5 flex justify-center flex-wrap">
|
<nav className="pt-5 flex justify-center flex-wrap">
|
||||||
|
<Notbyai />
|
||||||
<IconContext.Provider
|
<IconContext.Provider
|
||||||
value={{ color: "yellow", className: "p-2", size: "3em" }}
|
value={{ color: "yellow", className: "p-2", size: "3em" }}
|
||||||
>
|
>
|
||||||
|
@ -3,7 +3,7 @@ import { Link, useLoaderData } from "@remix-run/react";
|
|||||||
import { getMDXComponent } from "mdx-bundler/client/index.js";
|
import { getMDXComponent } from "mdx-bundler/client/index.js";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FaEdit } from "react-icons/fa";
|
import { FaEdit } from "react-icons/fa";
|
||||||
import { BlogWrapper } from "~/components/BlogWrapper";
|
import { Notbyai } from "~/components/Notbyai";
|
||||||
import { Title } from "~/components/Title";
|
import { Title } from "~/components/Title";
|
||||||
import { getMdxFile } from "~/utils/posts.server";
|
import { getMdxFile } from "~/utils/posts.server";
|
||||||
|
|
||||||
@ -54,22 +54,26 @@ export default function () {
|
|||||||
const MdxComponent = React.useMemo(() => getMDXComponent(code), [code]);
|
const MdxComponent = React.useMemo(() => getMDXComponent(code), [code]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-5">
|
<div className="space-y-6">
|
||||||
<Title>{title}</Title>
|
<Title>{title}</Title>
|
||||||
<BlogWrapper>
|
<div className="flex flex-col items-center">
|
||||||
<div className="dark:prose-invert prose-a:no-underline prose-a:font-bold prose-a:text-[#ffff00] prose-p:text-[#d6d6d6]">
|
<div className="space-y-5 sm:w-full sm:px-5 lg:w-5/6 xl:w-1/3">
|
||||||
<MdxComponent />
|
<div className="dark:prose-invert prose-a:no-underline prose-a:font-bold prose-a:text-[#ffff00] prose-p:text-[#d6d6d6]">
|
||||||
</div>
|
<MdxComponent />
|
||||||
<Link
|
|
||||||
to={`https://github.com/nullndr/website/edit/main/posts/${file}.mdx`}
|
|
||||||
className="hover:text-[#ffff00]"
|
|
||||||
>
|
|
||||||
<div className="flex justify-end items-center space-x-2 pb-5">
|
|
||||||
<FaEdit />
|
|
||||||
<div className="font-bold">Typo?</div>
|
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
<div>
|
||||||
</BlogWrapper>
|
<Link
|
||||||
|
to={`https://github.com/nullndr/website/edit/main/posts/${file}.mdx`}
|
||||||
|
className="hover:text-[#ffff00]"
|
||||||
|
>
|
||||||
|
<div className="flex justify-end items-center space-x-2 pb-5">
|
||||||
|
<FaEdit />
|
||||||
|
<div className="font-bold">Typo?</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
import { Link } from "@remix-run/react";
|
|
||||||
import { BlogWrapper } from "~/components/BlogWrapper";
|
|
||||||
|
|
||||||
type PostProps = {
|
|
||||||
filename: string;
|
|
||||||
title: string;
|
|
||||||
published: string;
|
|
||||||
description: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Post({ title, description, filename, published }: PostProps) {
|
|
||||||
return (
|
|
||||||
<BlogWrapper>
|
|
||||||
<Link to={filename}>
|
|
||||||
<div className="p-5 text-center font-bold border-gray-600 border-2 rounded-lg">
|
|
||||||
<span className="text-[#ffff00] hover:text-[#e6c2bf] text-2xl">
|
|
||||||
{title}
|
|
||||||
</span>
|
|
||||||
<span className="ml-2">{`(${new Date(
|
|
||||||
published,
|
|
||||||
).toLocaleDateString()})`}</span>
|
|
||||||
{description && <div className="mt-5 text-xl">{description}</div>}
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
</BlogWrapper>
|
|
||||||
);
|
|
||||||
}
|
|
26
app/routes/blog._index/PostPreview.tsx
Normal file
26
app/routes/blog._index/PostPreview.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { SerializeFrom } from "@remix-run/node";
|
||||||
|
import { Link } from "@remix-run/react";
|
||||||
|
import { useFormattedDate } from "~/hooks";
|
||||||
|
import type { Post } from "~/utils/posts.server";
|
||||||
|
|
||||||
|
export function PostPreview({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
filename,
|
||||||
|
published,
|
||||||
|
}: SerializeFrom<Post>) {
|
||||||
|
const formattedDate = useFormattedDate(published);
|
||||||
|
return (
|
||||||
|
<div className="sm:w-full sm:px-5 lg:w-5/6 xl:w-1/3">
|
||||||
|
<Link to={filename}>
|
||||||
|
<div className="space-y-4 py-3 text-center font-bold border-gray-600 border-2 rounded-lg">
|
||||||
|
<div className="text-[#ffff00] text-2xl">{title}</div>
|
||||||
|
<div className="text-xl">{description}</div>
|
||||||
|
<div>
|
||||||
|
<time>{formattedDate}</time>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -2,7 +2,7 @@ import { useLoaderData } from "@remix-run/react";
|
|||||||
import { Title } from "~/components/Title";
|
import { Title } from "~/components/Title";
|
||||||
import { findPosts } from "~/utils/posts.server";
|
import { findPosts } from "~/utils/posts.server";
|
||||||
import { EmptyState } from "./EmptyState";
|
import { EmptyState } from "./EmptyState";
|
||||||
import { Post } from "./Post";
|
import { PostPreview } from "./PostPreview";
|
||||||
|
|
||||||
export const handle = {
|
export const handle = {
|
||||||
to: "/",
|
to: "/",
|
||||||
@ -15,11 +15,16 @@ export const loader = () => {
|
|||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
const posts = useLoaderData<typeof loader>();
|
const posts = useLoaderData<typeof loader>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-5">
|
<div className="space-y-6">
|
||||||
<Title>Here I blog about whatever get my attention</Title>
|
<Title>Here I blog about whatever get my attention</Title>
|
||||||
{posts.length > 0 ? (
|
{posts.length > 0 ? (
|
||||||
posts.map((post, i) => <Post {...post} key={i} />)
|
<div className="flex flex-col items-center space-y-5">
|
||||||
|
{posts.map((post, i) => (
|
||||||
|
<PostPreview {...post} key={i} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<EmptyState />
|
<EmptyState />
|
||||||
)}
|
)}
|
||||||
|
@ -4,9 +4,8 @@ import { LinkWrapper } from "~/components/LinkWrapper";
|
|||||||
import { useMatch } from "./useMatch";
|
import { useMatch } from "./useMatch";
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
const { handle } = useMatch() as unknown as {
|
const { handle } = useMatch();
|
||||||
handle: { to: string; text: string };
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<LinkWrapper>
|
<LinkWrapper>
|
||||||
|
@ -8,5 +8,7 @@ export function useMatch() {
|
|||||||
throw new Error("Bruh");
|
throw new Error("Bruh");
|
||||||
}
|
}
|
||||||
|
|
||||||
return { handle, ...rest};
|
return { handle, ...rest } as unknown as {
|
||||||
|
handle: { to: string; text: string };
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import path from "path";
|
|||||||
type FrontMatter = {
|
type FrontMatter = {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
published: string;
|
published: Date;
|
||||||
isFeatured: boolean;
|
isFeatured: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -34,11 +34,14 @@ export const getMdxFile = async (file: string) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Post = Omit<FrontMatter, "published"> & {
|
||||||
|
filename: string;
|
||||||
|
published: string;
|
||||||
|
};
|
||||||
|
|
||||||
export const findPosts = async () => {
|
export const findPosts = async () => {
|
||||||
const files = await readdir(`posts`);
|
const files = await readdir(`posts`);
|
||||||
const posts: (FrontMatter & {
|
const posts: Post[] = [];
|
||||||
filename: string;
|
|
||||||
})[] = [];
|
|
||||||
for (const file of files.filter((file) => file.endsWith(".mdx"))) {
|
for (const file of files.filter((file) => file.endsWith(".mdx"))) {
|
||||||
const filePath = path.join(process.cwd(), `posts/${file}`);
|
const filePath = path.join(process.cwd(), `posts/${file}`);
|
||||||
const { frontmatter } = await bundleMDX<FrontMatter>({
|
const { frontmatter } = await bundleMDX<FrontMatter>({
|
||||||
@ -61,8 +64,9 @@ export const findPosts = async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
posts.push({
|
posts.push({
|
||||||
filename: file.replace(".mdx", ""),
|
|
||||||
...frontmatter,
|
...frontmatter,
|
||||||
|
filename: file.replace(".mdx", ""),
|
||||||
|
published: frontmatter.published.toISOString(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user