Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
28 changes: 10 additions & 18 deletions app/components/[category]/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,30 @@ import {
TabsTrigger,
} from "@/components/motion/tabs";
import { NewBadge } from "@/components/app/docs/new-badge";
import { ComponentCard } from "@/components/app/docs/component-card";
import { ComponentAbout } from "@/components/app/docs/component-about";
import { ComponentGuide } from "@/components/app/docs/component-guide";
import { CopyPage } from "@/components/app/docs/copy-page";
import {
PreviewExpand,
PreviewExpandStage,
PreviewExpandToggle,
PreviewReplayToggle,
} from "@/components/app/docs/preview-fullscreen";
import { JsonLd } from "@/components/app/analytics/json-ld";
import { getPreview, previews } from "@/components/previews";
import { pageUrlFor, withSignature } from "@/lib/signature";
import { readSourceFile } from "@/lib/source-files";
import { getComponentProps } from "@/lib/props-extractor";
import { componentAbout } from "@/lib/component-about";
import { componentDates } from "@/lib/component-dates";
import { findNativeComponent } from "@/lib/native";
import { PlatformSwitch } from "@/components/app/docs/native/platform-switch";
import { RelatedSection } from "@/components/app/docs/related-section";
import { PagePager } from "@/components/app/docs/page-pager";
import {
breadcrumbJsonLd,
componentJsonLd,
componentKeywords,
componentMetaDescription,
componentSeoTitle,
faqJsonLd,
relatedComponents,
} from "@/lib/seo";

