@internetarchive/ia-topnav 1.1.26 → 1.1.27-alpha.1

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