Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
86e3369
feat(ui): add blueprint hero illustrations
pasqualevitiello Oct 24, 2026
589575f
feat(ui): add matching 404 blueprint illustration
pasqualevitiello Oct 24, 2026
eec7ad0
Use selected recombination and interrupted-route illustrations
pasqualevitiello Oct 24, 2026
4c60fc6
Keep hero layouts in pages and center the 404 illustration
pasqualevitiello Oct 24, 2026
386baf2
Restore the original 404 back arrow and hover treatment
pasqualevitiello Oct 24, 2026
6132efe
Restore Particles search in the hero and refine page headings
pasqualevitiello Oct 24, 2026
ac544c0
Match the Chat heading to the main and Particles pages
pasqualevitiello Oct 24, 2026
6be016b
Match the Particles hero divider to the home page
pasqualevitiello Oct 24, 2026
7a20d2f
Add decorative markers to Chat section intersections
pasqualevitiello Oct 24, 2026
de14ac0
Refine the home and Particles hero copy
pasqualevitiello Oct 24, 2026
ee4b296
Mention Cal.com in the home hero description
pasqualevitiello Oct 24, 2026
481a498
Display the site footer on the 404 page
pasqualevitiello Oct 24, 2026
f54ce80
Hide home and Particles illustrations on smaller screens
pasqualevitiello Oct 24, 2026
25388e8
Add a third building block to the Particles illustration
pasqualevitiello Oct 24, 2026
bd177fc
Link Cal.com from the home hero description
pasqualevitiello Oct 24, 2026
986663b
Match Particles description width to the home hero
pasqualevitiello Oct 24, 2026
0c6baf4
Keep the Particles search popup below its field
pasqualevitiello Oct 24, 2026
49aae8e
Use a consistent background across the Chat page
pasqualevitiello Oct 24, 2026
009f342
Center Particles artwork and refine its construction grid
pasqualevitiello Oct 24, 2026
40c6c55
Let Particles copy determine hero spacing
pasqualevitiello Oct 24, 2026
2bddee7
Link the UI header logo to its own home page
pasqualevitiello Oct 24, 2026
d0eb46e
Adjust Particles illustration vertical margins
pasqualevitiello Oct 24, 2026
a9cde13
Match home illustration margins to Particles
pasqualevitiello Oct 24, 2026
54b8470
Reserve Particles search space during loading
pasqualevitiello Oct 24, 2026
0a46202
Simplify horizontal guides in the Particles illustration
pasqualevitiello Oct 24, 2026
993b65c
Set both hero illustration margins to lg:-my-12
pasqualevitiello Oct 24, 2026
fac8841
Cap hero copy columns consistently across UI pages
pasqualevitiello Oct 24, 2026
3b3a941
Increase desktop hero spacing across UI pages
pasqualevitiello Oct 24, 2026
b8fcf10
Offset the Chat hero demo into its vertical padding
pasqualevitiello Oct 24, 2026
dc77bb0
Tighten the 404 illustration vertical spacing
pasqualevitiello Oct 24, 2026
8ae9771
Reduce the Chat hero demo negative margin
pasqualevitiello Oct 24, 2026
e6d243f
Set Chat demo vertical margin to lg:-my-16
pasqualevitiello Oct 24, 2026
7a0eee5
feat(ui): animate the home, Particles, and 404 illustrations
pasqualevitiello Oct 25, 2026
338ddb8
fix(ui): remove illustration playback controls
pasqualevitiello Oct 25, 2026
426adbd
fix(ui): show the 404 illustration at native width
pasqualevitiello Oct 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 22 additions & 12 deletions apps/ui/app/chat/chat-showcase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ function InstallCommand({ command }: { command: string }) {
);
}

function SectionMarkers() {
return (
<div
aria-hidden="true"
className="container pointer-events-none absolute inset-0 z-50 before:absolute before:top-[-4.5px] before:-left-[11.5px] before:z-1 before:-ml-1 before:size-2 before:rounded-[2px] before:border before:border-border before:bg-popover before:bg-clip-padding before:shadow-xs after:absolute after:top-[-4.5px] after:-right-[11.5px] after:z-1 after:-mr-1 after:size-2 after:rounded-[2px] after:border after:border-border after:bg-background after:bg-clip-padding after:shadow-xs dark:after:bg-clip-border dark:before:bg-clip-border"
/>
);
}

