@internetarchive/ia-topnav 1.3.5-alpha8 → 1.3.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/ia-topnav",
3
- "version": "1.3.5-alpha8",
3
+ "version": "1.3.5",
4
4
  "description": "Top nav for Internet Archive",
5
5
  "license": "AGPL-3.0-only",
6
6
  "main": "index.js",
package/src/data/menus.js CHANGED
@@ -48,10 +48,6 @@ export function buildTopNavMenus(userid = '___USERID___', localLinks = true, way
48
48
  title: 'All Audio',
49
49
  url: `${prefix}/details/audio`,
50
50
  },
51
- {
52
- title: 'This Just In',
53
- url: `${prefix}/search.php?query=mediatype:audio&sort=-publicdate`,
54
- },
55
51
  {
56
52
  title: 'Grateful Dead',
57
53
  url: `${prefix}/details/GratefulDead`,
@@ -119,10 +115,6 @@ export function buildTopNavMenus(userid = '___USERID___', localLinks = true, way
119
115
  title: 'All Images',
120
116
  url: `${prefix}/details/image`,
121
117
  },
122
- {
123
- title: 'This Just In',
124
- url: `${prefix}/search.php?query=mediatype:image&sort=-publicdate`,
125
- },
126
118
  {
127
119
  title: 'Flickr Commons',
128
120
  url: `${prefix}/details/flickrcommons`,
@@ -212,10 +204,6 @@ export function buildTopNavMenus(userid = '___USERID___', localLinks = true, way
212
204
  title: 'All Software',
213
205
  url: `${prefix}/details/software`,
214
206
  },
215
- {
216
- title: 'This Just In',
217
- url: `${prefix}/search.php?query=mediatype:software&sort=-publicdate`,
218
- },
219
207
  {
220
208
  title: 'Old School Emulation',
221
209
  url: `${prefix}/details/tosec`,
@@ -293,32 +281,24 @@ export function buildTopNavMenus(userid = '___USERID___', localLinks = true, way
293
281
  ],
294
282
  },
295
283
  texts: {
296
- heading: 'Books',
284
+ heading: 'Texts',
297
285
  iconLinks: [
298
- {
299
- title: 'Books to Borrow',
300
- icon: `${prefix}/images/book-lend.png`,
301
- url: `${prefix}/details/inlibrary`,
302
- },
303
286
  {
304
287
  title: 'Open Library',
305
288
  icon: `${prefix}/images/widgetOL.png`,
306
289
  url: 'https://openlibrary.org/',
307
290
  },
308
- ],
309
- featuredLinks: [
310
291
  {
311
- title: 'All Books',
312
- url: `${prefix}/details/books`,
292
+ title: 'American Libraries',
293
+ icon: `${prefix}/services/img/americana`,
294
+ url: `${prefix}/details/americana`,
313
295
  },
296
+ ],
297
+ featuredLinks: [
314
298
  {
315
299
  title: 'All Texts',
316
300
  url: `${prefix}/details/texts`,
317
301
  },
318
- {
319
- title: 'This Just In',
320
- url: `${prefix}/search.php?query=mediatype:texts&sort=-publicdate`,
321
- },
322
302
  {
323
303
  title: 'Smithsonian Libraries',
324
304
  url: `${prefix}/details/smithsonian`,
@@ -443,10 +423,6 @@ export function buildTopNavMenus(userid = '___USERID___', localLinks = true, way
443
423
  title: 'All Video',
444
424
  url: `${prefix}/details/movies`,
445
425
  },
446
- {
447
- title: 'This Just In',
448
- url: `${prefix}/search.php?query=mediatype:movies&sort=-publicdate`,
449
- },
450
426
  {
451
427
  title: 'Prelinger Archives',
452
428
  url: `${prefix}/details/prelinger`,
@@ -57,7 +57,6 @@ class DropdownMenu extends TrackedElement {
57
57
  return html`<a
58
58
  href="${formatUrl(link.url, this.baseHost)}"
59
59
  class="${link.class}"
60
- tabindex="${this.open ? '' : '-1'}"
61
60
  @click=${this.trackClick}
62
61
  data-event-click-tracking="${this.config.eventCategory}|Nav${link.analyticsEvent}"
63
62
  aria-label=${calloutText ? `New feature: ${link.title}` : nothing}>
package/src/ia-topnav.js CHANGED
@@ -62,7 +62,6 @@ export default class IATopNav extends LitElement {
62
62
  username: { type: String },
63
63
  userProfileImagePath: { type: String },
64
64
  secondIdentitySlotMode: { type: String },
65
- currentTab: { type: Object },
66
65
  };
67
66
  }
68
67
 
@@ -78,7 +77,6 @@ export default class IATopNav extends LitElement {
78
77
  this.searchIn = '';
79
78
  this.selectedMenuOption = '';
80
79
  this.secondIdentitySlotMode = '';
81
- this.currentTab = {};
82
80
  }
83
81
 
84
82
  updated(props) {
@@ -276,7 +274,6 @@ export default class IATopNav extends LitElement {
276
274
  .selectedMenuOption=${this.selectedMenuOption}
277
275
  .username=${this.username}
278
276
  .userProfileImagePath=${this.userProfileImagePath}
279
- .currentTab=${this.currentTab}
280
277
  ?hideSearch=${this.hideSearch}
281
278
  @mediaTypeSelected=${this.mediaTypeSelected}
282
279
  @toggleSearchMenu=${this.toggleSearchMenu}
@@ -292,8 +289,6 @@ export default class IATopNav extends LitElement {
292
289
  .selectedMenuOption=${this.selectedMenuOption}
293
290
  .mediaSliderOpen=${this.mediaSliderOpen}
294
291
  .menus=${this.menus}
295
- tabindex="${this.mediaSliderOpen ? '1' : ''}"
296
- @moveFocusToOthers=${(e) => this.currentTab = e.detail}
297
292
  ></media-slider>
298
293
  </div>
299
294
  ${this.username ? this.userMenu : this.signedOutDropdown}
@@ -310,7 +305,6 @@ export default class IATopNav extends LitElement {
310
305
  <desktop-subnav
311
306
  .baseHost=${this.baseHost}
312
307
  .menuItems=${this.desktopSubnavMenuItems}
313
- @focus=${this.closeMenus}
314
308
  ></desktop-subnav>
315
309
  <div id="close-layer" class="${this.closeLayerClass}" @click=${this.closeMenus}></div>
316
310
  `;
@@ -67,9 +67,9 @@ class LoginButton extends TrackedElement {
67
67
  ${icons.user}
68
68
  </a>
69
69
  <span>
70
- <a href="${this.signupPath}" tabindex="1">Sign up</a>
70
+ <a href="${this.signupPath}">Sign up</a>
71
71
  |
72
- <a href="${this.loginPath}" tabindex="1">Log in</a>
72
+ <a href="${this.loginPath}">Log in</a>
73
73
  </span>
74
74
  </div>
75
75
  `;
@@ -18,7 +18,6 @@ class MediaButton extends TrackedElement {
18
18
  mediatype: { type: String },
19
19
  openMenu: { type: String },
20
20
  selected: { type: Boolean },
21
- selectedMenuOption: { type: String },
22
21
  followable: { type: Boolean },
23
22
  };
24
23
  }
@@ -36,16 +35,9 @@ class MediaButton extends TrackedElement {
36
35
  this.mediatype = '';
37
36
  this.openMenu = '';
38
37
  this.selected = false;
39
- this.selectedMenuOption = '';
40
38
  this.followable = false;
41
39
  }
42
40
 
43
- updated() {
44
- console.log(this.selectedMenuOption)
45
- // if (this.selectedMenuOption)
46
- // this.shadowDom.querySelector(`a.${this.mediatype}`).focus();
47
- }
48
-
49
41
  onClick(e) {
50
42
  this.trackClick(e);
51
43
  e.preventDefault();
@@ -103,26 +95,14 @@ class MediaButton extends TrackedElement {
103
95
  `;
104
96
  }
105
97
 
106
- emitHandleSubMenuKeyDown(e) {
107
- this.dispatchEvent(new CustomEvent('subMenuKeyDown1', {
108
- bubbles: true,
109
- composed: true,
110
- detail: {
111
- e
112
- }
113
- }));
114
- }
115
-
116
98
  render() {
117
99
  return html`
118
100
  <a
119
101
  href="${this.href}"
120
102
  class="menu-item ${this.mediatype} ${this.buttonClass}"
121
103
  @click=${this.followable ? this.trackClick : this.onClick}
122
- @keydown="${this.emitHandleSubMenuKeyDown}"
123
104
  data-event-click-tracking="${this.analyticsEvent}"
124
105
  title="${this.tooltipPrefix} ${this.mediatype} menu"
125
- tabindex="${this.openMenu === 'media' ? '' : '0'}"
126
106
  >
127
107
  ${this.menuItem}
128
108
  </a>
package/src/media-menu.js CHANGED
@@ -15,7 +15,7 @@ const menuSelection = [
15
15
  icon: 'texts',
16
16
  menu: 'texts',
17
17
  href: '/details/texts',
18
- label: 'Books',
18
+ label: 'Texts',
19
19
  },
20
20
  {
21
21
  icon: 'video',
@@ -67,11 +67,6 @@ class MediaMenu extends LitElement {
67
67
  config: { type: Object },
68
68
  openMenu: { type: String },
69
69
  selectedMenuOption: { type: String },
70
-
71
- isSubMenuOpen: { type: Boolean },
72
- focusedIndex: { type: Number },
73
-
74
- currentTab: { type: Object },
75
70
  };
76
71
  }
77
72
 
@@ -80,95 +75,8 @@ class MediaMenu extends LitElement {
80
75
  this.config = {};
81
76
  this.openMenu = '';
82
77
  this.selectedMenuOption = '';
83
-
84
- this.isSubMenuOpen = false;
85
- this.focusedIndex = -1;
86
- this.menuRef = [];
87
- this.subMenuRef = [];
88
-
89
- this.currentTab = {};
90
- this.focusOn = 0;
91
- }
92
-
93
- firstUpdated() {
94
- this.menuRef = Array.from(this.shadowRoot.querySelectorAll('media-button'));
95
- // this.subMenuRef = Array.from(this.shadowRoot.querySelectorAll('.submenu-item'));
96
- // this.shadowRoot.querySelector('media-button').focus();
97
- // this.addEventListener('keydown', this.handleKeyDown.bind(this));
98
-
99
- // this.shadowRoot.querySelector('.menu-group media-button').shadowRoot.querySelector(`${this.selectedMenuOption}`);
100
- }
101
-
102
- updated(props) {
103
- // console.log(props)
104
- if (props.has('currentTab')) {
105
- // console.log(this.currentTab.mediatype, this.currentTab.moveTo)
106
-
107
- // const dd = this.shadowRoot.querySelector('primary-nav').shadowRoot.querySelector('media-menu');
108
- const mediaButtons = Array.from(this.shadowRoot.querySelectorAll('media-button'));
109
- // console.log(mediaButtons)
110
-
111
- // let = newIndex1 = 0;
112
- mediaButtons.map((button, index) => {
113
- // console.log(button.shadowRoot.querySelector('a.menu-item'));
114
-
115
- const linkItem = button.shadowRoot.querySelector('a.menu-item');
116
- if (linkItem) {
117
- // console.log(linkItem)
118
- if (linkItem.classList.contains(`${this.selectedMenuOption}`)) {
119
- linkItem.classList.remove('selected');
120
- linkItem.blur();
121
-
122
- // newIndex1 = this.currentTab.moveTo === 'next' ? index++ : index--;
123
- // if (this.currentTab.moveTo)
124
- // mediaButtons[index].shadowRoot.querySelector('a.menu-item').blur();
125
- // if (this.currentTab.moveTo === 'next') {
126
- // mediaButtons[index + 1].shadowRoot.querySelector('a.menu-item').focus();
127
- // } else if (this.currentTab.moveTo === 'prev') {
128
- mediaButtons[this.currentTab.moveTo === 'next' ? index + 1 : index - 1].shadowRoot.querySelector('a.menu-item').focus();
129
- // }
130
- }
131
- }
132
- });
133
-
134
- // console.log('updatedddddddddddd', this.selectedMenuOption, this.shadowRoot.querySelector('.menu-group'));
135
-
136
-
137
- // this.shadowRoot.querySelector('.menu-group').focus();
138
- // console.log(props);
139
- // this.shadowRoot.querySelectorAll('media-button').shadowRoot.querySelector(`${this.selectedMenuOption}`);
140
-
141
- // this.requestUpdate();
142
- // this.updateRequest();
143
- // this.menuRef = Array.from(this.shadowRoot.querySelectorAll('media-button'));
144
- }
145
78
  }
146
79
 
147
- handleKeyDown(e) {
148
- // console.log('dddddddddddd')
149
- if (e.key === 'Tab') {
150
- console.log(this.menuRef)
151
- this.focusedIndex = (this.focusedIndex + 1) % this.menuRef.length;
152
- this.submenuFocusedIndex = -1; // reset submenu focus index
153
- this.menuRef[this.focusedIndex].focus();
154
- }
155
- }
156
-
157
- // handleSubMenuKeydown(e) {
158
- // console.log(e);
159
- // if (e.key === 'ArrowDown') {
160
- // this.focusedIndex = (this.focusedIndex + 1) % this.subMenuRef.length;
161
- // this.subMenuRef[this.focusedIndex].focus();
162
- // } else if (e.key === 'ArrowUp') {
163
- // this.focusedIndex = (this.focusedIndex - 1 + this.subMenuRef.length) % this.subMenuRef.length;
164
- // this.subMenuRef[this.focusedIndex].focus();
165
- // } else if (e.key === 'Escape') {
166
- // this.isSubMenuOpen = false;
167
- // this.requestUpdate();
168
- // setTimeout(() => this.menuRef[0]?.focus(), 0);
169
- // }
170
- // }
171
-
172
80
  get mediaMenuOptionsTemplate() {
173
81
  const buttons = menuSelection.map(({
174
82
  icon,
@@ -178,7 +86,6 @@ class MediaMenu extends LitElement {
178
86
  followable,
179
87
  }) => {
180
88
  const selected = this.selectedMenuOption === menu;
181
- // this.focusOn =
182
89
  return html`
183
90
  <media-button
184
91
  .config=${this.config}
@@ -189,9 +96,7 @@ class MediaMenu extends LitElement {
189
96
  .mediatype=${menu}
190
97
  .openMenu=${this.openMenu}
191
98
  .selected=${selected}
192
- .selectedMenuOption=${this.selectedMenuOption}
193
99
  data-mediatype="${menu}"
194
- .focusOn=${this.focusOn}
195
100
  ></media-button>
196
101
  `;
197
102
  });
@@ -212,6 +117,7 @@ class MediaMenu extends LitElement {
212
117
  <div class="overflow-clip">
213
118
  <nav
214
119
  class="media-menu-inner"
120
+ aria-hidden="${!this.menuOpened}"
215
121
  aria-expanded="${this.menuOpened}"
216
122
  >
217
123
  <div class="menu-group">
@@ -1,7 +1,6 @@
1
1
  import { LitElement, html } from 'https://offshoot.prod.archive.org/lit.js';
2
2
  import './media-subnav.js';
3
3
  import mediaSliderCSS from './styles/media-slider.js';
4
- import KeyboardNavigation from './lib/keyboard-navigation.js';
5
4
 
6
5
  class MediaSlider extends LitElement {
7
6
  static get styles() {
@@ -27,19 +26,6 @@ class MediaSlider extends LitElement {
27
26
  this.selectedMenuOption = 'texts';
28
27
  }
29
28
 
30
- updated(props) {
31
- if (props.has('selectedMenuOption') && this.selectedMenuOption) {
32
- const container = this.shadowRoot?.querySelector('.has-focused')?.shadowRoot;
33
-
34
- if (container) {
35
- const keyboardNavigation = new KeyboardNavigation(container, this.selectedMenuOption);
36
- this.addEventListener('keydown', keyboardNavigation.handleKeyDown);
37
- this.removeEventListener('keydown', this.previousKeydownListener);
38
- this.previousKeydownListener = keyboardNavigation.handleKeyDown;
39
- }
40
- }
41
- }
42
-
43
29
  shouldUpdate() {
44
30
  const scrollPane = this.shadowRoot ? this.shadowRoot.querySelector('.information-menu') : null;
45
31
 
@@ -61,49 +47,49 @@ class MediaSlider extends LitElement {
61
47
  <media-subnav
62
48
  .baseHost=${this.baseHost}
63
49
  .config=${this.config}
64
- class="${this.selectedMenuOption === 'audio' ? 'has-focused' : 'hidden'}"
50
+ class="${this.selectedMenuOption === 'audio' ? '' : 'hidden'}"
65
51
  menu="audio"
66
52
  .menuItems=${this.menus.audio}
67
53
  ></media-subnav>
68
54
  <media-subnav
69
55
  .baseHost=${this.baseHost}
70
56
  .config=${this.config}
71
- class="${this.selectedMenuOption === 'images' ? 'has-focused' : 'hidden'}"
57
+ class="${this.selectedMenuOption === 'images' ? '' : 'hidden'}"
72
58
  menu="images"
73
59
  .menuItems=${this.menus.images}
74
60
  ></media-subnav>
75
61
  <media-subnav
76
62
  .baseHost=${this.baseHost}
77
63
  .config=${this.config}
78
- class="${this.selectedMenuOption === 'software' ? 'has-focused' : 'hidden'}"
64
+ class="${this.selectedMenuOption === 'software' ? '' : 'hidden'}"
79
65
  menu="software"
80
66
  .menuItems=${this.menus.software}
81
67
  ></media-subnav>
82
68
  <media-subnav
83
69
  .baseHost=${this.baseHost}
84
70
  .config=${this.config}
85
- class="${this.selectedMenuOption === 'texts' ? 'has-focused' : 'hidden'}"
71
+ class="${this.selectedMenuOption === 'texts' ? '' : 'hidden'}"
86
72
  menu="texts"
87
73
  .menuItems=${this.menus.texts}
88
74
  ></media-subnav>
89
75
  <media-subnav
90
76
  .baseHost=${this.baseHost}
91
77
  .config=${this.config}
92
- class="${this.selectedMenuOption === 'video' ? 'has-focused' : 'hidden'}"
78
+ class="${this.selectedMenuOption === 'video' ? '' : 'hidden'}"
93
79
  menu="video"
94
80
  .menuItems=${this.menus.video}
95
81
  ></media-subnav>
96
82
  <media-subnav
97
83
  .baseHost=${this.baseHost}
98
84
  .config=${this.config}
99
- class="${this.selectedMenuOption === 'web' ? 'has-focused' : 'hidden'}"
85
+ class="${this.selectedMenuOption === 'web' ? '' : 'hidden'}"
100
86
  menu="web"
101
87
  .menuItems=${this.menus.web}
102
88
  ></media-subnav>
103
89
  <media-subnav
104
90
  .baseHost=${this.baseHost}
105
91
  .config=${this.config}
106
- class="${this.selectedMenuOption === 'more' ? 'has-focused' : 'hidden'}"
92
+ class="${this.selectedMenuOption === 'more' ? '' : 'hidden'}"
107
93
  menu="more"
108
94
  .menuItems=${this.menus.more}
109
95
  ></media-subnav>
package/src/nav-search.js CHANGED
@@ -34,6 +34,13 @@ class NavSearch extends TrackedElement {
34
34
  this.initSearchBetaOptIn();
35
35
  }
36
36
 
37
+ updated() {
38
+ if (this.open) {
39
+ this.shadowRoot.querySelector('[name=query]').focus();
40
+ }
41
+ return true;
42
+ }
43
+
37
44
  initSearchBetaOptIn() {
38
45
  this.inSearchBeta = !!window.localStorage?.getItem('SearchBeta-opt-in') ||
39
46
  !!window.localStorage?.getItem('SearchBeta-launched');
@@ -98,14 +105,13 @@ class NavSearch extends TrackedElement {
98
105
  class="search-field"
99
106
  placeholder="Search"
100
107
  autocomplete="off"
101
- value=${this.searchQuery || ''}
102
108
  @focus=${this.toggleSearchMenu}
109
+ value=${this.searchQuery || ''}
103
110
  />
104
111
  ${this.searchInsideInput}
105
112
  <button
106
113
  type="submit"
107
114
  class="search"
108
- tabindex="-1"
109
115
  data-event-click-tracking="${this.config.eventCategory}|NavSearchClose"
110
116
  >
111
117
  ${icons.search}
@@ -31,7 +31,6 @@ class PrimaryNav extends TrackedElement {
31
31
  userMenuOpen: { type: Boolean },
32
32
  username: { type: String },
33
33
  userProfileImagePath: { type: String },
34
- currentTab: { type: Object },
35
34
  };
36
35
  }
37
36
 
@@ -45,7 +44,6 @@ class PrimaryNav extends TrackedElement {
45
44
  this.userMenuOpen = false;
46
45
  this.mediaBaseHost = 'https://archive.org';
47
46
  this.secondIdentitySlotMode = '';
48
- this.currentTab = {};
49
47
  }
50
48
 
51
49
  toggleMediaMenu(e) {
@@ -154,11 +152,7 @@ class PrimaryNav extends TrackedElement {
154
152
  }
155
153
 
156
154
  get uploadButtonTemplate() {
157
- return html`
158
- <a href="${formatUrl('/create', this.baseHost)}"
159
- class="upload"
160
- @focus=${this.toggleMediaMenu}
161
- >
155
+ return html`<a href="${formatUrl('/create', this.baseHost)}" class="upload">
162
156
  ${icons.upload}
163
157
  <span>Upload</span>
164
158
  </a>`;
@@ -187,15 +181,6 @@ class PrimaryNav extends TrackedElement {
187
181
  const mediaMenuTabIndex = this.openMenu === 'media' ? '' : '-1';
188
182
  return html`
189
183
  <nav class=${this.hideSearch ? 'hide-search' : nothing}>
190
- <button
191
- class="hamburger"
192
- @click="${this.toggleMediaMenu}"
193
- data-event-click-tracking="${this.config.eventCategory}|NavHamburger"
194
- title="Open main menu"
195
- >
196
- <icon-hamburger ?active=${this.openMenu === 'media'}></icon-hamburger>
197
- </button>
198
-
199
184
  <div class=${`branding ${this.secondLogoClass}`}>
200
185
  <a
201
186
  href=${formatUrl('/', this.baseHost)}
@@ -203,25 +188,34 @@ class PrimaryNav extends TrackedElement {
203
188
  data-event-click-tracking="${this.config.eventCategory}|NavHome"
204
189
  title="Go home"
205
190
  class="link-home"
206
- tabindex="-1"
207
191
  >${icons.iaLogo}${logoWordmarkStacked}</a
208
192
  >
209
193
  ${this.secondLogoSlot}
210
194
  </div>
195
+
196
+ <div class="right-side-section">
197
+ ${this.mobileDonateHeart}
198
+ ${this.searchMenu}
199
+ ${this.uploadButtonTemplate}
200
+ ${this.userStateTemplate}
201
+ </div>
211
202
  <media-menu
212
203
  .baseHost=${this.baseHost}
213
204
  .config=${this.config}
214
205
  ?mediaMenuAnimate="${this.mediaMenuAnimate}"
206
+ tabindex="${mediaMenuTabIndex}"
215
207
  .selectedMenuOption=${this.selectedMenuOption}
216
208
  .openMenu=${this.openMenu}
217
- .currentTab=${this.currentTab}
218
209
  ></media-menu>
219
- <div class="right-side-section">
220
- ${this.mobileDonateHeart}
221
- ${this.userStateTemplate}
222
- ${this.uploadButtonTemplate}
223
- ${this.searchMenu}
224
- </div>
210
+ <button
211
+ class="hamburger"
212
+ @click="${this.toggleMediaMenu}"
213
+ tabindex="1"
214
+ data-event-click-tracking="${this.config.eventCategory}|NavHamburger"
215
+ title="Open main menu"
216
+ >
217
+ <icon-hamburger ?active=${this.openMenu === 'media'}></icon-hamburger>
218
+ </button>
225
219
  </nav>
226
220
  `;
227
221
  }
@@ -29,36 +29,6 @@ class SearchMenu extends TrackedElement {
29
29
  this.selectedSearchType = '';
30
30
  }
31
31
 
32
- firstUpdated() {
33
- this.shadowRoot.addEventListener('keydown', e => this.handleKeyDownEvent(e));
34
- }
35
-
36
- disconnectedCallback() {
37
- // Clean up event listener when the element is removed
38
- this.shadowRoot.removeEventListener('keydown', e => this.handleKeyDownEvent(e));
39
- }
40
-
41
- handleKeyDownEvent(e) {
42
- const searchTypes = this.shadowRoot.querySelectorAll('.search-menu-inner label input[type=radio]');
43
-
44
- const length = searchTypes.length - 1;
45
- if (!length) return;
46
-
47
- const searchTypeHandler = (index) => {
48
- e.preventDefault();
49
- const searchType = searchTypes[index];
50
- searchType.checked = true;
51
- searchType.dispatchEvent(new Event('change'));
52
- searchType.focus();
53
- };
54
-
55
- if (e.key === 'Home') {
56
- searchTypeHandler(0);
57
- } else if (e.key === 'End') {
58
- searchTypeHandler(length);
59
- }
60
- }
61
-
62
32
  selectSearchType(e) {
63
33
  this.selectedSearchType = e.target.value;
64
34
  }
@@ -92,7 +92,6 @@ export default css`
92
92
 
93
93
  @media (min-width: 890px) {
94
94
  nav {
95
- display: flex;
96
95
  overflow: visible;
97
96
  top: 0;
98
97
  left: auto;
@@ -147,7 +146,6 @@ export default css`
147
146
  a:focus {
148
147
  color: var(--linkHoverColor);
149
148
  background: var(--linkColor);
150
- outline: none;
151
149
  }
152
150
 
153
151
  .initial,
@@ -24,7 +24,7 @@ export default css`
24
24
  /* Mobile view styles */
25
25
  @media (max-width: 889px) {
26
26
  .media-menu-container {
27
- // position: relative;
27
+ position: relative;
28
28
  }
29
29
 
30
30
  .media-menu-inner {
@@ -39,7 +39,7 @@ export default css`
39
39
  .overflow-clip {
40
40
  position: absolute;
41
41
  z-index: -1; /** needs to be under the navigation, otherwise it intercepts clicks */
42
- top: 4rem;
42
+ top: 0;
43
43
  left: 0;
44
44
  height: 0;
45
45
  width: 100%;
@@ -10,8 +10,7 @@ export default css`
10
10
  nav {
11
11
  position: relative;
12
12
  display: -ms-grid;
13
- // display: grid;
14
- display: flex;
13
+ display: grid;
15
14
  height: 4rem;
16
15
  grid-template-areas: 'hamburger empty heart search user';
17
16
  -ms-grid-columns: 4rem minmax(1rem, 100%) 4rem 4rem 4rem;
@@ -30,7 +29,6 @@ export default css`
30
29
 
31
30
  .right-side-section {
32
31
  display: flex;
33
- margin-left: auto;
34
32
  user-select: none;
35
33
  }
36
34
  button {
@@ -88,9 +86,6 @@ export default css`
88
86
  fill: var(--activeColor);
89
87
  }
90
88
 
91
- .mobile-donate-link {
92
- display: inline-block;
93
- }
94
89
  .mobile-donate-link svg {
95
90
  height: 4rem;
96
91
  width: 4rem;
@@ -156,8 +151,7 @@ export default css`
156
151
  height: 100%;
157
152
  }
158
153
 
159
- .user-menu:hover,
160
- .user-menu:focus {
154
+ .user-menu:hover {
161
155
  color: var(--linkHoverColor);
162
156
  }
163
157
 
@@ -193,13 +187,6 @@ export default css`
193
187
  slot[name='opt-sec-logo'] {
194
188
  display: none;
195
189
  }
196
-
197
- .right-side-section {
198
- display: initial;
199
- }
200
- .right-side-section .user-info {
201
- float: right;
202
- }
203
190
  }
204
191
 
205
192
  @media (min-width: 890px) {
@@ -208,8 +195,12 @@ export default css`
208
195
  --userIconHeight: 3.2rem;
209
196
  }
210
197
 
198
+ .right-side-section {
199
+ display: contents;
200
+ }
201
+
211
202
  nav {
212
- display: flex;
203
+ display: block;
213
204
  z-index: 4;
214
205
  height: 5rem;
215
206
  padding-right: 1.5rem;
@@ -43,9 +43,6 @@ export default css`
43
43
  .advanced-search {
44
44
  text-decoration: none;
45
45
  color: var(--linkColor);
46
- line-height: normal;
47
- padding: 0.5rem;
48
- margin-top: 5px;
49
46
  }
50
47
 
51
48
  @media (min-width: 890px) {
@@ -89,8 +86,6 @@ export default css`
89
86
 
90
87
  label {
91
88
  padding: 0;
92
- font-weight: normal;
93
- margin: 0;
94
89
  }
95
90
 
96
91
  label + label {
package/src/user-menu.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { html } from 'https://offshoot.prod.archive.org/lit.js';
2
2
  import DropdownMenu from './dropdown-menu.js';
3
3
  import userMenuCSS from './styles/user-menu.js';
4
- import KeyboardNavigation from './lib/keyboard-navigation.js';
5
4
 
6
5
  class UserMenu extends DropdownMenu {
7
6
  static get styles() {
@@ -22,19 +21,6 @@ class UserMenu extends DropdownMenu {
22
21
  this.username = '';
23
22
  }
24
23
 
25
- updated(props) {
26
- if (props.has('open')) {
27
- const container = this.shadowRoot?.querySelector('.nav-container');
28
-
29
- if (container) {
30
- const keyboardNavigation = new KeyboardNavigation(container, 'usermenu');
31
- this.addEventListener('keydown', keyboardNavigation.handleKeyDown);
32
- this.removeEventListener('keydown', this.previousKeydownListener);
33
- this.previousKeydownListener = keyboardNavigation.handleKeyDown;
34
- }
35
- }
36
- }
37
-
38
24
  render() {
39
25
  return html`
40
26
  <div class="nav-container">
@@ -1,124 +0,0 @@
1
- export default class KeyboardNavigation {
2
- /**
3
- * Constructor for the KeyboardNavigation class.
4
- * @param {HTMLElement} elementsContainer - The container element that holds the focusable elements.
5
- * @param {string} menuOption - The type of menu option ('web' or 'usermenu').
6
- */
7
- constructor(elementsContainer, menuOption) {
8
- this.elementsContainer = elementsContainer;
9
- this.menuOption = menuOption;
10
- this.focusableElements = this.getFocusableElements();
11
- this.focusedIndex = this.getInitialFocusedIndex();
12
-
13
- this.focusableElements[this.focusedIndex]?.focus();
14
- this.handleKeyDown = this.handleKeyDown.bind(this);
15
- }
16
-
17
- /**
18
- * Returns the initial focused index based on the menu option.
19
- * @returns {number} The initial focused index (0 for 'web', 1 for 'usermenu').
20
- */
21
- getInitialFocusedIndex() {
22
- return this.menuOption === 'usermenu' ? 1 : 0;
23
- }
24
-
25
- /**
26
- * Gets an array of focusable elements within the container.
27
- * @returns {HTMLElement[]} An array of focusable elements.
28
- */
29
- getFocusableElements() {
30
- const focusableTagSelectors = 'a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])';
31
- const isDisabledOrHidden = el => !el.hasAttribute('disabled') && !el.getAttribute('aria-hidden');
32
-
33
- let elements;
34
- if (this.menuOption === 'web') {
35
- const waybackSlider = this.elementsContainer.querySelector('wayback-slider').shadowRoot;
36
- const waybackSearch = waybackSlider.querySelector('wayback-search');
37
- const waybackSearchElements = Array.from(waybackSearch.shadowRoot.querySelectorAll(focusableTagSelectors));
38
-
39
- const normalElements = Array.from(waybackSlider.querySelectorAll(focusableTagSelectors));
40
-
41
- const savePageForm = waybackSlider.querySelector('save-page-form');
42
- const savePageFormElements = Array.from(savePageForm.shadowRoot.querySelectorAll(focusableTagSelectors));
43
-
44
- elements = [...waybackSearchElements, ...normalElements, ...savePageFormElements];
45
- } else {
46
- elements = this.elementsContainer.querySelectorAll(focusableTagSelectors);
47
- }
48
-
49
- return Array.from(elements).filter(isDisabledOrHidden);
50
- }
51
-
52
- /**
53
- * Handles keyboard events and focuses the appropriate element.
54
- * @param {KeyboardEvent} event - The keyboard event object.
55
- */
56
- handleKeyDown(event) {
57
- const { key } = event;
58
- const isArrowKey = ['ArrowDown', 'ArrowRight', 'ArrowUp', 'ArrowLeft'].includes(key);
59
- const isTabKey = key === 'Tab';
60
-
61
- if (isArrowKey) {
62
- this.handleArrowKey(key);
63
- } else if (isTabKey) {
64
- this.handleTabKey(event);
65
- }
66
- }
67
-
68
- /**
69
- * Handles arrow key events and focuses the next or previous element.
70
- * @param {string} key - The key that was pressed ('ArrowDown', 'ArrowRight', 'ArrowUp', or 'ArrowLeft').
71
- */
72
- handleArrowKey(key) {
73
- const isDownOrRight = ['ArrowDown', 'ArrowRight'].includes(key);
74
- isDownOrRight ? this.focusNext() : this.focusPrevious();
75
- }
76
-
77
- /**
78
- * Focuses the previous focusable element in the container.
79
- */
80
- focusPrevious() {
81
- if (this.focusableElements.length === 0) return;
82
- this.focusedIndex = (this.focusedIndex - 1 + this.focusableElements.length) % this.focusableElements.length;
83
- this.focusableElements[this.focusedIndex]?.focus();
84
- }
85
-
86
- /**
87
- * Focuses the next focusable element in the container.
88
- */
89
- focusNext() {
90
- if (this.focusableElements.length === 0) return;
91
- this.focusedIndex = (this.focusedIndex + 1) % this.focusableElements.length;
92
- this.focusableElements[this.focusedIndex]?.focus();
93
- }
94
-
95
- /**
96
- * Handles the Tab key event and focuses the next or previous menu item.
97
- * @param {KeyboardEvent} event - The keyboard event object.
98
- */
99
- handleTabKey(event) {
100
- if (this.menuOption !== 'usermenu') {
101
- const isShiftPressed = event.shiftKey;
102
- this.focusNextMenuItem(isShiftPressed);
103
- }
104
-
105
- event.preventDefault();
106
- }
107
-
108
- /**
109
- * Focuses the next or previous menu item based on the provided flag.
110
- * @param {boolean} isPrevious - A flag indicating whether to focus the previous menu item.
111
- */
112
- focusNextMenuItem(isPrevious = false) {
113
- this.elementsContainer.dispatchEvent(
114
- new CustomEvent('moveFocusToOthers', {
115
- bubbles: true,
116
- composed: true,
117
- detail: {
118
- mediatype: this.menuOption,
119
- moveTo: isPrevious ? 'prev' : 'next',
120
- },
121
- })
122
- );
123
- }
124
- }