@utahdts/utah-design-system-header 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +576 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/style.css +1 -1
- package/dist/utah-design-system-header.es.js +5 -5
- package/dist/utah-design-system-header.umd.js +4 -4
- package/package.json +5 -4
- package/src/index.js +11 -0
- package/src/js/enumerations/childrenMenuTypes.js +13 -0
- package/src/js/enumerations/domConstants.js +149 -0
- package/src/js/enumerations/environments.js +16 -0
- package/src/js/enumerations/events.js +14 -0
- package/src/js/enumerations/popupPlacement.js +32 -0
- package/src/js/enumerations/sizes.js +12 -0
- package/src/js/enumerations/utahIdUrls.js +10 -0
- package/src/js/lifecycle/globalEvents.js +81 -0
- package/src/js/lifecycle/hookupMobileActionItemKeyboarding.js +114 -0
- package/src/js/lifecycle/lifecycle.js +180 -0
- package/src/js/misc/checkForError.js +16 -0
- package/src/js/misc/findRecursive.js +39 -0
- package/src/js/misc/isString.js +8 -0
- package/src/js/misc/isTouchDevice.js +9 -0
- package/src/js/misc/jsDocTypes.js +235 -0
- package/src/js/misc/notNull.js +15 -0
- package/src/js/misc/popupFocusHandler.js +209 -0
- package/src/js/misc/renderDOMSingle.js +61 -0
- package/src/js/misc/showHideElement.js +15 -0
- package/src/js/misc/toHash.js +18 -0
- package/src/js/misc/uuidv4.js +8 -0
- package/src/js/misc/valueOrFunctionValue.js +13 -0
- package/src/js/renderables/_html/NewTabAccessibility.html +4 -0
- package/src/js/renderables/actionItems/ActionItems.js +29 -0
- package/src/js/renderables/actionItems/html/ActionItem.html +5 -0
- package/src/js/renderables/actionItems/html/ActionItemMenuContent.html +3 -0
- package/src/js/renderables/actionItems/html/ActionItemsWrapper.html +1 -0
- package/src/js/renderables/actionItems/html/BadgeWrapperHtml.html +4 -0
- package/src/js/renderables/actionItems/html/MobileActionItem.html +7 -0
- package/src/js/renderables/actionItems/renderActionItem.js +103 -0
- package/src/js/renderables/actionItems/renderActionItemBadge.js +50 -0
- package/src/js/renderables/actionItems/renderMobileActionItem.js +97 -0
- package/src/js/renderables/actionItems/renderMobileActionItems.js +83 -0
- package/src/js/renderables/citizenExperience/CitizenExperience.js +24 -0
- package/src/js/renderables/citizenExperience/html/CitizenExperienceWrapper.html +1 -0
- package/src/js/renderables/citizenExperience/html/CitizenExperienceWrapperMobile.html +1 -0
- package/src/js/renderables/footer/html/Footer.html +41 -0
- package/src/js/renderables/footer/renderFooter.js +111 -0
- package/src/js/renderables/headerWrapper/HeaderWrapper.js +46 -0
- package/src/js/renderables/headerWrapper/html/HeaderLogoWrapper.html +1 -0
- package/src/js/renderables/headerWrapper/html/HeaderWrapper.html +1 -0
- package/src/js/renderables/headerWrapper/html/VerticalLine.html +1 -0
- package/src/js/renderables/icons/html/AlertIcon.html +1 -0
- package/src/js/renderables/icons/html/ChevronIcon.html +1 -0
- package/src/js/renderables/icons/html/ExternalLinkIcon.html +7 -0
- package/src/js/renderables/icons/html/GearIcon.html +1 -0
- package/src/js/renderables/icons/html/QuestionIcon.html +1 -0
- package/src/js/renderables/icons/html/WaffleIcon.html +1 -0
- package/src/js/renderables/logoTitle/LogoTitle.js +63 -0
- package/src/js/renderables/logoTitle/html/LogoTitleWrapper.html +4 -0
- package/src/js/renderables/logoTitle/html/LogoTitleWrapperLink.html +4 -0
- package/src/js/renderables/mainMenu/html/MainMenuItem.html +13 -0
- package/src/js/renderables/mainMenu/html/MainMenuWrapper.html +26 -0
- package/src/js/renderables/mainMenu/renderMainMenu.js +258 -0
- package/src/js/renderables/menu/html/MenuWithTitle.html +3 -0
- package/src/js/renderables/menu/renderMenuWithTitle.js +24 -0
- package/src/js/renderables/mobile/addMobileMenuContentItem.js +37 -0
- package/src/js/renderables/mobile/hookupHamburger.js +112 -0
- package/src/js/renderables/mobile/hookupUtahIdInMobileMenu.js +79 -0
- package/src/js/renderables/mobile/html/MobileMenuContentItemWrapper.html +2 -0
- package/src/js/renderables/mobile/html/MobileMenuWrapper.html +32 -0
- package/src/js/renderables/mobile/mobileMenuInteractionHandler.js +155 -0
- package/src/js/renderables/mobile/renderMobileMenuHomeMenu.js +15 -0
- package/src/js/renderables/mobile/util/getHamburgerElements.js +22 -0
- package/src/js/renderables/mobile/util/showHideHamburgerElements.js +32 -0
- package/src/js/renderables/popup/html/Popup.html +5 -0
- package/src/js/renderables/popup/renderPopup.js +41 -0
- package/src/js/renderables/popupMenu/html/PopupMenu.html +1 -0
- package/src/js/renderables/popupMenu/html/PopupMenuItem.html +12 -0
- package/src/js/renderables/popupMenu/renderPopupMenu.js +341 -0
- package/src/js/renderables/search/html/SearchModal.html +25 -0
- package/src/js/renderables/search/showSearchModal.js +132 -0
- package/src/js/renderables/tooltip/hookupTooltip.js +82 -0
- package/src/js/renderables/tooltip/html/Tooltip.html +5 -0
- package/src/js/renderables/utahId/UtahId.js +227 -0
- package/src/js/renderables/utahId/html/UtahIdButton.html +1 -0
- package/src/js/renderables/utahId/html/UtahIdWrapper.html +1 -0
- package/src/js/renderables/utahLogo/UtahLogo.js +48 -0
- package/src/js/renderables/utahLogo/html/UtahLogoLarge.html +17 -0
- package/src/js/renderables/utahLogo/html/UtahLogoMedium.html +17 -0
- package/src/js/renderables/utahLogo/html/UtahOfficialWebsiteHoverContent.html +4 -0
- package/src/js/renderables/utahLogo/html/UtahOfficialWebsitePopupContent.html +41 -0
- package/src/js/renderables/utahLogo/renderOfficialWebsite.js +139 -0
- package/src/js/settings/defaultSettings.js +31 -0
- package/src/js/settings/getUtahHeaderSettings.js +16 -0
- package/src/js/settings/settings.js +69 -0
- package/src/js/settings/settingsKeeper.js +47 -0
- package/src/js/utahId/httpRequest.js +42 -0
- package/src/js/utahId/utahIdData.js +165 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
// @ts-ignore
|
|
3
|
+
// eslint-disable-next-line import/no-unresolved
|
|
4
|
+
import LogoTitleWrapper from './html/LogoTitleWrapper.html?raw';
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
// eslint-disable-next-line import/no-unresolved
|
|
7
|
+
import LogoTitleWrapperLink from './html/LogoTitleWrapperLink.html?raw';
|
|
8
|
+
|
|
9
|
+
import domConstants, { getCssClassSelector } from '../../enumerations/domConstants';
|
|
10
|
+
import renderDOMSingle from '../../misc/renderDOMSingle';
|
|
11
|
+
import valueOrFunctionValue from '../../misc/valueOrFunctionValue';
|
|
12
|
+
import getUtahHeaderSettings from '../../settings/getUtahHeaderSettings';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @returns {Element}
|
|
16
|
+
*/
|
|
17
|
+
export default function LogoTitle() {
|
|
18
|
+
const logoTitleURL = getUtahHeaderSettings().titleURL;
|
|
19
|
+
const logoTitleWrapper = !logoTitleURL ? renderDOMSingle(LogoTitleWrapper) : renderDOMSingle(LogoTitleWrapperLink);
|
|
20
|
+
if (!logoTitleWrapper) {
|
|
21
|
+
throw new Error('LogoTitle: titleWrapper is null');
|
|
22
|
+
}
|
|
23
|
+
if (logoTitleURL) {
|
|
24
|
+
logoTitleWrapper.setAttribute('href', logoTitleURL);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Render Logo image
|
|
28
|
+
const logoWrapper = logoTitleWrapper.querySelector(getCssClassSelector(domConstants.TITLE__LOGO));
|
|
29
|
+
if (!logoWrapper) {
|
|
30
|
+
throw new Error('LogoTitle: logoWrapper is null');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const settingsLogo = getUtahHeaderSettings().logo;
|
|
34
|
+
const settingsShowTitle = getUtahHeaderSettings().showTitle;
|
|
35
|
+
const settingsTitle = getUtahHeaderSettings().title;
|
|
36
|
+
if (settingsLogo) {
|
|
37
|
+
/** @type {HTMLCollection | Element} */
|
|
38
|
+
let settingsLogoElement;
|
|
39
|
+
if (settingsLogo.htmlString) {
|
|
40
|
+
settingsLogoElement = renderDOMSingle(valueOrFunctionValue(settingsLogo.htmlString));
|
|
41
|
+
} else if (settingsLogo.element) {
|
|
42
|
+
settingsLogoElement = valueOrFunctionValue(settingsLogo.element);
|
|
43
|
+
} else if (settingsLogo.imageUrl) {
|
|
44
|
+
settingsLogoElement = renderDOMSingle(`<img src=${valueOrFunctionValue(settingsLogo.imageUrl)} id="design-system-logo" />`);
|
|
45
|
+
} else {
|
|
46
|
+
throw new Error('LogoTitle: logo set but has no settings');
|
|
47
|
+
}
|
|
48
|
+
settingsLogoElement.setAttribute('role', 'presentation');
|
|
49
|
+
logoWrapper.appendChild(settingsLogoElement);
|
|
50
|
+
} else {
|
|
51
|
+
logoTitleWrapper.removeChild(logoWrapper);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Render Title text
|
|
55
|
+
const title = document.createTextNode(settingsTitle);
|
|
56
|
+
const titleWrapper = logoTitleWrapper.querySelector(getCssClassSelector(domConstants.TITLE__TITLE));
|
|
57
|
+
titleWrapper?.appendChild(title);
|
|
58
|
+
if (!settingsShowTitle && settingsLogo) {
|
|
59
|
+
titleWrapper?.classList.add(domConstants.VISUALLY_HIDDEN);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return logoTitleWrapper;
|
|
63
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<li class="menu-item">
|
|
2
|
+
<span class="menu-item__title">
|
|
3
|
+
<button class="menu-item__button-title" type="button">
|
|
4
|
+
<span class="menu-item__link-title-span"></span>
|
|
5
|
+
<span class="menu-item__menu-arrow utds-icon-before-chevron-down" aria-hidden="true"></span>
|
|
6
|
+
</button>
|
|
7
|
+
<a class="menu-item__link-title">
|
|
8
|
+
<span class="menu-item__link-title-span"></span>
|
|
9
|
+
<span class="menu-item__menu-arrow utds-icon-before-chevron-down" aria-hidden="true"></span>
|
|
10
|
+
</a>
|
|
11
|
+
<span class="menu-chiclet"></span>
|
|
12
|
+
</span>
|
|
13
|
+
</li>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<div class="utah-design-system main-menu__outer">
|
|
2
|
+
<div class="main-menu__wrapper">
|
|
3
|
+
<nav class="horizontal-menu main-menu__nav">
|
|
4
|
+
<h2 class="main-menu__title visually-hidden"></h2>
|
|
5
|
+
<ul class="main-menu__menu-top"></ul>
|
|
6
|
+
</nav>
|
|
7
|
+
<button type="button" class="button icon-button icon-button--borderless main-menu__search">
|
|
8
|
+
<div>
|
|
9
|
+
<span class="utds-icon-before-search" aria-hidden="true"></span>
|
|
10
|
+
<span class="visually-hidden">search</span>
|
|
11
|
+
</div>
|
|
12
|
+
</button>
|
|
13
|
+
<div class="utds-header-mobile__vip-action-items--left">
|
|
14
|
+
</div>
|
|
15
|
+
<div class="utds-header-mobile__utah-id-wrapper">
|
|
16
|
+
</div>
|
|
17
|
+
<div class="utds-header-mobile__vip-action-items--right">
|
|
18
|
+
</div>
|
|
19
|
+
<button type="button" class="button icon-button icon-button--borderless main-menu__hamburger"
|
|
20
|
+
id="utds-main-menu__hamburger">
|
|
21
|
+
<div>
|
|
22
|
+
<span class="utds-icon-before-hamburger" id="utds-main-menu__hamburger-icon" aria-hidden="true"></span>
|
|
23
|
+
</div>
|
|
24
|
+
</button>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
// @ts-ignore
|
|
3
|
+
// eslint-disable-next-line import/no-unresolved
|
|
4
|
+
import MainMenuItem from './html/MainMenuItem.html?raw';
|
|
5
|
+
// @ts-ignore
|
|
6
|
+
// eslint-disable-next-line import/no-unresolved
|
|
7
|
+
import MainMenuWrapper from './html/MainMenuWrapper.html?raw';
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
// eslint-disable-next-line import/no-unresolved
|
|
10
|
+
import NewTabAccessibility from '../_html/NewTabAccessibility.html?raw';
|
|
11
|
+
|
|
12
|
+
import childrenMenuTypes from '../../enumerations/childrenMenuTypes';
|
|
13
|
+
import domConstants, { getCssClassSelector } from '../../enumerations/domConstants';
|
|
14
|
+
import findRecursive from '../../misc/findRecursive';
|
|
15
|
+
import notNull from '../../misc/notNull';
|
|
16
|
+
import popupFocusHandler from '../../misc/popupFocusHandler';
|
|
17
|
+
import renderDOMSingle from '../../misc/renderDOMSingle';
|
|
18
|
+
import uuidv4 from '../../misc/uuidv4';
|
|
19
|
+
import getUtahHeaderSettings from '../../settings/getUtahHeaderSettings';
|
|
20
|
+
import renderPopupMenu from '../popupMenu/renderPopupMenu';
|
|
21
|
+
import showSearchModal from '../search/showSearchModal';
|
|
22
|
+
import hookupTooltip from '../tooltip/hookupTooltip';
|
|
23
|
+
import { renderUtahIdForMobile } from '../utahId/UtahId';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {import('../../misc/jsDocTypes').PopupMenu} PopupMenu
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @returns {{mainMenuWrapper: HTMLElement, utahIdPopup: HTMLElement | null}}
|
|
31
|
+
*/
|
|
32
|
+
export default function renderMainMenu() {
|
|
33
|
+
const settings = getUtahHeaderSettings();
|
|
34
|
+
/** @type {HTMLElement} */
|
|
35
|
+
const mainMenuWrapper = renderDOMSingle(MainMenuWrapper);
|
|
36
|
+
|
|
37
|
+
let mainMenuNav = mainMenuWrapper.querySelector(getCssClassSelector(domConstants.MAIN_MENU__NAV));
|
|
38
|
+
if (!mainMenuNav) {
|
|
39
|
+
throw new Error('renderMainMenu(): mainMenu not created');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const titleTag = mainMenuNav.querySelector(getCssClassSelector(domConstants.MAIN_MENU__TITLE));
|
|
43
|
+
if (!titleTag) {
|
|
44
|
+
throw new Error('renderMainMenu(): titleTag not found');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const mainMenuId = 'main-menu__nav';
|
|
48
|
+
mainMenuNav.setAttribute('aria-labelledby', mainMenuId);
|
|
49
|
+
titleTag.setAttribute('id', mainMenuId);
|
|
50
|
+
if (settings.mainMenu) {
|
|
51
|
+
titleTag.innerHTML = settings.mainMenu.title;
|
|
52
|
+
} else {
|
|
53
|
+
mainMenuNav.remove();
|
|
54
|
+
mainMenuNav = null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (settings.mainMenu) {
|
|
58
|
+
const mainMenuTop = mainMenuNav?.querySelector(getCssClassSelector(domConstants.MAIN_MENU__MENU_TOP));
|
|
59
|
+
if (!mainMenuTop) {
|
|
60
|
+
throw new Error('renderMainMenu(): mainMenuTop not found');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// render top level menu items with popups for their children
|
|
64
|
+
settings.mainMenu.menuItems.forEach((menuItem) => {
|
|
65
|
+
const mainMenuItem = renderDOMSingle(MainMenuItem);
|
|
66
|
+
mainMenuTop.appendChild(mainMenuItem);
|
|
67
|
+
|
|
68
|
+
const mainMenuItemTitle = notNull(
|
|
69
|
+
mainMenuItem.querySelector(getCssClassSelector(domConstants.MENU_ITEM__TITLE)),
|
|
70
|
+
`renderMainMenu(): sub menu title not found for ${menuItem.title}`
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const mainMenuItemButtonTitle = notNull(
|
|
74
|
+
/** @type {HTMLElement} */(
|
|
75
|
+
mainMenuItemTitle.querySelector(getCssClassSelector(domConstants.MENU_ITEM__BUTTON_TITLE))
|
|
76
|
+
),
|
|
77
|
+
`renderMainMenu(): button title not found for ${menuItem.title}`
|
|
78
|
+
);
|
|
79
|
+
mainMenuItemButtonTitle.setAttribute('id', `${domConstants.MENU_ITEM__BUTTON_TITLE}__${menuItem.title}-${uuidv4()}`);
|
|
80
|
+
|
|
81
|
+
const mainMenuItemLinkTitle = notNull(
|
|
82
|
+
/** @type {HTMLElement} */(
|
|
83
|
+
mainMenuItemTitle.querySelector(getCssClassSelector(domConstants.MENU_ITEM__LINK_TITLE))
|
|
84
|
+
),
|
|
85
|
+
`renderMainMenu(): link title not found for ${menuItem.title}`
|
|
86
|
+
);
|
|
87
|
+
mainMenuItemLinkTitle.setAttribute('id', `${domConstants.MENU_ITEM__LINK_TITLE}__${menuItem.title}-${uuidv4()}`);
|
|
88
|
+
|
|
89
|
+
let menuItemTitleElement;
|
|
90
|
+
if (menuItem.actionFunctionUrl || menuItem.actionUrl) {
|
|
91
|
+
menuItemTitleElement = mainMenuItemLinkTitle;
|
|
92
|
+
mainMenuItemButtonTitle.remove();
|
|
93
|
+
} else if (menuItem.actionMenu || menuItem.actionFunction) {
|
|
94
|
+
menuItemTitleElement = mainMenuItemButtonTitle;
|
|
95
|
+
mainMenuItemLinkTitle.remove();
|
|
96
|
+
} else {
|
|
97
|
+
throw new Error(`renderMainMenu(): menuItem is missing an action: ${menuItem.title}`);
|
|
98
|
+
}
|
|
99
|
+
const menuItemTitleSpanElement = notNull(
|
|
100
|
+
menuItemTitleElement.querySelector(getCssClassSelector(domConstants.MENU_ITEM__LINK_TITLE_SPAN)),
|
|
101
|
+
`renderMainMenu(): main menu item title span not found for: ${menuItem.title}`
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// add selected to title if selected (or any children are selected)
|
|
105
|
+
if (menuItem.isSelected || (menuItem.actionMenu && findRecursive(menuItem.actionMenu, ['actionMenu'], (checkMenuItem) => !!checkMenuItem.isSelected))) {
|
|
106
|
+
menuItemTitleElement.classList.add(domConstants.MENU_ITEM__SELECTED);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (menuItem.actionMenu) {
|
|
110
|
+
// render children menu items
|
|
111
|
+
menuItemTitleSpanElement.innerHTML = menuItem.title;
|
|
112
|
+
|
|
113
|
+
/** @type {PopupMenu} */
|
|
114
|
+
const popupMenu = {
|
|
115
|
+
menuItems: menuItem.actionMenu,
|
|
116
|
+
title: menuItem.title,
|
|
117
|
+
};
|
|
118
|
+
const subMenuPopup = renderPopupMenu(
|
|
119
|
+
popupMenu,
|
|
120
|
+
menuItemTitleElement,
|
|
121
|
+
{
|
|
122
|
+
childrenMenuType: menuItem.childrenMenuType || childrenMenuTypes.FLYOUT,
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
mainMenuItem.appendChild(subMenuPopup);
|
|
126
|
+
popupFocusHandler(mainMenuItem, menuItemTitleElement, subMenuPopup, 'menu', { shouldFocusOnHover: true });
|
|
127
|
+
/** @type {string} */
|
|
128
|
+
let menuClass;
|
|
129
|
+
switch (menuItem.childrenMenuType) {
|
|
130
|
+
case childrenMenuTypes.INLINE:
|
|
131
|
+
menuClass = domConstants.MENU_ITEM__INLINE;
|
|
132
|
+
break;
|
|
133
|
+
case childrenMenuTypes.MEGA_MENU:
|
|
134
|
+
menuClass = domConstants.MENU_ITEM__MEGA_MENU;
|
|
135
|
+
break;
|
|
136
|
+
case childrenMenuTypes.FLYOUT:
|
|
137
|
+
default:
|
|
138
|
+
menuClass = domConstants.MENU_ITEM__FLY_OUT;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
mainMenuItem.classList.add(menuClass);
|
|
142
|
+
} else {
|
|
143
|
+
const mainMenuItemArrow = notNull(
|
|
144
|
+
menuItemTitleElement.querySelector(getCssClassSelector(domConstants.MENU_ITEM__ARROW)),
|
|
145
|
+
`renderMainMenu(): menu arrow not found for ${menuItem.title}`
|
|
146
|
+
);
|
|
147
|
+
mainMenuItemArrow.remove();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (menuItem.actionFunction) {
|
|
151
|
+
// custom function when triggered
|
|
152
|
+
menuItemTitleSpanElement.innerHTML = menuItem.title;
|
|
153
|
+
menuItemTitleElement.onclick = menuItem.actionFunction;
|
|
154
|
+
} else if (menuItem.actionFunctionUrl) {
|
|
155
|
+
menuItemTitleSpanElement.innerHTML = menuItem.title;
|
|
156
|
+
menuItemTitleElement.setAttribute('href', menuItem.actionFunctionUrl.url);
|
|
157
|
+
|
|
158
|
+
menuItemTitleElement.onclick = (e) => {
|
|
159
|
+
if (!menuItem.actionFunctionUrl?.skipHandleEvent) {
|
|
160
|
+
e.stopPropagation();
|
|
161
|
+
e.preventDefault();
|
|
162
|
+
}
|
|
163
|
+
menuItem.actionFunctionUrl?.actionFunction(e);
|
|
164
|
+
};
|
|
165
|
+
} else if (menuItem.actionUrl) {
|
|
166
|
+
// go to url when triggered
|
|
167
|
+
menuItemTitleSpanElement.innerHTML = menuItem.title;
|
|
168
|
+
menuItemTitleElement.setAttribute('href', menuItem.actionUrl.url);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (menuItem.actionUrl?.openInNewTab || menuItem.actionFunctionUrl?.openInNewTab) {
|
|
172
|
+
menuItemTitleElement.setAttribute('target', '_blank');
|
|
173
|
+
menuItemTitleElement.appendChild(renderDOMSingle(NewTabAccessibility));
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ===== UTAH ID ===== //
|
|
179
|
+
let utahIdPopup = null;
|
|
180
|
+
if (settings.utahId) {
|
|
181
|
+
const { button: utahIdButton, menu } = renderUtahIdForMobile();
|
|
182
|
+
utahIdPopup = menu;
|
|
183
|
+
const utahIdButtonWrapper = notNull(
|
|
184
|
+
mainMenuWrapper.querySelector(getCssClassSelector(domConstants.MOBILE__UTAH_ID)),
|
|
185
|
+
'renderMainMenu: utahIdButtonWrapper not found'
|
|
186
|
+
);
|
|
187
|
+
utahIdButtonWrapper.appendChild(utahIdButton);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ===== SEARCH ICON ===== //
|
|
191
|
+
const searchIcon = notNull(
|
|
192
|
+
/** @type {HTMLElement} */(
|
|
193
|
+
mainMenuWrapper.querySelector(getCssClassSelector(domConstants.MAIN_MENU__SEARCH))
|
|
194
|
+
),
|
|
195
|
+
'renderMainMenu: searchIcon not found'
|
|
196
|
+
);
|
|
197
|
+
if (settings.onSearch) {
|
|
198
|
+
hookupTooltip(searchIcon, document.createTextNode('Search'));
|
|
199
|
+
if (searchIcon.onclick) {
|
|
200
|
+
throw new Error('searchIcon already has onclick');
|
|
201
|
+
}
|
|
202
|
+
searchIcon.onclick = () => showSearchModal();
|
|
203
|
+
|
|
204
|
+
if (!settings.mainMenu) {
|
|
205
|
+
const citizenExperienceWrapper = notNull(
|
|
206
|
+
document.querySelector(getCssClassSelector(domConstants.CITIZEN_EXPERIENCE)),
|
|
207
|
+
'renderMainMenu: citizen experience wrapper not found'
|
|
208
|
+
);
|
|
209
|
+
// if actions AND search, but not utahId nor menu
|
|
210
|
+
// Desktop: the search is with the action icons
|
|
211
|
+
// mobile: the search is on main menu bar with hamburger
|
|
212
|
+
// so make a copy of the menu bar search so it can be mobile and citizen
|
|
213
|
+
const mobileSearchIcon = renderDOMSingle(searchIcon.outerHTML);
|
|
214
|
+
hookupTooltip(mobileSearchIcon, document.createTextNode('Search'));
|
|
215
|
+
mobileSearchIcon.onclick = () => showSearchModal();
|
|
216
|
+
searchIcon.classList.add(domConstants.DESKTOP__HIDDEN);
|
|
217
|
+
|
|
218
|
+
// search icon is the far right item in the citizen experience (no utahid button)
|
|
219
|
+
// there is no main menu, so move search in to top header by utahID button UDS-564
|
|
220
|
+
if (settings.utahId !== false) {
|
|
221
|
+
// place search icon just to left of utahId button
|
|
222
|
+
const utahIdWrapper = notNull(document.querySelector(getCssClassSelector(domConstants.UTAH_ID)), 'renderMainMenu: utahId wrapper not found');
|
|
223
|
+
citizenExperienceWrapper.insertBefore(mobileSearchIcon, utahIdWrapper);
|
|
224
|
+
} else {
|
|
225
|
+
citizenExperienceWrapper.appendChild(mobileSearchIcon);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// UDS-564 - move search top top right if no main menu
|
|
230
|
+
if (!settings.mainMenu && !settings.actionItems && settings.utahId === false) {
|
|
231
|
+
// create search clone
|
|
232
|
+
const searchIconMobile = renderDOMSingle(/** @type {HTMLElement} */(searchIcon).outerHTML);
|
|
233
|
+
// run same hookup stuff above
|
|
234
|
+
hookupTooltip(searchIconMobile, document.createTextNode('Search'));
|
|
235
|
+
if (searchIconMobile.onclick) {
|
|
236
|
+
throw new Error('searchIconMobile already has onclick');
|
|
237
|
+
}
|
|
238
|
+
searchIconMobile.onclick = () => showSearchModal();
|
|
239
|
+
|
|
240
|
+
// place in mobile citizen experience
|
|
241
|
+
const citizenExperienceMobile = notNull(
|
|
242
|
+
document.querySelector(getCssClassSelector(domConstants.CITIZEN_EXPERIENCE_MOBILE)),
|
|
243
|
+
'renderMainMenu: citizen-experience--mobile not found'
|
|
244
|
+
);
|
|
245
|
+
// move search to top right citizen experience because main menu is toast
|
|
246
|
+
citizenExperienceMobile.appendChild(searchIconMobile);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (!settings.onSearch) {
|
|
250
|
+
if (settings.mainMenu || (!settings.mainMenu && settings.utahId)) {
|
|
251
|
+
// add a blank div to consume space (only if there is a main menu)
|
|
252
|
+
searchIcon.parentElement?.insertBefore(renderDOMSingle('<div class="main-menu__search-placeholder">'), searchIcon);
|
|
253
|
+
}
|
|
254
|
+
searchIcon.remove();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return { mainMenuWrapper, utahIdPopup };
|
|
258
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
// @ts-ignore
|
|
3
|
+
// eslint-disable-next-line import/no-unresolved
|
|
4
|
+
import MenuWithTitle from './html/MenuWithTitle.html?raw';
|
|
5
|
+
|
|
6
|
+
import renderDOMSingle from '../../misc/renderDOMSingle';
|
|
7
|
+
import domConstants, { getCssClassSelector } from '../../enumerations/domConstants';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {HTMLElement} menu
|
|
11
|
+
* @param {string} title
|
|
12
|
+
* @returns {HTMLElement}
|
|
13
|
+
*/
|
|
14
|
+
export default function renderMenuWithTitle(menu, title) {
|
|
15
|
+
const menuWithTitle = renderDOMSingle(MenuWithTitle);
|
|
16
|
+
const menuTitleDiv = menuWithTitle.querySelector(getCssClassSelector(domConstants.POPUP_MENU_WRAPPER__WRAPPER_TITLE));
|
|
17
|
+
if (!menuTitleDiv) {
|
|
18
|
+
throw new Error('renderMenuWithTitle: menuTitleDiv not found');
|
|
19
|
+
}
|
|
20
|
+
menuTitleDiv.appendChild(document.createTextNode(title));
|
|
21
|
+
|
|
22
|
+
menuWithTitle.appendChild(menu);
|
|
23
|
+
return menuWithTitle;
|
|
24
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
// @ts-ignore
|
|
3
|
+
// eslint-disable-next-line import/no-unresolved
|
|
4
|
+
import MobileMenuContentItemWrapper from './html/MobileMenuContentItemWrapper.html?raw';
|
|
5
|
+
|
|
6
|
+
import domConstants, { getCssClassSelector } from '../../enumerations/domConstants';
|
|
7
|
+
import renderDOMSingle from '../../misc/renderDOMSingle';
|
|
8
|
+
import uuidv4 from '../../misc/uuidv4';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {HTMLElement} mobileMenuContentItem
|
|
12
|
+
* @returns {HTMLElement} the already added element
|
|
13
|
+
*/
|
|
14
|
+
export default function addMobileMenuContentItem(mobileMenuContentItem) {
|
|
15
|
+
const mobileMenuWrapper = document.querySelector(getCssClassSelector(domConstants.MOBILE_MENU__WRAPPER));
|
|
16
|
+
if (!mobileMenuWrapper) {
|
|
17
|
+
throw new Error('addMobileMenuContentItem: mobileMenuWrapper not found');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const mobileContentWrapper = mobileMenuWrapper.querySelector(getCssClassSelector(domConstants.MOBILE_MENU__CONTENT));
|
|
21
|
+
if (!mobileContentWrapper) {
|
|
22
|
+
throw new Error('addMobileMenuContentItem: mobileContentWrapper not found');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// wrap the mobileMenuContentItem in a content_item div
|
|
26
|
+
const contentItemWrapper = renderDOMSingle(MobileMenuContentItemWrapper);
|
|
27
|
+
|
|
28
|
+
// put content in the div
|
|
29
|
+
contentItemWrapper.appendChild(mobileMenuContentItem);
|
|
30
|
+
|
|
31
|
+
// put content_item div in mobile menu content area
|
|
32
|
+
mobileContentWrapper.appendChild(contentItemWrapper);
|
|
33
|
+
|
|
34
|
+
// always have an ID for easier aria hookup
|
|
35
|
+
contentItemWrapper.setAttribute('id', uuidv4());
|
|
36
|
+
return contentItemWrapper;
|
|
37
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import domConstants, { getCssClassSelector } from '../../enumerations/domConstants';
|
|
3
|
+
import checkForError from '../../misc/checkForError';
|
|
4
|
+
import notNull from '../../misc/notNull';
|
|
5
|
+
import getUtahHeaderSettings from '../../settings/getUtahHeaderSettings';
|
|
6
|
+
import renderActionItemBadge from '../actionItems/renderActionItemBadge';
|
|
7
|
+
import { closeOfficialWebsite } from '../utahLogo/renderOfficialWebsite';
|
|
8
|
+
import mobileMenuInteractionHandler from './mobileMenuInteractionHandler';
|
|
9
|
+
import getHamburgerElements from './util/getHamburgerElements';
|
|
10
|
+
import { hideMobileMenu } from './util/showHideHamburgerElements';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {HTMLElement} mobileMainMenuContentItem
|
|
14
|
+
*/
|
|
15
|
+
export default function hookupHamburger(mobileMainMenuContentItem) {
|
|
16
|
+
const { hamburger } = getHamburgerElements('hookupHamburger');
|
|
17
|
+
const hamburgerNotNull = /** @param {string} context */ (context) => notNull(hamburger, `hookupHamburger: hamburger required but is null: ${context}`);
|
|
18
|
+
|
|
19
|
+
const settings = getUtahHeaderSettings();
|
|
20
|
+
const actionItemHasBadge = settings.actionItems?.some((actionItem) => !!actionItem.badge);
|
|
21
|
+
if (actionItemHasBadge) {
|
|
22
|
+
const badge = renderActionItemBadge({ label: 'Home Badge' });
|
|
23
|
+
if (badge) {
|
|
24
|
+
hamburgerNotNull('home badge').appendChild(badge);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
hideMobileMenu();
|
|
29
|
+
|
|
30
|
+
function firstBarActionItem() {
|
|
31
|
+
const actionItem = notNull(
|
|
32
|
+
/** @type {HTMLElement} */(document.querySelectorAll(`.${domConstants.MOBILE_MENU__ACTION_BAR} .${domConstants.MOBILE_MENU_ACTION_BAR__ACTION_ITEM_WRAPPER}`)[0]),
|
|
33
|
+
'hookupHamburger: no action items to select on mobile hamburger open'
|
|
34
|
+
);
|
|
35
|
+
const iconButton = actionItem.querySelector('button');
|
|
36
|
+
const contentWrapperId = iconButton?.getAttribute('aria-controls');
|
|
37
|
+
return { actionItem, actionItemWrapper: contentWrapperId ? document.getElementById(contentWrapperId) : null };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// hookup aria to home menu (can't in mobile menu interaction handler because it maybe removed later)
|
|
41
|
+
const actionItem = notNull(
|
|
42
|
+
/** @type {HTMLElement} */(document.querySelectorAll(`.${domConstants.MOBILE_MENU__ACTION_BAR} .${domConstants.MOBILE_MENU_ACTION_BAR__ACTION_ITEM_WRAPPER}`)[0]),
|
|
43
|
+
'hookupHamburger: no action items to select on mobile hamburger open'
|
|
44
|
+
);
|
|
45
|
+
const actionItemButton = actionItem.querySelector?.('button');
|
|
46
|
+
const actionItemId = (actionItemButton || actionItem).getAttribute('id');
|
|
47
|
+
if (!actionItemId) {
|
|
48
|
+
throw new Error('mobileMenuInteractionHandler: actionItemId not found');
|
|
49
|
+
}
|
|
50
|
+
if (mobileMainMenuContentItem) {
|
|
51
|
+
const mobileMainMenuContentItemId = mobileMainMenuContentItem.getAttribute('id');
|
|
52
|
+
if (!mobileMainMenuContentItemId) {
|
|
53
|
+
throw new Error('mobileMenuInteractionHandler: mobileMainMenuContentItemId not found');
|
|
54
|
+
}
|
|
55
|
+
(actionItemButton || actionItem).setAttribute('aria-controls', mobileMainMenuContentItemId);
|
|
56
|
+
mobileMainMenuContentItem.setAttribute('aria-labelledby', actionItemId);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (hamburger) {
|
|
60
|
+
mobileMenuInteractionHandler(
|
|
61
|
+
hamburger,
|
|
62
|
+
() => firstBarActionItem().actionItemWrapper,
|
|
63
|
+
() => firstBarActionItem().actionItem,
|
|
64
|
+
{
|
|
65
|
+
additionalOnClick: () => closeOfficialWebsite(),
|
|
66
|
+
ariaHasPopupType: 'menu',
|
|
67
|
+
shouldOnClickCloseMenu: true,
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// when hamburger is in an "open" state (mobile menu is open) and the hamburger loses focus (tabbed off of)
|
|
73
|
+
// then move focus to the first action item in the mobile action item bar. UDS-234
|
|
74
|
+
if (hamburger) {
|
|
75
|
+
checkForError(!!hamburger.onblur, 'hookupHamburger: hamburger already has an onblur event');
|
|
76
|
+
hamburger.onblur = () => {
|
|
77
|
+
const { mobileMenu } = getHamburgerElements('showMobileMenu');
|
|
78
|
+
if (mobileMenu.classList.contains(domConstants.IS_OPEN)) {
|
|
79
|
+
const actionBarClass = getCssClassSelector(domConstants.MOBILE_MENU__ACTION_BAR);
|
|
80
|
+
const actionItemWrapperClass = getCssClassSelector(domConstants.MOBILE_MENU_ACTION_BAR__ACTION_ITEM_WRAPPER);
|
|
81
|
+
const actionItemButtonClass = getCssClassSelector(domConstants.ICON_BUTTON);
|
|
82
|
+
const firstMobileActionItem = (
|
|
83
|
+
/** @type {HTMLElement | null} */
|
|
84
|
+
(document.querySelector(`${actionBarClass} ${actionItemWrapperClass}:first-child ${actionItemButtonClass}`))
|
|
85
|
+
);
|
|
86
|
+
firstMobileActionItem?.focus();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// if no bar, move hamburger to mobile citizen experience UDS-564
|
|
92
|
+
if (((settings.mainMenu || settings.actionItems) && !settings.onSearch && settings.utahId === false)) {
|
|
93
|
+
const citizenExperienceMobile = notNull(
|
|
94
|
+
document.querySelector(getCssClassSelector(domConstants.CITIZEN_EXPERIENCE_MOBILE)),
|
|
95
|
+
'hookupHamburger: citizen experience mobile not found'
|
|
96
|
+
);
|
|
97
|
+
citizenExperienceMobile.appendChild(hamburgerNotNull('adding to citizen experience'));
|
|
98
|
+
const mainMenu = notNull(
|
|
99
|
+
document.querySelector(getCssClassSelector(domConstants.MAIN_MENU)),
|
|
100
|
+
'hookupHamburger: main menu not found'
|
|
101
|
+
);
|
|
102
|
+
mainMenu.classList.add(domConstants.MOBILE__HIDDEN);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (settings.onSearch && !settings.mainMenu) {
|
|
106
|
+
const mainMenu = notNull(
|
|
107
|
+
document.querySelector(getCssClassSelector(domConstants.MAIN_MENU)),
|
|
108
|
+
'renderMainMenu: main menu not found'
|
|
109
|
+
);
|
|
110
|
+
mainMenu.classList.add(domConstants.DESKTOP__HIDDEN);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import domConstants, { getCssClassSelector } from '../../enumerations/domConstants';
|
|
3
|
+
import utahIdUrls from '../../enumerations/utahIdUrls';
|
|
4
|
+
import getUtahHeaderSettings from '../../settings/getUtahHeaderSettings';
|
|
5
|
+
import { getCurrentUtahIdData } from '../../utahId/utahIdData';
|
|
6
|
+
import addMobileMenuContentItem from './addMobileMenuContentItem';
|
|
7
|
+
import mobileMenuInteractionHandler from './mobileMenuInteractionHandler';
|
|
8
|
+
|
|
9
|
+
export function removeUtahIdInMobileMenu() {
|
|
10
|
+
const profileActionItem = document.getElementById(domConstants.MOBILE_MENU_ACTON_BAR__PROFILE_ID);
|
|
11
|
+
if (!profileActionItem) {
|
|
12
|
+
throw new Error('removeUtahIdInMobileMenu: profileActionItem not found');
|
|
13
|
+
}
|
|
14
|
+
const profileActionItemWrapper = /** @type {HTMLElement} */ (
|
|
15
|
+
profileActionItem.closest(getCssClassSelector(domConstants.MOBILE_MENU_ACTION_BAR__ACTION_ITEM_WRAPPER))
|
|
16
|
+
);
|
|
17
|
+
if (!profileActionItemWrapper) {
|
|
18
|
+
throw new Error('removeUtahIdInMobileMenu: profileActionItemWrapper not found');
|
|
19
|
+
}
|
|
20
|
+
profileActionItemWrapper.remove();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {HTMLElement} mobileMenuWrapper
|
|
25
|
+
* @param {HTMLElement} utahIdPopup
|
|
26
|
+
*/
|
|
27
|
+
export function hookupUtahIdInMobileMenu(mobileMenuWrapper, utahIdPopup) {
|
|
28
|
+
// get utahIdButton in the Mobile Menu
|
|
29
|
+
const utahIdWrapper = document.querySelector(getCssClassSelector(domConstants.MOBILE__UTAH_ID));
|
|
30
|
+
if (!utahIdWrapper) {
|
|
31
|
+
throw new Error('hookupUtahIdInMobileMenu: utahIdWrapper not found');
|
|
32
|
+
}
|
|
33
|
+
const utahIdButton = /** @type {HTMLElement} */ (utahIdWrapper.querySelector(getCssClassSelector(domConstants.UTAH_ID__BUTTON)));
|
|
34
|
+
if (!utahIdButton) {
|
|
35
|
+
throw new Error('hookupUtahIdInMobileMenu: utahIdButton not found');
|
|
36
|
+
}
|
|
37
|
+
const mobileContentWrapper = mobileMenuWrapper.querySelector(getCssClassSelector(domConstants.MOBILE_MENU__CONTENT));
|
|
38
|
+
if (!mobileContentWrapper) {
|
|
39
|
+
throw new Error('hookupUtahIdInMobileMenu: mobileContentWrapper not found');
|
|
40
|
+
}
|
|
41
|
+
const profileActionItem = document.getElementById(domConstants.MOBILE_MENU_ACTON_BAR__PROFILE_ID);
|
|
42
|
+
if (!profileActionItem) {
|
|
43
|
+
throw new Error('hookupUtahIdInMobileMenu: profileActionItem not found');
|
|
44
|
+
}
|
|
45
|
+
const profileActionItemWrapper = /** @type {HTMLElement} */ (
|
|
46
|
+
profileActionItem.closest(getCssClassSelector(domConstants.MOBILE_MENU_ACTION_BAR__ACTION_ITEM_WRAPPER))
|
|
47
|
+
);
|
|
48
|
+
if (!profileActionItemWrapper) {
|
|
49
|
+
throw new Error('hookupHamburger: profileActionItemWrapper not found');
|
|
50
|
+
}
|
|
51
|
+
// clicking button goes to mobile menu content menu
|
|
52
|
+
const utahIdPopupContentWrapper = addMobileMenuContentItem(utahIdPopup);
|
|
53
|
+
mobileMenuInteractionHandler(
|
|
54
|
+
utahIdButton,
|
|
55
|
+
utahIdPopupContentWrapper,
|
|
56
|
+
profileActionItemWrapper,
|
|
57
|
+
{
|
|
58
|
+
ariaHasPopupType: 'menu',
|
|
59
|
+
onClickHandler: (e) => {
|
|
60
|
+
const currentUtahIdData = getCurrentUtahIdData();
|
|
61
|
+
const settings = getUtahHeaderSettings();
|
|
62
|
+
let result = false;
|
|
63
|
+
if (!currentUtahIdData?.isDefinitive || !currentUtahIdData?.userInfo?.authenticated) {
|
|
64
|
+
result = true;
|
|
65
|
+
const onSignIn = (settings.utahId !== false && settings.utahId !== true && settings.utahId?.onSignIn);
|
|
66
|
+
if (onSignIn) {
|
|
67
|
+
onSignIn(e);
|
|
68
|
+
} else {
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
e.stopPropagation();
|
|
71
|
+
window.location.href = utahIdUrls.SIGN_IN;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
},
|
|
76
|
+
shouldOnClickCloseMenu: true,
|
|
77
|
+
}
|
|
78
|
+
);
|
|
79
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<div class="utah-design-system utds-header-mobile-menu" id="utds-header-mobile-menu">
|
|
2
|
+
<div class="utds-header-mobile-menu__backdrop" aria-hidden></div>
|
|
3
|
+
<div class="utds-header-mobile-menu__wrapper">
|
|
4
|
+
<div class="utds-header-mobile-menu__action-bar" role="tablist">
|
|
5
|
+
|
|
6
|
+
<div class="utds-header-mobile-menu__action-item" role="tab">
|
|
7
|
+
<button type="button" class="icon-button icon-button--borderless utds-header-action-item__icon-button icon-home"
|
|
8
|
+
id="utds-header-mobile-menu_action-bar__home">
|
|
9
|
+
<div class="utds-header-action-item__title visually-hidden">Main Menu</div>
|
|
10
|
+
<span class="utds-icon-before-home-menu" aria-hidden="true" role="presentation">
|
|
11
|
+
</span>
|
|
12
|
+
</button>
|
|
13
|
+
<span class="menu-chiclet"></span>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="utds-header-mobile-menu__action-item" role="tab">
|
|
16
|
+
<button type="button"
|
|
17
|
+
class="icon-button icon-button--borderless utds-header-action-item__icon-button icon-profile"
|
|
18
|
+
id="utds-header-mobile-menu_action-bar__profile">
|
|
19
|
+
<div class="utds-header-action-item__title visually-hidden">Profile</div>
|
|
20
|
+
<span class="utds-icon-before-account" aria-hidden="true" role="presentation">
|
|
21
|
+
</span>
|
|
22
|
+
</button>
|
|
23
|
+
<span class="menu-chiclet"></span>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
</div>
|
|
27
|
+
<div class="utds-header-mobile-menu__content"> </div>
|
|
28
|
+
<div aria-hidden tabindex="0" class="utds-header-mobile-menu__hidden-last-focusable visually-hidden">
|
|
29
|
+
end of mobile content form
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|