-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathau-dropdown.gjs
144 lines (128 loc) · 3.42 KB
/
au-dropdown.gjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import { AuButton } from '@appuniversum/ember-appuniversum';
import FloatingUiModifier from '@appuniversum/ember-appuniversum/private/modifiers/floating-ui';
import { hash } from '@ember/helper';
import { on } from '@ember/modifier';
import { action } from '@ember/object';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { focusTrap } from 'ember-focus-trap';
import { modifier } from 'ember-modifier';
import { ChevronDownIcon } from './icons/chevron-down';
export default class AuDropdown extends Component {
@tracked referenceElement = undefined;
@tracked arrowElement = undefined;
@tracked dropdownOpen = false;
floatingUi = FloatingUiModifier;
reference = modifier(
(element) => {
this.referenceElement = element;
},
{ eager: false },
);
arrow = modifier(
(element) => {
this.arrowElement = element;
},
{ eager: false },
);
@action
openDropdown() {
this.dropdownOpen = true;
}
@action
closeDropdown() {
this.dropdownOpen = false;
this.args.onClose?.();
}
@action
toggleDropdown() {
this.dropdownOpen = !this.dropdownOpen;
if (!this.dropdownOpen) {
this.args.onClose?.();
}
}
@action
clickOutsideDeactivates(event) {
let isClosedByToggleButton = this.referenceElement.contains(event.target);
if (!isClosedByToggleButton) {
this.closeDropdown();
}
return true;
}
get alignment() {
if (this.args.alignment == 'left') return 'bottom-start';
if (this.args.alignment == 'right') return 'bottom-end';
return 'bottom';
}
get skin() {
if (this.args.skin) return this.args.skin;
else return 'naked';
}
get icon() {
if (this.args.icon) return this.args.icon;
else return ChevronDownIcon;
}
get iconAlignment() {
if (this.args.iconAlignment) return this.args.iconAlignment;
else return 'right';
}
get floatingUiOptions() {
return {
arrow: {
offset: 0,
},
};
}
<template>
{{~!~}}
<div class="au-c-dropdown" ...attributes>
<AuButton
{{this.reference}}
@skin={{this.skin}}
@size={{@size}}
@icon={{this.icon}}
@iconAlignment={{this.iconAlignment}}
@hideText={{@hideText}}
@alert={{@alert}}
aria-haspopup="true"
aria-expanded="{{if this.dropdownOpen 'true' 'false'}}"
type="button"
{{on "click" this.toggleDropdown}}
data-test-dropdown-button
data-au-dropdown-toggle
>
<span class="au-c-dropdown__name" data-test-dropdown-title>
{{@title}}
</span>
</AuButton>
{{#if this.dropdownOpen}}
<div
{{this.floatingUi
this.referenceElement
this.arrowElement
defaultPlacement=this.alignment
options=this.floatingUiOptions
}}
class="au-c-dropdown__floater"
>
<div {{this.arrow}} class="au-c-dropdown__arrow"></div>
<div
{{focusTrap
shouldSelfFocus=true
focusTrapOptions=(hash
clickOutsideDeactivates=this.clickOutsideDeactivates
)
}}
{{on "click" this.closeDropdown}}
class="au-c-dropdown__menu"
role="menu"
tabindex="-1"
>
{{yield}}
</div>
</div>
{{/if}}
</div>
{{~!~}}
</template>
}