Move resource list and guide page titles into the shared topbar, introduce ListPageLayout for tighter spacing, and align knowledge edit with the prompt editor chrome. Co-authored-by: Cursor <cursoragent@cursor.com>
81 lines
1.5 KiB
TypeScript
81 lines
1.5 KiB
TypeScript
"use client";
|
|
|
|
import type { ReactNode } from "react";
|
|
|
|
import { cn } from "@/lib/utils";
|
|
|
|
import { PageTopbar, TopbarPortal } from "./topbar-portal";
|
|
|
|
export function ListPageLayout({
|
|
title,
|
|
description,
|
|
action,
|
|
children,
|
|
className,
|
|
}: {
|
|
title: string;
|
|
description?: ReactNode;
|
|
action?: ReactNode;
|
|
children: ReactNode;
|
|
className?: string;
|
|
}) {
|
|
const hasHeader = Boolean(description || action);
|
|
|
|
return (
|
|
<>
|
|
<TopbarPortal>
|
|
<PageTopbar title={title} />
|
|
</TopbarPortal>
|
|
|
|
<div
|
|
data-app-content="list"
|
|
className={cn(
|
|
"mx-auto flex w-full max-w-[1440px] flex-col gap-4",
|
|
className,
|
|
)}
|
|
>
|
|
{hasHeader && (
|
|
<div
|
|
className={cn(
|
|
"flex flex-col gap-3 sm:flex-row sm:items-center sm:gap-4",
|
|
description && action
|
|
? "sm:justify-between"
|
|
: action
|
|
? "sm:justify-end"
|
|
: "",
|
|
)}
|
|
>
|
|
{description && (
|
|
<p className="max-w-2xl text-sm leading-6 text-muted-foreground">
|
|
{description}
|
|
</p>
|
|
)}
|
|
{action}
|
|
</div>
|
|
)}
|
|
|
|
{children}
|
|
</div>
|
|
</>
|
|
);
|
|
}
|
|
|
|
export function ListPageSection({
|
|
children,
|
|
className,
|
|
}: {
|
|
children: ReactNode;
|
|
className?: string;
|
|
}) {
|
|
return (
|
|
<section
|
|
className={cn(
|
|
"rounded-2xl border border-hairline bg-card p-5 shadow-sm",
|
|
className,
|
|
)}
|
|
>
|
|
{children}
|
|
</section>
|
|
);
|
|
}
|