diff --git a/frontend/src/components/maps/LocationMapBottomSheetSections.jsx b/frontend/src/components/maps/LocationMapBottomSheetSections.jsx
index 51b0e97..dc774f3 100644
--- a/frontend/src/components/maps/LocationMapBottomSheetSections.jsx
+++ b/frontend/src/components/maps/LocationMapBottomSheetSections.jsx
@@ -108,6 +108,20 @@ export function LocationMapOverview({ ariaLabel, rows }) {
);
}
+function InlineStateAction({ label, value, actionLabel, actionText = "Show", onAction }) {
+ return (
+
+ {label}
+ {value}
+ {onAction ? (
+
+ ) : null}
+
+ );
+}
+
export function SelectedMapObjectForm({
selectedObject,
zones = [],
@@ -180,16 +194,16 @@ export function SelectedZoneItemsPanel({
return (
-
- {hasHiddenSelectedItems
- ? "Items are assigned here, but hidden by layer filters."
- : "No items assigned to this zone yet."}
-
{hasHiddenSelectedItems ? (
-
- ) : null}
+
+ ) : (
+
+ )}
);
@@ -204,12 +218,13 @@ export function SelectedZoneItemsPanel({
/>
{hasHiddenSelectedItems ? (
-
- {hiddenSelectedItemCount} more hidden by layer filters.
-
-
+
) : null}
@@ -228,12 +243,12 @@ export function UnmappedItemsPanel({
Unmapped Items
-
- Unmapped items are hidden by layer filters.
-
-
+
);
@@ -253,12 +268,13 @@ export function UnmappedItemsPanel({
/>
{hiddenUnmappedItemCount > 0 ? (
-
- {hiddenUnmappedItemCount} more hidden by layer filters.
-
-
+
) : null}
diff --git a/frontend/src/styles/pages/LocationMapManager.css b/frontend/src/styles/pages/LocationMapManager.css
index 63422a5..7a1dcf0 100644
--- a/frontend/src/styles/pages/LocationMapManager.css
+++ b/frontend/src/styles/pages/LocationMapManager.css
@@ -717,37 +717,45 @@
.location-map-zone-empty {
display: grid;
- gap: 0.55rem;
-}
-
-.location-map-zone-empty button {
- min-height: 40px;
- width: fit-content;
- padding: 0.45rem 0.7rem;
- border: 1px solid var(--color-border-light);
- border-radius: 8px;
- background: #15283b;
- color: #f8fafc;
- font-weight: 800;
- cursor: pointer;
+ gap: 0.35rem;
}
.location-map-zone-hidden-note {
- display: grid;
- gap: 0.45rem;
margin-top: 0.55rem;
}
-.location-map-zone-hidden-note p {
- margin: 0;
-}
-
-.location-map-zone-hidden-note button {
- min-height: 40px;
- width: fit-content;
- padding: 0.45rem 0.7rem;
+.location-map-inline-state {
+ min-height: 42px;
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) auto auto;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.25rem 0.35rem 0.25rem 0.55rem;
border: 1px solid var(--color-border-light);
border-radius: 8px;
+ background: rgba(15, 23, 34, 0.56);
+ color: #f8fafc;
+}
+
+.location-map-inline-state span {
+ min-width: 0;
+ color: #9fb3c8;
+ font-size: 0.82rem;
+ font-weight: 800;
+}
+
+.location-map-inline-state strong {
+ color: #f8fafc;
+ font-weight: 900;
+ white-space: nowrap;
+}
+
+.location-map-inline-state button {
+ min-height: 34px;
+ min-width: 64px;
+ padding: 0.35rem 0.6rem;
+ border: 1px solid var(--color-border-light);
+ border-radius: 999px;
background: #15283b;
color: #f8fafc;
font-weight: 800;
diff --git a/frontend/tests/location-map-manager.spec.ts b/frontend/tests/location-map-manager.spec.ts
index 80d8701..8ed1c45 100644
--- a/frontend/tests/location-map-manager.spec.ts
+++ b/frontend/tests/location-map-manager.spec.ts
@@ -2914,7 +2914,10 @@ test("viewer can buy selected zone items from the map", async ({ page }) => {
await expect(page.locator(".confirm-buy-modal")).toHaveCount(0);
await expect(page.locator(".location-map-sheet-count")).toHaveText("0 shown");
await expect(bakeryArea.locator(".location-map-count")).toHaveText("0 shown");
- await expect(page.getByText("Items are assigned here, but hidden by layer filters.")).toBeVisible();
+ const hiddenZoneState = page.locator(".location-map-zone-items .location-map-inline-state", { hasText: "Hidden" });
+ await expect(hiddenZoneState).toContainText("2");
+ await expect(hiddenZoneState.getByRole("button", { name: "Show Zone Items" })).toHaveText("Show");
+ await expect(page.getByText("Items are assigned here, but hidden by layer filters.")).toHaveCount(0);
await page.getByRole("button", { name: "Layers" }).click();
await page.getByRole("button", { name: "Bought" }).click();
@@ -3196,7 +3199,7 @@ test("viewer shows completed zone items without rebuy actions", async ({ page })
await expect(newlyBoughtRow.locator("small")).toHaveText("Bought");
});
-test("viewer explains when unmapped items are hidden by filters", async ({ page }) => {
+test("viewer shows compact state when unmapped items are hidden by filters", async ({ page }) => {
await mockMapShell(page);
const mapState = {
@@ -3228,13 +3231,15 @@ test("viewer explains when unmapped items are hidden by filters", async ({ page
await page.getByRole("button", { name: "Unmapped" }).click();
await expect(page.getByText("other batteries")).toHaveCount(0);
- await expect(page.getByText("Unmapped items are hidden by layer filters.")).toBeVisible();
- await expect(page.getByRole("button", { name: "Show Unmapped Items" })).toBeVisible();
+ const hiddenUnmappedState = page.locator(".location-map-unmapped-list .location-map-inline-state", { hasText: "Hidden" });
+ await expect(hiddenUnmappedState).toContainText("1");
+ await expect(hiddenUnmappedState.getByRole("button", { name: "Show Unmapped Items" })).toHaveText("Show");
+ await expect(page.getByText("Unmapped items are hidden by layer filters.")).toHaveCount(0);
await page.getByRole("button", { name: "Show Unmapped Items" }).click();
await expect(page.getByText("other batteries")).toBeVisible();
- await expect(page.getByText("Unmapped items are hidden by layer filters.")).toHaveCount(0);
+ await expect(hiddenUnmappedState).toHaveCount(0);
await expect(page.getByRole("button", { name: "Layers, 3 changed" })).toBeVisible();
});
@@ -3280,16 +3285,18 @@ test("viewer marks partial unmapped counts when filters hide some items", async
await expect(page.getByText("visible batteries")).toBeVisible();
await expect(page.getByText("hidden batteries")).toHaveCount(0);
- await expect(page.getByText("1 more hidden by layer filters.")).toBeVisible();
- await expect(page.getByRole("button", { name: "Show All Unmapped Items" })).toBeVisible();
+ const hiddenUnmappedState = page.locator(".location-map-unmapped-list .location-map-inline-state", { hasText: "Hidden" });
+ await expect(hiddenUnmappedState).toContainText("1");
+ await expect(hiddenUnmappedState.getByRole("button", { name: "Show All Unmapped Items" })).toHaveText("Show All");
+ await expect(page.getByText("1 more hidden by layer filters.")).toHaveCount(0);
await page.getByRole("button", { name: "Show All Unmapped Items" }).click();
await expect(page.getByText("hidden batteries")).toBeVisible();
- await expect(page.getByText("1 more hidden by layer filters.")).toHaveCount(0);
+ await expect(hiddenUnmappedState).toHaveCount(0);
});
-test("viewer explains when selected zone items are hidden by filters", async ({ page }) => {
+test("viewer shows compact state when selected zone items are hidden by filters", async ({ page }) => {
await mockMapShell(page);
const mapState = publishedMapState([
@@ -3327,7 +3334,10 @@ test("viewer explains when selected zone items are hidden by filters", async ({
await frozenArea.locator("rect").first().click();
await expect(page.locator(".location-map-sheet-count")).toHaveText("0 shown");
- await expect(page.getByText("Items are assigned here, but hidden by layer filters.")).toBeVisible();
+ const hiddenZoneState = page.locator(".location-map-zone-items .location-map-inline-state", { hasText: "Hidden" });
+ await expect(hiddenZoneState).toContainText("1");
+ await expect(hiddenZoneState.getByRole("button", { name: "Show Zone Items" })).toHaveText("Show");
+ await expect(page.getByText("Items are assigned here, but hidden by layer filters.")).toHaveCount(0);
await expect(page.getByText("frozen salmon")).toHaveCount(0);
await page.getByRole("button", { name: "Show Zone Items" }).click();
@@ -3398,8 +3408,10 @@ test("viewer marks partial zone counts when filters hide some items", async ({ p
await expect(page.locator(".location-map-sheet-count")).toHaveText("1 shown");
await expect(page.getByText("visible bread")).toBeVisible();
await expect(page.getByText("hidden baguette")).toHaveCount(0);
- await expect(page.getByText("1 more hidden by layer filters.")).toBeVisible();
- await expect(page.getByRole("button", { name: "Show All Zone Items" })).toBeVisible();
+ const hiddenZoneState = page.locator(".location-map-zone-items .location-map-inline-state", { hasText: "Hidden" });
+ await expect(hiddenZoneState).toContainText("1");
+ await expect(hiddenZoneState.getByRole("button", { name: "Show All Zone Items" })).toHaveText("Show All");
+ await expect(page.getByText("1 more hidden by layer filters.")).toHaveCount(0);
await page.getByRole("button", { name: "Show All Zone Items" }).click();
@@ -3472,7 +3484,10 @@ test("viewer handles empty and many-item zone panels without default pins", asyn
await page.locator('[data-object-key="1562"]').locator("rect").first().click();
await expect(page.locator(".location-map-sheet-count")).toHaveText("0 items");
- await expect(page.getByText("No items assigned to this zone yet.")).toBeVisible();
+ const emptyZoneState = page.locator(".location-map-zone-items .location-map-inline-state", { hasText: "Items" });
+ await expect(emptyZoneState).toContainText("0");
+ await expect(emptyZoneState.getByRole("button")).toHaveCount(0);
+ await expect(page.getByText("No items assigned to this zone yet.")).toHaveCount(0);
await page.locator('[data-object-key="1561"]').locator("rect").first().click();
await expect(page.locator(".location-map-sheet-count")).toHaveText("14 items");