diff --git a/e2e/tests/journeys.spec.ts b/e2e/tests/journeys.spec.ts index b7ab141..2d1f881 100644 --- a/e2e/tests/journeys.spec.ts +++ b/e2e/tests/journeys.spec.ts @@ -567,6 +567,12 @@ test('a desktop postcode search opens on the map with the list beside it', async await expect(card.getByRole('button', { name: /Compar/ })).toBeVisible(); await expect(page.locator('.sc-pin').first()).toBeVisible({ timeout: 15_000 }); + // The count and the sort share one line at the top of the list. + const heading = await pane.getByRole('heading', { level: 2 }).boundingBox(); + const sort = await pane.getByRole('combobox').boundingBox(); + expect(Math.abs((heading!.y + heading!.height / 2) - (sort!.y + sort!.height / 2))) + .toBeLessThan(8); + // The split runs to the bottom of the screen rather than stopping short. const split = await page.locator('[class*="mapViewContainer"]').boundingBox(); expect(split!.y + split!.height).toBeGreaterThan(800 - 40); diff --git a/nextjs-app/__tests__/components/ResultsMapView.test.tsx b/nextjs-app/__tests__/components/ResultsMapView.test.tsx index 332dbea..812a81f 100644 --- a/nextjs-app/__tests__/components/ResultsMapView.test.tsx +++ b/nextjs-app/__tests__/components/ResultsMapView.test.tsx @@ -94,7 +94,8 @@ it('lists a name search, which has no map', async () => { it('puts the count and the sort in the list beside the map, once', async () => { await renderMap(); - expect(screen.getAllByRole('heading', { name: /3 schools within 1.0 miles of SW196AR/ })).toHaveLength(1); + // Short beside the map, so it shares one line with the sort. + expect(screen.getAllByRole('heading', { name: '3 schools within 1 mile' })).toHaveLength(1); expect(screen.getAllByRole('combobox')).toHaveLength(1); }); @@ -172,3 +173,9 @@ it('lets a keyboard pick a pin from the list, with a real button', async () => { expect(screen.getByTestId('map')).toHaveAttribute('data-selected', '2'); expect(show).toHaveAttribute('aria-pressed', 'true'); }); + +it('keeps the postcode in the heading in list view, where there is room', async () => { + await renderMap(); + fireEvent.click(screen.getByRole('button', { name: 'List' })); + expect(screen.getByRole('heading', { name: '3 schools within 1.0 miles of SW196AR' })).toBeInTheDocument(); +}); diff --git a/nextjs-app/components/HomeView.module.css b/nextjs-app/components/HomeView.module.css index 7ea8c08..75ce66d 100644 --- a/nextjs-app/components/HomeView.module.css +++ b/nextjs-app/components/HomeView.module.css @@ -608,13 +608,32 @@ border-right: 1px solid var(--border); } +/* One line: the count takes what the sort leaves, and truncates rather than + wrap if a narrow pane cannot fit both. */ .mapListPane .resultsHeader { - gap: 0.5rem; + flex-wrap: nowrap; + gap: 0.75rem; padding: 0.875rem 1rem 0.75rem; } .mapListPane .resultsHeader h2 { - font-size: var(--step-1); + flex: 1; + min-width: 0; + font-size: var(--step-0); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.mapListPane .resultsHeaderActions { + flex-shrink: 0; +} + +/* A select is as wide as its longest option ("Highest Reading, Writing & + Maths %", 281px), more than half the pane. Cap it; a long choice truncates. */ +.mapListPane .sortSelect { + max-width: 11rem; + text-overflow: ellipsis; } .mapContainer { diff --git a/nextjs-app/components/HomeView.tsx b/nextjs-app/components/HomeView.tsx index ceb5ce8..bcbec00 100644 --- a/nextjs-app/components/HomeView.tsx +++ b/nextjs-app/components/HomeView.tsx @@ -583,14 +583,20 @@ export function HomeView({ initialSchools, filters, totalSchools, howItWorks, ed ) ); + const schoolCount = `${initialSchools.total.toLocaleString()} school${initialSchools.total !== 1 ? 's' : ''}`; + // The count and the sort. Above the list in list view; at the top of the // list pane, beside the map, in map view. const resultsHeader = (

- {isLocationSearch && initialSchools.location_info - ? `${initialSchools.total.toLocaleString()} school${initialSchools.total !== 1 ? 's' : ''} within ${(initialSchools.location_info.radius / 1.60934).toFixed(1)} miles of ${initialSchools.location_info.postcode}` - : `${initialSchools.total.toLocaleString()} school${initialSchools.total !== 1 ? 's' : ''} found` + {/* Beside the map the heading shares one line with the sort, so it + drops the postcode, which the search box just above already shows. */} + {isMapView && radiusMiles != null + ? `${schoolCount} within ${radiusMiles} mile${radiusMiles === 1 ? '' : 's'}` + : isLocationSearch && initialSchools.location_info + ? `${schoolCount} within ${(initialSchools.location_info.radius / 1.60934).toFixed(1)} miles of ${initialSchools.location_info.postcode}` + : `${schoolCount} found` }