diff --git a/apps/web/src/library/artifact-card.tsx b/apps/web/src/library/artifact-card.tsx deleted file mode 100644 index c91e59157..000000000 --- a/apps/web/src/library/artifact-card.tsx +++ /dev/null @@ -1,80 +0,0 @@ -// Dense library card: kind badge, title, optional snippet, and a meta -// line (owner · source · size · updated). Pure presentational — the page -// owns selection and preview. - -import { Badge, artifactKindLabel, formatRelativeTime } from "@corbits/react-ui"; -import type { ReactNode } from "react"; - -import type { ArtifactSummary } from "./artifact-summary"; - -export type ArtifactCardMeta = { - readonly sourceChannel?: string | null; - readonly sizeLabel?: string | null; - readonly snippet?: string | null; -}; - -export type ArtifactCardProps = { - readonly artifact: ArtifactSummary; - readonly meta?: ArtifactCardMeta; - readonly selected?: boolean; - readonly now?: number | undefined; - readonly onSelect?: () => void; - - readonly trailing?: ReactNode; -}; - -function metaLine( - artifact: ArtifactSummary, - meta: ArtifactCardMeta | undefined, - now: number | undefined, -): string { - const parts: string[] = []; - if (meta?.sourceChannel !== undefined && meta.sourceChannel !== null) { - parts.push(meta.sourceChannel); - } - if (meta?.sizeLabel !== undefined && meta.sizeLabel !== null) { - parts.push(meta.sizeLabel); - } - const when = formatRelativeTime(artifact.updatedAt ?? artifact.createdAt, now); - if (when !== "") parts.push(when); - return parts.join(" · "); -} - -export function ArtifactCard({ - artifact, - meta, - selected = false, - now, - onSelect, - trailing, -}: ArtifactCardProps) { - const line = metaLine(artifact, meta, now); - const snippet = meta?.snippet; - return ( - - ); -} diff --git a/apps/web/src/library/index.ts b/apps/web/src/library/index.ts index f335e0a7c..461a6c15b 100644 --- a/apps/web/src/library/index.ts +++ b/apps/web/src/library/index.ts @@ -1,8 +1,6 @@ export * from "./artifact-summary"; export { sortArtifacts, filterArtifacts } from "./sort-filter"; export type { ArtifactSort } from "./sort-filter"; -export { ArtifactCard } from "./artifact-card"; -export type { ArtifactCardMeta, ArtifactCardProps } from "./artifact-card"; export { LIBRARY_KIND_SEGMENTS, artifactMatchesLibraryKindSegment, diff --git a/apps/web/src/pages/library-page.css b/apps/web/src/pages/library-page.css new file mode 100644 index 000000000..4b464d62d --- /dev/null +++ b/apps/web/src/pages/library-page.css @@ -0,0 +1,22 @@ +/* Artifacts and Skills list pages (mockups: artifacts.html, skills.html). */ +.page-lede { + margin: 0 0 var(--space-4, 1rem); + color: var(--ink-soft); + font-size: 0.9375rem; +} + +.library-row-title { + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.library-row-icon { + flex: none; + color: var(--ink-soft); +} + +.skill-row-name { + font-family: var(--font-mono); + font-size: 13px; +} diff --git a/apps/web/src/pages/library-page.tsx b/apps/web/src/pages/library-page.tsx index 3609bbe01..cd0778c75 100644 --- a/apps/web/src/pages/library-page.tsx +++ b/apps/web/src/pages/library-page.tsx @@ -15,15 +15,13 @@ import { TableHead, TableHeader, TableRow, - ViewToggle, artifactKindLabel, formatRelativeTime, toast, useListSelection, } from "@corbits/react-ui"; -import type { SelectionCheckboxState, UseListSelectionResult, ViewMode } from "@corbits/react-ui"; +import type { SelectionCheckboxState, UseListSelectionResult } from "@corbits/react-ui"; import { - ArtifactCard, ArtifactRenderer, artifactMatchesLibraryKindSegment, filterArtifacts, @@ -36,7 +34,14 @@ import { } from "@/library"; import type { ArtifactSort, ArtifactSummary } from "@/library"; import { useQueryClient } from "@tanstack/react-query"; -import { ArrowsDownUp, ArrowSquareOut, LinkSimple as LinkIcon, Stack, X } from "@/lib/icons"; +import { + ArrowsDownUp, + ArrowSquareOut, + FileText, + LinkSimple as LinkIcon, + Stack, + X, +} from "@/lib/icons"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import type { MouseEvent as ReactMouseEvent } from "react"; import { describeApiError, ListSkeleton, QueryView, SignedOutNotice } from "@/lib/api-query"; @@ -50,6 +55,7 @@ import { } from "../api"; import { isAdditiveSelectClick, isRowActivationKey } from "../activatable-row"; import { useBench } from "../bench-context"; +import "./library-page.css"; import { readLastWorkbenchId } from "../last-workbench"; import { consumePendingLibraryUpload, LIBRARY_UPLOAD_EVENT } from "../library-upload"; import { resolveLibraryWorkbenchScope } from "../library-workbench-scope"; @@ -154,7 +160,12 @@ function ArtifactRows({ rowLabel={artifact.title} /> - {artifact.title} + + + + {artifactKindLabel(artifact.kind)} @@ -315,7 +326,6 @@ export function LibraryPage({ }) { const [localQuery, setLocalQuery] = useState(""); const [sort, setSort] = useState("newest"); - const [viewMode, setViewMode] = useState("rows"); const [localSelected, setLocalSelected] = useState(null); const fileInputRef = useRef(null); @@ -338,14 +348,6 @@ export function LibraryPage({ // your picks, since `useListSelection` keeps them in internal state. const selection = useListSelection({ ids: visibleIds }); - // Only rows has checkboxes, so a selection has nothing to anchor to in - // cards — clearing on view change is simpler than adding card checkboxes. - const [selectionViewMode, setSelectionViewMode] = useState(viewMode); - if (selectionViewMode !== viewMode) { - setSelectionViewMode(viewMode); - selection.clear(); - } - const openPicker = useCallback(() => { if (uploading === true) return; fileInputRef.current?.click(); @@ -464,7 +466,6 @@ export function LibraryPage({ ))} - {onUpload !== undefined ? (