feat: shared tile look for cards and pages, plus new page pieces in SDK 1.1.0

This commit is contained in:
LukeGus committed 2026-11-04 18:57:18 -06:00
1 parent 1867be3f58
commit 19bdd589f3
41 files changed
+1497 -207

No files matched your search

+32 -36
View File
@@ -17,8 +17,9 @@ import {
TriangleAlert,
} from "lucide-react";
import { Button } from "@/components/button";
import { Card } from "@/components/card";
import { Facts, PANEL } from "@/components/panel-layout";
import { Facts } from "@/components/panel-layout";
import { TileStack } from "@/components/tile-grid/TileStack";
import { TileWall } from "@/components/tile-grid/TileWall";
import { FakeSwitch, SectionCard } from "@/components/section-card";
import {
Select,
@@ -52,7 +53,7 @@ import { PluginReleaseNotes, PluginVideo } from "./PluginReleaseNotes";
import type { PluginsManager } from "./use-plugins-manager";
const LINK_ROW =
"flex items-center gap-2 border border-border bg-card px-3 py-2.5 text-left text-[11px] text-muted-foreground transition-colors hover:border-accent-brand/40 hover:text-foreground";
"flex w-full items-center gap-2 px-3 py-2.5 text-left text-[11px] text-muted-foreground transition-colors hover:bg-muted/40 hover:text-foreground";
export function PluginDetail({
plugin,
@@ -93,10 +94,8 @@ export function PluginDetail({
const tryableBeta = betaToTry(plugin);
return (
<div
className={`mx-auto flex w-full max-w-5xl flex-col ${PANEL.gap} ${PANEL.body}`}
>
<Card className="flex-row flex-wrap items-start gap-4 px-4 py-4">
<TileStack>
<div className="flex flex-row flex-wrap items-start gap-3 p-3">
<PluginIconBox
name={plugin.icon}
size="lg"
@@ -223,10 +222,10 @@ export function PluginDetail({
</Button>
)}
</div>
</Card>
</div>
{plugin.installed && failed && plugin.lastError && (
<div className="flex items-start gap-2 border border-destructive/30 bg-destructive/5 px-3 py-2.5">
<div className="flex items-start gap-2 bg-destructive/5 px-3 py-2.5">
<TriangleAlert className="mt-px size-3.5 shrink-0 text-destructive" />
<div className="flex min-w-0 flex-col gap-0.5">
<span className="text-xs font-medium">
@@ -242,7 +241,7 @@ export function PluginDetail({
)}
{plugin.status === "server" && (
<div className="flex items-start gap-2 border border-border bg-muted/30 px-3 py-2.5">
<div className="flex items-start gap-2 bg-muted/30 px-3 py-2.5">
<Server className="mt-px size-3.5 shrink-0 text-muted-foreground" />
<span className="text-[11px] leading-snug text-muted-foreground">
{t("plugins.manager.runsOnServerHint")}
@@ -250,13 +249,13 @@ export function PluginDetail({
</div>
)}
<div className="grid grid-cols-1 gap-2 lg:grid-cols-3">
<div className="flex flex-col gap-2 lg:col-span-2">
<div className="grid grid-cols-1 lg:grid-cols-3">
<TileStack className="-mb-px border-border lg:col-span-2 lg:border-r">
<PluginVideo videoId={plugin.videoId} name={plugin.name} />
{plugin.features.length > 0 && (
<SectionCard title={t("plugins.manager.features")} icon={null}>
<ul className="grid grid-cols-1 gap-x-4 gap-y-1.5 px-4 py-3 sm:grid-cols-2">
<ul className="grid grid-cols-1 gap-x-4 gap-y-1.5 py-3 sm:grid-cols-2">
{plugin.features.map((feature) => (
<li
key={feature}
@@ -277,11 +276,11 @@ export function PluginDetail({
key={capability}
capability={capability}
showId
className="px-4 py-2.5"
className="py-2.5"
/>
))}
{plugin.capabilities.length === 0 && (
<div className="px-4 py-2.5 text-[11px] text-muted-foreground">
<div className="py-2.5 text-[11px] text-muted-foreground">
{t("plugins.manager.consent.none")}
</div>
)}
@@ -292,10 +291,7 @@ export function PluginDetail({
<SectionCard title={t("plugins.manager.envVars")} icon={null}>
<div className="divide-y divide-border">
{plugin.env.map((v) => (
<div
key={v.name}
className="flex flex-col gap-0.5 px-4 py-2.5"
>
<div key={v.name} className="flex flex-col gap-0.5 py-2.5">
<div className="flex flex-wrap items-center gap-2">
<code className="font-mono text-xs font-semibold">
{v.name}
@@ -331,12 +327,12 @@ export function PluginDetail({
onDelete={() => manager.removeData(plugin)}
/>
)}
</div>
</TileStack>
<div className="flex flex-col gap-2">
<TileStack className="-mb-px">
{contributions.length > 0 && (
<SectionCard title={t("plugins.manager.addsToTermix")} icon={null}>
<div className="flex flex-col gap-2 px-4 py-3">
<div className="flex flex-col gap-2 py-3">
<div className="flex flex-wrap gap-1">
{contributions.map((c) => (
<span
@@ -358,7 +354,7 @@ export function PluginDetail({
{plugin.inRegistry && compatible.length > 0 && (
<SectionCard title={t("plugins.manager.version")} icon={null}>
<div className="flex flex-col gap-2 px-4 py-3">
<div className="flex flex-col gap-2 py-3">
<span className="text-[11px] leading-snug text-muted-foreground">
{plugin.installed
? t("plugins.manager.versionPickHintInstalled")
@@ -414,7 +410,7 @@ export function PluginDetail({
{plugin.installed && (
<SectionCard title={t("plugins.manager.updates")} icon={null}>
<div className="divide-y divide-border">
<div className="flex items-center justify-between gap-3 px-4 py-3">
<div className="flex items-center justify-between gap-3 py-3">
<div className="flex min-w-0 flex-col gap-0.5">
<span className="text-xs font-medium">
{t("plugins.manager.autoUpdate")}
@@ -431,7 +427,7 @@ export function PluginDetail({
}
/>
</div>
<div className="flex items-center justify-between gap-3 px-4 py-3">
<div className="flex items-center justify-between gap-3 py-3">
<div className="flex min-w-0 flex-col gap-0.5">
<span className="flex items-center gap-1.5 text-xs font-medium">
<FlaskConical className="size-3 text-muted-foreground" />
@@ -455,7 +451,7 @@ export function PluginDetail({
}
/>
</div>
<div className="flex items-center justify-between gap-3 px-4 py-3">
<div className="flex items-center justify-between gap-3 py-3">
<div className="flex min-w-0 flex-col gap-0.5">
<span className="flex items-center gap-1.5 text-xs font-medium">
<Pin className="size-3 text-muted-foreground" />
@@ -565,9 +561,9 @@ export function PluginDetail({
</span>
</a>
)}
</div>
</TileStack>
</div>
</div>
</TileStack>
);
}
@@ -625,16 +621,16 @@ function DataCard({
}
>
{error ? (
<div className="px-4 py-3 text-[11px] text-muted-foreground">
<div className="py-3 text-[11px] text-muted-foreground">
{t("plugins.manager.data.loadFailed")}
</div>
) : !data ? (
<div className="px-4 py-3 text-[11px] text-muted-foreground">
<div className="py-3 text-[11px] text-muted-foreground">
{t("plugins.manager.loading")}
</div>
) : (
<div className="-mx-3 -my-1 flex flex-col md:-mx-4">
<div className="grid grid-cols-2 gap-px bg-border sm:grid-cols-4">
<div className="-mx-3 -my-1 flex flex-col">
<TileWall gridClassName="grid-cols-2 sm:grid-cols-4">
<Stat
label={t("plugins.manager.data.tables")}
value={`${data.tables.length}`}
@@ -655,13 +651,13 @@ function DataCard({
label={t("plugins.manager.data.files")}
value={formatBytes(data.filesBytes)}
/>
</div>
</TileWall>
{data.tables.length > 0 && (
<div className="divide-y divide-border border-t border-border">
{data.tables.map((table) => (
<div
key={table.name}
className="flex items-center gap-2 px-4 py-1.5"
className="flex items-center gap-2 px-3 py-1.5"
>
<span className="min-w-0 flex-1 truncate font-mono text-[11px]">
{table.name}
@@ -675,7 +671,7 @@ function DataCard({
))}
</div>
)}
<div className="flex flex-wrap gap-x-4 gap-y-1 border-t border-border px-4 py-2 text-[11px] text-muted-foreground">
<div className="flex flex-wrap gap-x-4 gap-y-1 border-t border-border py-2 text-[11px] text-muted-foreground">
<span>
{t("plugins.manager.data.migrations", {
count: data.migrations.length,
@@ -701,7 +697,7 @@ function Stat({
hint?: string;
}) {
return (
<div className="flex flex-col gap-0.5 bg-card px-4 py-2.5">
<div className="flex flex-col gap-0.5 px-3 py-2.5">
<span className="text-[10px] font-semibold uppercase tracking-widest text-muted-foreground">
{label}
</span>