@internetarchive/ia-topnav 1.1.19 → 1.1.21-alpha

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.
Files changed (89) hide show
  1. package/.eslintrc +16 -16
  2. package/.storybook/.babelrc +15 -15
  3. package/.storybook/addons.js +7 -7
  4. package/.storybook/config.js +11 -11
  5. package/.storybook/webpack.config.js +5 -5
  6. package/LICENSE +661 -661
  7. package/README.md +145 -145
  8. package/demo.html +41 -41
  9. package/index.d.ts +105 -105
  10. package/index.js +3 -3
  11. package/package.json +65 -65
  12. package/src/assets/img/hamburger.js +36 -36
  13. package/src/assets/img/ia-icon.js +33 -33
  14. package/src/assets/img/icon-audio.js +23 -23
  15. package/src/assets/img/icon-close.js +16 -16
  16. package/src/assets/img/icon-donate.js +15 -15
  17. package/src/assets/img/icon-ellipses.js +15 -15
  18. package/src/assets/img/icon-ia-logo.js +24 -24
  19. package/src/assets/img/icon-images.js +15 -15
  20. package/src/assets/img/icon-search.js +15 -15
  21. package/src/assets/img/icon-software.js +15 -15
  22. package/src/assets/img/icon-texts.js +15 -15
  23. package/src/assets/img/icon-upload.js +15 -15
  24. package/src/assets/img/icon-user.js +15 -15
  25. package/src/assets/img/icon-video.js +15 -15
  26. package/src/assets/img/icon-web.js +15 -15
  27. package/src/assets/img/icon.js +18 -18
  28. package/src/assets/img/icons.js +29 -29
  29. package/src/assets/img/user.js +38 -38
  30. package/src/assets/img/wordmark-stacked.js +13 -13
  31. package/src/data/menus.js +603 -603
  32. package/src/desktop-subnav.js +45 -45
  33. package/src/dropdown-menu.js +98 -98
  34. package/src/ia-topnav.js +285 -285
  35. package/src/lib/formatUrl.js +1 -1
  36. package/src/lib/location-handler.js +5 -5
  37. package/src/lib/query-handler.js +7 -7
  38. package/src/lib/toSentenceCase.js +8 -8
  39. package/src/login-button.js +79 -79
  40. package/src/media-button.js +113 -113
  41. package/src/media-menu.js +133 -133
  42. package/src/media-slider.js +104 -104
  43. package/src/media-subnav.js +112 -112
  44. package/src/more-slider.js +33 -33
  45. package/src/nav-search.js +124 -124
  46. package/src/primary-nav.js +211 -211
  47. package/src/save-page-form.js +59 -59
  48. package/src/search-menu.js +115 -115
  49. package/src/signed-out-dropdown.js +10 -10
  50. package/src/styles/base.js +48 -48
  51. package/src/styles/desktop-subnav.js +37 -37
  52. package/src/styles/dropdown-menu.js +143 -143
  53. package/src/styles/ia-topnav.js +88 -88
  54. package/src/styles/login-button.js +70 -70
  55. package/src/styles/media-button.js +153 -153
  56. package/src/styles/media-menu.js +70 -70
  57. package/src/styles/media-slider.js +81 -81
  58. package/src/styles/media-subnav.js +156 -156
  59. package/src/styles/more-slider.js +15 -15
  60. package/src/styles/nav-search.js +134 -130
  61. package/src/styles/primary-nav.js +254 -254
  62. package/src/styles/save-page-form.js +53 -52
  63. package/src/styles/search-menu.js +104 -103
  64. package/src/styles/signed-out-dropdown.js +31 -31
  65. package/src/styles/user-menu.js +31 -31
  66. package/src/styles/wayback-search.js +48 -48
  67. package/src/styles/wayback-slider.js +30 -30
  68. package/src/tracked-element.js +27 -27
  69. package/src/user-menu.js +42 -42
  70. package/src/wayback-search.js +18 -18
  71. package/src/wayback-slider.js +88 -88
  72. package/stories/topnav-element.stories.js +7 -7
  73. package/test/assets/img/hamburger.test.js +15 -15
  74. package/test/assets/img/user.test.js +15 -15
  75. package/test/data/menus.test.js +19 -19
  76. package/test/dropdown-menu.test.js +25 -25
  77. package/test/ia-icon.test.js +13 -13
  78. package/test/ia-topnav.test.js +273 -273
  79. package/test/login-button.test.js +15 -15
  80. package/test/media-button.test.js +19 -19
  81. package/test/media-menu.test.js +40 -40
  82. package/test/media-slider.test.js +57 -57
  83. package/test/more-slider.test.js +13 -13
  84. package/test/nav-search.test.js +61 -61
  85. package/test/primary-nav.test.js +82 -82
  86. package/test/save-page-form.test.js +35 -35
  87. package/test/search-menu.test.js +49 -49
  88. package/test/user-menu.test.js +33 -33
  89. package/test/wayback-slider.test.js +80 -80
