Files
Saxon FletcherandClaude Opus 5.5 d3f3903b69 feat(studio): show recent notebooks on the project homepage (#50825)
<img width="1758" height="1252" alt="image"
src="https://github.com/user-attachments/assets/6f5ff072-9b47-4265-924d-0ca22368f6cb"
/>


## What

With the Explorer feature preview on, the homepage **Reports** row
becomes a **Notebooks** row showing the four newest notebooks.

- Advisor and notebook cards share a new `HomeCard` layout: same height
and header, content anchored to the bottom, 3-line description clamp.
- Notebook cards show the cell count, the creation date, and an
**Analyze** button that starts the same chat as the Explorer notebook
tab (`useAnalyzeNotebook`, now shared by both).
- Advisor lint cards replace the assistant dropdown with two icon
buttons: **Ask Assistant** and **Copy prompt**. Copy prompt shows a
check after copying.
- The empty state matches the Reports one.

## How to test

1. Turn on the Explorer feature preview and open a project's Home page.
2. The Reports row should be replaced by Notebooks. With no notebooks,
you should see the empty state; **Create your first notebook** opens a
new notebook in Explorer.
3. Click a notebook card to open it. Click **Analyze** to start an
assistant chat. It should be disabled on a notebook with no cells.
4. On an advisor lint card, check **Ask Assistant** opens the assistant
with the lint prompt, and **Copy prompt** copies it and briefly shows a
check.
5. Turn the preview off: the Reports row comes back unchanged.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Project home now displays up to four notebooks, with options to create
a notebook, open it, and see its cell count.
* Start an AI analysis of a notebook directly from its card or from the
notebook explorer. Analysis is unavailable for notebooks without cells.
  * Advisor cards now offer a one-click AI chat and a copyable prompt.
* Project home shows notebooks when the Explorer preview is enabled;
otherwise, it continues to show custom reports.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 16:41:56 +08:00

64 lines
2.2 KiB
TypeScript

import Link from 'next/link'
import type { ReactNode } from 'react'
import { Card, CardContent, CardHeader, CardTitle, cn } from 'ui'
// Stretches the title's link/button over the whole card so the card is clickable without
// nesting the header actions inside an interactive element
const STRETCHED_TARGET_CLASS =
'block w-full truncate text-left outline-hidden after:absolute after:inset-0 after:rounded-lg focus-visible:after:ring-1 focus-visible:after:ring-foreground-muted'
type HomeCardTarget = { href: string; onClick?: never } | { onClick: () => void; href?: never }
type HomeCardProps = HomeCardTarget & {
icon: ReactNode
label: string
title: string
/** Rendered on the right of the header, above the card's click target */
actions?: ReactNode
description?: ReactNode
meta?: ReactNode
className?: string
}
/** Fixed-height card used by the project homepage rows, with its content anchored to the bottom */
export const HomeCard = ({
href,
onClick,
icon,
label,
title,
actions,
description,
meta,
className,
}: HomeCardProps) => (
<Card className={cn('relative h-64 flex flex-col', className)}>
<CardHeader className="border-b-0 shrink-0 flex flex-row gap-2 space-y-0 justify-between items-center">
<div className="flex flex-row items-center gap-3">
{icon}
<CardTitle className="text-foreground-light">{label}</CardTitle>
</div>
{actions && <div className="relative z-10 flex items-center gap-1">{actions}</div>}
</CardHeader>
<CardContent className="pt-0 flex flex-col justify-end flex-1 min-h-0">
<h3 className="mb-1">
{href !== undefined ? (
<Link href={href} className={STRETCHED_TARGET_CLASS}>
{title}
</Link>
) : (
<button type="button" tabIndex={0} onClick={onClick} className={STRETCHED_TARGET_CLASS}>
{title}
</button>
)}
</h3>
{description && (
<div className="text-sm text-muted-foreground line-clamp-3 [&_a]:relative [&_a]:z-10">
{description}
</div>
)}
{meta && <p className="mt-3 text-sm text-foreground-lighter">{meta}</p>}
</CardContent>
</Card>
)