From 06567942139e7b3e118a8fcc479ee3e684936fc5 Mon Sep 17 00:00:00 2001 From: Sanne de Vries Date: Tue, 19 May 2026 15:38:53 +0200 Subject: [PATCH 1/4] Paginate exploration candidates with "Show more" - Show 10 results per column, then reveal 5 more per click up to 20. - Keep already-picked steps visible even if they're further down the list. --- .../dashboard/extra/exploration/constants.ts | 3 +- .../extra/exploration/exploration-column.tsx | 56 ++++++++++++++++++- .../controllers/api/stats_controller.ex | 3 +- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/assets/js/dashboard/extra/exploration/constants.ts b/assets/js/dashboard/extra/exploration/constants.ts index ee2363b1968f..7d14f76ac315 100644 --- a/assets/js/dashboard/extra/exploration/constants.ts +++ b/assets/js/dashboard/extra/exploration/constants.ts @@ -16,5 +16,6 @@ export const DIRECTION_OPTIONS: ExplorationDirectionOption[] = [ export const PAGE_FILTER_KEYS = ['page', 'entry_page', 'exit_page'] -export const MAX_VISIBLE_CANDIDATES = 10 +export const INITIAL_VISIBLE_CANDIDATES = 10 +export const SHOW_MORE_INCREMENT = 5 export const MIN_GRID_COLUMNS = 3 diff --git a/assets/js/dashboard/extra/exploration/exploration-column.tsx b/assets/js/dashboard/extra/exploration/exploration-column.tsx index ac6450d127fb..d2a0fc7f6439 100644 --- a/assets/js/dashboard/extra/exploration/exploration-column.tsx +++ b/assets/js/dashboard/extra/exploration/exploration-column.tsx @@ -8,14 +8,18 @@ import { } from '../../util/number-formatter' import { CursorIcon, FolderIcon } from '../../components/icons' import { popover } from '../../components/popover' -import { ChevronUpDownIcon } from '@heroicons/react/20/solid' +import { + ChevronUpDownIcon, + EllipsisHorizontalIcon +} from '@heroicons/react/20/solid' import { FlagIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline' import { roundedPercentage } from './helpers' import { journeyStepsEqual, JourneyStep, JourneySuggestion } from './journey' import { DIRECTION, DIRECTION_OPTIONS, - MAX_VISIBLE_CANDIDATES, + INITIAL_VISIBLE_CANDIDATES, + SHOW_MORE_INCREMENT, ExplorationDirection } from './constants' @@ -341,13 +345,40 @@ export function ExplorationColumn({ onFilterChange((e.target as HTMLInputElement).value) ) + // Track how many times the user has clicked "Show N more" for this column. + // Reset whenever the underlying results array reference changes so a new + // candidate list (filter change, journey change, etc.) starts collapsed. + const [expandCount, setExpandCount] = useState(0) + useEffect(() => { + setExpandCount(0) + }, [results]) + + // If the selected step lives beyond INITIAL_VISIBLE_CANDIDATES in a frozen + // column, make sure it is still visible by expanding the base window to + // include it. The user picked it from a list they could see, so it should + // remain visible after selection. + const selectedIndex = + selected && results.length > 0 + ? results.findIndex(({ step }) => journeyStepsEqual(step, selected)) + : -1 + const baseVisibleCount = Math.max( + INITIAL_VISIBLE_CANDIDATES, + selectedIndex >= 0 ? selectedIndex + 1 : 0 + ) + const visibleCount = Math.min( + results.length, + baseVisibleCount + expandCount * SHOW_MORE_INCREMENT + ) + const remainingCount = Math.max(0, results.length - visibleCount) + const showMoreCount = Math.min(SHOW_MORE_INCREMENT, remainingCount) + // When a step is selected but there are no candidate results, // synthesise a single-item list from the funnel data so // the selected step is still rendered in the column. const listItems = selected && results.length === 0 ? [{ step: selected, visitors: selectedVisitors ?? 0 }] - : results.slice(0, MAX_VISIBLE_CANDIDATES) + : results.slice(0, visibleCount) const stepMaxVisitors = maxVisitors ?? results[0]?.visitors @@ -427,6 +458,25 @@ export function ExplorationColumn({ onSelect={onSelectHandler} /> ))} + {showMoreCount > 0 && ( +
  • + +
  • + )} )} diff --git a/lib/plausible_web/controllers/api/stats_controller.ex b/lib/plausible_web/controllers/api/stats_controller.ex index 08fde268c4da..55e2c7d7a9ec 100644 --- a/lib/plausible_web/controllers/api/stats_controller.ex +++ b/lib/plausible_web/controllers/api/stats_controller.ex @@ -225,7 +225,8 @@ defmodule PlausibleWeb.Api.StatsController do Exploration.next_steps(site, query, journey, search_term: search_term, direction: direction, - include_wildcard?: include_wildcard? + include_wildcard?: include_wildcard?, + max_candidates: 20 ), funnel <- maybe_include_funnel(include_funnel?, query, journey, direction) do json(conn, %{next: next_steps, funnel: funnel}) From 7efeef4ed80befb6354cc50596b83f192f9e3a2d Mon Sep 17 00:00:00 2001 From: Sanne de Vries Date: Wed, 20 May 2026 14:56:53 +0200 Subject: [PATCH 2/4] Bump exploration max candidates to 50 and increment to 10 --- assets/js/dashboard/extra/exploration/constants.ts | 2 +- extra/lib/plausible/stats/exploration.ex | 2 +- lib/plausible_web/controllers/api/stats_controller.ex | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/js/dashboard/extra/exploration/constants.ts b/assets/js/dashboard/extra/exploration/constants.ts index 7d14f76ac315..a64a87b6a736 100644 --- a/assets/js/dashboard/extra/exploration/constants.ts +++ b/assets/js/dashboard/extra/exploration/constants.ts @@ -17,5 +17,5 @@ export const DIRECTION_OPTIONS: ExplorationDirectionOption[] = [ export const PAGE_FILTER_KEYS = ['page', 'entry_page', 'exit_page'] export const INITIAL_VISIBLE_CANDIDATES = 10 -export const SHOW_MORE_INCREMENT = 5 +export const SHOW_MORE_INCREMENT = 10 export const MIN_GRID_COLUMNS = 3 diff --git a/extra/lib/plausible/stats/exploration.ex b/extra/lib/plausible/stats/exploration.ex index 73d3a1c14ee1..5eb92dd557cc 100644 --- a/extra/lib/plausible/stats/exploration.ex +++ b/extra/lib/plausible/stats/exploration.ex @@ -33,7 +33,7 @@ defmodule Plausible.Stats.Exploration do } @max_steps 20 - @max_candidates 20 + @max_candidates 50 @next_steps_defaults [ search_term: "", diff --git a/lib/plausible_web/controllers/api/stats_controller.ex b/lib/plausible_web/controllers/api/stats_controller.ex index 55e2c7d7a9ec..3239139e742c 100644 --- a/lib/plausible_web/controllers/api/stats_controller.ex +++ b/lib/plausible_web/controllers/api/stats_controller.ex @@ -226,7 +226,7 @@ defmodule PlausibleWeb.Api.StatsController do search_term: search_term, direction: direction, include_wildcard?: include_wildcard?, - max_candidates: 20 + max_candidates: 50 ), funnel <- maybe_include_funnel(include_funnel?, query, journey, direction) do json(conn, %{next: next_steps, funnel: funnel}) From e6eaff8abb4f81e275ab2be16d4f6e0c67c3066e Mon Sep 17 00:00:00 2001 From: Adrian Gruntkowski Date: Thu, 21 May 2026 12:30:08 +0200 Subject: [PATCH 3/4] Extract number to a module attribute for clarity --- lib/plausible_web/controllers/api/stats_controller.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/plausible_web/controllers/api/stats_controller.ex b/lib/plausible_web/controllers/api/stats_controller.ex index 3239139e742c..5a03f31fbe4f 100644 --- a/lib/plausible_web/controllers/api/stats_controller.ex +++ b/lib/plausible_web/controllers/api/stats_controller.ex @@ -210,6 +210,8 @@ defmodule PlausibleWeb.Api.StatsController do end end + @exploration_max_candidates 50 + def exploration_next_with_funnel(conn, %{"journey" => steps} = params) do site = conn.assigns.site search_term = params["search_term"] || "" @@ -226,7 +228,7 @@ defmodule PlausibleWeb.Api.StatsController do search_term: search_term, direction: direction, include_wildcard?: include_wildcard?, - max_candidates: 50 + max_candidates: @exploration_max_candidates ), funnel <- maybe_include_funnel(include_funnel?, query, journey, direction) do json(conn, %{next: next_steps, funnel: funnel}) From fb90e3f6ab5955266285fdb25ada24bade3dcae5 Mon Sep 17 00:00:00 2001 From: Adrian Gruntkowski Date: Thu, 21 May 2026 13:10:54 +0200 Subject: [PATCH 4/4] Add e2e tests for load more --- .../extra/exploration/exploration-column.tsx | 2 +- e2e/tests/dashboard/exploration.spec.ts | 126 ++++++++++++++++++ 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/assets/js/dashboard/extra/exploration/exploration-column.tsx b/assets/js/dashboard/extra/exploration/exploration-column.tsx index d2a0fc7f6439..a598e8210464 100644 --- a/assets/js/dashboard/extra/exploration/exploration-column.tsx +++ b/assets/js/dashboard/extra/exploration/exploration-column.tsx @@ -459,7 +459,7 @@ export function ExplorationColumn({ /> ))} {showMoreCount > 0 && ( -
  • +