Skip to content

Commit 6458b21

Browse files
authored
Merge pull request #399 from hannakim91/co-locate-es-header-navbar-link-component
Convert classic component to glimmer component and co-locate
2 parents 27ef64c + d6e682b commit 6458b21

File tree

3 files changed

+95
-95
lines changed

3 files changed

+95
-95
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<li
2+
class='navbar-list-item {{if this.isDropdown "dropdown"}}'
3+
{{did-insert this.setElement}}
4+
{{will-destroy this.unregisterListener}}
5+
>
6+
{{#if (eq @link.type 'link')}}
7+
<a class='navbar-list-item-link' href={{@link.href}}>
8+
{{@link.name}}
9+
</a>
10+
{{/if}}
11+
{{#if (eq @link.type 'dropdown')}}
12+
<button
13+
type='button'
14+
class='navbar-list-item-dropdown-toggle {{
15+
if this.isDropdownOpen 'active'
16+
}}'
17+
aria-expanded={{this.isExpanded}}
18+
{{on 'click' this.toggleDropdown}}
19+
{{on 'blur' this.processBlur}}
20+
>
21+
{{@link.name}}
22+
</button>
23+
{{#if this.isDropdownOpen}}
24+
<ul class='navbar-dropdown-list'>
25+
{{#each @link.items as |item|}}
26+
{{#if (eq item.type 'link')}}
27+
<li class='navbar-dropdown-list-item'>
28+
<a class='navbar-dropdown-list-item-link' href={{item.href}}>
29+
{{item.name}}
30+
</a>
31+
</li>
32+
{{/if}}
33+
{{#if (eq item.type 'divider')}}
34+
<li role='separator' class='separator'></li>
35+
{{/if}}
36+
{{/each}}
37+
</ul>
38+
{{/if}}
39+
{{/if}}
40+
</li>
Lines changed: 55 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,53 @@
11
/* eslint-disable ember/no-classic-components, ember/no-classic-classes, ember/require-tagless-components, prettier/prettier, ember/no-get, ember/no-component-lifecycle-hooks, ember/require-super-in-lifecycle-hooks */
2-
import Component from '@ember/component';
3-
import layout from 'ember-styleguide/templates/components/es-header-navbar-link';
4-
import { computed } from '@ember/object';
5-
import { equal } from '@ember/object/computed';
2+
import Component from '@glimmer/component';
63
import { inject as service } from '@ember/service';
74
import { schedule, next } from '@ember/runloop';
85
import { action } from '@ember/object';
6+
import { tracked } from '@glimmer/tracking';
97

10-
export default Component.extend({
11-
layout,
12-
tagName: 'li',
13-
classNames: ['navbar-list-item'],
14-
classNameBindings: ['isDropdown:dropdown'],
15-
isDropdown: equal('link.type', 'dropdown'),
16-
isDropdownOpen: false,
8+
export default class EsHeaderNavbarLink extends Component {
9+
@service navbar;
1710

18-
// because aria-expanded requires a string value instead of a boolean
19-
isExpanded: computed('isDropdownOpen', function() {
20-
return this.isDropdownOpen ? 'true' : 'false';
21-
}),
11+
@tracked element = null;
12+
@tracked linkType = this.args.link.type;
13+
@tracked isDropdownOpen = false;
2214

23-
navbar: service(),
15+
get isDropdown() {
16+
return this.linkType === 'dropdown';
17+
}
2418

25-
init() {
26-
this._super(...arguments);
27-
this.get('navbar').register(this);
28-
},
29-
30-
didInsertElement() {
31-
let button = this.element.querySelector('.navbar-list-item-dropdown-toggle');
19+
// because aria-expanded requires a string value instead of a boolean
20+
get isExpanded() {
21+
return this.isDropdownOpen ? 'true' : 'false';
22+
}
3223

33-
if (button) {
34-
button.addEventListener('blur', () => this.processBlur());
35-
}
36-
},
24+
constructor() {
25+
super(...arguments);
26+
this.navbar.register(this);
27+
}
3728

3829
setupLinkBlurs() {
3930
if (this.linkBlursActive) {
4031
return;
4132
}
4233

43-
this.set('linkBlursActive', true);
44-
34+
this.linkBlursActive = true;
4535
let links = Array.from(this.element.querySelectorAll('.navbar-dropdown-list-item-link'));
4636

47-
links.forEach(ancor => {
48-
ancor.addEventListener('blur', () => this.processBlur());
37+
links.forEach(anchor => {
38+
anchor.addEventListener('blur', () => this.processBlur());
4939
});
50-
},
40+
}
41+
42+
@action
43+
setElement(element) {
44+
this.element = element;
45+
}
5146

5247
@action
5348
toggleDropdown(event) {
54-
this.get('navbar').closePopupMenu(this);
55-
this.toggleProperty('isDropdownOpen');
49+
this.navbar.closePopupMenu(this);
50+
this.isDropdownOpen = !this.isDropdownOpen;
5651

5752
if (this.isDropdownOpen) {
5853
// if it's open, let's make sure it can do some things
@@ -68,20 +63,9 @@ export default Component.extend({
6863
this.processKeyPress();
6964
});
7065
}
71-
},
72-
73-
closeDropdown() {
74-
// set the isDropdownOpen to false, which will make the dropdown go away
75-
this.set('isDropdownOpen', false);
76-
},
77-
78-
openDropdown() {
79-
//might not need this
80-
// open the dropdown and set the focus to the first item inside
81-
this.set('isDropdownOpen', true);
82-
this.processFirstElementFocus();
83-
},
66+
}
8467

68+
@action
8569
processBlur() {
8670
next(this, function() {
8771
let subItems = Array.from(this.element.querySelectorAll('.navbar-dropdown-list li'));
@@ -92,17 +76,35 @@ export default Component.extend({
9276
this.closeDropdown();
9377
}
9478
});
95-
},
79+
}
80+
81+
@action
82+
unregisterListener(element) {
83+
element.removeEventListener('keydown', this.triggerDropdown);
84+
element.removeEventListener('click', this.triggerDropdown);
85+
}
86+
87+
closeDropdown() {
88+
// set the isDropdownOpen to false, which will make the dropdown go away
89+
this.isDropdownOpen = false;
90+
}
91+
92+
openDropdown() {
93+
//might not need this
94+
// open the dropdown and set the focus to the first item inside
95+
this.isDropdownOpen = true;
96+
this.processFirstElementFocus();
97+
}
9698

9799
processClick() {
98100
// TODO handle mouseclick outside the current dropdown
99-
},
101+
}
100102

101103
processFirstElementFocus() {
102104
// Identify the first item in the dropdown list & set focus on it
103105
let firstFocusable = this.element.querySelector('.navbar-dropdown-list li:first-of-type a');
104106
firstFocusable.focus();
105-
},
107+
}
106108

107109
processKeyPress() {
108110
// add event listeners
@@ -122,18 +124,13 @@ export default Component.extend({
122124
return;
123125
}
124126
});
125-
},
127+
}
126128

127129
returnFocus() {
128130
// after that rendering bit happens, we need to return the focus to the trigger
129131
schedule('afterRender', this, function() {
130132
let dropdownTrigger = this.element.querySelector('.navbar-list-item-dropdown-toggle');
131133
dropdownTrigger.focus();
132134
});
133-
},
134-
135-
willDestroyElement() {
136-
document.removeEventListener('keydown', this.triggerDropdown);
137-
// document.removeEventListener('click', this.triggerDropdown);
138-
},
139-
});
135+
}
136+
}

addon/templates/components/es-header-navbar-link.hbs

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)