fix: #3617499 Follow the design system for the header search icon and box
Issue: https://www.drupal.org/project/vartheme_bs5_horizonaid/issues/3617499
Implements the six header-search designs from the VBNGO Stylesheet — 9641-704 and 9640-614 (the search bar, desktop and mobile), 751-5190 (header desktop) and the three mobile header states 9641-993 / 9641-1107 / 9640-556.
What changed and why
icon-toggle was an older fork of the base vartheme_bs5 component: no panel prop, no expand_in_editor, no Bootstrap Dropdown, and its own show/hide code. It rendered a 384×125 box with no close button where the design draws a 720×42 bar with one. This re-syncs it with base and keeps brand values in this theme's SCSS below a marked divider, so everything above stays re-syncable next time base moves.
The panel would not open — a duplicated library, not a missing one
The component asked for vartheme_bs5/bs-dropdown-script while every other component here asks for the Horizon Aid library. Both themes are on disk, so Bootstrap's dropdown.js was evaluated twice from two theme paths. Each evaluation registers its own document-level click data-API handler over an independent Dropdown class and instance map, so a single click toggled two instances — the measured event sequence was show → shown → hide → hidden, leaving aria-expanded="false".
The lesson worth carrying: when re-syncing a component across themes, the namespace has to be rewritten in the library dependencies, not only in Twig.
Two further defects in this theme's own code
- The unscoped exposed-filter card skin (
views-exposed-filters.scssplus ahook_form_alter()that attaches it to every exposed form) applied its 1.25rem inset inside the header bar, pushing the field off the design's 8px gap. - Below lg the band began half a gutter outside the viewport and stood 50px tall instead of 74px:
icon-toggle.jsresolves its band withclosest()over a selector list ending insection, and this theme wraps the header in an edge-to-edge Section, while the header's own.dropdown-menupadding outweighed the band's own.
Both are restated in the brand block. The closest() and padding issues are arguably worth fixing upstream in vartheme_bs5.
Measured against the designs
| Design | Measured | |
|---|---|---|
| open panel, desktop 1440 | 720 × 42 | 720 × 42 |
| open panel, mobile 375 | 343 × 42 | 343 × 42 |
| icon → field gap | 8px | 8px |
| placeholder | 14px, line-height 1.5 | 14px / 21px |
| bottom border | 0.5px #0d2c54 |
0.5px, navy rgb(13,44,84) |
| focus on open | yes | yes |
| Escape / close button / outside click | close | all close, focus returns to the trigger |
Accessibility
The exposed field keeps its label so it has an accessible name, and the bar renders that label visually hidden (Bootstrap's visually-hidden) because the design shows none there. The label is hidden, never removed — measured 1×1, position:absolute, accessible name Search by keyword. On the results page it stays visible, which the six designs do not cover. The recipe half of this (giving the exposed filter a non-empty label) is on #3617244.
Deliberately not in this MR
views-view-searchis untouched. My working clone was behindc33b469e, so a re-sync there would have replaced this branch's newer five-file version (including its SCSS) with base's three files and dropped the search-results styling.- The 17.5px search glyph. This build emits
.fs-5{1rem}/.fs-6{0.875rem}, so 17.5px needs a new$font-sizesstep inscss/_bootstrap-variables.scssplus an enum change inbootstrap-icon, which mints new component versions. I used the nearest step (16px) rather than add!importantor invent a class. That is a token decision for the maintainer. - Mobile push vs overlay. Figma pushes the menu down by exactly the 74px band; base uses
position: fixedand overlays. Following the design needs the panel to be an in-flow row in the base theme's header structure, so the geometry here is faithful and the positioning is left as base's. The designs make the menu and search mutually exclusive anyway.
Checkpoints
- File an issue
- Addition/Change/Update/Fix
- Reviewed by a human
- Code review by maintainers
AI-Generated: Yes