Problem/Motivation

The search results page renders through the shared Views view component, which is written for a listing rather than for a results page. Three things follow from that, and a fourth comes from the exposed filter skin.

1. The results page has no heading of its own. The shared component prints title, which a Views page display leaves empty, so the page opens straight into a filter bar with nothing naming it. The page therefore has zero h1 elements.

2. The result summary is printed above the search box. The shared component emits header before exposed. On a listing that is right; on a results page it puts "Showing 1-10 of 12" above the field the visitor came to use.

3. The empty state is a bare paragraph. A search that matches nothing renders loose text with no surface, which reads as a page that failed to load rather than as an answer.

4. The search form inherits the listing filter card's layout. The exposed filter skin is built for a row of filters plus Apply Filters and Reset, so it puts the actions on their own full-width line:

  .form-actions {
    display: flex;
    flex: 1 0 100%;
  }

The search form has a single keyword field and no reset, so the Search button drops onto a second line underneath a half-empty one. Its field also renders without the magnifier, because the icon rule keys on the listing filters' search identifier while the search view's identifier is keywords.

Worth recording for anyone styling the empty state: --bs-tertiary-bg resolves to #212529 in this theme, so a notice built on that token would put body-coloured text on a dark surface.

Steps to reproduce

  1. Install a site that uses this theme and has a search results page at /search.
  2. Open /search?keywords=water.
  3. The page has no h1; the result count sits above the search box.
  4. Open /search?keywords=telescope: the "no results" text has no surface.
  5. Narrow the viewport, or put the same form in a header panel: the Search button wraps below the field.

Proposed resolution

  1. Add a Views view search organism that takes the same template_preprocess_views_view() variables and prints them in the order a results page reads: the view title as the page h1, then the exposed filter bar, then the result summary, then the rows. It gives the empty state a view-empty--notice panel built from --bs-secondary-bg-subtle and --bs-border-color.
  2. Add templates/views/views-view--search--page.html.twig so only the search page display renders through it and every other view keeps the shared component's order.
  3. Add a views-exposed-form--search modifier to the exposed filters component: the keyword field and the Search button share one line at every width, the field carries the magnifier, and the doubled bottom margin is dropped. The magnifier moves into a mixin so the listing filters and the search form share one definition instead of two copies of the same inline SVG.
  4. Attach that modifier class from hook_form_alter(), matched on the form-ID prefix, the way the events and blog filter rows already are, so a search form gets it wherever it renders.

Verified on a clean install (dropped database, drush site:install, 78 items indexed), in a real browser at 1440px and 390px:

  • exactly one h1, reading "Search", on every results state;
  • order is heading, then filter bar, then summary, then rows;
  • field and Search button on one line: field 1142x47 and button 102x42 at the same y on desktop, 212x47 and 102x42 at 390px, and 196x47 and 102x42 inside a 384px header panel with no overflow;
  • empty-state notice #f7f9fa behind #212529 text, contrast 14.61:1, 20px radius, 24px padding;
  • 0 console errors, no horizontal overflow introduced.

Remaining tasks

  • ✔ File an issue
  • ✔ Addition/Change/Update/Fix
  • ✔ Testing to ensure no regression
  • ✔ Automated unit/functional testing coverage
  • ➖ Developer Documentation support
  • ➖ User Guide Documentation support
  • ➖ UX/UI designer responsibilities
  • ✔ Accessibility and Readability
  • ❌ Reviewed by a human
  • ❌ Code review by maintainers
  • ❌ Full testing and approval
  • ❌ Credit contributors
  • ❌ Review with the product owner
  • ❌ Update Release Notes
  • ❌ Release

User interface changes

  • The search results page gains a page heading, and its search box moves above the result summary.
  • A search that finds nothing shows a bordered notice instead of loose text.
  • The search form's field and button sit on one line, and the field carries the magnifier.

API changes

  • New component vartheme_bs5_horizonaid:views-view-search. No existing component's props or slots change.

Data model changes

  • N/A

Release notes snippet

  • Search results now carry a page heading, show the search box above the result summary, keep the field and the Search button on one line, and render a readable notice when nothing matches.

AI-Generated: Yes

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

rajab natshah created an issue. See original summary.

  • rajab natshah committed c33b469e on 1.0.x
    fix: #3617499 Give the search results page a heading and keep its filter...

  • rajab natshah committed 979934e8 on 1.0.x
    fix: #3617499 Follow the design system for the header search icon and...
rajab natshah’s picture

Assigned: Unassigned » josebc
Status: Active » Needs review
Issue tags: +vartheme_bs5_horizonaid-1.0.0-alpha2
rajab natshah’s picture

Assigned: josebc » mohammed j. razem
rajab natshah’s picture

Assigned: mohammed j. razem » Unassigned
Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.