Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash. | 1 | /** |
| 2 | * Artifacts as lists show them (docs/ARTIFACTS_MODE.md section 6.2): rows | |
| 3 | * grouped by the day they were last edited, in the viewer's time zone, or | |
| 4 | * cards with a picture drawn from each one's preview. Each has its kind, | |
| 5 | * who can see it, its space, when it was edited and by whom, and its ⋯ | |
| 6 | * menu. | |
| 7 | */ | |
| 8 | import type { Folio } from "@g1t/contracts"; | |
| 9 | import { useMemo } from "react"; | |
| 10 | import { Link } from "react-router"; | |
| 11 | ||
| 12 | import { dayGroups } from "../../lib/folios"; | |
| 13 | import { TimeAgo } from "../ui"; | |
| 14 | import { Hint } from "../ui/hint"; | |
| Artifacts' home keeps its filters on one row beside the search box, and an artifact in someone else's Private shows whose it is instead of reading "Private". | 15 | import { useFoliosData } from "./actions"; |
| Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash. | 16 | import { FolioThumbnail, KindIcon } from "./kinds"; |
| 17 | import { FolioMenu } from "./menu"; | |
| 18 | import { AccessMark } from "./parts"; | |
| 19 | ||
| Artifacts' home keeps its filters on one row beside the search box, and an artifact in someone else's Private shows whose it is instead of reading "Private". | 20 | /** Where it sits, in a word: its space; else your Private, or whose it is when it's someone else's. */ |
| 21 | function placeOf(folio: Folio, me: string | undefined): string { | |
| 22 | if (folio.space) return folio.space.name; | |
| 23 | return `user:${folio.owner.id}` === me ? "Private" : folio.owner.display_name; | |
| 24 | } | |
| 25 | ||
| Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash. | 26 | function Edited({ folio }: { folio: Folio }) { |
| 27 | const by = folio.edited_by?.display_name; | |
| 28 | return ( | |
| 29 | <Hint label={by ? `Edited by ${by}` : "Edited"}> | |
| 30 | <span className="shrink-0 text-xs whitespace-nowrap text-faint" tabIndex={-1}> | |
| 31 | Edited <TimeAgo at={folio.edited_at} /> | |
| 32 | </span> | |
| 33 | </Hint> | |
| 34 | ); | |
| 35 | } | |
| 36 | ||
| 37 | export function FolioRow({ slug, folio, onError }: { slug: string; folio: Folio; onError?: (message: string) => void }) { | |
| Artifacts' home keeps its filters on one row beside the search box, and an artifact in someone else's Private shows whose it is instead of reading "Private". | 38 | const me = useFoliosData()?.me.key; |
| Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash. | 39 | return ( |
| 40 | <li className="group relative flex items-center gap-3 px-3 py-2 transition-colors hover:bg-raised/60 sm:px-4"> | |
| 41 | <KindIcon kind={folio.kind} /> | |
| 42 | <span className="flex min-w-0 grow items-center gap-2"> | |
| 43 | <Link to={folio.path} prefetch="intent" className="min-w-0 truncate text-sm text-fg after:absolute after:inset-0 hover:text-accent"> | |
| 44 | {folio.icon && <span className="mr-1.5">{folio.icon}</span>} | |
| 45 | {folio.title || "Untitled"} | |
| 46 | </Link> | |
| 47 | {folio.stale && ( | |
| 48 | <Hint label="Possibly out of date: code it cites changed"> | |
| 49 | <span className="relative size-1.5 shrink-0 rounded-full bg-warn" aria-label="Possibly out of date" /> | |
| 50 | </Hint> | |
| 51 | )} | |
| 52 | </span> | |
| 53 | <span className="relative hidden shrink-0 sm:flex"> | |
| 54 | <AccessMark folio={folio} /> | |
| 55 | </span> | |
| Artifacts' home keeps its filters on one row beside the search box, and an artifact in someone else's Private shows whose it is instead of reading "Private". | 56 | <span className="hidden w-32 shrink-0 truncate text-xs text-faint md:block">{placeOf(folio, me)}</span> |
| Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash. | 57 | <span className="relative w-28 shrink-0 text-right max-sm:w-auto"> |
| 58 | <Edited folio={folio} /> | |
| 59 | </span> | |
| 60 | <span className="relative"> | |
| 61 | <FolioMenu slug={slug} folio={folio} onError={onError} /> | |
| 62 | </span> | |
| 63 | </li> | |
| 64 | ); | |
| 65 | } | |
| 66 | ||
| 67 | /** Rows under Today, Yesterday, then dates. */ | |
| 68 | export function FolioDays({ slug, items, zone, onError }: { slug: string; items: Folio[]; zone: string; onError?: (message: string) => void }) { | |
| 69 | const days = useMemo(() => dayGroups(items, (f) => f.edited_at, zone), [items, zone]); | |
| 70 | return ( | |
| 71 | <div className="space-y-6"> | |
| 72 | {days.map((day) => ( | |
| 73 | <section key={day.key} aria-label={day.label}> | |
| 74 | <h3 className="mb-1.5 px-1 text-xs font-medium text-faint">{day.label}</h3> | |
| 75 | <ul className="divide-y divide-line overflow-hidden rounded-xl border border-line bg-surface"> | |
| 76 | {day.items.map((f) => ( | |
| 77 | <FolioRow key={f.id} slug={slug} folio={f} onError={onError} /> | |
| 78 | ))} | |
| 79 | </ul> | |
| 80 | </section> | |
| 81 | ))} | |
| 82 | </div> | |
| 83 | ); | |
| 84 | } | |
| 85 | ||
| 86 | export function FolioCard({ slug, folio, onError }: { slug: string; folio: Folio; onError?: (message: string) => void }) { | |
| Artifacts' home keeps its filters on one row beside the search box, and an artifact in someone else's Private shows whose it is instead of reading "Private". | 87 | const me = useFoliosData()?.me.key; |
| Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash. | 88 | return ( |
| 89 | <div className="group relative flex flex-col overflow-hidden rounded-xl border border-line bg-surface transition-colors hover:border-line-strong"> | |
| 90 | <div className="pointer-events-none h-32 shrink-0 border-b border-line"> | |
| 91 | <FolioThumbnail folio={folio} /> | |
| 92 | </div> | |
| 93 | <div className="flex items-start gap-2.5 px-3.5 pt-3 pb-3"> | |
| 94 | <KindIcon kind={folio.kind} size={14} box={24} /> | |
| 95 | <span className="min-w-0 grow"> | |
| 96 | <Link to={folio.path} prefetch="intent" className="line-clamp-1 text-sm font-medium text-fg after:absolute after:inset-0 group-hover:text-accent"> | |
| 97 | {folio.icon && <span className="mr-1">{folio.icon}</span>} | |
| 98 | {folio.title || "Untitled"} | |
| 99 | </Link> | |
| 100 | <span className="mt-0.5 flex items-center gap-1.5 text-[0.6875rem] text-faint"> | |
| Artifacts' home keeps its filters on one row beside the search box, and an artifact in someone else's Private shows whose it is instead of reading "Private". | 101 | <span className="truncate">{placeOf(folio, me)}</span> |
| Artifacts is a mode in the rail, the shell and the phone's tab bar in place of Docs: its home lists everything you can open by day or as cards under All, Yours and Shared with you, with search, filters and tiles to start a doc (slides, designs and dashboards say they are coming soon), and its sidebar holds favorites, spaces, Private, Shared, projects' docs and the trash. | 102 | <span aria-hidden="true">·</span> |
| 103 | <span className="relative"> | |
| 104 | <Edited folio={folio} /> | |
| 105 | </span> | |
| 106 | </span> | |
| 107 | </span> | |
| 108 | <span className="relative -mt-1 -mr-1.5 flex items-center"> | |
| 109 | <span className="relative"> | |
| 110 | <AccessMark folio={folio} /> | |
| 111 | </span> | |
| 112 | <FolioMenu slug={slug} folio={folio} onError={onError} /> | |
| 113 | </span> | |
| 114 | </div> | |
| 115 | </div> | |
| 116 | ); | |
| 117 | } | |
| 118 | ||
| 119 | export function FolioGrid({ slug, items, onError }: { slug: string; items: Folio[]; onError?: (message: string) => void }) { | |
| 120 | return ( | |
| 121 | <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"> | |
| 122 | {items.map((f) => ( | |
| 123 | <FolioCard key={f.id} slug={slug} folio={f} onError={onError} /> | |
| 124 | ))} | |
| 125 | </div> | |
| 126 | ); | |
| 127 | } |