diff --git a/web/src/app/community/u/[username]/page.tsx b/web/src/app/community/u/[username]/page.tsx index 48c106979..a447a3f12 100644 --- a/web/src/app/community/u/[username]/page.tsx +++ b/web/src/app/community/u/[username]/page.tsx @@ -84,7 +84,6 @@ export default async function CommunityUserPage(props: RouteParams) {

{stats.join(" · ")}

- {isSelf && (
diff --git a/web/src/components/community/Community.module.css b/web/src/components/community/Community.module.css index 3ab63201e..054ecebc6 100644 --- a/web/src/components/community/Community.module.css +++ b/web/src/components/community/Community.module.css @@ -3467,12 +3467,15 @@ } /* Your own profile's right-hand side: the CTA, and on a phone the sign-out - that the header cannot fit. */ + that the header cannot fit. The auto margin rather than a spacer span: at + 390px the name and the CTA do not fit on one line, and a spacer stays on + the first line while the CTA wraps to the left edge of the second. */ .profileSelfActions { display: flex; flex-direction: column; align-items: flex-end; gap: 10px; + margin-left: auto; } /* Off by default — the header's copy is the one you see on a desktop. */ @@ -4141,6 +4144,12 @@ grid-column: span 2; } + /* In the grid a spacer would take a cell of its own and push Empty deck + onto a third row. */ + .actionRow > .headerSpacer { + display: none; + } + .actionRow button, .actionRow a { min-height: 44px; @@ -4160,9 +4169,12 @@ padding: 14px 16px; } - /* The section nav moves to the tab bar at the bottom of the screen. */ + /* The section nav moves to the tab bar at the bottom of the screen, and the + gap that held it apart from the links goes with it. Only the header's own + gap: seven other rows use the same span to push a button right, and the + deck panel is drawn inside this
, hence the child combinator. */ .sectionNav, - .headerSpacer { + .pageHeader > .headerSpacer { display: none; } diff --git a/web/src/components/community/communityCss.test.ts b/web/src/components/community/communityCss.test.ts index 3c03df59f..39d7769d2 100644 --- a/web/src/components/community/communityCss.test.ts +++ b/web/src/components/community/communityCss.test.ts @@ -106,6 +106,54 @@ describe("the deck grid on a phone", () => { }); }); +/** Every rule inside each `@media ` block, its selector list split. */ +function mediaRules(source: string, query: string) { + return source + .replace(/\/\*[\s\S]*?\*\//g, "") + .split(`\n@media ${query} {`) + .slice(1) + .flatMap((part) => [...part.slice(0, part.indexOf("\n}")).matchAll(/\n {2}([^{}]+) \{([^}]*)\}/g)]) + .map(([, selectors, body]) => ({ selectors: selectors.split(",").map((s) => s.trim()), body })); +} + +// On 26 October a bare `.headerSpacer { display: none }` in the phone block, +// meant for the page header's gap, took out the same span in eight other rows. +// At 390px the comment Post button sat at x 16 instead of 316, the deck +// panel's ↑ buttons wandered between x 115 and 213 with each title's length, +// and Make & publish on your own profile moved to the left edge. +describe("the header spacer on a phone", () => { + const community = css("Community.module.css"); + + it("hides only the page header's own spacer", () => { + const hidden = mediaRules(community, MOBILE_MEDIA_QUERY) + .flatMap(({ selectors }) => selectors) + .filter((selector) => selector.endsWith(".headerSpacer")); + expect(hidden).toEqual([".pageHeader > .headerSpacer"]); + }); + + // The deck panel opens from the header's deck chip and is drawn inside the + //
, so a descendant selector would still reach its rows. + it("reaches the header's spacer as a child, not the deck panel inside it", () => { + expect(community).not.toMatch(/\.pageHeader \.headerSpacer/); + }); + + // In the two-column action grid a spacer is a cell of its own, and Empty + // deck would drop to a third row. + it("still hides it in the action grid, wherever that grid is drawn", () => { + const grid = mediaRules(community, "(max-width: 900px)"); + expect(grid.find(({ selectors }) => selectors.includes(".actionRow"))?.body).toContain("display: grid;"); + const spacer = grid.find(({ selectors }) => selectors.includes(".actionRow > .headerSpacer")); + expect(spacer, ".actionRow > .headerSpacer is missing from @media (max-width: 900px)").toBeDefined(); + expect(spacer!.body).toContain("display: none;"); + }); + + // At 390px "@ada YOU" and its stats line take the first line, and the + // actions wrap to a second one where no spacer reaches. + it("keeps your profile's actions right when they wrap under the name", () => { + expect(declarations(rule(community, ".profileSelfActions"))).toContain("margin-left: auto"); + }); +}); + // The community's text colours, against each ground they are drawn on. On 26 // October the faint ink was #6B6558, 3.18:1 on the well-2 and 3.40:1 on the // page, and axe found 426 color-contrast failures over eleven community pages,