Fix Admin feedback filter overflow (#6825)

## Why
Long community hostnames can make the native Community select exceed the
Admin feedback filter grid, pushing the Received and Status controls
outside the filter bar and creating horizontal overflow.

## What
- Allow filter labels and selects to shrink within their grid tracks
- Add a browser regression test covering an unusually long community
hostname

## Risk Assessment
Low — this is limited to Admin feedback filter sizing and preserves the
existing desktop and mobile grid layouts.

## Before
The Community select expands past the filter bar and pushes the Received
and Status controls outside it.

![Admin feedback filters before the
fix](https://raw.githubusercontent.com/block/buzz/f6c2f6d2cb1386feecf4dd6ac2849ab263b1b1a4/pr-6825--01-before.png)

## After
Long community names remain contained, keeping all four controls inside
the filter bar.

![Admin feedback filters after the
fix](https://raw.githubusercontent.com/block/buzz/f6c2f6d2cb1386feecf4dd6ac2849ab263b1b1a4/pr-6825--02-after.png)

## References
- Verified on Blox at the local checkout revision: Admin checks passed
and all 9 Playwright tests passed

Generated with Codex
This commit is contained in:
Luke Tornquist
2026-08-26 10:05:01 -04:00
committed by GitHub
parent db514b153a
commit dcee330b5c
2 changed files with 71 additions and 0 deletions

View File

@@ -195,6 +195,7 @@ h1 {
.feedback-filters label {
display: grid;
gap: 0.45rem;
min-width: 0;
}
.feedback-filters label > span {
@@ -221,6 +222,8 @@ h1 {
}
.feedback-filters select {
width: 100%;
min-width: 0;
padding: 0 2.25rem 0 1rem;
}

View File

@@ -224,6 +224,74 @@ test("feedback can be searched and filtered by community and time", async ({
await expect(page.getByText("Calls are much more reliable")).toHaveCount(0);
});
test("feedback filters keep long community names usable", async ({ page }) => {
await page.route("**/api/admin/v1/feedback", (route) =>
route.fulfill({
contentType: "application/json",
body: JSON.stringify([
{
id: "long-community",
communityId: "long-community",
communityHost: `${"long-community-name.".repeat(4)}buzz.example.com`,
submitterPubkey: "21".repeat(32),
category: "bug",
bodySummary: "The filter row stays within its container",
receivedAt: new Date().toISOString(),
},
]),
}),
);
for (const viewport of [
{ name: "desktop", width: 1200 },
{ name: "mobile", width: 720 },
]) {
await test.step(viewport.name, async () => {
await page.setViewportSize({ width: viewport.width, height: 720 });
await page.goto("/feedback");
const filters = page.locator(".feedback-filters");
const search = page.getByRole("searchbox", { name: "Search feedback" });
const community = page.getByRole("combobox", { name: "Community" });
const status = page.getByLabel("Status");
await expect(filters).toBeVisible();
await expect(community).toBeVisible();
await expect(status).toBeVisible();
const [filtersBox, searchBox, communityBox, statusBox] =
await Promise.all([
filters.boundingBox(),
search.boundingBox(),
community.boundingBox(),
status.boundingBox(),
]);
if (!filtersBox || !searchBox || !communityBox || !statusBox) {
throw new Error("feedback filter bounds were unavailable");
}
expect(statusBox.x + statusBox.width).toBeLessThanOrEqual(
filtersBox.x + filtersBox.width,
);
if (viewport.name === "desktop") {
const rootFontSize = await page.evaluate(() =>
Number.parseFloat(
getComputedStyle(document.documentElement).fontSize,
),
);
expect(communityBox.width).toBeGreaterThanOrEqual(14 * rootFontSize);
} else {
expect(Math.abs(communityBox.width - searchBox.width)).toBeLessThan(1);
}
const pageWidths = await page.evaluate(() => ({
client: document.documentElement.clientWidth,
scroll: document.documentElement.scrollWidth,
}));
expect(pageWidths.scroll).toBe(pageWidths.client);
});
}
});
test("feedback status is stored locally by feedback id", async ({ page }) => {
await page.route("**/api/admin/v1/feedback", (route) =>
route.fulfill({