diff --git a/TODO.md b/TODO.md new file mode 100644 index 000000000..12bc55e17 --- /dev/null +++ b/TODO.md @@ -0,0 +1,21 @@ +# GH-101 Header Redesign + +## Known Issues + +1. On CMS & Docs, there is a large gap in the navigation bar. +2. On CMS, mobile navbar opens and closes very slowly. +3. The portal login link is a bit too wide. +4. The code is often difficult to follow. + +## New Issues + +- remove down arrow on mobile toggle +- if close is issue, allow click on bottom no link area of lsit to close menu +- remove click on portal nav toggle (for consistency with cms/search nav) +- turn off scrolling when mobile menu is open +- docs “Next” button is too high a z-index +- rollover on all, do not let dropdown be clickable to return + +## Production Bug + +- Docs mobile nav not working… fix may be delayed, pending WMA CEPv2 chat diff --git a/taccsite_cms/static/site_cms/css/src/_imports/components/bootstrap.navbar.css b/taccsite_cms/static/site_cms/css/src/_imports/components/bootstrap.navbar.css new file mode 100644 index 000000000..df4d086c8 --- /dev/null +++ b/taccsite_cms/static/site_cms/css/src/_imports/components/bootstrap.navbar.css @@ -0,0 +1,17 @@ +/* +Navbar (Bootstrap) + +Add to Bootstrap styles. See: + +- [Bootstrap Grid](https://getbootstrap.com/docs/4.0/components/navbar/) + +Styleguide Components.Bootstrap.Navbar +*/ + +/* To support collapsing navbar horizontally */ +/* SEE: https://stackoverflow.com/a/50064701/11817077 */ +.collapsing.width { + transition-property: width, visibility; + width: 0; + height: auto; +} diff --git a/taccsite_cms/static/site_cms/css/src/_imports/trumps/for-portal.header.css b/taccsite_cms/static/site_cms/css/src/_imports/trumps/for-portal.header.css index 3e872dc5f..bb9c4fcb3 100644 --- a/taccsite_cms/static/site_cms/css/src/_imports/trumps/for-portal.header.css +++ b/taccsite_cms/static/site_cms/css/src/_imports/trumps/for-portal.header.css @@ -7,31 +7,44 @@ Styleguide Trumps.ForOtherSites.Portal */ @import url("_imports/tools/selectors.css"); + + +/* Selectors */ + +/* HACK: Relying on definition from `s-header.css` */ +/* @custom-selector :--portal-button */ + + + /* Ammend `s-header.css` (for Header because of Body) */ @media (--nav-compressed) { - /* To position navbar+button based on screen width instead of parent width */ - /* FAQ: Portal body min-width places a static button outside narrow screen */ + /* To position navbar menus/buttons based on window width not parent width */ + /* FAQ: Portal at body min. width places menu buttons outside narrow screen */ + /* NOTE: If Portal had no horz. body scroll, then we would not need this */ :--for-portal .s-header :--navbar-toggle { position: absolute; /* assumes Bootstrap `.navbar { position: relative }` */ width: env(--header-navbar-toggle-width); left: calc( 100vw - - env(--header-navbar-mobile-right-pad) - env(--header-navbar-toggle-width) - ); /* full screen width – distance from right of screen – its own width */ - - /* To overwrite `s-header.css` */ - margin-right: auto; + - env(--header-navbar-toggle-width--portal-user) + ); /* FAQ: = window width – width of all toggles */ + } + :--for-portal .s-header .s-portal-nav { + position: absolute; /* assumes Bootstrap `.navbar { position: relative }` */ + width: env(--header-navbar-toggle-width--portal-user); /* !!!: Makes "Log In" link too wide */ + left: calc( + 100vw + - env(--header-navbar-toggle-width--portal-user) + ); /* FAQ: = window width – its own width (not others, cuz it's the last) */ } - :--for-portal .s-header .navbar-collapse { - width: calc( - 100vw - env(--header-navbar-mobile-right-pad) - ); - /* To overwrite `s-header.css` */ - right: auto; + /* To prevent negligible width change from browser dynamic calculation */ + /* CAVEAT: Only Portal may use this cuz only its markup knows login state */ + :--for-portal .s-header.is-portal-user :--portal-button { + width: env(--header-navbar-toggle-width--portal-user); } } diff --git a/taccsite_cms/static/site_cms/css/src/_imports/trumps/s-header.css b/taccsite_cms/static/site_cms/css/src/_imports/trumps/s-header.css index 44c522d8e..5d2f24524 100644 --- a/taccsite_cms/static/site_cms/css/src/_imports/trumps/s-header.css +++ b/taccsite_cms/static/site_cms/css/src/_imports/trumps/s-header.css @@ -34,6 +34,105 @@ Styleguide Trumps.Scopes.Header +/* + * MIXINS + */ + + + + + +/* To create noticable line between each item */ +%s-header-nav-link-border { + /* To ensure any background color does not cover box-shadow */ + position: relative; + + box-shadow: + /* x pos. */ calc(var(--nav-link-horz-pad) / 2) + /* y pos. */ calc(-1 * (2px + calc(var(--nav-link-horz-pad) / 2))) + /* blur */ 0 + /* spread */ calc(-1 * calc(var(--nav-link-horz-pad) / 2)) + /* color */ var(--nav-line-color); +} + +/* To create negligible line between each item */ +%s-header-menu-link-border { + /* To ensure any background color does not cover box-shadow */ + position: relative; + + box-shadow: + /* x pos. */ 0 + /* y pos. */ calc(-1 * (1px + var(--menu-link-horz-pad))) + /* blur */ 0 + /* spread */ calc(-1 * var(--menu-link-horz-pad)) + /* color */ var(--menu-line-color); +} + +%s-header-mobile-menu { + /* Layout: To stretch menu to cover most of page */ + position: fixed; + top: 0; + right: 0; + height: 100vh; + width: calc(100vw - env(--header-navbar-mobile-menu-offset)); + + /* Layout: To be above body content on Portal & Docs (not harmful on CMS) */ + z-index: 2; /* 2 overlaps `.s-header__menu-backdrop` on page with scrollbar */ + + /* Style */ + padding-top: env(--header-brandbar-mobile-height); + background-color: env(--header-link-bkgd-color); + border-left: env(--border-width--normal) solid var(--global-color-primary--dark); +} + + + + + +/* + * JAVASCRIPT + */ + + + + + +@media (--nav-compressed) { + + /* To allow a click outside a menu to close the menu */ + .s-header .show + .s-header__menu-backdrop { + /* Layout: To stretch element to always span full screen size */ + position: fixed; + top: 0; + left: 0; + height: 100vh; + width: env(--header-navbar-mobile-menu-offset); + + /* Layout: To be above body content on Portal & Docs (not harmful on CMS) */ + z-index: 1; + + /* Style: To blur and/or lighten the content behind the element */ + @supports (backdrop-filter: none) { + & { + /* To blur and lighten content behind the element */ + backdrop-filter: blur(18px) brightness(85%); + background-color: transparent; + } + } + @supports not (backdrop-filter: none) { + & { + /* To lighten content behind the element */ + background-color: rgba(var(--global-color-primary--x-light-rgb), 0.75); + } + } + } + +} + + + + + /* * GENERAL */ @@ -54,9 +153,20 @@ Styleguide Trumps.Scopes.Header +/* Elements */ + +/* To overwrite html-elements.css */ +.s-header a:active { + position: unset; + top: unset; +} + + + + + /* Variables */ -/* FAQ: These have `--header` prefix because they can be used outside header */ @media (--nav-expanded) { :root { --header-brandbar-height: env(--header-brandbar-normal-height); @@ -64,6 +174,16 @@ Styleguide Trumps.Scopes.Header --portal-navlink-max-width: none; } + + .s-header { + --menu-link-horz-pad: 11px; + --menu-line-color: env(--header-bkgd-color); + + --nav-line-color: transparent; + --nav-link-vert-pad: unset; + /* SEE: "Nav: Variables (Addendum)" */ + /* --nav-link-horz-pad: … */ + } } @media (--nav-compressed) { :root { @@ -72,6 +192,16 @@ Styleguide Trumps.Scopes.Header --portal-navlink-max-width: env(--portal-navlink-mobile-max-width); } + + .s-header { + --menu-link-horz-pad: 24px; + --menu-line-color: transparent; + + --nav-line-color: env(--header-accent-color); + --nav-link-vert-pad: 12px; + /* To line up navbar left-hand content with logo */ + --nav-link-horz-pad: calc(env(--header-navbar-toggle-width) / 2); + } } @@ -120,15 +250,9 @@ Styleguide Trumps.Scopes.Header /* Logo */ #header-logo { - /* To allow projects to change value and responsive design to use value */ - --space-after-logo-before-nav: 25px; - display: flex; align-items: center; - /* To overwrite Bootstrap */ - margin-right: var(--space-after-logo-before-nav); - /* FAQ: In case image does not load and browser shows alt text */ color: env(--header-text-color); } @@ -150,37 +274,6 @@ Styleguide Trumps.Scopes.Header -/* Logo: Mobile */ - -@media (--nav-expanded) { - #header-logo { - /* To manage logo width influence on other elements */ - /* To prevent zero-width element as it is loaded */ - /* To align position of first CMS nav link with Portal section headers */ - /* CAVEAT: Only works on narrow-enough logos */ - min-width: calc(190px - var(--space-after-logo-before-nav)); - - /* To align logo (whole image not just visible pixels) w/ Portal side nav */ - margin-left: env(--header-navbar-normal-left-pad); - } -} - - - -/* Logo: Desktop */ - -@media (--nav-compressed) { - #header-logo { - /* To prevent wide image from forcing `.navbar-toggler` to be wrapped */ - max-width: calc(188px - var(--space-after-logo-before-nav)); - - /* To match space between logo and left side of window */ - margin-left: env(--header-navbar-mobile-left-pad); - } -} - - - /* @@ -227,6 +320,9 @@ Styleguide Trumps.Scopes.Header } /* To overwrite Bootstrap */ +.s-header.navbar { + flex-wrap: nowrap; +} .s-header.navbar, /* To overwrite Bootstrap (see "Portal & Docs Selectors") */ :--for-docs .s-header.navbar, @@ -255,15 +351,22 @@ Styleguide Trumps.Scopes.Header /* FAQ: Set height of descendants, but not of CMS and Portal and mobile navs */ :--nav-bar-fake-bkgd, #header-logo, +/* FAQ: We set height of immediate content of elements, because: + - height for navbar elements is not respected as navbar collapses + - height for portal nav would hide its dropdown menu */ .s-header :--navbar-toggle, -.s-header .s-search-bar { +.s-header .navbar-collapse:not(.show) .s-search-bar::part(form), +.s-header :--portal-button { height: var(--header-navbar-height); } +.s-header .navbar-collapse:is(.show, .collapsing) .s-search-bar::part(form), +.s-header :--portal-message { + height: env(--header-navbar-normal-height); +} /* To support shrinking and truncation of certain nav elements */ /* SEE: https://css-tricks.com/flexbox-truncated-text/ */ .s-header .navbar-collapse, - #header-logo, .s-header .s-cms-nav, .s-header .s-search-bar { min-width: 0; } @@ -281,6 +384,10 @@ Styleguide Trumps.Scopes.Header @custom-selector :--navbar-toggle .navbar-toggler; +@custom-selector :--navbar-toggle__text + .navbar-toggler-text; +@custom-selector :--navbar-toggle__icon + .navbar-toggler-icon; @custom-selector :--navbar-toggle--opened .navbar-toggler[aria-expanded="true"]; @custom-selector :--navbar-toggle--closed @@ -294,17 +401,25 @@ Styleguide Trumps.Scopes.Header /* Layout */ - /* To layout the toggle as a "mobile button" */ - .s-header :--navbar-toggle--opened, - .s-header :--navbar-toggle--closed { + /* To push toggle (and everything to its right) to the right of the navbar */ + .s-header .navbar-collapse:not(.show) + :--navbar-toggle { + margin-left: auto; + } + + /* To layout the toggle content for a "mobile button" */ + .s-header :--navbar-toggle { /* WARNING: Do not set `display` outside of (--nav-compressed) */ /* FAQ: The button as Bootstrap `.navbar-toggler` uses `display: none` */ display: grid; } .s-header :--navbar-toggle--opened { @extend %x-mobile-button--only-icon; } .s-header :--navbar-toggle--closed { @extend %x-mobile-button--no-toggle; } - .s-header :--navbar-toggle::after { @extend %x-mobile-button__text; } - .s-header :--navbar-toggle::before { @extend %x-mobile-button__icon; } + .s-header :--navbar-toggle__icon { @extend %x-mobile-button__icon; } + .s-header :--navbar-toggle__text { @extend %x-mobile-button__text; } + /* AFTER GH-101: Remove this ruleset */ + .s-header :--navbar-toggle:not(.gh-101)::after { + @extend %x-mobile-button__text; + } @@ -313,23 +428,20 @@ Styleguide Trumps.Scopes.Header /* To layout the button */ .s-header :--navbar-toggle { width: env(--header-navbar-toggle-width); - - /* Prevent wrap of button while it has static width */ - /* FAQ: Wrap happens if logo is wide and button layout is not flexible */ - /* FAQ: Set flexible width that never wraps button (on Frontera) */ - /* FAQ: Set maximum width at env. variable */ - margin-right: clamp(0px, 15%, env(--header-navbar-mobile-right-pad)); } /* To style the button */ .s-header :--navbar-toggle { padding: 0; /* to overwrite Bootstrap */ - background-color: env(--header-portal-nav-bkgd-color); - /* To overwrite Bootstrap */ border: none; border-radius: 0; + background-color: env(--header-bkgd-color); + } + .s-header :--navbar-toggle:hover, + .s-header :--navbar-toggle:active { + background-color: env(--header-link-bkgd-color); } /* To isolate styles that require more specificity to override Portal */ @@ -340,30 +452,33 @@ Styleguide Trumps.Scopes.Header color: env(--header-text-color); } - .s-header :--navbar-toggle:hover, - .s-header :--navbar-toggle:active { - background-color: env(--header-link-bkgd-color); - } - /* Icon */ /* To overwrite Bootstrap */ - .s-header .navbar-toggler-icon { display: none; } + .s-header :--navbar-toggle__icon { background-image: none !important; } /* To swap Bootstrap icon for Cortal icon */ /* HACK: To apply icon styles without using a class in the markup */ /* FAQ: For dynamic markup change, Portal & Docs markup must be updated */ /* SEE: https://getbootstrap.com/docs/4.0/components/collapse/#events */ - .s-header :--navbar-toggle { @extend [class*=" icon-"]; } - .s-header :--navbar-toggle::before { @extend .icon; } + .s-header :--navbar-toggle__icon { + @extend [class*=" icon-"]; + @extend .icon; + } /* To change icon without using dynamic icon classes */ - .s-header :--navbar-toggle--opened { @extend .icon-close; } - .s-header :--navbar-toggle--closed { @extend .icon-burger; } - /* To stretch icon to mimic icon in design (which is not available yet) */ - .s-header :--navbar-toggle--closed::before { transform: scaleX(1.5); } + .s-header :--navbar-toggle--opened :--navbar-toggle__icon { + @extend .icon-close; + } + .s-header :--navbar-toggle--closed :--navbar-toggle__icon { + @extend .icon-burger; + } + /* To stretch icon to mimic icon in design */ + .s-header :--navbar-toggle--closed :--navbar-toggle__icon { + transform: scaleX(1.5); + } /* To overwrite `.icon` */ - .s-header :--navbar-toggle::before { + .s-header :--navbar-toggle__icon { font-size: 30px; /* WARNING: Do not use `rem` until `html { 62.5%; }` */ } @@ -371,16 +486,25 @@ Styleguide Trumps.Scopes.Header /* Text */ - .s-header :--navbar-toggle::after { - content: attr(data-icon-label); + .s-header :--navbar-toggle__text { + line-height: 1.4; /* to overwrite Bootstrap *//* to match `body` */ } - /* To apply style to old markup (see "Portal & Docs Selectors") */ - /* FAQ: This selector does not use `:--for-portal` but has similar purpose */ - .s-header :--navbar-toggle:not([data-icon-label])::after { + + /* To hide text of button when menu is open */ + .s-header :--navbar-toggle--opened :--navbar-toggle__text { + display: none; + } + + /* AFTER GH-101: Remove this block i.e. rely only on `[data-icon-label]` */ + /* To create fake text that does not exist in old markup */ + /* FAQ: The `:not(.gh-101)` applies style only to old markup */ + .s-header :--navbar-toggle:not(.gh-101)::after { content: 'Menu'; } - /* FAQ: Only the closed state is supposed to have text */ - .s-header :--navbar-toggle--opened::after { display: none; } + /* To hide fake text of button when menu is open */ + .s-header :--navbar-toggle--opened:not(.gh-101)::after { + display: none; + } } @@ -396,40 +520,13 @@ Styleguide Trumps.Scopes.Header @media (--nav-compressed) { - /* Style */ - + /* To make the navbar act similar to an overlay menu */ + /* CAVEAT: If menu is open, and layout switches from collapsed to expanded to collapsed, then menu will remain open upon return to collapsed layout. */ .s-header .navbar-collapse { - padding-top: 12px; + /* Layout */ + @extend %s-header-mobile-menu; - @supports (backdrop-filter: none) { - & { - backdrop-filter: blur(18px) brightness(85%); - background-color: rgba(var(--global-color-primary--x-dark-rgb), 0.6); - } - } - @supports not (backdrop-filter: none) { - & { - background-color: rgba(var(--global-color-primary--x-dark-rgb), 0.95); - } - } - - border: env(--border-width--normal) solid var(--global-color-primary--dark); - } - - - - /* Layout */ - - /* HACK: To make the navbar act similar to a dropdown */ - /* TODO: We should either use dropdown or create TACC nav component (GH-12) */ - /* CAVEAT: If menu is open, and layout switches from collapsed to expanded to collapsed, then menu will remain open upon return to collapsed layout. - /* CAVEAT: If menu is open, and user clicks anywhere outside the navbar, then menu remains open. But a real dropdown would be closed after such a click. */ - .s-header .navbar-collapse { - position: absolute; /* assumes Bootstrap `.navbar { position: relative }` */ - top: 100%; - left: 0; - right: env(--header-navbar-mobile-right-pad); - z-index: 1; /* To be above main content in Portal & Docs */ + transition-duration: 0s; /* to overwrite Bootstrap */ } } @@ -442,27 +539,6 @@ Styleguide Trumps.Scopes.Header -/* Nav: Variables */ - -@media (--nav-expanded) { - .s-header .navbar-nav { - --nav-line-color: transparent; - --nav-link-vert-pad: unset; - /* SEE: "Nav: Variables (Addendum)" */ - /* --nav-link-horz-pad: … */ - } -} -@media (--nav-compressed) { - .s-header .navbar-nav { - --nav-line-color: env(--header-accent-color); - --nav-link-vert-pad: 0.425em; - /* To line up navbar left-hand content with logo */ - --nav-link-horz-pad: calc(env(--header-navbar-toggle-width) / 2); - } -} - - - /* Nav: Variables (Addendum) */ /* To reduce space between nav links when space is limited */ @@ -470,18 +546,18 @@ Styleguide Trumps.Scopes.Header @media (--nav-expanded) and (--nav-wide-and-below) { /* TODO: Hardcode `is-on-portal` in Portal & Docs markup, then remove the `:--for-cms` selector prefix */ - :--for-cms .s-header:not(.is-on-portal) .navbar-nav { + :--for-cms .s-header:not(.is-on-portal) { --nav-link-horz-pad: 1em; } } /* FAQ: Reduce space at wider breakpoint when Portal Nav is present */ @media (--nav-expanded) and (--nav-x-wide-and-below) { - .s-header.is-on-portal .navbar-nav, + .s-header.is-on-portal, /* To apply style to old markup (see "Portal & Docs Selectors") */ /* TODO: Hardcode `is-on-portal` in Portal & Docs markup, then remove the `:--for-*` selectors */ - :--for-docs .s-header .navbar-nav, - :--for-portal .s-header .navbar-nav { + :--for-docs .s-header, + :--for-portal .s-header { --nav-link-horz-pad: 1em; } } @@ -492,19 +568,19 @@ Styleguide Trumps.Scopes.Header /* To have 15px of space for 12px font */ /* TODO: Hardcode `is-on-portal` in Portal & Docs markup, then remove the `:--for-cms` selector prefix */ - :--for-cms .s-header:not(.is-on-portal) .navbar-nav { + :--for-cms .s-header:not(.is-on-portal) { --nav-link-horz-pad: 1.5em; } } /* FAQ: Increase space at wider breakpoint when Portal Nav is present */ @media (--nav-expanded) and (--nav-x-wide-and-above) { /* To have 15px of space for 12px font */ - .s-header.is-on-portal .navbar-nav, + .s-header.is-on-portal, /* To apply style to old markup (see "Portal & Docs Selectors") */ /* TODO: Hardcode `is-on-portal` in Portal & Docs markup, then remove the `:--for-*` selectors */ - :--for-docs .s-header .navbar-nav, - :--for-portal .s-header .navbar-nav { + :--for-docs .s-header, + :--for-portal .s-header { --nav-link-horz-pad: 1.5em; } } @@ -515,6 +591,27 @@ Styleguide Trumps.Scopes.Header @media (--nav-expanded) { + /* To align text of CMS nav first link with text of Portal section header */ + .s-cms-nav { + margin-left: calc( -1 * var(--nav-link-horz-pad) ); + } + #header-logo { + /* FAQ: Projects with wide logos may change this value to tweak alignment */ + --space-after-logo-before-nav: env(--header-navbar-normal-left-pad); + + /* To prevent zero-width element as it is loaded */ + /* FAQ: This only has effect on narrow-enough logos */ + /* NOTE: Do not use on mobile, because section header alignment would be + moot if Portal were to even support mobile, because the section + header position would change, because sidebar would be hidden */ + min-width: calc(203px - var(--space-after-logo-before-nav)); + + /* To align logo (whole image not just visible pixels) w/ Portal side nav */ + margin-left: env(--header-navbar-normal-left-pad); + /* To overwrite Bootstrap */ + margin-right: var(--space-after-logo-before-nav); + } + /* To align CMS nav to the right ONLY if there is no Portal */ /* TODO: Hardcode `is-on-portal` in Portal & Docs markup, then remove the `:--for-cms` selector prefix */ @@ -541,8 +638,14 @@ Styleguide Trumps.Scopes.Header } /* To match design */ - .s-cms-nav { - padding-top: 8px; + .s-cms-nav, + .s-portal-nav .dropdown-menu { + padding-top: 5px; + } + + #header-logo { + /* To align logo (whole image not just visible pixels) w/ Portal side nav */ + margin-left: env(--header-navbar-normal-left-pad); } } @@ -567,37 +670,39 @@ Styleguide Trumps.Scopes.Header .nav-item.active .nav-link, .nav-item.dropdown.show .nav-link; */ -@custom-selector :--portal-nav-link--user - .s-portal-nav .nav-link.dropdown-toggle; -@custom-selector :--portal-nav-link--guest - .s-portal-nav .nav-link:not(.dropdown-toggle); -@custom-selector :--portal-nav-link__icon - .s-portal-nav .nav-link .icon; -@custom-selector :--portal-nav-link__text - .s-portal-nav .nav-link .nav-text; - +@custom-selector :--portal-nav-link + .s-portal-nav .nav-link; +@custom-selector :--portal-button + .s-portal-nav .dropdown:not(.show) .nav-link, + .s-portal-nav .nav-item:not(.dropdown) .nav-link; +@custom-selector :--portal-button--user + .s-portal-nav .dropdown:not(.show) .nav-link.dropdown-toggle; +@custom-selector :--portal-button--guest + .s-portal-nav .nav-item:not(.dropdown) .nav-link:not(.dropdown-toggle); +@custom-selector :--portal-button__icon + .s-portal-nav .dropdown:not(.show) .nav-link .icon, + .s-portal-nav :not(.dropdown) .nav-link .icon; +@custom-selector :--portal-button__text + .s-portal-nav .dropdown:not(.show) .nav-link .nav-text, + .s-portal-nav :not(.dropdown) .nav-link .nav-text; +@custom-selector :--portal-message + .s-portal-nav .dropdown.show .nav-link; +@custom-selector :--portal-message__icon + .s-portal-nav .dropdown.show .nav-link .icon; +@custom-selector :--portal-message__text + .s-portal-nav .dropdown.show .nav-link .nav-text; /* Nav Link: General */ +/* To layout the link */ .s-header .nav-link { /* To support truncation */ - /* To vertically center text and icons (if any) */ display: flex; + /* To vertically center text and icons (if any) */ align-items: center; } -.s-header .s-portal-nav .nav-link { - /* To horizontally center align icon, text, and toggle as a group */ - justify-content: center; - - /* To prevent expansion upon dropdown menu open */ - width: var(--portal-navlink-max-width); - - /* To prevent "Log In" from wrapping as it slides into place */ - /* NOTE: This affects username also, but it should not have any whitespace */ - white-space: nowrap; -} /* Nav Link: General: Desktop */ @@ -605,9 +710,6 @@ Styleguide Trumps.Scopes.Header .s-header .nav-link { height: 100%; } - .s-header .s-portal-nav .nav-link { - background-color: env(--header-portal-nav-bkgd-color); - } } /* Nav Link: General: Mobile */ @@ -616,10 +718,6 @@ Styleguide Trumps.Scopes.Header .s-header .s-cms-nav .nav-link { font-size: 2em; } - .s-header .s-portal-nav .nav-link { - /* To align portal nav link to the right */ - margin-left: auto; - } } @@ -638,101 +736,132 @@ Styleguide Trumps.Scopes.Header padding-bottom: var(--nav-link-vert-pad); } -/* Nav Link: Spacing: Desktop */ + + +/* Nav Link: Portal */ + +.s-header :--portal-button { + background-color: env(--header-portal-nav-bkgd-color); +} + +/* Nav Link: Portal: Desktop */ @media (--nav-expanded) { - .s-header .s-portal-nav .nav-link, + .s-header :--portal-nav-link, /* To overwrite Bootstrap (see "Portal & Docs Selectors") */ - :--for-portal .s-portal-nav .nav-link { + :--for-portal :--portal-nav-link { /* To match space between logo and left side of window */ --nav-link-horz-pad: env(--header-navbar-normal-left-pad); } - .s-header :--portal-nav-link__icon { - margin-right: 0.5em; - } + .s-header :--portal-nav-link { + /* To horizontally center align icon, text, and toggle as a group */ + justify-content: center; -} + /* To prevent expansion upon dropdown menu open */ + max-width: var(--portal-navlink-max-width); -/* Nav Link: Spacing: Mobile */ + /* To prevent wrapping of this as it slides into place */ + /* NOTE: This affects username also, but it should not have any whitespace */ + white-space: nowrap; + } -/* To match design of collapsed navbar Portal Nav but take liberty with when */ -@media (--nav-compressed) /* dev liberty */ { + /* CAVEAT: The selector must be specific enough to override Bootstrap */ + .s-header :--portal-nav-link, + /* To overwrite Bootstrap (see "Portal & Docs Selectors") */ + :--for-portal .s-header :--portal-nav-link { + padding-right: var(--nav-link-horz-pad, 0); + padding-left: var(--nav-link-horz-pad, 0); + } - .s-header .s-portal-nav .nav-link { - min-width: calc(2 * env(--header-navbar-toggle-width)); /* dev liberty */ + /* Icon */ - padding-top: 0; /* to overwrite Bootstrap */ - padding-bottom: 0; /* to overwrite Bootstrap */ - /* NOTE: Might as well be zero (given `width` is expected max-width), - but if username exceeds expectation some padding would look good */ - --nav-link-horz-pad: 1em; + .s-header :--portal-nav-link__icon { + margin-right: 0.5em; } } +/* Nav Link: Portal: Mobile */ +@media (--nav-compressed) { -/* Nav Link: Icon (Mobile-Only) */ + .s-header :--portal-nav-link/*,*//* ???: Is below selector necessary here? */ + /* To overwrite Bootstrap (see "Portal & Docs Selectors") */ + /* :--for-portal :--portal-nav-link */ { + /* To match design */ + --nav-link-vert-pad: 0; + } -@media (--nav-compressed) { + .s-header :--portal-button { + width: fit-content; - /* Layout */ + /* To avoid wrapping of button */ + /* FAQ: Wrap happens if logo is wide and button layout is not flexible */ + /* NOTE: The `clamp()` solution avoids using third media query for navbar */ + padding-right: clamp( + var(--nav-link-horz-pad, 0), + 3vw, + env(--header-navbar-mobile-right-pad) + ); /* FAQ: The widths must prevent wrap when `#header-logo` is max. width */ + padding-left: var(--nav-link-horz-pad, 0); + + /* NOTE: This is for the edge case that username exceeds expectation */ + --nav-link-horz-pad: 12px; + } - /* To layout each link as a "mobile button" */ - .s-header .s-portal-nav .nav-link { + /* Icon */ + + /* To make link appear as a button when menu is closed */ + .s-header :--portal-button { display: grid; } - .s-header :--portal-nav-link--user { - @extend %x-mobile-button--has-toggle; + .s-header :--portal-button--user { @extend %x-mobile-button--has-toggle;} + .s-header :--portal-button--guest { @extend %x-mobile-button--no-toggle; } + .s-header :--portal-button__icon { @extend %x-mobile-button__icon; } + .s-header :--portal-button__text { @extend %x-mobile-button__text; } + .s-header :--portal-button::after { @extend %x-mobile-button__toggle; } + /* AFTER GH-101: Remove this ruleset */ + .s-header :--portal-button:not(.gh-101)::before { + @extend %x-mobile-button__text; } - .s-header :--portal-nav-link--guest { - @extend %x-mobile-button--no-toggle; + + /* To make link appear as a welcome message when menu is open */ + .s-header :--portal-message__icon { + margin-right: 0.875em; /* To approximate design via "pretty" `em` value */ } - .s-header :--portal-nav-link__icon { - @extend %x-mobile-button__icon; + .s-header :--portal-message__text { + font-size: 18px; /* WARNING: Do not use `rem` until `html { 62.5%; }` */ + font-weight: var(--regular); } - .s-header .s-portal-nav .nav-link::before { - @extend %x-mobile-button__text; + .s-header :--portal-message__text::before { + content: 'Welcome, '; } - .s-header .s-portal-nav .nav-link::after { - @extend %x-mobile-button__toggle; + .s-header :--portal-message::after { + display: none; } - - - /* Text */ - - /* To apply style to old markup (see "Portal & Docs Selectors") */ - /* FAQ: This selector does not use `:--for-portal` but has similar purpose */ - .s-header :--portal-nav-link--guest::before { - content: 'Log In'; - } - /* Use content for text, not actual text */ - /* FAQ: For consistency with `:--navbar-toggle` */ - /* FAQ: Because the text need not be selectable anyway */ - .s-header :--portal-nav-link__text { display: none; } - /* To hide the stray text */ - .s-header :--portal-nav-link--guest { font-size: 0; } - } /* Nav Link: Separator */ -/* To create line between each item */ -.s-header .nav-item + .nav-item .nav-link { - /* To ensure any background color does not cover box-shadow */ - position: relative; +/* Nav Link: Separator: Desktop */ - box-shadow: - /* x pos. */ calc(var(--nav-link-horz-pad) / 2) - /* y pos. */ calc(-1 * (2px + calc(var(--nav-link-horz-pad) / 2))) - /* blur */ 0 - /* spread */ calc(-1 * calc(var(--nav-link-horz-pad) / 2)) - /* color */ var(--nav-line-color); +@media (--nav-expanded) { + .s-header .nav-item + .nav-item .nav-link { + @extend %s-header-nav-link-border; + } +} + +/* Nav Link: Separator: Mobile */ + +@media (--nav-compressed) { + .s-header .nav-item + .nav-item:not(.dropdown.show) .nav-link { + @extend %s-header-nav-link-border; + } } @@ -803,37 +932,25 @@ Styleguide Trumps.Scopes.Header -/* Dropdown: Variables */ - -@media (--nav-expanded) { - .s-header .dropdown { - --menu-link-horz-pad: 11px; - --menu-line-color: env(--header-bkgd-color); - } -} -@media (--nav-compressed) { - .s-header .dropdown { - --menu-link-horz-pad: 26px; - --menu-line-color: transparent; - } -} - - - /* Dropdown: Toggle */ .s-header .dropdown-toggle::after { @extend %x-arrow; - --size: 0.375em; --line: 0.1em; /* to get 1px at 12px text and 2px at 24px text */ --color: env(--header-text-color); + + position: relative; /* to allow use of `top` (to vertically align) */ +} + +/* Dropdown: Toggle: Layout: Default */ + +.s-header .dropdown-toggle::after { + --size: 0.375em; --nudge: 0.24em; margin-left: 0.6em; - position: relative; /* to allow use of `top` (to vertically align) */ } -/* To vertically align with text */ .s-header .dropdown-toggle[aria-expanded="true"]::after { @extend %x-arrow--up; top: var(--nudge); @@ -843,25 +960,42 @@ Styleguide Trumps.Scopes.Header bottom: var(--nudge); } +/* Dropdown: Toggle: Layout: Mobile */ +@media (--nav-compressed) { + /* CMS Menu */ + .s-header .s-cms-nav .dropdown-toggle::after { + --size: 0.2em; + --nudge: 0.1em; + } + .s-header .s-cms-nav .dropdown-toggle[aria-expanded="true"]::after { + @extend %x-arrow--left; + margin-right: calc(-1 * var(--size)); /* to pull text closer */ + left: calc((-1 * var(--size) * 2) - var(--nudge)); /* to align arrow */ + order: -1; /* move to far left */ + top: auto; /* overwrite default */ + } + .s-header .s-cms-nav .dropdown-toggle[aria-expanded="false"]::after { + @extend %x-arrow--right; + margin-left: auto; + right: var(--nudge); + /* order: 2; /* retain position */ + bottom: auto; /* overwrite default */ + } -/* Dropdown Menu */ - -/* To layout menu */ -.s-header .s-portal-nav .dropdown-menu { - /* To stretch dropdown width to match width of its parent */ - width: 100%; } -/* To style menu */ -/* To overwrite Bootstrap */ -/* FAQ: Bootstrap has styles we do not want a value for, so `unset` */ -.s-header .dropdown-menu { - margin: unset; - border-radius: unset; + + + +/* Dropdown Menu */ + +.s-header .dropdown-menu { + margin: unset; /* to undo Bootstrap */ + border-radius: unset; /* to undo Bootstrap */ } @@ -870,7 +1004,7 @@ Styleguide Trumps.Scopes.Header @media (--nav-expanded) { - /* Dropdowns */ + /* All Dropdowns */ /* To overwrite Bootstrap */ .s-header .dropdown-menu { @@ -882,6 +1016,13 @@ Styleguide Trumps.Scopes.Header font-size: 12px; /* WARNING: Do not use `rem` until `html { 62.5%; }` */ } + /* Portal Nav */ + + .s-header .s-portal-nav .dropdown-menu { + /* To stretch dropdown width to match the width of its parent */ + min-width: 100%; + } + } @@ -890,29 +1031,81 @@ Styleguide Trumps.Scopes.Header @media (--nav-compressed) { + /* CMS Menu & Portal Nav */ + /* To overwrite Bootstrap */ - .s-header .dropdown-menu { - font-size: 20px; /* WARNING: Do not use `rem` until `html { 62.5%; }` */ - } .s-header .s-cms-nav .dropdown-menu { padding: 0 0 0.5em 0; + margin: unset; /* to undo Bootstrap */ background-color: transparent; border: none; - /* To indent dropdown menu */ - /* To match CMS nav menu padding */ - margin-left: calc(env(--header-navbar-toggle-width) / 2); + font-size: 18px; /* WARNING: Do not use `rem` until `html { 62.5%; }` */ } .s-header .s-portal-nav .dropdown-menu { - /* To retain dropdown, not push-down, behavior */ - /* FAQ: Bootstrap uses `static` for navbar dropdowns until wide screen */ - position: absolute; + /* padding-top: unset; /* to undo Bootstrap *//* FAQ: Set elsewhere by us */ + padding-bottom: unset; /* to undo Bootstrap */ - padding: 0; - - background-color: env(--header-link-bkgd-color); + background-color: transparent; border: none; + + font-size: 24px; /* WARNING: Do not use `rem` until `html { 62.5%; }` */ + } + + /* CMS Nav */ + + .s-header .s-cms-nav .dropdown-menu { + @extend %s-header-nav-link-border; + + /* To allow `position: relative` to not move the menu */ + /* SEE: `_navbar.scss` + .navbar-nav .dropdown-menu { position: static; float: none; } */ + top: 0; + } + + /* Portal Nav */ + + /* To make the navbar act similar to an overlay menu */ + /* CAVEAT: If menu is open, and layout switches from collapsed to expanded to collapsed, then menu will remain open upon return to collapsed layout. */ + .s-header .s-portal-nav .dropdown.show { + /* Layout */ + @extend %s-header-mobile-menu; + + left: auto; /* to overwrite Bootstrap */ + } + .s-header .s-portal-nav .dropdown.show .dropdown-menu { + flex-grow: 1; + } + + /* Nested Dropdown */ + + /* To hide sibling dropdowns */ + /* CAVEAT: Relies on JavaScript specific to `s-cms-nav` (fallback: `… ~ …` */ + .s-header .js-has-open-menu .dropdown:not(.show), + /* CAVEAT: Does not hide previous siblings (solution: `js-has-open-menu`) */ + .s-header .nav-item.dropdown.show ~ .nav-item { + display: none; + } + + /* To provide a back button */ + .s-header .s-cms-nav .dropdown-toggle[aria-expanded="true"] { + flex-wrap: wrap; + } + .s-header .s-cms-nav .dropdown-toggle[aria-expanded="true"]::after, + .s-header .s-cms-nav .dropdown-toggle[aria-expanded="true"]::before { + /* To approximate design */ + margin-bottom: 32px; + } + .s-header .s-cms-nav .dropdown-toggle[aria-expanded="true"]::before { + content: 'All'; + flex-grow: 1; + + /* Style */ + font-size: 18px; /* WARNING: Do not use `rem` until `html { 62.5%; }` */ + } + .s-header .s-cms-nav .dropdown-toggle[aria-expanded="true"] .nav-text { + flex-basis: 100%; } } @@ -930,7 +1123,7 @@ Styleguide Trumps.Scopes.Header .s-header .dropdown-item { border-left: env(--border-width--x-thick) solid transparent; - font-weight: env(--medium); + font-weight: env(--bold); } @@ -941,7 +1134,7 @@ Styleguide Trumps.Scopes.Header --nav-link-vert-pad: 0.4em; /* To overwrite Bootstrap */ - padding: var(--nav-link-vert-pad) var(--menu-link-horz-pad); + padding: var(--nav-link-vert-pad) var(--menu-link-horz-pad, 0); } @@ -949,16 +1142,24 @@ Styleguide Trumps.Scopes.Header /* Dropdown Item: Separator */ /* To create line between each item */ -.s-header .dropdown-item + .dropdown-item { - /* To ensure any background color does not cover box-shadow */ - position: relative; +.s-header .s-cms-nav .dropdown-item + .dropdown-item { + @extend %s-header-menu-link-border; +} - box-shadow: - /* x pos. */ 0 - /* y pos. */ calc(-1 * (1px + var(--menu-link-horz-pad))) - /* blur */ 0 - /* spread */ calc(-1 * var(--menu-link-horz-pad)) - /* color */ var(--menu-line-color); +/* Dropdown Item: Separator: Desktop */ + +@media (--nav-expanded) { + .s-header .s-portal-nav .dropdown-item + .dropdown-item { + @extend %s-header-menu-link-border; + } +} + +/* Dropdown Item: Separator: Mobile */ + +@media (--nav-compressed) { + .s-header .s-portal-nav .dropdown-item + .dropdown-item { + @extend %s-header-nav-link-border; + } } @@ -1019,7 +1220,7 @@ Styleguide Trumps.Scopes.Header --input-font-size: 14px; /* To match design */ - --space-after-search-before-nav: 12px; + --space-after-search: 12px; /* To insert flexible space between search bar and CMS nav */ --space-before-search: auto; @@ -1027,17 +1228,16 @@ Styleguide Trumps.Scopes.Header } @media (--nav-compressed) { .s-header .s-search-bar { - /* NOTE: Deviates from design cuz "Mobile Nav Top Row" height deviates */ - --input-height: 38px; + --input-height: 45px; /* WARNING: Do not use `rem` until `html { 62.5%; }` */ --button-font-size: 24px; --input-font-size: 18px; - /* SEE: "Mobile Nav Top Row" */ - /* --space-after-search-before-nav: … */ + /* To match design */ + --space-after-search: 0; - /* To line up logo with navbar left-hand content */ - --space-before-search: env(--header-navbar-mobile-left-pad); + /* To let padding manage space */ + --space-before-search: 0; } } @@ -1114,7 +1314,7 @@ Styleguide Trumps.Scopes.Header then remove the `:--for-*` selectors */ :--for-docs .s-header .s-search-bar, :--for-portal .s-header .s-search-bar { - margin-right: var(--space-after-search-before-nav, 0); + margin-right: var(--space-after-search, 0); } /* Create space before search bar EVEN IF only search bar exists */ .s-header .s-search-bar { @@ -1134,53 +1334,23 @@ Styleguide Trumps.Scopes.Header @media (--nav-compressed) { - /* To move portal nav & search bar to top of navbar */ - /* FAQ: The `.show` & `.collapsing` allow Bootstrap `display: none` to work */ - .s-header .navbar-collapse.show, - .s-header .navbar-collapse.collapsing { + /* To move portal nav & search bar to top of menu */ + .s-header .navbar-collapse:is(.show, .collapsing), + .s-header .s-portal-nav .dropdown.show { display: flex; flex-direction: column; } - .s-header .s-portal-nav { order: -1; } - .s-header .s-search-bar { order: -2; } + .s-header .navbar-collapse:is(.show, .collapsing) .s-search-bar { order: -2; } + .s-header :--portal-message { order: -1; } + + /* To create a bar at top of menu */ + .s-header .navbar-collapse:is(.show, .collapsing) .s-search-bar, + .s-header :--portal-message { + padding-left: var(--menu-link-horz-pad, 0); + padding-right: var(--menu-link-horz-pad, 0); - /* To combine search bar & portal nav into one row */ - .s-header .s-search-bar { - /* To make space for portal nav in which to shove portal nav */ - --space-after-search-before-nav: calc( - var(--portal-navlink-max-width) + 5px - ); - } - .s-header .s-portal-nav { - /* To shove portal nav into same row as search bar */ - margin-top: calc(-1 * env(--header-navbar-mobile-height)); - } - - /* To set height */ - /* FAQ: We set height of immediate content of elements, because: - - height for elements is not respected as navbar collapses - - height for portal nav would hide its dropdown menu - */ - .s-header .s-search-bar::part(form), - .s-header .s-portal-nav .nav-link { - height: var(--header-navbar-height); - } - - /* To make a fake background */ - /* HACK: Create background with a pseudo element that matches "row" height */ - .s-header .s-portal-nav { position: relative; } - .s-header .s-portal-nav::before { - content: ''; - position: absolute; - left: 0; - top: 0; - height: 100%; - width: 100%; - z-index: -1; background-color: env(--header-bkgd-color); } - /* To ensure search bar can be focused i.e. is above the fake background */ - .s-header .s-search-bar { z-index: 1; } } @@ -1220,7 +1390,7 @@ Styleguide Trumps.Scopes.Header /* To add space between icon and text for ONLY portal nav top-level and CMS */ .s-header .s-portal-nav .dropdown-item .icon, .s-header .s-cms-nav .icon { - margin-right: 0.5em; + display: none; } } diff --git a/taccsite_cms/static/site_cms/css/src/_imports/trumps/s-header.twig.html b/taccsite_cms/static/site_cms/css/src/_imports/trumps/s-header.twig.html index 214208ab9..ce1a35409 100644 --- a/taccsite_cms/static/site_cms/css/src/_imports/trumps/s-header.twig.html +++ b/taccsite_cms/static/site_cms/css/src/_imports/trumps/s-header.twig.html @@ -10,8 +10,6 @@ - multiple internal scope (`s-`) classes (only via `./s-portal-nav.html`) (only via `./s-cms-nav.html`) -- FontAwesome class names - (only via `./s-portal-nav.html`) - illegally-nested markup (`ul > div > li`) (only via `./s-portal-nav.html`) --> @@ -26,7 +24,7 @@