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
33 changes: 26 additions & 7 deletions plugins/timeline-comments/app-style.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,36 @@ describe("timeline comments visual contract", () => {
expect(css).toContain("@media (prefers-reduced-motion: reduce)");
});

it("leaves comment input focus indication to the browser", () => {
expect(css).not.toContain("outline: none !important;");
expect(css).not.toMatch(
/\.bb-comments-textarea,[\s\S]*?\.bb-comments-panel textarea \{[^}]*outline:\s*none;/u,
it("uses BB input tokens for comment input states", () => {
expect(css).toMatch(
/\.bb-comments-mention-input \{[\s\S]*border: 1px solid var\(--input, var\(--border\)\);[\s\S]*background: var\(--background\);/u,
);
expect(css).toMatch(
/\.bb-comments-mention-input:focus-within \{[\s\S]*border-color: var\(--ring\);[\s\S]*0 0 0 1px var\(--ring\);/u,
);
expect(css).toMatch(
/\.bb-comments-mention-input:has\(\.bb-comments-error\) \{[\s\S]*var\(--destructive-text/u,
);
expect(css).toMatch(
/\.bb-comments-mention-input\[aria-busy="true"\] \.bb-comments-input-surface,[\s\S]*var\(--surface-recessed\) 55%/u,
);
expect(css).not.toContain(".bb-comments-mention-input:has(");
expect(css).not.toMatch(
/\.bb-comments-panel textarea:focus-visible \{[^}]*outline:/u,
expect(css).toMatch(
/\.bb-comments-mention-input textarea:focus,[\s\S]*outline: none;[\s\S]*box-shadow: none;/u,
);
expect(css).toMatch(
/\.bb-comments-composer-action:focus-visible,[\s\S]*color-mix\(in oklab, var\(--foreground\) 15%, transparent\)/u,
);
});

it("keeps the pre-restyle submit control unchanged", () => {
expect(css).toMatch(
/\.bb-comments-submit-shortcut \{\n position: static;\n display: flex;\n min-width: 27px;\n height: 18px;[\s\S]*? cursor: pointer;\n\}/u,
);
expect(css).toMatch(
/\.bb-comments-submit-shortcut:hover:not\(:disabled\) \{\n background: var\(--surface-recessed\);\n color: var\(--foreground\);\n\}/u,
);
expect(css).toMatch(
/\.bb-comments-submit-shortcut:disabled \{\n cursor: default;\n opacity: 0\.3;\n\}/u,
);
});
});
60 changes: 59 additions & 1 deletion plugins/timeline-comments/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@
box-sizing: border-box;
padding: 5px 6px;
overflow: visible;
transition: border-color 120ms ease;
transition:
border-color 120ms ease,
box-shadow 120ms ease;
}
.bb-comments-textarea,
.bb-comments-reply-input,
Expand Down Expand Up @@ -517,6 +519,60 @@
min-width: 0;
flex: 1;
flex-direction: column;
border: 1px solid var(--input, var(--border));
border-radius: 8px;
background: var(--background);
box-shadow: 0 1px 2px
color-mix(in oklab, var(--foreground) 8%, transparent);
transition:
border-color 120ms ease,
background-color 120ms ease,
box-shadow 120ms ease;
}
.bb-comments-composer .bb-comments-mention-input {
border: 0;
border-radius: 5px;
background: transparent;
box-shadow: none;
}
.bb-comments-mention-input:focus-within {
border-color: var(--ring);
box-shadow: 0 0 0 1px var(--ring);
}
.bb-comments-composer:focus-within {
border-color: var(--ring);
box-shadow:
0 0 0 1px var(--ring),
0 6px 18px color-mix(in oklab, var(--foreground) 12%, transparent);
}
.bb-comments-composer .bb-comments-mention-input:focus-within {
border-color: transparent;
box-shadow: none;
}
.bb-comments-mention-input:has(.bb-comments-error) {
border-color: var(--destructive-text, var(--foreground));
}
.bb-comments-composer:has(.bb-comments-error) {
border-color: var(--destructive-text, var(--foreground));
}
.bb-comments-mention-input[aria-busy="true"] .bb-comments-input-surface,
.bb-comments-mention-input:has(textarea[aria-disabled="true"])
.bb-comments-input-surface {
background: color-mix(
in oklab,
var(--surface-recessed) 55%,
var(--background)
);
}
.bb-comments-mention-input[aria-busy="true"] textarea,
.bb-comments-mention-input textarea[aria-disabled="true"] {
color: var(--muted-foreground);
cursor: wait;
}
.bb-comments-mention-input textarea:focus,
.bb-comments-mention-input textarea:focus-visible {
outline: none;
box-shadow: none;
}
.bb-comments-mention-input[data-mention-input-expanded="false"] {
height: 30px;
Expand All @@ -527,6 +583,8 @@
flex: 1;
padding: 3px 9px 0;
overflow: hidden;
border-radius: inherit;
transition: background-color 120ms ease;
}
.bb-comments-input-row {
display: flex;
Expand Down
64 changes: 62 additions & 2 deletions plugins/timeline-comments/browser-check/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const replies = Array.from({ length: 12 }, (_, index) => ({
}));

const nativeFetch = window.fetch.bind(window);
let rejectNextReply = true;
window.fetch = async (input, init) => {
const url = String(input);
const method = url.split("/").at(-1);
Expand All @@ -78,6 +79,20 @@ window.fetch = async (input, init) => {
nextCursor: null,
};
} else if (method === "reply") {
await wait(260);
if (rejectNextReply) {
rejectNextReply = false;
return new Response(
JSON.stringify({
ok: false,
error: { message: "Unable to save this comment." },
}),
{
status: 500,
headers: { "content-type": "application/json" },
},
);
}
const insertedReply = {
id: "comment_reply_incremental",
threadId: summaries[0]!.id,
Expand Down Expand Up @@ -222,7 +237,7 @@ void (async () => {
throw new Error("Thread popover escaped the viewport");
if (document.activeElement !== popover)
throw new Error("Thread popover did not receive focus");
const reply = popover.querySelector<HTMLTextAreaElement>(
let reply = popover.querySelector<HTMLTextAreaElement>(
".bb-comments-reply-input",
);
let replyButton = popover.querySelector<HTMLButtonElement>(
Expand All @@ -238,9 +253,21 @@ void (async () => {
throw new Error("Reply input typography did not match BB normal text");
}
const emptyReplyHeight = reply.getBoundingClientRect().height;
const replyComposer = reply.closest<HTMLElement>(
let replyComposer = reply.closest<HTMLElement>(
".bb-comments-mention-input",
)!;
const restingBorderColor = getComputedStyle(replyComposer).borderColor;
reply.focus();
await wait(150);
const focusedComposerStyle = getComputedStyle(replyComposer);
if (
focusedComposerStyle.borderColor === restingBorderColor ||
focusedComposerStyle.boxShadow === "none"
) {
throw new Error(
`Focused reply did not use the BB ring treatment: resting=${restingBorderColor} focused=${focusedComposerStyle.borderColor} shadow=${focusedComposerStyle.boxShadow}`,
);
}
setTextareaValue(reply, "First line\nSecond line\nThird line");
await wait(30);
if (replyComposer.getAnimations().length === 0)
Expand Down Expand Up @@ -270,6 +297,14 @@ void (async () => {
throw new Error("Valid reply did not enable submission");
if (replyComposer.dataset.mentionInputExpanded !== "true")
throw new Error("Expanded reply layout did not stay latched like Moss");
setTextareaValue(reply, "x".repeat(10_001));
await wait(150);
if (
replyComposer.querySelector(".bb-comments-error") === null ||
getComputedStyle(replyComposer).borderColor === restingBorderColor
) {
throw new Error("Invalid reply did not expose the BB destructive state");
}
setTextareaValue(reply, "");
await wait(30);
if (replyComposer.getAnimations().length === 0)
Expand All @@ -278,6 +313,31 @@ void (async () => {
if (replyComposer.dataset.mentionInputExpanded !== "false")
throw new Error("Cleared reply did not restore inline layout");
setTextareaValue(reply, "Ready");
replyButton = popover.querySelector<HTMLButtonElement>(
'button[aria-label="Submit comment"]',
);
replyButton?.click();
await wait(150);
if (
replyComposer.getAttribute("aria-busy") !== "true" ||
!reply.readOnly ||
getComputedStyle(
replyComposer.querySelector<HTMLElement>(
".bb-comments-input-surface",
)!,
).backgroundColor === "rgba(0, 0, 0, 0)"
) {
throw new Error("Submitting reply did not expose its disabled BB state");
}
await wait(140);
reply = popover.querySelector<HTMLTextAreaElement>(
".bb-comments-reply-input",
);
replyComposer = reply.closest<HTMLElement>(".bb-comments-mention-input")!;
if (replyComposer.hasAttribute("aria-busy") || reply.readOnly)
throw new Error("Submitted reply did not restore the editable state");
if (!popover.textContent?.includes("Unable to save this comment."))
throw new Error("Failed reply did not expose the error state");
if (CSS.highlights.get("bb-timeline-comments")?.size !== 8) {
throw new Error("Custom Highlight registry did not retain every anchor");
}
Expand Down
13 changes: 11 additions & 2 deletions plugins/timeline-comments/browser-check/run.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,23 @@ try {
.locator('[data-comment-editing="true"] textarea')
.evaluate((textarea) => {
const style = getComputedStyle(textarea);
const composer = textarea.closest(".bb-comments-mention-input");
const composerStyle =
composer instanceof HTMLElement ? getComputedStyle(composer) : null;
return {
active: document.activeElement === textarea,
outlineStyle: style.outlineStyle,
composerBorderColor: composerStyle?.borderColor,
composerBoxShadow: composerStyle?.boxShadow,
};
});
if (!focusedEditInput.active || focusedEditInput.outlineStyle !== "auto") {
if (
!focusedEditInput.active ||
focusedEditInput.outlineStyle !== "none" ||
focusedEditInput.composerBoxShadow === "none"
) {
throw new Error(
`Edit input did not keep the browser-native focus outline: ${JSON.stringify(focusedEditInput)}`,
`Edit input did not use the BB focus ring: ${JSON.stringify(focusedEditInput)}`,
);
}
await page.screenshot({ path: screenshot });
Expand Down
Loading
Loading