Public: anyone can read this; the crew can change it.
The /search page speaks the home page's language #9692
Check · Review · Land · Live done — Landed and live in production.
mason/forge:mason/9689-the-search-page-speaks-the-home-page-s-l → main 2 commits fork
3 files
changed +17
−2
docs/design/areas/search.md +4
| @@ -7,3 +7,7 @@ What a search finds is other people's words, so inside `[data-search]` (an attri | ||
| 7 | 7 | the one-line ellipsis. A matching line of code keeps `white-space: pre` and scrolls inside its own box |
| 8 | 8 | (`overflow-x: auto`). The query box may shrink. No fixed width; the page does not scroll sideways. No new class. |
| 9 | 9 | The owner's phone look of `/search?q=sample` is attached to the pull. |
| 10 | ||
| 11 | ## Rows under a heading (#9689) | |
| 12 | ||
| 13 | Each section of the results (apps and repositories, issues and pull requests, code) is a heading over a `.list` of `.row`s in a `.card.bare` (#9588): rows on the page's one background, no box. No new class; `test/studio-search.test.ts` holds it. |
src/web/pages/search.ts +5 −2
| @@ -46,7 +46,6 @@ import { | ||
| 46 | 46 | dot, |
| 47 | 47 | empty, |
| 48 | 48 | field as formField, |
| 49 | listCard, | |
| 50 | 49 | repoCounts, |
| 51 | 50 | row, |
| 52 | 51 | seg, |
| @@ -88,6 +87,10 @@ interface Apps { | ||
| 88 | 87 | readonly enterable: ReadonlySet<string>; |
| 89 | 88 | } |
| 90 | 89 | |
| 90 | /** A section's rows on the page's one background: a heading over rows, no box. */ | |
| 91 | const rowsUnderHeading = (rows: Html[]): Html => | |
| 92 | card(html`<ul class="list">${rows}</ul>`, { pad: false, extra: "bare" }); | |
| 93 | ||
| 91 | 94 | const privateBadge = (yes: boolean): Html => |
| 92 | 95 | when(yes, () => badge("Private", { icon: "lock", variant: "secondary" })); |
| 93 | 96 | |
| @@ -321,7 +324,7 @@ function section( | ||
| 321 | 324 | }), |
| 322 | 325 | }), |
| 323 | 326 | }) |
| 324 | : listCard(rows)} | |
| 327 | : rowsUnderHeading(rows)} | |
| 325 | 328 | ${after} |
| 326 | 329 | ${when( |
| 327 | 330 | truncated, |
test/studio-search.test.ts +8
| @@ -195,6 +195,14 @@ describe("finding things in the studio: /search", () => { | ||
| 195 | 195 | expect(html).toContain("Apps & repos"); |
| 196 | 196 | }); |
| 197 | 197 | |
| 198 | test("results are rows under a heading, not a boxed card", async () => { | |
| 199 | const html = mainOf(await (await asAlice("/search?q=chess")).text()); | |
| 200 | const lists = html.match(/<div\s+class="card bare"[^>]*>\s*<ul class="list">/g) ?? []; | |
| 201 | expect(lists.length).toBeGreaterThanOrEqual(2); | |
| 202 | expect(html).not.toMatch(/<div\s+class="card"[^>]*>\s*<ul class="list">/); | |
| 203 | expect(html).toMatch(/<h2 class="mt" id="repos">/); | |
| 204 | }); | |
| 205 | ||
| 198 | 206 | test("an empty query is an empty result, not an error page", async () => { |
| 199 | 207 | const res = await asAlice("/search"); |
| 200 | 208 | expect(res.status).toBe(200); |