Expand Down Expand Up @@ -165,7 +163,6 @@ export default async function ComponentPage({
creditUrl?.searchParams.set("ref", "beui");

const nativeComponent = findNativeComponent(comp.slug);
const about = componentAbout[comp.slug];
const webContent = (
<>
{comp.examples?.length ? (
Expand Down Expand Up @@ -232,9 +229,6 @@ export default async function ComponentPage({
{ name: comp.name, path: componentPath(cat.slug, comp.slug) },
]),
componentJsonLd(cat, comp),
...(about
? [faqJsonLd(componentPath(cat.slug, comp.slug), about.faq)]
: []),
]}
/>
<div id="overview" className="scroll-mt-24">
Expand Down Expand Up @@ -266,9 +260,6 @@ export default async function ComponentPage({
componentName={comp.name}
/>
</div>
<p className="mt-2 max-w-2xl text-muted-foreground">
{comp.description}
</p>
</div>

{/* Wide screens pick the platform from the right sidebar. */}
Expand Down Expand Up @@ -296,7 +287,6 @@ export default async function ComponentPage({
</Link>
) : null}
<RelatedSection related={related} />
{about ? <ComponentAbout name={comp.name} about={about} /> : null}

{comp.credit ? (
<section className="mt-12 border-t border-border pt-8">
Expand All @@ -321,6 +311,7 @@ export default async function ComponentPage({
}).format(new Date(`${dates.updatedAt}T00:00:00Z`))}
</time>
</p>
<PagePager category={cat.slug} slug={comp.slug} />
</div>
);
}
Expand Down Expand Up @@ -360,11 +351,6 @@ async function ExampleBlock({
{example.file.split("/").pop()}
</code>
</div>
{example.description ? (
<p className="mb-4 text-sm text-muted-foreground">
{example.description}
</p>
) : null}
<div id={`${example.slug}-preview`} className="scroll-mt-24">
<PreviewExpand stageId={`${example.slug}-stage`}>
<Tabs defaultValue="preview" variant="pill">
Expand Down Expand Up @@ -392,8 +378,11 @@ async function ExampleBlock({
Code
</TabsTrigger>
</TabsList>
<div className="flex items-center gap-2">
<PreviewReplayToggle />
<PreviewExpandToggle />
</div>
</div>
<TabsContent value="preview" className="mt-4">
<PreviewExpandStage className="flex min-h-[260px] items-center justify-center py-10">
{Preview ? <Preview /> : null}
Expand Down Expand Up @@ -491,7 +480,10 @@ async function DefaultTabs({
Code
</TabsTrigger>
</TabsList>
<PreviewExpandToggle />
<div className="flex items-center gap-2">
<PreviewReplayToggle />
<PreviewExpandToggle />
</div>
</div>
<TabsContent value="preview" className="mt-4">
<PreviewExpandStage className="flex min-h-[320px] items-center justify-center py-10">
Expand Down
38 changes: 7 additions & 31 deletions app/components/[category]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { categoryPath } from "@/lib/component-paths";
import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { findCategory, registry } from "@/lib/registry";
import { ComponentCard } from "@/components/app/docs/component-card";
import { LandingComponentCard } from "@/components/app/landing/landing-component-card";
import { JsonLd } from "@/components/app/analytics/json-ld";
import { isComponentNew } from "@/lib/component-status";
import { breadcrumbJsonLd, categoryJsonLd } from "@/lib/seo";
Expand Down Expand Up @@ -218,17 +218,9 @@ export default async function CategoryPage({
{group.description}
</p>
</div>
<div className="mt-5 grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3">
<div className="mt-5 grid grid-cols-1 gap-4 [grid-auto-rows:17rem] sm:grid-cols-2 2xl:grid-cols-3">
{group.components.map((comp) => (
<ComponentCard
key={comp.slug}
categorySlug={cat.slug}
slug={comp.slug}
name={comp.name}
description={comp.description}
badge={comp.badge}
launchedAt={comp.launchedAt}
/>
<LandingComponentCard key={comp.slug} component={comp} category={cat.slug} />
))}
</div>
</section>
Expand All @@ -241,17 +233,9 @@ export default async function CategoryPage({
<h2 className="font-display text-xs font-medium uppercase text-muted-foreground">
New
</h2>
<div className="mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3">
<div className="mt-4 grid grid-cols-1 gap-4 [grid-auto-rows:17rem] sm:grid-cols-2 2xl:grid-cols-3">
{newComponents.map((comp) => (
<ComponentCard
key={comp.slug}
categorySlug={cat.slug}
slug={comp.slug}
name={comp.name}
description={comp.description}
badge={comp.badge}
launchedAt={comp.launchedAt}
/>
<LandingComponentCard key={comp.slug} component={comp} category={cat.slug} />
))}
</div>
</section>
Expand All @@ -262,17 +246,9 @@ export default async function CategoryPage({
<h2 className="font-display text-xs font-medium uppercase text-muted-foreground">
{content.allLabel}
</h2>
<div className="mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3">
<div className="mt-4 grid grid-cols-1 gap-4 [grid-auto-rows:17rem] sm:grid-cols-2 2xl:grid-cols-3">
{components.map((comp) => (
<ComponentCard
key={comp.slug}
categorySlug={cat.slug}
slug={comp.slug}
name={comp.name}
description={comp.description}
badge={comp.badge}
launchedAt={comp.launchedAt}
/>
<LandingComponentCard key={comp.slug} component={comp} category={cat.slug} />
))}
</div>
</section>
Expand Down
4 changes: 2 additions & 2 deletions app/docs/motion-patterns/motion-patterns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ function RecipeCard({ recipe }: { recipe: Recipe }) {
<div className="grid gap-6 lg:grid-cols-[minmax(0,0.8fr)_minmax(18rem,1.2fr)] lg:items-stretch lg:gap-8">
<div className="flex flex-col">
<div className="flex items-center gap-3">
<span className="flex size-8 items-center justify-center rounded-lg border border-border bg-card">
<span className="flex size-8 items-center justify-center rounded-full border border-border bg-card">
<Icon className="size-3.5 text-foreground" aria-hidden="true" />
</span>
<span className="font-mono text-[10px] uppercase tracking-wider text-muted-foreground">
Expand Down Expand Up @@ -752,7 +752,7 @@ function RecipeDemoView({ demo }: { demo: RecipeDemo }) {
transition: { duration: 0.12, ease: EASE_OUT },
}}
transition={{ duration: 0.18, ease: EASE_OUT }}
className="mt-2 rounded-xl bg-background p-4 text-sm text-foreground"
className="mt-2 rounded-lg bg-background p-4 text-sm text-foreground"
>
{tab === "Preview" ? "Live component view" : "Copy-ready source"}
</motion.div>
Expand Down
7 changes: 2 additions & 5 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

@custom-variant dark (&:where(.dark, .dark *));

/* Height of the announcement strip above the header. The page and sidebars
add it to the header offset; set it to 0px when there's no strip. */
/* Height of the announcement strip above the header. The strip sits in the
page flow and scrolls away; the header and sidebars stick below it. */
:root {
--announcement-h: 2.5rem;
}
Expand Down Expand Up @@ -79,9 +79,6 @@
);
}

/* Color theme presets (full token sets) are injected at runtime from
lib/themes.ts via PreferencesProvider, keyed by data-theme on <html>. */

@theme inline {
/* Strong easing curves shared across every component. */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
Expand Down
19 changes: 8 additions & 11 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { GoogleAnalytics } from "@/components/app/analytics/google-analytics";
import { ThemeProvider } from "@/components/app/chrome/theme-provider";
import { PreferencesProvider } from "@/components/app/preferences/preferences-provider";
import { PreferencesPanel } from "@/components/app/preferences/preferences-panel";
import { SiteHeader } from "@/components/app/chrome/site-header";
import { NativeStrip } from "@/components/app/chrome/native-strip";
import { SiteFrame } from "@/components/app/chrome/site-frame";
import { KeyboardShortcuts } from "@/components/app/chrome/keyboard-shortcuts";
import { JsonLd } from "@/components/app/analytics/json-ld";
Expand Down Expand Up @@ -129,15 +128,13 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<body className="min-h-screen antialiased">
<JsonLd data={siteJsonLd()} />
<ThemeProvider>
<PreferencesProvider>
<KeyboardShortcuts />
<SiteHeader />
<main className="pt-[calc(3.5rem+var(--announcement-h))]">
<SiteFrame>{children}</SiteFrame>
</main>
<PreferencesPanel />
<GoogleAnalytics measurementId={googleAnalyticsId} />
</PreferencesProvider>
<KeyboardShortcuts />
<NativeStrip />
<SiteHeader />
<main>
<SiteFrame>{children}</SiteFrame>
</main>
<GoogleAnalytics measurementId={googleAnalyticsId} />
</ThemeProvider>
</body>
</html>
Expand Down
50 changes: 50 additions & 0 deletions components/app/chrome/docs-footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import Image from "next/image";
import Link from "next/link";

const LINKS = [
{ href: "https://github.com/starc007/ui-components", label: "GitHub" },
{ href: "/changelog", label: "Changelog" },
{ href: "/changelog/rss.xml", label: "RSS" },
{ href: "/docs/ai-agents", label: "For coding agents" },
{ href: "/llms.txt", label: "llms.txt" },
{ href: "/sponsors", label: "Sponsor" },
];

/** Slim footer that closes the content column on docs pages. */
export function DocsFooter() {
return (
<footer className="mt-16 flex flex-col gap-4 border-t border-border pt-6 pb-2 text-sm text-muted-foreground sm:flex-row sm:items-center sm:justify-between">
<Link prefetch={false} href="/" className="inline-flex items-center gap-2 text-foreground">
<Image
src="/beui-mark.png"
alt=""
width={20}
height={20}
className="size-5 rounded-md"
/>
<span className="font-medium">beUI</span>
<span className="hidden text-muted-foreground md:inline">The motion toolkit for React & Next.js</span>
</Link>
<nav aria-label="Footer">
<ul className="flex flex-wrap gap-x-4 gap-y-2">
{LINKS.map((item) => {
const external = item.href.startsWith("http");
return (
<li key={item.href}>
<Link
prefetch={false}
href={item.href}
target={external ? "_blank" : undefined}
rel={external ? "noreferrer noopener" : undefined}
className="transition-colors hover:text-foreground"
>
{item.label}
</Link>
</li>
);
})}
</ul>
</nav>
</footer>
);
}
1 change: 1 addition & 0 deletions components/app/chrome/mobile-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function MobileNav() {
<Button
variant="ghost"
size="icon"
className="rounded-full"
onClick={() => setOpen(true)}
aria-label="Open navigation"
aria-haspopup="dialog"
Expand Down
4 changes: 2 additions & 2 deletions components/app/chrome/native-strip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const PRESALE_URL =

/**
* Site-wide announcement above the header: beUI Native is free, and points to
* the beUI Pro for mobile presale. Its height is --announcement-h, which the
* page and sidebars add to the header offset.
* the beUI Pro for mobile presale. It sits in the page flow above the sticky
* header, so it scrolls away with the page.
*/
export function NativeStrip() {
const waveGradientId = useId();
Expand Down
4 changes: 2 additions & 2 deletions components/app/chrome/page-transition.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ export function PageTransition({ children }: { children: ReactNode }) {
initial={
mounted
? shouldTranslate
? { opacity: 0, y: 24 }
? { opacity: 0, y: 8 }
: { opacity: 0 }
: false
}
animate={shouldTranslate ? { opacity: 1, y: 0 } : { opacity: 1 }}
transition={{ duration: shouldTranslate ? 0.6 : 0.2, ease: EASE_OUT }}
transition={{ duration: shouldTranslate ? 0.25 : 0.2, ease: EASE_OUT }}
onAnimationComplete={() => {
const el = ref.current;
if (!el) return;
Expand Down
Loading
Loading