mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-11-06 02:25:24 +00:00
feat: shared tile look for cards and pages, plus new page pieces in SDK 1.1.0
This commit is contained in:
1 parent
1867be3f58
commit
19bdd589f3
41 files changed
+1497
-207
No files matched your search
@@ -42,6 +42,8 @@ import {
|
||||
type PanelViewMode,
|
||||
} from "@/components/panel-layout";
|
||||
import { DataView, type DataColumn } from "@/components/data-view";
|
||||
import { StatusDot } from "@/components/status";
|
||||
import { TileStack } from "@/components/tile-grid/TileStack";
|
||||
import { InlineView, SurfaceScope } from "@/components/surface/surface-scope";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
@@ -321,7 +323,7 @@ function Toolbar({
|
||||
children?: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<div className="flex flex-wrap items-center gap-2 border-b border-border px-3 py-2">
|
||||
<div className="relative min-w-40 max-w-md flex-1">
|
||||
<Search className="pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
|
||||
<Input
|
||||
@@ -346,8 +348,13 @@ function Group({
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<section className="flex flex-col gap-2.5">
|
||||
<GroupHeading title={title} count={count} />
|
||||
<section className="flex flex-col">
|
||||
<GroupHeading
|
||||
plain
|
||||
title={title}
|
||||
count={count}
|
||||
className="border-b border-border px-3 py-1.5"
|
||||
/>
|
||||
{children}
|
||||
</section>
|
||||
);
|
||||
@@ -653,7 +660,7 @@ function ActiveFilters({
|
||||
});
|
||||
}
|
||||
return (
|
||||
<div className="flex min-h-6 flex-wrap items-center gap-1.5">
|
||||
<div className="flex min-h-6 flex-wrap items-center gap-1.5 border-b border-border px-3 py-1.5">
|
||||
<span className="text-[11px] text-muted-foreground">
|
||||
{t("plugins.manager.filters.results", { count: shown })}
|
||||
</span>
|
||||
@@ -703,7 +710,7 @@ function Pager({
|
||||
const per = Number(size);
|
||||
if (total <= Number(PAGE_SIZES[0])) return null;
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-2 border-t border-border pt-2.5">
|
||||
<div className="flex flex-wrap items-center gap-2 px-3 py-2">
|
||||
<span className="text-[11px] tabular-nums text-muted-foreground">
|
||||
{t("plugins.manager.pager.range", {
|
||||
from: (page - 1) * per + 1,
|
||||
@@ -895,7 +902,7 @@ function InstalledSection({
|
||||
rail={<FilterRail rows={searched} facets={facets} onFacets={setFacets} />}
|
||||
>
|
||||
{(filtersButton) => (
|
||||
<div className={`flex flex-col ${PANEL.gap} ${PANEL.body}`}>
|
||||
<div className="flex flex-col">
|
||||
<Toolbar
|
||||
query={query}
|
||||
onQuery={onQuery}
|
||||
@@ -1083,43 +1090,38 @@ function InstalledCard({
|
||||
}
|
||||
/>
|
||||
|
||||
{failed ? (
|
||||
<div className="flex items-center gap-2 border-t border-border bg-destructive/5 px-3 py-2">
|
||||
<TriangleAlert className="size-3.5 shrink-0 text-destructive" />
|
||||
<div className="flex items-center gap-1.5 px-3 pb-2.5">
|
||||
{failed ? (
|
||||
<span
|
||||
className="flex-1 truncate text-[11px] text-muted-foreground"
|
||||
className="flex min-w-0 items-center gap-1.5 text-[11px] text-destructive"
|
||||
title={plugin.lastError ?? undefined}
|
||||
>
|
||||
{plugin.status === "blocked"
|
||||
? t("plugins.manager.status.blocked")
|
||||
: t("plugins.manager.status.failed")}
|
||||
<TriangleAlert className="size-3 shrink-0" />
|
||||
<span className="truncate">
|
||||
{plugin.status === "blocked"
|
||||
? t("plugins.manager.status.blocked")
|
||||
: t("plugins.manager.status.failed")}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
) : !running ? (
|
||||
<div className="flex items-center gap-2 border-t border-border px-3 py-2">
|
||||
<span className="size-1.5 shrink-0 bg-muted-foreground/40" />
|
||||
<span className="text-[11px] text-muted-foreground">
|
||||
{plugin.status === "server"
|
||||
? t("plugins.manager.status.server")
|
||||
: plugin.status === "safeMode"
|
||||
? t("plugins.manager.status.safeMode")
|
||||
: t("plugins.manager.status.disabled")}
|
||||
) : (
|
||||
<span className="flex min-w-0 items-center gap-1.5 text-[11px] text-muted-foreground">
|
||||
<StatusDot tone={running ? "ok" : "idle"} className="size-1.5" />
|
||||
<span className="truncate">
|
||||
{!running
|
||||
? plugin.status === "server"
|
||||
? t("plugins.manager.status.server")
|
||||
: plugin.status === "safeMode"
|
||||
? t("plugins.manager.status.safeMode")
|
||||
: t("plugins.manager.status.disabled")
|
||||
: plugin.pinnedVersion
|
||||
? t("plugins.manager.pinnedTo", {
|
||||
version: plugin.pinnedVersion,
|
||||
})
|
||||
: t("plugins.manager.status.running")}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-2 border-t border-border px-3 py-2">
|
||||
<span className="size-1.5 shrink-0 bg-green-500" />
|
||||
<span className="text-[11px] text-muted-foreground">
|
||||
{plugin.pinnedVersion
|
||||
? t("plugins.manager.pinnedTo", {
|
||||
version: plugin.pinnedVersion,
|
||||
})
|
||||
: t("plugins.manager.status.running")}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex items-center gap-1.5 border-t border-border px-3 py-2">
|
||||
)}
|
||||
<div className="flex-1" />
|
||||
{plugin.updateAvailable && !plugin.pinnedVersion && !failed && (
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -1159,11 +1161,7 @@ function InstalledCard({
|
||||
: t("plugins.manager.enable")}
|
||||
</Button>
|
||||
)}
|
||||
<DocsLink
|
||||
href={plugin.docs}
|
||||
variant="icon"
|
||||
className="ml-auto size-6"
|
||||
/>
|
||||
<DocsLink href={plugin.docs} variant="icon" className="size-6" />
|
||||
{!plugin.defaultLook && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -1171,10 +1169,7 @@ function InstalledCard({
|
||||
disabled={busy || locked}
|
||||
title={t("plugins.manager.uninstall")}
|
||||
aria-label={t("plugins.manager.uninstall")}
|
||||
className={cn(
|
||||
"text-muted-foreground hover:text-destructive",
|
||||
!plugin.docs && "ml-auto",
|
||||
)}
|
||||
className="text-muted-foreground hover:text-destructive"
|
||||
onClick={() => void manager.uninstall(plugin)}
|
||||
>
|
||||
<Trash2 className="size-3" />
|
||||
@@ -1442,7 +1437,7 @@ function BrowseSection({
|
||||
}
|
||||
>
|
||||
{(filtersButton) => (
|
||||
<div className={`flex flex-col ${PANEL.gap} ${PANEL.body}`}>
|
||||
<div className="flex flex-col">
|
||||
<Toolbar
|
||||
query={query}
|
||||
onQuery={onQuery}
|
||||
@@ -1551,7 +1546,7 @@ function BrowseCard({
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<div className="flex items-center gap-2 border-t border-border px-3 py-2">
|
||||
<div className="flex items-center gap-2 px-3 pb-2.5">
|
||||
<span className="min-w-0 flex-1 truncate text-[10px] text-muted-foreground">
|
||||
{plugin.unsupported && !plugin.installed
|
||||
? ""
|
||||
@@ -1646,9 +1641,9 @@ function UpdatesSection({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`flex flex-col ${PANEL.gap} ${PANEL.body}`}>
|
||||
<TileStack>
|
||||
{plain.length > 0 && (
|
||||
<Card className="flex-row items-center gap-3 px-3 py-2.5">
|
||||
<div className="flex items-center gap-3 px-3 py-2.5">
|
||||
<span className="flex-1 text-xs text-muted-foreground">
|
||||
{t("plugins.manager.updatesReady", { count: plain.length })}
|
||||
{gated.length > 0 &&
|
||||
@@ -1664,20 +1659,17 @@ function UpdatesSection({
|
||||
<Download className="size-3.5" />
|
||||
{t("plugins.manager.updateAll")}
|
||||
</Button>
|
||||
</Card>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col gap-3">
|
||||
{[...gated, ...plain, ...pinned].map((p) => (
|
||||
<UpdateRow
|
||||
key={p.id}
|
||||
plugin={p}
|
||||
manager={manager}
|
||||
onOpen={() => onOpen(p.id)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{[...gated, ...plain, ...pinned].map((p) => (
|
||||
<UpdateRow
|
||||
key={p.id}
|
||||
plugin={p}
|
||||
manager={manager}
|
||||
onOpen={() => onOpen(p.id)}
|
||||
/>
|
||||
))}
|
||||
</TileStack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user