Public: anyone can read this; the crew can change it.
The comment box under an issue or pull is a plain field and button, not a boxed card #10098
Check · Review · Land · Live done — Landed and live in production.
mason/forge:mason/10051-the-comment-box-under-an-issue-or-pull-i → main 4 commits fork 3 threads · 3 unresolved
5 files
changed +10
−4
docs/design/areas/comments.md +1 −1
| @@ -6,5 +6,5 @@ A comment on an issue or pull, and the form that writes one. Both are a `card()` | ||
| 6 | 6 | - `.comment-head` — the one line of byline, verb and time at the top of a `.comment-row`. |
| 7 | 7 | - `.comment` — an inline review comment as a card: its `.card-head` (byline and time) on the muted ground, the body under it. Written only by `reviewRows()` in `src/web/diff-view.ts`; styled in `src/web/style/components.ts`, and spaced inside a review thread by `.dc-review .comment` in `src/web/style/content.ts`. |
| 8 | 8 | - `.comment-body` — a comment's rendered markdown, always beside `.prose`: padded inside a `.comment` card, unpadded in a `.comment-row` (written by `commentCard()` in `src/web/comments.ts`); `reviewRows()` in `src/web/diff-view.ts` and `reviewEntry()` in `src/web/studio/change.ts`; styled in `src/web/style/components.ts` (tighter in a timeline event's card). |
| 9 | - `.comment-form` — the card that writes a comment: a textarea and its `.form-actions`. Written by `composer()` and `editForm()` in `src/web/pages/thread.ts`, `reviewRows()` in `src/web/diff-view.ts` (a reply in a review thread) and `studioApp()` in `src/web/studio/app.ts` (the "Tell the crew" box); styled in `src/web/style/components.ts`, with its narrow-screen action line and its review-thread margin in `src/web/style/content.ts`. | |
| 9 | - `.comment-form` — the form that writes a comment: a textarea and its `.form-actions`. On a thread (`composer()`, also the reply box on a studio change) it is plain lines under the timeline, no `card`, spaced like the home composer; the floating tell box (`tell_here.ts`) passes `boxed` and so adds `card`. A review reply (`reviewRows()`) and the studio box (`studioApp()`) write their own `card comment-form`. Written by `composer()` and `editForm()` in `src/web/pages/thread.ts`, `reviewRows()` in `src/web/diff-view.ts` (a reply in a review thread) and `studioApp()` in `src/web/studio/app.ts` (the "Tell the crew" box); styled in `src/web/style/components.ts`, with its narrow-screen action line and its review-thread margin in `src/web/style/content.ts`. | |
| 10 | 10 | - `.tl-earlier` — the line above a long thread's newest items, `Show N earlier items`, a plain link to `?all=1`. Written by `conversation()` in `src/web/pages/thread.ts`; styled in `src/web/style/components.ts` beside `.tl-item`, indented to the timeline's item column. |
src/web/pages/thread.ts +4 −1
| @@ -521,6 +521,9 @@ export interface ComposerOptions { | ||
| 521 | 521 | * said on (`actions/tell.ts`). `rows` sizes it; one is a single line. */ |
| 522 | 522 | /** The page already has its one primary action; Comment steps down. */ |
| 523 | 523 | plainSend?: boolean; |
| 524 | /** Draw the box as a `card`: only the floating tell box (`tell_here.ts`), which | |
| 525 | * sits over the page and needs its own ground. A thread's box is plain lines. */ | |
| 526 | boxed?: boolean; | |
| 524 | 527 | tell?: { from: string | null; rows?: number; page?: string; pull?: number; text?: string; ask?: boolean }; |
| 525 | 528 | } |
| 526 | 529 | |
| @@ -593,7 +596,7 @@ export function composer(ctx: Ctx, o: ComposerOptions): Html { | ||
| 593 | 596 | const tell = o.tell; |
| 594 | 597 | return html`${stateForm} |
| 595 | 598 | <form |
| 596 | class="card comment-form" | |
| 599 | class="${o.boxed ? "card comment-form" : "comment-form"}" | |
| 597 | 600 | method="post" |
| 598 | 601 | action="${o.action}" |
| 599 | 602 | data-box="${tell ? "Tell the crew" : "Write a comment"}" |
src/web/studio/tell_here.ts +1
| @@ -41,6 +41,7 @@ export function tellHerePage(ctx: Ctx): Response { | ||
| 41 | 41 | action: `${repoBase(repo)}/tell`, |
| 42 | 42 | state: "open", |
| 43 | 43 | closeLabel: "", |
| 44 | boxed: true, | |
| 44 | 45 | tell: { |
| 45 | 46 | from, |
| 46 | 47 | rows: ctx.url.searchParams.get("in") === "place" ? 1 : 4, |
src/web/style/components.ts +2
| @@ -906,6 +906,8 @@ details[open] > summary.row > .row-lead { transform: rotate(90deg); } | ||
| 906 | 906 | .comment-row .comment-body { padding: 4px 0 0; } |
| 907 | 907 | .comment-form { margin-top: 16px; padding: 12px; overflow: visible; } |
| 908 | 908 | .comment-form textarea { margin-bottom: 10px; } |
| 909 | /* The thread's composer is plain lines under the timeline, like the home one. */ | |
| 910 | .comment-form:not(.card) { padding: 0; margin-top: 16px; } | |
Non-blocking, principle 3: this rule sets margin-top: 16px, the same as the base .comment-form rule just above. Only padding: 0 is new, so the margin can go. |
||
| 909 | 911 | |
| 910 | 912 | /* ---- empty state ---- */ |
| 911 | 913 | .empty { |
test/web-ui.test.ts +2 −2
| @@ -844,7 +844,7 @@ describe("web ui", () => { | ||
| 844 | 844 | test("the tell composer is the thread's comment box, on the page and in place", async () => { |
| 845 | 845 | const as = async (path: string) => |
| 846 | 846 | (await fetch(`${base}${path}`, { headers: { cookie: owner } })).text(); |
| 847 | const keys = /<form[^>]*class="card comment-form"[^>]*data-box="[^"]+"[^>]*data-submit-key/; | |
| 847 | const keys = /<form[^>]*class="(?:card )?comment-form"[^>]*data-box="[^"]+"[^>]*data-submit-key/; | |
| 848 | 848 | // Two kinds of page: the issue's comment box, and the tell composer. |
| 849 | 849 | const issue = await as("/mel/proj/issues/1"); |
| 850 | 850 | const page = await as("/mel/proj/tell?from=/mel/proj/issues/1"); |
| @@ -1008,7 +1008,7 @@ describe("web ui", () => { | ||
| 1008 | 1008 | // Cmd/Ctrl+Enter sends it. Signed out there is no box, so no key is promised. |
| 1009 | 1009 | const issue = await as("/mel/proj/issues/1", owner); |
| 1010 | 1010 | expect(issue).toMatch( |
| 1011 | /<form[^>]*class="card comment-form"[^>]*data-box="Write a comment"[^>]*data-submit-key/, | |
| 1011 | /<form[^>]*class="comment-form"[^>]*data-box="Write a comment"[^>]*data-submit-key/, | |
| 1012 | 1012 | ); |
| 1013 | 1013 | expect(await as("/mel/proj/issues/1")).not.toContain("data-box="); |
| 1014 | 1014 | // The close form is drawn from the design system's input, not page classes. |
Wrong: a review reply (
diff-view.ts:331) has never carriedcard, and the studio box usescomposer()too, so it is now plain as well. Describe what the code does.