diff --git a/packages/unity-bootstrap-theme/public/img/custom-mobile-header-icon/menu-search-icon.png b/packages/unity-bootstrap-theme/public/img/custom-mobile-header-icon/menu-search-icon.png new file mode 100644 index 0000000000..e3a14e52a1 Binary files /dev/null and b/packages/unity-bootstrap-theme/public/img/custom-mobile-header-icon/menu-search-icon.png differ diff --git a/packages/unity-bootstrap-theme/src/js/global-header.js b/packages/unity-bootstrap-theme/src/js/global-header.js index 0463ff66a4..e696342a4e 100644 --- a/packages/unity-bootstrap-theme/src/js/global-header.js +++ b/packages/unity-bootstrap-theme/src/js/global-header.js @@ -11,6 +11,52 @@ const initGlobalHeader = () => { }; EventHandler.on(window, "scroll.uds.header", handleWindowScroll); + + // Search toggle (v2 header only) + const searchButtons = document.querySelectorAll( + ".uds-header-v2 .header-top-search .search-button" + ); + searchButtons.forEach(btn => { + btn.addEventListener("click", () => { + const form = btn.closest(".header-top-search"); + if (form) { + form.classList.add("open"); + const input = form.querySelector(".search-input"); + if (input) input.focus(); + } + }); + }); + + // Mobile search: toggle submit button visibility based on input value + document + .querySelectorAll(".uds-header-v2 .navbar-mobile-search input[type=search]") + .forEach(input => { + input.addEventListener("input", () => { + const form = input.closest(".navbar-mobile-search"); + if (form) { + if (input.value.length > 0) { + form.classList.add("has-value"); + } else { + form.classList.remove("has-value"); + } + } + }); + }); + + // Close search on blur if empty (v2 header only) + document + .querySelectorAll(".uds-header-v2 .header-top-search .search-input") + .forEach(input => { + input.addEventListener("blur", () => { + if (!input.value) { + const form = input.closest(".header-top-search"); + if (form) { + // Small delay to allow submit button click to register + setTimeout(() => form.classList.remove("open"), 200); + } + } + }); + }); }; window.initGlobalHeader = window.initGlobalHeader || initGlobalHeader; diff --git a/packages/unity-bootstrap-theme/src/scss/extends/_global-header.scss b/packages/unity-bootstrap-theme/src/scss/extends/_global-header.scss index 412f7e70c2..b30ad9dfc4 100644 --- a/packages/unity-bootstrap-theme/src/scss/extends/_global-header.scss +++ b/packages/unity-bootstrap-theme/src/scss/extends/_global-header.scss @@ -107,7 +107,8 @@ $fa-search: url($image-assets-path + "/font-awesome-svg/search.svg"); text-decoration: underline; } - &.visually-hidden, &.visually-hidden-focusable { + &.visually-hidden, + &.visually-hidden-focusable { justify-self: flex-start; } } @@ -211,12 +212,12 @@ $fa-search: url($image-assets-path + "/font-awesome-svg/search.svg"); } #asu-header.scrolled { - #wrapper-header-top { + &:not(.uds-header-v2) #wrapper-header-top { height: 0; overflow: hidden; } - #header-top { + &:not(.uds-header-v2) #header-top { height: 0; overflow: hidden; } @@ -1155,3 +1156,225 @@ the content of the header } } } + +/*-------------------------------------------------------------- +# Global Header V2 Overrides +# Scoped under .uds-header-v2 so pre-existing headers are unaffected. +--------------------------------------------------------------*/ + +#asu-header.uds-header-v2 { + // --- Top bar: search button/input/submit --- + #wrapper-header-top { + padding: 0.5rem 0rem; + } + #header-top { + .nav > *:not(:last-child) { + margin-right: 1.5rem; + } + .nav > *:nth-last-child(2) { + margin-right: 0.75rem; + } + .nav-link { + padding: 0; + margin: 0; + } + .header-top-search { + display: flex; + align-items: center; + + .search-button { + border: none; + background: transparent; + cursor: pointer; + font-size: 0.75rem; + line-height: 1; + color: $asu-gray-1; + display: inline-flex; + align-items: center; + vertical-align: middle; + white-space: nowrap; + + span { + margin-right: 0.25rem; + } + } + + .search-input { + width: 200px; + background-color: $uds-color-base-white; + border: 1px solid $asu-gray-5; + border-radius: 0; + padding: 0.5rem; + font-weight: 400; + font-size: 0.75rem; + line-height: 1; + color: $asu-gray-3; + outline: $asu-gray-1; + margin: 0; + margin-left: 1.5rem; + display: none; + vertical-align: middle; + height: auto; + background-image: none; + + &::placeholder { + font-size: 0.75rem; + line-height: 1; + } + + &:focus, + &:focus-visible { + border: 1px solid $asu-gray-1; + box-shadow: none !important; + } + } + + .search-submit { + margin-left: 0.5rem; + font-weight: 700; + font-size: 0.875rem; + line-height: 1; + padding: 0.5rem 1rem; + border: none; + display: none; + } + + &.open { + margin-left: -1rem; + + .search-button { + display: none; + } + + .search-input { + display: unset; + } + + .search-submit { + display: inline-flex; + } + } + } + } + + // --- Toggler button --- + #header-main .navbar-toggler { + background: transparent; + border-radius: 0; + cursor: pointer; + min-width: 44px; + min-height: 44px; + + .menu-search-icon { + display: none; + } + + &.collapsed .menu-search-icon { + display: unset; + width: 24px; + height: auto; + } + + &.collapsed .fa-stack { + display: none; + } + + .fa-circle.fa-stack-2x { + color: transparent; + } + } + + // --- Mobile: hide fa-home icon, show mobile search above nav --- + #header-main .navbar-nav .nav-link .fa-home { + display: none; + } + + .navbar-collapse.collapsing .navbar-mobile-footer, + .navbar-collapse.show .navbar-mobile-footer { + position: fixed; + bottom: 0; + right: 0; + width: 100%; + } + + > .navbar-mobile-search, + #header-main .navbar-mobile-search { + padding: $uds-size-spacing-2 $uds-size-spacing-4; + width: 100%; + position: relative; + display: flex; + align-items: center; + + .mobile-search-icon { + position: absolute; + left: calc(#{$uds-size-spacing-4} + 10px); + color: $asu-gray-3; + font-size: 14px; + pointer-events: none; + z-index: 1; + } + + &.has-value .mobile-search-icon { + display: none; + } + + &.has-value input { + padding-left: 1rem; + } + + input { + width: 100%; + background-color: $uds-color-base-white; + border: 1px solid $asu-gray-5; + border-radius: 0; + padding-left: 32px; + padding: 0.5rem 3rem 0.5rem 2.25rem; + + &::-webkit-search-cancel-button, + &::-webkit-search-decoration, + &::-webkit-search-results-button, + &::-webkit-search-results-decoration { + display: none; + -webkit-appearance: none; + } + } + + .mobile-search-submit { + display: none; + position: absolute; + top: 50%; + right: calc(#{$uds-size-spacing-4} + 0.5rem); + transform: translate(0, -50%); + border-radius: 50%; + width: 2rem; + height: 2rem; + background-color: $uds-color-base-maroon; + color: $uds-color-base-white; + border: none; + cursor: pointer; + font-size: 0.75rem; + padding: 0; + align-items: center; + justify-content: center; + z-index: 10; + } + + &.has-value .mobile-search-submit { + display: flex; + } + } + + // --- Desktop overrides --- + @include media-breakpoint-up(xl) { + #header-main .navbar-mobile-search { + display: none; + } + + #header-main .navbar-nav > .nav-link-home { + .fa-home { + display: inline-block; + font-size: 16px; + } + } + } +} diff --git a/packages/unity-bootstrap-theme/stories/organisms/global-header/global-header.templates.jsx b/packages/unity-bootstrap-theme/stories/organisms/global-header/global-header.templates.jsx index 1eb39c8780..bf6a3bd233 100644 --- a/packages/unity-bootstrap-theme/stories/organisms/global-header/global-header.templates.jsx +++ b/packages/unity-bootstrap-theme/stories/organisms/global-header/global-header.templates.jsx @@ -2,12 +2,13 @@ import React from "react"; import vertlogo from "./arizona-state-university-logo-vertical.png"; import horizlogo from "./arizona-state-university-logo.png"; import starbucksLogo from "./asu-starbucks.png"; +const menuSearchIcon = "/img/custom-mobile-header-icon/menu-search-icon.png"; export const Basic = () => ( <>
@@ -52,33 +53,42 @@ export const Basic = () => ( Colleges and Schools
- - Sparky - - Sign Out + Sign In
+ - + @@ -104,7 +114,7 @@ export const Basic = () => (
( data-ga-header-type="click" data-ga-header="menu button label" > - + Menu and Search Icon -
-
- Subdomain name +