function SectionHeading({
id,
title,
Expand Down Expand Up @@ -108,21 +117,21 @@ export function ChatShowcase() {
<ChatDemo
renderTriggers={(select) => (
<>
<section className="container grid items-center gap-12 py-14 md:grid-cols-2 md:gap-14 md:py-20 lg:gap-24">
<div className="flex min-w-0 flex-col items-start">
<section className="container grid items-center gap-12 py-14 md:grid-cols-2 md:gap-14 md:py-20 lg:gap-24 lg:py-28">
<div className="flex w-full min-w-0 max-w-xl flex-col items-start">
<Badge
variant="outline"
className="mb-6 h-7 gap-1.5 rounded-full px-2.5 text-xs shadow-xs/5 sm:h-7"
>
<MessagesSquareIcon aria-hidden="true" className="size-3.5" />
Chat UI
</Badge>
<h1 className="font-bold font-heading text-5xl leading-none tracking-tight lg:text-6xl xl:text-7xl">
<h1 className="text-balance font-bold font-heading text-[clamp(2.25rem,1.5rem+2.6vw,4rem)] leading-none [font-optical-sizing:auto] [font-synthesis:none] [font-variation-settings:'GEOM'_50]">
Make room
<br />
for conversation.
</h1>
<p className="mt-6 max-w-md text-pretty text-lg text-muted-foreground">
<p className="mt-6 text-pretty text-lg text-muted-foreground">
Chat components for React with replies, reactions, mentions, and
delivery states built in. Copy the source and make it yours.
</p>
Expand All @@ -149,7 +158,7 @@ export function ChatShowcase() {
Built with Base UI, Tailwind CSS, and Motion
</p>
</div>
<div className="mx-auto w-full max-w-md">
<div className="mx-auto w-full max-w-md lg:-my-16">
<Tabs defaultValue="direct" className="gap-5">
<TabsList
aria-label="Conversation type"
Expand All @@ -170,8 +179,9 @@ export function ChatShowcase() {

<section
aria-labelledby="chat-features"
className="border-t bg-muted/24"
className="relative border-t"
>
<SectionMarkers />
<div className="container py-14 md:py-20">
<SectionHeading
id="chat-features"
Expand All @@ -182,7 +192,8 @@ export function ChatShowcase() {
</div>
</section>

<section aria-labelledby="chat-states" className="border-t">
<section aria-labelledby="chat-states" className="relative border-t">
<SectionMarkers />
<div className="container py-14 md:py-20">
<SectionHeading
id="chat-states"
Expand All @@ -209,10 +220,8 @@ export function ChatShowcase() {
</div>
</section>

<section
aria-labelledby="chat-layouts"
className="border-t bg-muted/24"
>
<section aria-labelledby="chat-layouts" className="relative border-t">
<SectionMarkers />
<div className="container py-14 md:py-20">
<SectionHeading
id="chat-layouts"
Expand All @@ -223,7 +232,8 @@ export function ChatShowcase() {
</div>
</section>

<section aria-labelledby="chat-build" className="border-t">
<section aria-labelledby="chat-build" className="relative border-t">
<SectionMarkers />
<div className="container grid gap-12 py-14 md:grid-cols-[2fr_3fr] md:py-20">
<div className="flex flex-col items-start">
<h2
Expand Down
31 changes: 20 additions & 11 deletions apps/ui/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,37 @@
import {
PageHeader,
PageHeaderDescription,
PageHeaderHeading,
} from "@coss/ui/shared/page-header";
import { SiteFooter } from "@coss/ui/shared/site-footer";
import { RiArrowLeftLine } from "@remixicon/react";
import type { Metadata } from "next";
import Link from "next/link";
import { Button } from "@/registry/default/ui/button";
import { NotFoundBlueprint } from "@/components/not-found-blueprint";
import { NotFoundMotion } from "@/components/not-found-motion";

export const metadata: Metadata = {
description:
"The page you're looking for doesn't exist or may have been moved.",
"The page you’re looking for doesn’t exist or may have been moved.",
title: "Page Not Found",
};

export default function NotFound() {
return (
<div className="container w-full">
<PageHeader>
<PageHeaderHeading>Page Not Found</PageHeaderHeading>
<PageHeaderDescription>
The page you&apos;re looking for doesn&apos;t exist or may have been
moved.
<>
<section className="container flex w-full flex-1 flex-col items-center gap-5 py-10 text-center [font-optical-sizing:auto] [font-synthesis:none] md:py-14 lg:py-16">
<div className="pointer-events-none w-full max-w-140 select-none lg:-my-12">
<NotFoundMotion>
<NotFoundBlueprint />
</NotFoundMotion>
</div>
<PageHeaderHeading className="text-balance leading-[1.08] [font-variation-settings:'GEOM'_50]">
Page Not Found
</PageHeaderHeading>
<PageHeaderDescription className="max-w-md text-pretty">
The page you’re looking for doesn’t exist or may have been moved.
</PageHeaderDescription>
<div className="mt-4">
<div className="mt-1">
<Button
className="group"
render={
Expand All @@ -38,7 +46,8 @@ export default function NotFound() {
size="lg"
/>
</div>
</PageHeader>
</div>
</section>
<SiteFooter />
</>
);
}
39 changes: 28 additions & 11 deletions apps/ui/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
PageHeader,
PageHeaderDescription,
PageHeaderHeading,
} from "@coss/ui/shared/page-header";
Expand All @@ -18,27 +17,40 @@ import {
} from "@/registry/default/ui/card";
import { particles } from "@/registry/registry-particles";
import { getCategoryThumbnail } from "@/components/category-thumbnails";
import { PrimitivesBlueprint } from "@/components/primitives-blueprint";
import { PrimitivesMotion } from "@/components/primitives-motion";
import { categories } from "@/config/categories";
import { PAGES_NEW } from "@/lib/docs";

const description = "Built for developers and AI.";
const description =
"Accessible React components we use to build Cal.com, powered by Base UI and styled with Tailwind CSS. Designed for developers and AI, with source code you can make your own.";
const particleCount = particles.length;

export const metadata: Metadata = {
description,
title: "A new, modern UI component library built on top of Base UI - coss ui",
title: "A modern React UI component library – coss ui",
};

export default function Page() {
return (
<>
<div className="container w-full">
<PageHeader className="max-w-2xl *:items-start *:text-left">
<PageHeaderHeading>
A new, modern UI component library built on top of Base UI.
<section className="container grid w-full items-center gap-6 py-10 md:py-14 lg:grid-cols-2 lg:gap-10 lg:py-28 xl:gap-16">
<div className="flex w-full min-w-0 max-w-xl flex-col items-start gap-5 [font-optical-sizing:auto] [font-synthesis:none]">
<PageHeaderHeading className="text-balance text-[clamp(2.25rem,1.5rem+2.6vw,4rem)] leading-none [font-variation-settings:'GEOM'_50] lg:text-[clamp(2.25rem,1.5rem+2.6vw,4rem)]">
A modern React UI component library.
</PageHeaderHeading>
<PageHeaderDescription>{description}</PageHeaderDescription>
<div className="mt-2 flex gap-2">
<PageHeaderDescription>
Accessible React components we use to build{" "}
<Link
className="underline underline-offset-4 hover:text-foreground"
href="https://cal.com"
>
Cal.com
</Link>
, powered by Base UI and styled with Tailwind CSS. Designed for
developers and AI, with source code you can make your own.
</PageHeaderDescription>
<div className="mt-1 flex flex-wrap gap-2">
<Button render={<Link href="/docs" />} size="lg">
Get started
</Button>
Expand All @@ -50,8 +62,13 @@ export default function Page() {
Browse {particleCount} particles
</Button>
</div>
</PageHeader>
</div>
</div>
<div className="pointer-events-none mx-auto hidden w-full max-w-140 select-none lg:-my-24 lg:block">
<PrimitivesMotion>
<PrimitivesBlueprint />
</PrimitivesMotion>
</div>
</section>
<div className="relative before:absolute before:inset-x-0 before:top-0 before:h-px before:bg-border/64">
<div
aria-hidden="true"
Expand Down
54 changes: 37 additions & 17 deletions apps/ui/app/particles/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
PageHeader,
PageHeaderDescription,
PageHeaderHeading,
} from "@coss/ui/shared/page-header";
Expand All @@ -9,14 +8,16 @@ import { isValidRegistryCategory } from "@/registry/registry-categories";
import { particles } from "@/registry/registry-particles";
import { ParticlesDisplay } from "./particles-display";
import SearchContainer from "./search-container";
import { ParticlesBlueprint } from "@/components/particles-blueprint";
import { ParticlesMotion } from "@/components/particles-motion";

const particleCount = particles.length;

const description = `Discover ${particleCount} ready-to-use particles, the building blocks of your design system. Filter by category to find the perfect component for your project.`;
const description = `Explore ${particleCount} ready-to-use UI patterns built from coss ui components. Copy the code, customize the details, and make them part of your product.`;

export const metadata: Metadata = {
description,
title: "Browse Particles - coss ui",
title: "Build more with Particles – coss ui",
};

async function ParticlesDisplayServer({
Expand Down Expand Up @@ -58,19 +59,38 @@ export default function Page({
searchParams: Promise<{ tags?: string }>;
}) {
return (
<div className="container w-full">
<PageHeader className="*:pb-8!">
<PageHeaderHeading>Browse Particles</PageHeaderHeading>
<PageHeaderDescription className="max-w-2xl">
{description}
</PageHeaderDescription>
</PageHeader>
<Suspense>
<SearchContainer />
</Suspense>
<Suspense>
<ParticlesDisplayServer searchParams={searchParams} />
</Suspense>
</div>
<>
<section className="container grid w-full items-center gap-6 py-10 md:py-14 lg:grid-cols-2 lg:gap-10 lg:py-28 xl:gap-16">
<div className="flex w-full min-w-0 max-w-xl flex-col items-start gap-5 [font-optical-sizing:auto] [font-synthesis:none]">
<PageHeaderHeading className="text-balance text-[clamp(2.25rem,1.5rem+2.6vw,4rem)] leading-none [font-variation-settings:'GEOM'_50] lg:text-[clamp(2.25rem,1.5rem+2.6vw,4rem)]">
Build more with Particles.
</PageHeaderHeading>
<PageHeaderDescription className="text-pretty">
{description}
</PageHeaderDescription>
<div className="mt-2 min-h-12 w-full sm:min-h-11">
<Suspense>
<SearchContainer />
</Suspense>
</div>
</div>
<div className="pointer-events-none mx-auto hidden w-full max-w-140 select-none lg:-my-24 lg:block">
<ParticlesMotion>
<ParticlesBlueprint />
</ParticlesMotion>
</div>
</section>
<div className="relative before:absolute before:inset-x-0 before:top-0 before:h-px before:bg-border/64">
<div
aria-hidden="true"
className="container pointer-events-none absolute inset-0 z-50 before:absolute before:top-[-3.5px] before:-left-[11.5px] before:z-1 before:-ml-1 before:size-2 before:rounded-[2px] before:border before:border-border before:bg-popover before:bg-clip-padding before:shadow-xs after:absolute after:top-[-3.5px] after:-right-[11.5px] after:z-1 after:-mr-1 after:size-2 after:rounded-[2px] after:border after:border-border after:bg-background after:bg-clip-padding after:shadow-xs dark:after:bg-clip-border dark:before:bg-clip-border"
/>
<div className="container w-full pt-8 md:pt-12">
<Suspense>
<ParticlesDisplayServer searchParams={searchParams} />
</Suspense>
</div>
</div>
</>
);
}
12 changes: 5 additions & 7 deletions apps/ui/app/particles/search-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,10 @@ export default function SearchContainer() {
);

return (
<div className="mb-8 md:mb-12 lg:mb-16">
<SearchField
items={searchItems}
onItemsChange={updateSelectedItems}
selectedItems={selectedItems}
/>
</div>
<SearchField
items={searchItems}
onItemsChange={updateSelectedItems}
selectedItems={selectedItems}
/>
);
}
Loading
Loading