Skip to content

Commit 4f4220d

Browse files
committed
feat: homepage, footer & improve features section
1 parent 9f829b2 commit 4f4220d

9 files changed

Lines changed: 160 additions & 106 deletions

File tree

apps/website/src/app/docs/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import SidebarLinks from "@/components/docs/sidebar-links";
44
import { Sidebar, SidebarPageContent } from "@/components/ui/sidebar";
55
import Header from "@/components/header";
66
import SidebarMobileMenu from "@/components/docs/sidebar-mobile-menu";
7+
import Footer from "@/components/footer";
78

89
interface DocsLayoutProps {
910
children: ReactNode;
@@ -19,6 +20,7 @@ const DocsLayout = ({ children }: DocsLayoutProps) => {
1920
<SidebarPageContent>
2021
<SidebarMobileMenu />
2122
{children}
23+
<Footer />
2224
</SidebarPageContent>
2325
</>
2426
);

apps/website/src/app/page.tsx

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import type { Metadata } from "next";
2+
3+
import { globals } from "@/globals";
14
import { getDocument } from "@/utils/docs";
25
import { notFound } from "next/navigation";
36

@@ -8,22 +11,44 @@ import Container from "@/components/container";
811
import Header from "@/components/header";
912
import Footer from "@/components/footer";
1013

14+
export async function generateMetadata(): Promise<Metadata> {
15+
const websiteUrl = "https://code-blocks.pheralb.dev";
16+
const data = getDocument({
17+
folder: "general",
18+
document: "home",
19+
});
20+
return {
21+
openGraph: {
22+
type: "website",
23+
url: websiteUrl,
24+
title: `${data?.title} - ${globals.title}`,
25+
description: data?.description,
26+
siteName: websiteUrl,
27+
images: [
28+
{
29+
url: new URL(`/api/docs/og?document=home&folder=general`, websiteUrl),
30+
},
31+
],
32+
},
33+
};
34+
}
35+
1136
const Home = () => {
1237
const document = getDocument({
1338
folder: "general",
1439
document: "home",
1540
});
1641
if (!document) return notFound();
1742
return (
18-
<>
19-
<Container>
20-
<Header layout="app" />
21-
<Article className="pb-14">
22-
<MDX code={document.mdx} />
23-
</Article>
24-
</Container>
25-
<Footer />
26-
</>
43+
<main className="pb-4">
44+
<Container>
45+
<Header layout="app" />
46+
<Article className="pb-8">
47+
<MDX code={document.mdx} />
48+
</Article>
49+
</Container>
50+
<Footer />
51+
</main>
2752
);
2853
};
2954

apps/website/src/components/docs/sidebar-links.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { SidebarLinkItem } from "@/components/docs/sidebar-link-item";
1010
const SidebarLinks = () => {
1111
const pathname = usePathname();
1212
return (
13-
<nav className="flex flex-col space-y-6">
13+
<nav className="flex flex-1 flex-col space-y-6 pb-6">
1414
{SidebarLinksData.map((data) => (
1515
<SidebarGroup title={data.groupTitle} key={data.groupTitle}>
1616
{data.items.map((link) => {
Lines changed: 70 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,84 @@
11
import type { ReactNode } from "react";
22

33
import { cn } from "@/utils/cn";
4-
import { PaletteIcon } from "lucide-react";
5-
6-
import { ShadcnUI } from "@/components/ui/svgs/shadcn";
7-
import { Card, CardHeader } from "@/components/ui/card";
8-
9-
export default function Features() {
10-
return (
11-
<section>
12-
<div className="mx-auto grid gap-4 pt-6 lg:grid-cols-2">
13-
<FeatureCard>
14-
<CardHeader>
15-
<CardHeading
16-
icon={<PaletteIcon size={20} />}
17-
title="Customizable"
18-
description="Copy, extend and modify all components and utilities"
19-
/>
20-
</CardHeader>
21-
</FeatureCard>
22-
<FeatureCard>
23-
<CardHeader>
24-
<CardHeading
25-
icon={<ShadcnUI width={20} height={20} />}
26-
title="shadcn/ui"
27-
description="Add components to your shadcn registry"
28-
/>
29-
</CardHeader>
30-
</FeatureCard>
31-
</div>
32-
</section>
33-
);
34-
}
4+
import { BoxIcon, ClipboardIcon, HighlighterIcon } from "lucide-react";
5+
import { ShadcnUI } from "@/components/ui/svgs";
356

367
interface FeatureCardProps {
37-
children: ReactNode;
38-
className?: string;
8+
icon: ReactNode;
9+
title: string;
10+
description: string;
11+
children?: ReactNode;
3912
}
4013

41-
const FeatureCard = ({ children, className }: FeatureCardProps) => (
42-
<Card className={cn("group relative rounded-none", className)}>
43-
<CardDecorator />
44-
{children}
45-
</Card>
46-
);
14+
const iconSize = 24;
15+
const iconClassName = cn("text-neutral-600 dark:text-neutral-400");
4716

4817
const CardDecorator = () => (
4918
<>
50-
<span className="absolute -top-px -left-px block size-2 border-t-2 border-l-2 border-neutral-900 dark:border-neutral-600"></span>
51-
<span className="absolute -top-px -right-px block size-2 border-t-2 border-r-2 border-neutral-900 dark:border-neutral-600"></span>
52-
<span className="absolute -bottom-px -left-px block size-2 border-b-2 border-l-2 border-neutral-900 dark:border-neutral-600"></span>
53-
<span className="absolute -right-px -bottom-px block size-2 border-r-2 border-b-2 border-neutral-900 dark:border-neutral-600"></span>
19+
<span className="absolute -top-px -left-px block size-2 border-t-2 border-l-2 border-neutral-400 dark:border-neutral-600"></span>
20+
<span className="absolute -top-px -right-px block size-2 border-t-2 border-r-2 border-neutral-400 dark:border-neutral-600"></span>
21+
<span className="absolute -bottom-px -left-px block size-2 border-b-2 border-l-2 border-neutral-400 dark:border-neutral-600"></span>
22+
<span className="absolute -right-px -bottom-px block size-2 border-r-2 border-b-2 border-neutral-400 dark:border-neutral-600"></span>
5423
</>
5524
);
5625

57-
interface CardHeadingProps {
58-
icon: ReactNode
59-
title: string;
60-
description: string;
61-
}
26+
const FeatureCard = ({
27+
icon,
28+
title,
29+
description,
30+
children,
31+
}: FeatureCardProps) => {
32+
return (
33+
<div
34+
className={cn(
35+
"group relative",
36+
"not-prose flex flex-col",
37+
"border border-neutral-200 p-8 dark:border-neutral-800",
38+
)}
39+
>
40+
<CardDecorator />
41+
<div className="mb-4">{icon}</div>
42+
<h2 className="font-headings text-2xl font-semibold tracking-tight text-black dark:text-white">
43+
{title}
44+
</h2>
45+
<p className="mt-2 text-pretty text-neutral-600 dark:text-neutral-400">
46+
{description}
47+
</p>
48+
{children}
49+
</div>
50+
);
51+
};
6252

63-
const CardHeading = ({ icon: Icon, title, description }: CardHeadingProps) => (
64-
<div className="p-3">
65-
<span className="flex items-center gap-2 text-neutral-500 dark:text-neutral-400">
66-
{Icon}
67-
{title}
68-
</span>
69-
<p className="mt-4 text-2xl font-semibold">{description}</p>
70-
</div>
71-
);
53+
export default function Features() {
54+
return (
55+
<section className="mx-auto grid gap-4 pt-6 lg:grid-cols-2">
56+
<FeatureCard
57+
icon={<ClipboardIcon size={iconSize} className={iconClassName} />}
58+
title="Copy-Paste"
59+
description="Copy the components and utilities you need and paste them into your project. It's 100% yours."
60+
/>
61+
<FeatureCard
62+
icon={<HighlighterIcon className={iconClassName} />}
63+
title="Syntax Highlighter"
64+
description="Use Shiki or Sugar-High to add syntax highlighting to your code blocks."
65+
/>
66+
<FeatureCard
67+
icon={<BoxIcon size={iconSize} className={iconClassName} />}
68+
title="Blocks"
69+
description="Built-in components to extend your code blocks with extra content and interactivity."
70+
/>
71+
<FeatureCard
72+
icon={
73+
<ShadcnUI
74+
width={iconSize}
75+
height={iconSize}
76+
className={iconClassName}
77+
/>
78+
}
79+
title="shadcn/ui compatible"
80+
description="Add components & utilities using shadcn/ui CLI."
81+
/>
82+
</section>
83+
);
84+
}

apps/website/src/components/footer.tsx

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,47 @@
1-
import { cn } from "@/utils/cn";
2-
import Container from "./container";
3-
import { HeartIcon } from "lucide-react";
4-
import { ExternalLink } from "./ui/external-link";
1+
import { globals } from "@/globals";
2+
import { ExternalLink } from "@/components/ui/external-link";
3+
import { GitHub, XformerlyTwitter } from "@/components/ui/svgs";
4+
import Container from "@/components/container";
5+
import { ArrowUpRightIcon, SparklesIcon } from "lucide-react";
6+
7+
const Links = [
8+
{
9+
title: "GitHub",
10+
href: globals.githubUrl,
11+
icon: <GitHub height={14} />,
12+
},
13+
{
14+
title: "Twitter",
15+
href: globals.twitterUrl,
16+
icon: <XformerlyTwitter height={14} />,
17+
},
18+
];
519

620
const Footer = () => {
721
return (
8-
<footer
9-
className={cn(
10-
"md:fixed md:bottom-0",
11-
"flex w-full items-center py-4.5",
12-
"text-sm text-neutral-600 dark:text-neutral-400",
13-
)}
14-
>
15-
<Container className="flex items-center justify-between space-x-1.5">
16-
<div className="flex items-center space-x-1">
17-
<p>Made with</p>
18-
<HeartIcon className="size-4 text-red-500" />
19-
<p>
20-
by{" "}
21-
<ExternalLink
22-
href="https://pheralb.dev"
23-
className="underline decoration-neutral-400 underline-offset-4 transition-colors hover:text-black hover:decoration-black dark:decoration-neutral-600 dark:hover:text-white dark:hover:decoration-white"
24-
>
25-
pheralb
26-
</ExternalLink>
27-
</p>
22+
<footer className="py-6">
23+
<Container>
24+
<div className="flex flex-wrap justify-between gap-6">
25+
<ExternalLink
26+
href="https://pheralb.dev/"
27+
className="font-headings order-last flex items-center text-center text-sm text-neutral-600 transition-colors hover:text-neutral-950 md:order-first dark:text-neutral-400 dark:hover:text-neutral-50"
28+
>
29+
<SparklesIcon size={14} className="mr-2" />
30+
<span>Created by pheralb</span>
31+
<ArrowUpRightIcon size={12} className="ml-1" />
32+
</ExternalLink>
33+
<div className="order-first flex flex-wrap justify-center gap-6 text-sm md:order-last">
34+
{Links.map((link, index) => (
35+
<ExternalLink
36+
key={index}
37+
href={link.href}
38+
className="flex items-center space-x-2 text-neutral-600 transition-colors hover:text-neutral-950 dark:text-neutral-400 dark:hover:text-neutral-50"
39+
>
40+
{link.icon}
41+
<span>{link.title}</span>
42+
</ExternalLink>
43+
))}
44+
</div>
2845
</div>
2946
</Container>
3047
</footer>

apps/website/src/components/hero.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,18 @@ const Hero = () => {
1818
)}
1919
>
2020
<div className="flex flex-col items-center justify-center space-y-2">
21-
<h1 className="font-headings text-dark text-4xl font-semibold tracking-tight lg:text-5xl dark:text-white">
21+
<h1 className="font-headings text-4xl font-semibold tracking-tight text-neutral-950 lg:text-5xl dark:text-neutral-50">
2222
Build beautiful code blocks
2323
</h1>
2424
<p className="font-medium text-neutral-500 dark:text-neutral-400">
25-
Show code snippets with syntax highlighting in your React project.
25+
Ready to use UI components and utilities to show your snippets
26+
beautifully.
2627
</p>
2728
</div>
2829
<div
2930
className={cn(
3031
"flex flex-col items-center justify-center space-y-2 md:flex-row md:space-y-0 md:space-x-2",
31-
"animate-in fill-mode-backwards fade-in slide-in-from-bottom-4 duration-500 delay-100",
32+
"animate-in fill-mode-backwards fade-in slide-in-from-bottom-4 delay-100 duration-500",
3233
)}
3334
>
3435
<Link

apps/website/src/components/ui/card.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function CardHeader({ className, ...props }: ComponentProps<"div">) {
1919
<div
2020
data-slot="card-header"
2121
className={cn(
22-
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start px-4 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
22+
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
2323
className,
2424
)}
2525
{...props}
@@ -64,13 +64,7 @@ function CardAction({ className, ...props }: ComponentProps<"div">) {
6464
}
6565

6666
function CardContent({ className, ...props }: ComponentProps<"div">) {
67-
return (
68-
<div
69-
data-slot="card-content"
70-
className={cn(className)}
71-
{...props}
72-
/>
73-
);
67+
return <div data-slot="card-content" className={cn(className)} {...props} />;
7468
}
7569

7670
function CardFooter({ className, ...props }: ComponentProps<"div">) {

apps/website/src/components/ui/sidebar.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ const Sidebar = ({ children, position }: SidebarProps) => {
3131
"hidden md:block",
3232
"overflow-x-hidden overflow-y-auto",
3333
"border-neutral-200 dark:border-neutral-800",
34-
"bg-neutral-100 dark:bg-neutral-900",
34+
"bg-neutral-50 dark:bg-neutral-900",
3535
position === "left" ? "left-0 border-r" : "right-0 border-l",
3636
)}
3737
>
38-
<div className="overscroll-none py-6">{children}</div>
38+
<div className="flex h-full flex-col space-y-6 overscroll-none py-6">
39+
{children}
40+
</div>
3941
</aside>
4042
);
4143
};

apps/website/src/docs/home.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
2-
title: Code Blocks
3-
description: A code-block UI component. Built with Shiki.
2+
title: Build beautiful code blocks
3+
description: Ready to use UI components and utilities to show your snippets beautifully.
44
category: [General]
55
---
66

0 commit comments

Comments
 (0)