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
118 changes: 62 additions & 56 deletions apps/web/src/pages/library-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,15 @@ function PreviewPane({
}

/**
* Artifact gallery with dense cards (kind badge, title, owner · updated)
* and an in-stage preview when a row is selected. Real data only.
* The Files stage: a row list of everything this workbench owns, with an
* in-stage preview when a row is selected. Real data only.
*
* Every control the page owns — the workbench lens, the name filter, sort,
* the rows/grid toggle, Upload — lives in `StageTopBar`'s action slot
* (DESIGN.md → Pages & Routing: the top nav owns the page's actions, and a
* page body never floats its own). The name filter is a filter control, not
* a second search: the product has exactly one search surface and it is the
* palette the top bar already carries (DESIGN.md → Search).
*/
export function LibraryPage({
artifacts,
Expand Down Expand Up @@ -440,6 +447,59 @@ export function LibraryPage({
All
</Button>
) : null}
{workbenchScope !== null && onScopeChange !== undefined ? (
<div
role="group"
aria-label="Files scope"
className="hidden items-center gap-1 lg:flex"
>
<Button
type="button"
size="sm"
variant={scope === "workbench" ? "outline" : "ghost"}
aria-pressed={scope === "workbench"}
onClick={() => onScopeChange("workbench")}
>
{workbenchScope.title}
</Button>
<Button
type="button"
size="sm"
variant={scope === "all" ? "outline" : "ghost"}
aria-pressed={scope === "all"}
onClick={() => onScopeChange("all")}
>
All workbenches
</Button>
</div>
) : null}
<LibrarySearchInput
label="Filter files"
placeholder="Filter by name"
value={activeQuery}
onChange={setActiveQuery}
/>
<Menu>
<MenuTrigger asChild>
<Button
type="button"
variant="ghost"
size="sm"
aria-label={SORT_LABEL[sort]}
title={SORT_LABEL[sort]}
>
<ArrowsDownUp />
</Button>
</MenuTrigger>
<MenuContent align="end">
{(Object.keys(SORT_LABEL) as ArtifactSort[]).map((option) => (
<MenuItem key={option} onSelect={() => setSort(option)}>
{SORT_LABEL[option]}
</MenuItem>
))}
</MenuContent>
</Menu>
<ViewToggle mode={viewMode} onChange={setViewMode} />
{onUpload !== undefined ? (
<Button
size="sm"
Expand Down Expand Up @@ -468,60 +528,6 @@ export function LibraryPage({
}}
/>
) : null}
<div className="page-toolbar">
{workbenchScope !== null && onScopeChange !== undefined ? (
<div
role="group"
aria-label="Files scope"
className="flex items-center gap-1"
>
<Button
type="button"
size="sm"
variant={scope === "workbench" ? "outline" : "ghost"}
aria-pressed={scope === "workbench"}
onClick={() => onScopeChange("workbench")}
>
{workbenchScope.title}
</Button>
<Button
type="button"
size="sm"
variant={scope === "all" ? "outline" : "ghost"}
aria-pressed={scope === "all"}
onClick={() => onScopeChange("all")}
>
All workbenches
</Button>
</div>
) : null}
<LibrarySearchInput
label="Search files"
value={activeQuery}
onChange={setActiveQuery}
/>
<Menu>
<MenuTrigger asChild>
<Button
type="button"
variant="ghost"
size="sm"
aria-label={SORT_LABEL[sort]}
title={SORT_LABEL[sort]}
>
<ArrowsDownUp />
</Button>
</MenuTrigger>
<MenuContent align="end">
{(Object.keys(SORT_LABEL) as ArtifactSort[]).map((option) => (
<MenuItem key={option} onSelect={() => setSort(option)}>
{SORT_LABEL[option]}
</MenuItem>
))}
</MenuContent>
</Menu>
<ViewToggle mode={viewMode} onChange={setViewMode} />
</div>
{uploadError !== undefined && uploadError !== null ? (
<p className="px-4 pt-2 text-sm text-destructive sm:px-7" role="alert">
{uploadError}
Expand Down
14 changes: 7 additions & 7 deletions apps/web/src/pages/plugin-skill-detail-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,12 @@ export function PluginSkillDetailPanel({
</DialogBody>
) : (
<DialogBody className="flex flex-col gap-4">
<div className="flex items-center gap-2">
<Badge tone={state.skill.scope === "tenant" ? "info" : "neutral"}>
<div className="flex flex-wrap items-center gap-3">
<p className="text-sm text-muted-foreground">
{state.skill.scope === "tenant"
? "Shared with everyone"
: "Just you"}
</Badge>
? "Everyone in this workbench can use this skill."
: "Only you can use this skill."}
</p>
<Button
type="button"
size="sm"
Expand All @@ -153,8 +153,8 @@ export function PluginSkillDetailPanel({
}
>
{state.skill.scope === "tenant"
? "Make private"
: "Share with everyone"}
? "Make it private to me"
: "Share with everyone here"}
</Button>
</div>
<pre className="whitespace-pre-wrap break-words border border-border bg-muted/30 p-3 font-mono text-xs leading-relaxed">
Expand Down
Loading
Loading