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
15 changes: 12 additions & 3 deletions apps/web/src/markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,24 @@ function inline(
const href = match[5].replace(MARKS, "");
if (href.startsWith(DOCUMENT_LINK) && openDocument !== undefined) {
const id = decodeURIComponent(href.slice(DOCUMENT_LINK.length));
// An inline span rather than a button: a button never breaks across lines,
// so a title in a sentence would jump to its own line and shed its
// punctuation. No href, since a document has no address to open elsewhere.
out.push(
<button
<span
key={key}
type="button"
role="button"
tabIndex={0}
className="artifact-mention"
onClick={() => openDocument(id)}
onKeyDown={(event) => {
if (event.key !== "Enter" && event.key !== " ") return;
event.preventDefault();
openDocument(id);
}}
>
{label}
</button>,
</span>,
);
} else if (href.startsWith("https://") || href.startsWith("http://")) {
out.push(
Expand Down
10 changes: 0 additions & 10 deletions apps/web/src/pages/workspace-layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -145,19 +145,9 @@
}

.artifact-mention {
display: inline-flex;
align-items: center;
min-height: 44px;
min-width: 44px;
margin: 0;
padding: 0 var(--space-1);
border: 0;
background: transparent;
color: var(--wb-foreground);
font: inherit;
text-decoration: underline;
text-underline-offset: 0.15em;
cursor: pointer;
}

.artifact-mention:focus-visible {
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/pages/workspace/print-document.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const SHEET_CLASS = "print-sheet";
// Controls and selection affordances stay on screen; a document mention prints as its text.
const SCREEN_ONLY = ".pane-bar, .passage-offer, button:not(.artifact-mention)";
// Controls and selection affordances stay on screen.
const SCREEN_ONLY = ".pane-bar, .passage-offer, button";

/**
* Prints the document a pane shows through the browser's dialog, whose "Save as PDF"
Expand Down
38 changes: 38 additions & 0 deletions apps/web/src/pages/workspace/transcript.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
maxTurnText,
} from "@corbits-builder/schemas/conversation";
import { wording } from "../../config.ts";
import { Markdown } from "../../markdown.tsx";
import { DocumentDecision } from "./document-decision.tsx";
import {
awaitingCommit,
Expand Down Expand Up @@ -96,6 +97,43 @@ describe("conversation transcript", () => {
expect(html).not.toContain("sha256");
});

test("a bold document name stays inline in its sentence and opens by click or key", () => {
const source =
"Already written into **Ways to build your list**. What the app does is next.";
const documents = [{ id: "approaches", title: "Ways to build your list" }];
const html = renderToStaticMarkup(
<RoomThread
turns={[{ role: "assistant", text: source, at: 2 }]}
documents={documents}
onOpenDocument={() => {}}
/>,
);
// Inline, not a <button>: a button is one unbreakable box, so the title would leave the line.
expect(html).toContain(
'into <strong><span role="button" tabindex="0" class="artifact-mention">Ways to build your list</span></strong>. What',
);
expect(html).not.toContain("href");

const opened: string[] = [];
const mention = findElement(
Markdown({
source: "See [Ways to build your list](document:approaches).",
openDocument: (id) => opened.push(id),
}),
"span",
);
(mention?.props["onClick"] as (() => void) | undefined)?.();
const onKeyDown = mention?.props["onKeyDown"] as
| ((event: { key: string; preventDefault(): void }) => void)
| undefined;
const prevented: string[] = [];
for (const key of ["Enter", " ", "Tab"]) {
onKeyDown?.({ key, preventDefault: () => prevented.push(key) });
}
expect(opened).toEqual(["approaches", "approaches", "approaches"]);
expect(prevented).toEqual(["Enter", " "]);
});

test("an approval asks about the document in words", () => {
const html = renderToStaticMarkup(
<RoomThread
Expand Down