package/src/nav-search.js CHANGED
@@ -1,124 +1,124 @@
1
- import { nothing, html } from 'https://offshoot.ux.archive.org/lit.js';
2
-
3
- import TrackedElement from './tracked-element.js';
4
- import navSearchCSS from './styles/nav-search.js';
5
- import icons from './assets/img/icons.js';
6
- import formatUrl from './lib/formatUrl.js';
7
-
8
- class NavSearch extends TrackedElement {
9
- static get styles() {
10
- return navSearchCSS;
11
- }
12
-
13
- static get properties() {
14
- return {
15
- baseHost: { type: String },
16
- config: { type: Object },
17
- locationHandler: { type: Object },
18
- open: { type: Boolean },
19
- openMenu: { type: String },
20
- searchIn: { type: String },
21
- searchQuery: { type: String },
22
- };
23
- }
24
-
25
- constructor() {
26
- super();
27
- this.config = {};
28
- this.locationHandler = () => {};
29
- this.open = false;
30
- this.openMenu = '';
31
- this.searchIn = '';
32
- this.inSearchBeta = false;
33
-
34
- this.initSearchBetaOptIn();
35
- }
36
-
37
- updated() {
38
- if (this.open) {
39
- this.shadowRoot.querySelector('[name=query]').focus();
40
- }
41
- return true;
42
- }
43
-
44
- initSearchBetaOptIn() {
45
- this.inSearchBeta = !!window.localStorage?.getItem('SearchBeta-opt-in');
46
- }
47
-
48
- search(e) {
49
- const query = this.shadowRoot.querySelector('[name=query]').value;
50
-
51
- if (!query) {
52
- e.preventDefault();
53
- return false;
54
- }
55
-
56
- // TV search points to a detail page with a q param instead
57
- if (this.searchIn === 'TV') {
58
- this.locationHandler(formatUrl(`/details/tv?q=${query}`, this.baseHost));
59
- e.preventDefault();
60
- return false;
61
- }
62
-
63
- this.trackSubmit(e);
64
- return true;
65
- }
66
-
67
- toggleSearchMenu() {
68
- if (this.openMenu === 'search') {
69
- return;
70
- }
71
- this.dispatchEvent(new CustomEvent('menuToggled', {
72
- detail: {
73
- menuName: 'search'
74
- },
75
- composed: true,
76
- bubbles: true,
77
- }));
78
- }
79
-
80
- get searchInsideInput() {
81
- return this.searchIn ? html`<input type='hidden' name='sin' value='${this.searchIn}' />` : nothing;
82
- }
83
-
84
- get searchEndpoint() {
85
- return this.inSearchBeta ? '/search' : '/search.php';
86
- }
87
-
88
- render() {
89
- const searchMenuClass = this.open ? 'flex' : 'search-inactive';
90
-
91
- return html`
92
- <div class="search-activated fade-in ${searchMenuClass}">
93
- <form
94
- id="nav-search"
95
- class="highlight"
96
- action=${formatUrl(this.searchEndpoint, this.baseHost)}
97
- method="get"
98
- @submit=${this.search}
99
- data-event-submit-tracking="${this.config.eventCategory}|NavSearchSubmit"
100
- >
101
- <input
102
- type="text"
103
- name="query"
104
- class="search-field"
105
- placeholder="Search"
106
- autocomplete="off"
107
- @focus=${this.toggleSearchMenu}
108
- value=${this.searchQuery || ''}
109
- />
110
- ${this.searchInsideInput}
111
- <button
112
- type="submit"
113
- class="search"
114
- data-event-click-tracking="${this.config.eventCategory}|NavSearchClose"
115
- >
116
- ${icons.search}
117
- </button>
118
- </form>
119
- </div>
120
- `;
121
- }
122
- }
123
-
124
- customElements.define('nav-search', NavSearch);
1
+ import { nothing, html } from 'https://offshoot.ux.archive.org/lit.js';
2
+
3
+ import TrackedElement from './tracked-element.js';
4
+ import navSearchCSS from './styles/nav-search.js';
5
+ import icons from './assets/img/icons.js';
6
+ import formatUrl from './lib/formatUrl.js';
7
+
8
+ class NavSearch extends TrackedElement {
9
+ static get styles() {
10
+ return navSearchCSS;
11
+ }
12
+
13
+ static get properties() {
14
+ return {
15
+ baseHost: { type: String },
16
+ config: { type: Object },
17
+ locationHandler: { type: Object },
18
+ open: { type: Boolean },
19
+ openMenu: { type: String },
20
+ searchIn: { type: String },
21
+ searchQuery: { type: String },
22
+ };
23
+ }
24
+
25
+ constructor() {
26
+ super();
27
+ this.config = {};
28
+ this.locationHandler = () => {};
29
+ this.open = false;
30
+ this.openMenu = '';
31
+ this.searchIn = '';
32
+ this.inSearchBeta = false;
33
+
34
+ this.initSearchBetaOptIn();
35
+ }
36
+
37
+ updated() {
38
+ if (this.open) {
39
+ this.shadowRoot.querySelector('[name=query]').focus();
40
+ }
41
+ return true;
42
+ }
43
+
44
+ initSearchBetaOptIn() {
45
+ this.inSearchBeta = !!window.localStorage?.getItem('SearchBeta-opt-in');
46
+ }
47
+
48
+ search(e) {
49
+ const query = this.shadowRoot.querySelector('[name=query]').value;
50
+
51
+ if (!query) {
52
+ e.preventDefault();
53
+ return false;
54
+ }
55
+
56
+ // TV search points to a detail page with a q param instead
57
+ if (this.searchIn === 'TV') {
58
+ this.locationHandler(formatUrl(`/details/tv?q=${query}`, this.baseHost));
59
+ e.preventDefault();
60
+ return false;
61
+ }
62
+
63
+ this.trackSubmit(e);
64
+ return true;
65
+ }
66
+
67
+ toggleSearchMenu() {
68
+ if (this.openMenu === 'search') {
69
+ return;
70
+ }
71
+ this.dispatchEvent(new CustomEvent('menuToggled', {
72
+ detail: {
73
+ menuName: 'search'
74
+ },
75
+ composed: true,
76
+ bubbles: true,
77
+ }));
78
+ }
79
+
80
+ get searchInsideInput() {
81
+ return this.searchIn ? html`<input type='hidden' name='sin' value='${this.searchIn}' />` : nothing;
82
+ }
83
+
84
+ get searchEndpoint() {
85
+ return this.inSearchBeta ? '/search' : '/search.php';
86
+ }
87
+
88
+ render() {
89
+ const searchMenuClass = this.open ? 'flex' : 'search-inactive';
90
+
91
+ return html`
92
+ <div class="search-activated fade-in ${searchMenuClass}">
93
+ <form
94
+ id="nav-search"
95
+ class="highlight"
96
+ action=${formatUrl(this.searchEndpoint, this.baseHost)}
97
+ method="get"
98
+ @submit=${this.search}
99
+ data-event-submit-tracking="${this.config.eventCategory}|NavSearchSubmit"
100
+ >
101
+ <input
102
+ type="text"
103
+ name="query"
104
+ class="search-field"
105
+ placeholder="Search"
106
+ autocomplete="off"
107
+ @focus=${this.toggleSearchMenu}
108
+ value=${this.searchQuery || ''}
109
+ />
110
+ ${this.searchInsideInput}
111
+ <button
112
+ type="submit"
113
+ class="search"
114
+ data-event-click-tracking="${this.config.eventCategory}|NavSearchClose"
115
+ >
116
+ ${icons.search}
117
+ </button>
118
+ </form>
119
+ </div>
120
+ `;
121
+ }
122
+ }
123
+
124
+ customElements.define('nav-search', NavSearch);
@@ -1,211 +1,211 @@
1
- import { html, nothing } from 'https://offshoot.ux.archive.org/lit.js';
2
- import TrackedElement from './tracked-element.js';
3
- import icons from './assets/img/icons.js';
4
- import './assets/img/hamburger.js';
5
- import './login-button.js';
6
- import './nav-search.js';
7
- import './media-menu.js';
8
- import logoWordmarkStacked from './assets/img/wordmark-stacked.js';
9
- import primaryNavCSS from './styles/primary-nav.js';
10
- import locationHandler from './lib/location-handler.js';
11
- import formatUrl from './lib/formatUrl.js';
12
-
13
- class PrimaryNav extends TrackedElement {
14
- static get styles() {
15
- return primaryNavCSS;
16
- }
17
-
18
- static get properties() {
19
- return {
20
- mediaBaseHost: { type: String },
21
- baseHost: { type: String },
22
- hideSearch: { type: Boolean },
23
- config: { type: Object },
24
- openMenu: { type: String },
25
- screenName: { type: String },
26
- searchIn: { type: String },
27
- searchQuery: { type: String },
28
- secondIdentitySlotMode: { type: String },
29
- selectedMenuOption: { type: String },
30
- signedOutMenuOpen: { type: Boolean },
31
- userMenuOpen: { type: Boolean },
32
- username: { type: String },
33
- userProfileImagePath: { type: String },
34
- userProfileLastModified: { type: String },
35
- };
36
- }
37
-
38
- constructor() {
39
- super();
40
- this.config = {};
41
- this.openMenu = '';
42
- this.searchIn = '';
43
- this.selectedMenuOption = '';
44
- this.signedOutMenuOpen = false;
45
- this.userMenuOpen = false;
46
- this.mediaBaseHost = 'https://archive.org';
47
- this.secondIdentitySlotMode = '';
48
- }
49
-
50
- toggleMediaMenu(e) {
51
- this.trackClick(e);
52
- this.dispatchEvent(
53
- new CustomEvent('menuToggled', {
54
- detail: {
55
- menuName: 'media',
56
- },
57
- }),
58
- );
59
- }
60
-
61
- toggleSearchMenu(e) {
62
- this.trackClick(e);
63
- this.dispatchEvent(
64
- new CustomEvent('menuToggled', {
65
- detail: {
66
- menuName: 'search',
67
- },
68
- }),
69
- );
70
- }
71
-
72
- toggleUserMenu(e) {
73
- this.trackClick(e);
74
- this.dispatchEvent(
75
- new CustomEvent('menuToggled', {
76
- detail: {
77
- menuName: 'user',
78
- },
79
- }),
80
- );
81
- }
82
-
83
- get truncatedScreenName() {
84
- if (this.screenName && this.screenName.length > 10) {
85
- return `${this.screenName.substr(0, 9)}…`;
86
- }
87
- return this.screenName;
88
- }
89
-
90
- get userIcon() {
91
- const userMenuClass = this.openMenu === 'user' ? 'active' : '';
92
- const userMenuToolTip = this.openMenu === 'user' ? 'Close user menu' : 'Expand user menu';
93
-
94
- return html`
95
- <button
96
- class="user-menu ${userMenuClass}"
97
- title="${userMenuToolTip}"
98
- @click="${this.toggleUserMenu}"
99
- data-event-click-tracking="${this.config.eventCategory}|NavUserMenu"
100
- >
101
- <img
102
- src="${this.mediaBaseHost}${this.userProfileImagePath}?${this.userProfileLastModified}"
103
- alt="${this.username}"
104
- />
105
- <span class="username">${this.truncatedScreenName}</span>
106
- </button>
107
- `;
108
- }
109
-
110
- get loginIcon() {
111
- return html`
112
- <login-button
113
- .baseHost=${this.baseHost}
114
- .config=${this.config}
115
- .dropdownOpen=${this.signedOutMenuOpen}
116
- .openMenu=${this.openMenu}
117
- @signedOutMenuToggled=${this.signedOutMenuToggled}
118
- ></login-button>
119
- `;
120
- }
121
-
122
- get searchMenuOpen() {
123
- return this.openMenu === 'search';
124
- }
125
-
126
- get allowSecondaryIcon() {
127
- return this.secondIdentitySlotMode === 'allow';
128
- }
129
-
130
- get searchMenu() {
131
- if (this.hideSearch) return nothing;
132
-
133
- return html`
134
- <button
135
- class="search-trigger"
136
- @click="${this.toggleSearchMenu}"
137
- data-event-click-tracking="${this.config.eventCategory}|NavSearchOpen"
138
- >
139
- ${icons.search}
140
- </button>
141
- <nav-search
142
- .baseHost=${this.baseHost}
143
- .config=${this.config}
144
- .locationHandler=${locationHandler}
145
- .open=${this.searchMenuOpen}
146
- .openMenu=${this.openMenu}
147
- .searchIn=${this.searchIn}
148
- .searchQuery=${this.searchQuery}
149
- ></nav-search>
150
- `;
151
- }
152
-
153
- get secondLogoSlot() {
154
- return this.allowSecondaryIcon
155
- ? html`
156
- <slot name="opt-sec-logo"></slot>
157
- <slot name="opt-sec-logo-mobile"></slot>
158
- `
159
- : nothing;
160
- }
161
-
162
- get secondLogoClass() {
163
- return this.allowSecondaryIcon ? 'second-logo' : '';
164
- }
165
-
166
- render() {
167
- const mediaMenuTabIndex = this.openMenu === 'media' ? '' : '-1';
168
- return html`
169
- <nav>
170
- <div class=${`branding ${this.secondLogoClass}`}>
171
- <a
172
- href=${formatUrl('/', this.baseHost)}
173
- @click=${this.trackClick}
174
- data-event-click-tracking="${this.config.eventCategory}|NavHome"
175
- title="Go home"
176
- class="link-home"
177
- >${icons.iaLogo}${logoWordmarkStacked}</a
178
- >
179
- ${this.secondLogoSlot}
180
- </div>
181
- ${this.searchMenu}
182
- <a href="${formatUrl('/create', this.baseHost)}" class="upload">
183
- ${icons.upload}
184
- <span>Upload</span>
185
- </a>
186
- <div class="user-info">
187
- ${this.username ? this.userIcon : this.loginIcon}
188
- </div>
189
- <media-menu
190
- .baseHost=${this.baseHost}
191
- .config=${this.config}
192
- ?mediaMenuAnimate="${this.mediaMenuAnimate}"
193
- tabindex="${mediaMenuTabIndex}"
194
- .selectedMenuOption=${this.selectedMenuOption}
195
- .openMenu=${this.openMenu}
196
- ></media-menu>
197
- <button
198
- class="hamburger"
199
- @click="${this.toggleMediaMenu}"
200
- tabindex="1"
201
- data-event-click-tracking="${this.config.eventCategory}|NavHamburger"
202
- title="Open main menu"
203
- >
204
- <icon-hamburger ?active=${this.openMenu === 'media'}></icon-hamburger>
205
- </button>
206
- </nav>
207
- `;
208
- }
209
- }
210
-
211
- customElements.define('primary-nav', PrimaryNav);
1
+ import { html, nothing } from 'https://offshoot.ux.archive.org/lit.js';
2
+ import TrackedElement from './tracked-element.js';
3
+ import icons from './assets/img/icons.js';
4
+ import './assets/img/hamburger.js';
5
+ import './login-button.js';
6
+ import './nav-search.js';
7
+ import './media-menu.js';
8
+ import logoWordmarkStacked from './assets/img/wordmark-stacked.js';
9
+ import primaryNavCSS from './styles/primary-nav.js';
10
+ import locationHandler from './lib/location-handler.js';
11
+ import formatUrl from './lib/formatUrl.js';
12
+
13
+ class PrimaryNav extends TrackedElement {
14
+ static get styles() {
15
+ return primaryNavCSS;
16
+ }
17
+
18
+ static get properties() {
19
+ return {
20
+ mediaBaseHost: { type: String },
21
+ baseHost: { type: String },
22
+ hideSearch: { type: Boolean },
23
+ config: { type: Object },
24
+ openMenu: { type: String },
25
+ screenName: { type: String },
26
+ searchIn: { type: String },
27
+ searchQuery: { type: String },
28
+ secondIdentitySlotMode: { type: String },
29
+ selectedMenuOption: { type: String },
30
+ signedOutMenuOpen: { type: Boolean },
31
+ userMenuOpen: { type: Boolean },
32
+ username: { type: String },
33
+ userProfileImagePath: { type: String },
34
+ userProfileLastModified: { type: String },
35
+ };
36
+ }
37
+
38
+ constructor() {
39
+ super();
40
+ this.config = {};
41
+ this.openMenu = '';
42
+ this.searchIn = '';
43
+ this.selectedMenuOption = '';
44
+ this.signedOutMenuOpen = false;
45
+ this.userMenuOpen = false;
46
+ this.mediaBaseHost = 'https://archive.org';
47
+ this.secondIdentitySlotMode = '';
48
+ }
49
+
50
+ toggleMediaMenu(e) {
51
+ this.trackClick(e);
52
+ this.dispatchEvent(
53
+ new CustomEvent('menuToggled', {
54
+ detail: {
55
+ menuName: 'media',
56
+ },
57
+ }),
58
+ );
59
+ }
60
+
61
+ toggleSearchMenu(e) {
62
+ this.trackClick(e);
63
+ this.dispatchEvent(
64
+ new CustomEvent('menuToggled', {
65
+ detail: {
66
+ menuName: 'search',
67
+ },
68
+ }),
69
+ );
70
+ }
71
+
72
+ toggleUserMenu(e) {
73
+ this.trackClick(e);
74
+ this.dispatchEvent(
75
+ new CustomEvent('menuToggled', {
76
+ detail: {
77
+ menuName: 'user',
78
+ },
79
+ }),
80
+ );
81
+ }
82
+
83
+ get truncatedScreenName() {
84
+ if (this.screenName && this.screenName.length > 10) {
85
+ return `${this.screenName.substr(0, 9)}…`;
86
+ }
87
+ return this.screenName;
88
+ }
89
+
90
+ get userIcon() {
91
+ const userMenuClass = this.openMenu === 'user' ? 'active' : '';
92
+ const userMenuToolTip = this.openMenu === 'user' ? 'Close user menu' : 'Expand user menu';
93
+
94
+ return html`
95
+ <button
96
+ class="user-menu ${userMenuClass}"
97
+ title="${userMenuToolTip}"
98
+ @click="${this.toggleUserMenu}"
99
+ data-event-click-tracking="${this.config.eventCategory}|NavUserMenu"
100
+ >
101
+ <img
102
+ src="${this.mediaBaseHost}${this.userProfileImagePath}?${this.userProfileLastModified}"
103
+ alt="${this.username}"
104
+ />
105
+ <span class="username">${this.truncatedScreenName}</span>
106
+ </button>
107
+ `;
108
+ }
109
+
110
+ get loginIcon() {
111
+ return html`
112
+ <login-button
113
+ .baseHost=${this.baseHost}
114
+ .config=${this.config}
115
+ .dropdownOpen=${this.signedOutMenuOpen}
116
+ .openMenu=${this.openMenu}
117
+ @signedOutMenuToggled=${this.signedOutMenuToggled}
118
+ ></login-button>
119
+ `;
120
+ }
121
+
122
+ get searchMenuOpen() {
123
+ return this.openMenu === 'search';
124
+ }
125
+
126
+ get allowSecondaryIcon() {
127
+ return this.secondIdentitySlotMode === 'allow';
128
+ }
129
+
130
+ get searchMenu() {
131
+ if (this.hideSearch) return nothing;
132
+
133
+ return html`
134
+ <button
135
+ class="search-trigger"
136
+ @click="${this.toggleSearchMenu}"
137
+ data-event-click-tracking="${this.config.eventCategory}|NavSearchOpen"
138
+ >
139
+ ${icons.search}
140
+ </button>
141
+ <nav-search
142
+ .baseHost=${this.baseHost}
143
+ .config=${this.config}
144
+ .locationHandler=${locationHandler}
145
+ .open=${this.searchMenuOpen}
146
+ .openMenu=${this.openMenu}
147
+ .searchIn=${this.searchIn}
148
+ .searchQuery=${this.searchQuery}
149
+ ></nav-search>
150
+ `;
151
+ }
152
+
153
+ get secondLogoSlot() {
154
+ return this.allowSecondaryIcon
155
+ ? html`
156
+ <slot name="opt-sec-logo"></slot>
157
+ <slot name="opt-sec-logo-mobile"></slot>
158
+ `
159
+ : nothing;
160
+ }
161
+
162
+ get secondLogoClass() {
163
+ return this.allowSecondaryIcon ? 'second-logo' : '';
164
+ }
165
+
166
+ render() {
167
+ const mediaMenuTabIndex = this.openMenu === 'media' ? '' : '-1';
168
+ return html`
169
+ <nav>
170
+ <div class=${`branding ${this.secondLogoClass}`}>
171
+ <a
172
+ href=${formatUrl('/', this.baseHost)}
173
+ @click=${this.trackClick}
174
+ data-event-click-tracking="${this.config.eventCategory}|NavHome"
175
+ title="Go home"
176
+ class="link-home"
177
+ >${icons.iaLogo}${logoWordmarkStacked}</a
178
+ >
179
+ ${this.secondLogoSlot}
180
+ </div>
181
+ ${this.searchMenu}
182
+ <a href="${formatUrl('/create', this.baseHost)}" class="upload">
183
+ ${icons.upload}
184
+ <span>Upload</span>
185
+ </a>
186
+ <div class="user-info">
187
+ ${this.username ? this.userIcon : this.loginIcon}
188
+ </div>
189
+ <media-menu
190
+ .baseHost=${this.baseHost}
191
+ .config=${this.config}
192
+ ?mediaMenuAnimate="${this.mediaMenuAnimate}"
193
+ tabindex="${mediaMenuTabIndex}"
194
+ .selectedMenuOption=${this.selectedMenuOption}
195
+ .openMenu=${this.openMenu}
196
+ ></media-menu>
197
+ <button
198
+ class="hamburger"
199
+ @click="${this.toggleMediaMenu}"
200
+ tabindex="1"
201
+ data-event-click-tracking="${this.config.eventCategory}|NavHamburger"
202
+ title="Open main menu"
203
+ >
204
+ <icon-hamburger ?active=${this.openMenu === 'media'}></icon-hamburger>
205
+ </button>
206
+ </nav>
207
+ `;
208
+ }
209
+ }
210
+
211
+ customElements.define('primary-nav', PrimaryNav);