Files
fuel-alert/docs/superpowers/specs/2026-06-12-inline-fuel-pills-design.md
Ovidiu U 4c0017cb91 Add design spec for inline Petrol/Diesel quick pills
Surfaces the two everyday fuels as one-tap pills in the results filter
bar, left of the Filters pill; the popover keeps the four long-tail
fuels under a "More fuels" section. Results-bar only, no API change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 11:28:26 +01:00

4.6 KiB

Inline Petrol/Diesel Quick Pills — Design

Date: 2026-06-12 Status: Approved (brainstorm) Branch: feature/inline-fuel-pills

Problem

After a station search, the only way to change fuel type is to open the "Filters" popover, which buries the two everyday fuels — Petrol (e10) and Diesel (b7_standard) — behind a button. Almost every user wants one of those two. We want them surfaced as one-tap pills directly in the results filter bar, while keeping the four long-tail fuels (Premium e5, Prem Diesel b7_premium, b10, hvo) reachable.

Scope

  • Single file: resources/js/components/PostSearchFilters.vue.
  • No backend/API change — server-side fuel filtering already exists via the fuel_type query param on /api/stations.
  • Home.vue unchanged — the pills reuse the existing search event contract the popover already emits.
  • HeroSearch.vue unchanged — placement is results-bar only (the hero keeps forwarding whatever fuelType is in the URL).

Layout

The top row of the filter bar changes from a single right-aligned "Filters" button to:

[ ⛽ Petrol ] [ Diesel ] ……………… [ ≡ Filters ▾ ]
  • Two fuel pills left-aligned; the Filters pill pushed right via ml-auto.
  • All three reuse the existing pill !rounded-xl class + is-active state, so they are visually identical (the user's explicit "same row, same style" requirement).
  • (lucide:fuel) icon on Petrol only; Diesel is label-only (matches the user's mock).
  • The row stays flex flex-wrap items-center so it wraps gracefully on narrow screens.

Fuel model

  • Primary fuels (pills): e10 → "Petrol", b7_standard → "Diesel".
  • Long-tail fuels (popover "More fuels"): every other entry in FUEL_TYPESe5, b7_premium, b10, hvo. Derived by filtering FUEL_TYPES to exclude the two primary values, so the list stays driven by the shared window.FUEL_TYPES source rather than a second hard-coded list.

The two primary fuel values (e10, b7_standard) are defined once as a local constant in the component, with the short pill labels ("Petrol" / "Diesel"). The canonical enum labels ("Petrol (E10)", "Diesel (B7)") are intentionally not used on the pills — the short forms are a UX shortening.

Behaviour

  • Tapping Petrol sets fuelType = 'e10'; tapping Diesel sets fuelType = 'b7_standard'. Either triggers an immediate re-search via the existing watch([fuelType, radius, sort]) — no new emit wiring.
  • The popover "Fuel" section is relabeled "More fuels" and renders only the long-tail fuels. Selecting one re-searches and drops both pill highlights.

Highlighting — the selected fuel is always visible

  • e10 active → Petrol pill is-active.
  • b7_standard active → Diesel pill is-active.
  • A long-tail fuel active → neither pill highlighted, but the selected fuel is highlighted inside the "More fuels" grid, and the Filters pill shows its active state + badge. Selection is never ambiguous in any state.

Filters badge / active count

  • Fuel contributes to the Filters badge (activeCount) only when a long-tail fuel is active — the pills already display Petrol/Diesel selection, so those need no badge.
  • Radius, sort, and brand contribute to activeCount as before.
  • hasActive (which controls the "Clear all" affordance) likewise treats fuel as active only when a long-tail fuel is selected.

Clear all

  • Resets radius / sort / brand to their defaults.
  • If a long-tail fuel is selected, snaps fuel back to Petrol (e10) so the badge clears.
  • A Petrol/Diesel pill choice is left alone (the default is Petrol anyway).

Accessibility

  • The two pills form a role="radiogroup" labelled "Fuel" with aria-checked on each, consistent with the existing radio pattern already used in this component for radius/sort/brand.
  • The "More fuels" grid remains its own radiogroup.

Out of scope

  • No new filter criteria (supermarket-only, open-now, amenities, price ceiling).
  • No hero fuel selector.
  • No server-side brand filtering (brand stays a client-side filter in Home.vue).
  • No change to the radius or sort options.

Testing

  • npm run build must succeed (no Vite/compile regressions).
  • Behavioural verification of: Petrol/Diesel toggles re-search and highlight; selecting a long-tail fuel via the popover shows the badge with neither pill highlighted; "Clear all" resets radius/sort/brand and snaps a long-tail fuel back to Petrol.
  • The exact mechanism (Pest 4 browser test vs. a JS unit harness vs. manual) is decided in the implementation plan after confirming what frontend test infrastructure exists in the repo.