@apptegy/nuxt-navigation 0.1.6 → 0.1.8

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/dist/module.d.mts CHANGED
@@ -2,6 +2,6 @@ import * as _nuxt_schema from '@nuxt/schema';
2
2
 
3
3
  interface ModuleOptions {
4
4
  }
5
- declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
5
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
6
6
 
7
7
  export { type ModuleOptions, _default as default };
package/dist/module.d.ts CHANGED
@@ -2,6 +2,6 @@ import * as _nuxt_schema from '@nuxt/schema';
2
2
 
3
3
  interface ModuleOptions {
4
4
  }
5
- declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
5
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
6
6
 
7
7
  export { type ModuleOptions, _default as default };
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@apptegy/nuxt-navigation",
3
3
  "configKey": "@apptegy/nuxt-navigation",
4
- "version": "0.1.6",
4
+ "version": "0.1.8",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.8.3",
7
7
  "unbuild": "unknown"
@@ -22,7 +22,7 @@
22
22
  >
23
23
  <img v-if="isDropdown" src="../../assets/img/help-toggle.svg" alt="" class="help-center-btn-icon">
24
24
  <img v-else src="../../assets/img/help.svg" alt="" class="help-center-btn-icon">
25
- <span>
25
+ <span v-if="expandedSidebar">
26
26
  {{ isDropdown ? $t('navigation.helpCenter') : $t('navigation.helpArticles') }}
27
27
  </span>
28
28
  <img
@@ -47,6 +47,8 @@ const props = withDefaults(defineProps<IHelpArticlesProps>(), {
47
47
  helpArticleOptions: () => [],
48
48
  })
49
49
 
50
+ const { state: expandedSidebar } = useSidebar();
51
+
50
52
  const expanded = ref(false);
51
53
  const helpBtnActions = ref();
52
54
  const dropdownScrollHeight = ref(0);
@@ -1,6 +1,14 @@
1
1
  <template>
2
2
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden>
3
- <rect x="4.3335" y="5.5" width="15.3333" height="13" rx="0.666667" stroke="currentColor"/>
4
- <path d="M10 6L10 18" stroke="currentColor" stroke-linecap="round"/>
3
+ <rect x="4.3335" y="5.5" width="15.3333" height="13" rx="0.666667" stroke="currentColor"/>
4
+ <rect x="4.3335" y="5.5" :width="expanded ? 6: 2" height="13" rx="0.666667" fill="currentColor" stroke="currentColor" stroke-linecap="round"/>
5
5
  </svg>
6
6
  </template>
7
+
8
+ <script setup lang="ts">
9
+ const { state: expanded } = useSidebar();
10
+ </script>
11
+
12
+ <style scoped>
13
+ rect{transition:width .2s}
14
+ </style>
@@ -1,69 +1,11 @@
1
- <template>
2
- <div class="org-selection">
3
- <label id="org-dropdown-label" class="sr-only">
4
- {{ $t("navigation.orgDropdown") }}
5
- </label>
6
- <div
7
- ref="dropdownTriggerRef"
8
- aria-labelledby="org-dropdown-label"
9
- aria-controls="organizations-options-list"
10
- :aria-expanded="active"
11
- aria-haspopup="listbox"
12
- role="combobox"
13
- class="dropdown-trigger"
14
- >
15
- <input
16
- ref="inputRef"
17
- type="text"
18
- class="org-title"
19
- :placeholder="$t('navigation.orgPlaceholder')"
20
- :value="active ? searchQuery : selectedOrg?.name"
21
- @keydown="keydownActionsOnTrigger"
22
- @click.prevent="toggleDropdown"
23
- @input="handleDropdownSearch"
24
- >
25
- <span v-if="selectedOrg?.intranet" class="badge selected">
26
- <a-icon icon="16:lock-locked" />
27
- {{ $t("navigation.orgBadge") }}
28
- </span>
29
- </div>
30
- <div
31
- v-show="active"
32
- id="organizations-options-list"
33
- class="dropdown"
34
- role="listbox"
35
- >
36
- <div
37
- v-for="(option) in sortedOrgs"
38
- :key="option.id"
39
- ref="optionRef"
40
- v-on-click-outside="onClickOutsideHandler"
41
- role="option"
42
- class="org-option"
43
- :class="{ selected: option.id === modelValue }"
44
- :aria-selected="option.id === modelValue"
45
- tabindex="-1"
46
- @keydown="handleSelectedOrg($event, option.id)"
47
- @click="handleSelectedOrg($event, option.id)"
48
- >
49
- <span :class="{ pinned: option.pinned, 'item-flex': true }"
50
- >{{ option.name }}
51
- <span v-if="option.intranet" class="badge selected">
52
- <a-icon icon="16:lock-locked" />
53
- {{ $t("navigation.orgBadge") }}
54
- </span>
55
- </span>
56
- </div>
57
- </div>
58
- </div>
59
- </template>
60
-
61
1
  <script setup lang="ts">
62
- import { useDropdown, useNuxtApp } from "#imports";
2
+ import { useDropdown, useNuxtApp, useAppConfig } from "#imports";
63
3
  import { vOnClickOutside } from "@vueuse/components";
64
4
  import { ref, computed } from "vue";
65
5
 
66
6
  const { $t } = useNuxtApp();
7
+ const appConfig = useAppConfig();
8
+ const zIndex = computed(() => appConfig?.navigation?.zIndex || 100)
67
9
 
68
10
  interface IOrg {
69
11
  name: string;
@@ -74,17 +16,17 @@ interface IOrg {
74
16
 
75
17
  interface IOrgSelectProps {
76
18
  orgs: Array<IOrg>;
77
- modelValue: number
19
+ modelValue: number;
78
20
  }
79
21
 
80
22
  const emit = defineEmits<{
81
- 'update:model-value': [index: number]
82
- }>();
23
+ "update:model-value": [index: number];
24
+ }>();
83
25
 
84
26
  const dropdownTriggerRef = ref();
85
27
  const optionRef = ref();
86
28
  const selectedOrg = computed(() => {
87
- return props.orgs.find(({id}) => id == props.modelValue);
29
+ return props.orgs.find(({ id }) => id == props.modelValue);
88
30
  });
89
31
 
90
32
  const props = defineProps<IOrgSelectProps>();
@@ -116,16 +58,76 @@ const sortedOrgs = computed(() => {
116
58
  });
117
59
 
118
60
  function handleSelectedOrg($event: KeyboardEvent | MouseEvent, orgId: number) {
119
- if($event.type == 'click') {
61
+ if ($event.type == "click") {
120
62
  emit("update:model-value", orgId);
121
63
  closeDropdown();
122
- } else if ($event.type == 'keydown') {
64
+ } else if ($event.type == "keydown") {
123
65
  emit("update:model-value", orgId);
124
66
  handleKeydown($event as KeyboardEvent, orgId);
125
67
  }
126
68
  }
127
69
  </script>
128
70
 
71
+ <template>
72
+ <div class="org-selection">
73
+ <label id="org-dropdown-label" class="sr-only">
74
+ {{ $t("navigation.orgDropdown") }}
75
+ </label>
76
+ <div
77
+ ref="dropdownTriggerRef"
78
+ aria-labelledby="org-dropdown-label"
79
+ aria-controls="organizations-options-list"
80
+ :aria-expanded="active"
81
+ aria-haspopup="listbox"
82
+ role="combobox"
83
+ class="dropdown-trigger"
84
+ >
85
+ <input
86
+ ref="inputRef"
87
+ type="text"
88
+ class="org-title"
89
+ :placeholder="$t('navigation.orgPlaceholder')"
90
+ :value="active ? searchQuery : selectedOrg?.name"
91
+ @keydown="keydownActionsOnTrigger"
92
+ @click.prevent="toggleDropdown"
93
+ @input="handleDropdownSearch"
94
+ >
95
+ <span v-if="selectedOrg?.intranet" class="badge selected">
96
+ <a-icon icon="16:lock-locked" />
97
+ {{ $t("navigation.orgBadge") }}
98
+ </span>
99
+ </div>
100
+ <div
101
+ v-show="active"
102
+ id="organizations-options-list"
103
+ class="dropdown"
104
+ role="listbox"
105
+ >
106
+ <div
107
+ v-for="option in sortedOrgs"
108
+ :key="option.id"
109
+ ref="optionRef"
110
+ v-on-click-outside="onClickOutsideHandler"
111
+ role="option"
112
+ class="org-option"
113
+ :class="{ selected: option.id === modelValue }"
114
+ :aria-selected="option.id === modelValue"
115
+ tabindex="-1"
116
+ @keydown="handleSelectedOrg($event, option.id)"
117
+ @click="handleSelectedOrg($event, option.id)"
118
+ >
119
+ <span :class="{ pinned: option.pinned, 'item-flex': true }"
120
+ >{{ option.name }}
121
+ <span v-if="option.intranet" class="badge selected">
122
+ <a-icon icon="16:lock-locked" />
123
+ {{ $t("navigation.orgBadge") }}
124
+ </span>
125
+ </span>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ </template>
130
+
129
131
  <style scoped>
130
132
  #organizations-options-list {
131
133
  position: absolute;
@@ -133,7 +135,7 @@ function handleSelectedOrg($event: KeyboardEvent | MouseEvent, orgId: number) {
133
135
  max-height: 300px;
134
136
  overflow-y: auto;
135
137
  background-color: var(--primary-white);
136
- z-index: 50;
138
+ z-index: v-bind(zIndex);
137
139
  }
138
140
 
139
141
  .org-selection {
@@ -168,11 +170,14 @@ function handleSelectedOrg($event: KeyboardEvent | MouseEvent, orgId: number) {
168
170
  white-space: nowrap;
169
171
  cursor: pointer;
170
172
  }
171
- .org-selection .dropdown-trigger .org-title:focus {
173
+ .org-selection .dropdown-trigger .org-title:focus-visible {
172
174
  outline: none;
173
175
  }
176
+ .org-selection .dropdown {
177
+ border-radius: 0 0 4px 4px;
178
+ box-shadow: 0px 6px 20px 0px rgba(0, 0, 0, 0.06);
179
+ }
174
180
  .org-selection .dropdown .org-option {
175
- display: block;
176
181
  padding: 12px;
177
182
  min-height: 40px;
178
183
  line-height: 16px;
@@ -200,7 +205,7 @@ function handleSelectedOrg($event: KeyboardEvent | MouseEvent, orgId: number) {
200
205
  background-color: var(--purple-50);
201
206
  padding: 2px 4px;
202
207
  color: white;
203
- border-radius: 4px;
208
+ border-radius: 2px;
204
209
  text-transform: uppercase;
205
210
  }
206
211
  .org-selection .badge svg {
@@ -4,6 +4,8 @@
4
4
  role="navigation"
5
5
  aria-label="Main"
6
6
  :class="{ expanded }"
7
+ @mouseenter="onHover"
8
+ @mouseleave="onHoverLeave"
7
9
  >
8
10
  <a
9
11
  ref="skip-to-content"
@@ -13,14 +15,15 @@
13
15
  >
14
16
  {{ $t('navigation.skipToContent') }}
15
17
  </a>
18
+ <div class="navbar--header">
19
+ <slot name="switcher" />
20
+ </div>
16
21
  <div class="navbar--content">
17
- <slot name="switcher" />
18
22
  <ul class="navbar-applications">
19
23
  <li v-for="application of applications" :key="application.id">
20
24
  <NavSidebarSection
21
25
  :application="application"
22
26
  :active="currentApplication === application.text"
23
- :navbar-expanded="expanded"
24
27
  >
25
28
  <slot v-if="currentApplication === application.text" />
26
29
  </NavSidebarSection>
@@ -28,37 +31,32 @@
28
31
  <li>
29
32
  <NavHelpArticles
30
33
  v-if="showHelpArticles"
31
- :navbar-expanded="expanded"
32
34
  :help-article-options="helpArticleOptions"
33
35
  />
34
36
  </li>
35
37
  </ul>
36
-
37
38
  </div>
38
39
  <div class="navbar--footer">
39
40
  <NavImpersonateInfoPanel
40
41
  v-if="impersonatedUser.show"
41
42
  :impersonated-user="impersonatedUser"
42
43
  />
43
- </div>
44
44
 
45
45
  <slot name="logo">
46
46
  <NuxtLink :to="homepageUrl">
47
47
  <div class="navbar--logo">
48
- <img v-if="expanded" :src="logo.src" :alt="logo.alt">
49
- <img v-else :src="logo.iconSrc" :alt="logo.alt">
48
+ <img :src="expanded ? logo.src : logo.iconSrc" :alt="logo.alt">
50
49
  </div>
51
50
  </NuxtLink>
52
51
  </slot>
52
+ </div>
53
53
  </nav>
54
54
  </template>
55
55
 
56
56
  <script setup lang="ts">
57
- import { useNuxtApp, useSidebar, ref } from '#imports';
57
+ import { useNuxtApp, useSidebar } from '#imports';
58
58
  const { $t } = useNuxtApp();
59
- const { state } = useSidebar();
60
-
61
- const expanded = ref(state);
59
+ const { state: expanded } = useSidebar();
62
60
 
63
61
  interface IApplications {
64
62
  id: number;
@@ -107,10 +105,24 @@ withDefaults(defineProps<ISidebarProps>(), {
107
105
  logo: () => ({
108
106
  alt: 'Thrillshare',
109
107
  src: 'logo.svg',
110
- iconSrc: 'logo.svg',
108
+ iconSrc: 'icon.svg',
111
109
  })
112
110
  })
113
111
 
112
+ // Debounced Expand on Hover
113
+ let expandedTimer;
114
+ function onHover() {
115
+ if(!expanded.value) {
116
+ expandedTimer = setTimeout(() => {
117
+ expanded.value = true;
118
+ }, 280);
119
+ }
120
+ }
121
+ function onHoverLeave() {
122
+ if(!expanded.value) {
123
+ clearTimeout(expandedTimer);
124
+ }
125
+ }
114
126
 
115
127
  </script>
116
128
 
@@ -118,15 +130,14 @@ withDefaults(defineProps<ISidebarProps>(), {
118
130
  .navbar {
119
131
  grid-area: navsidebar;
120
132
  display: grid;
121
- grid-template-rows: 1fr auto auto;
133
+ grid-template-rows: 0fr auto 0fr;
122
134
  font: var(--font-regular);
123
135
  background-color: var(--dscl-nav-background-color, var(--purple-70));
124
136
  color: var(--dscl-nav-font-color, var(--dscl-light-font, var(--primary-white)));
125
- transition: min-width 0.3s ease-in-out, translate 0.2s ease-in-out;
137
+ transition: width 0.3s ease-in-out, translate 0.2s ease-in-out;
126
138
  height: 100vh;
127
139
  overflow-y: auto;
128
- min-width: 0px;
129
- translate: -256px;
140
+ width: 64px;
130
141
  }
131
142
  .navbar a:focus-visible {
132
143
  outline: var(--orange) auto 2px;
@@ -134,10 +145,13 @@ withDefaults(defineProps<ISidebarProps>(), {
134
145
  box-shadow: inset 0 0 0px 4px var(--primary-white);
135
146
  }
136
147
  .navbar.expanded {
137
- transition: min-width 0.3s ease-in-out, translate 0.2s ease-in-out;
138
- min-width: 256px;
148
+ transition: width 0.3s ease-in-out, translate 0.2s ease-in-out;
149
+ width: 256px;
139
150
  translate: 0px;
140
151
  }
152
+ .navbar.expanded .navbar--content ul {
153
+ width: 256px;
154
+ }
141
155
  .navbar--logo {
142
156
  padding: 16px;
143
157
  background-color: var(--dscl-nav-background-color, var(--purple-70));
@@ -146,7 +160,6 @@ withDefaults(defineProps<ISidebarProps>(), {
146
160
  .navbar--content {
147
161
  display: flex;
148
162
  flex-direction: column;
149
- flex-basis: auto;
150
163
  margin-top: 24px;
151
164
  background-color: var(--dscl-nav-background-color, var(--purple-70));
152
165
  }
@@ -154,15 +167,16 @@ withDefaults(defineProps<ISidebarProps>(), {
154
167
  list-style: none;
155
168
  padding: 0;
156
169
  margin: 0;
157
- max-width: 256px;
170
+ width: 64px;
158
171
  }
159
172
  .navbar--footer {
160
173
  display: flex;
161
174
  flex-direction: column;
175
+ height: fit-content;
162
176
  }
163
177
  .navbar .skip-to-content {
164
178
  overflow: hidden;
165
- padding: 15px 23px 14px;
179
+ padding: 16px 24px 14px;
166
180
  position: absolute;
167
181
  left: 5px;
168
182
  top: 5px;
@@ -1,15 +1,24 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ icon: string;
4
+ }>();
5
+ const { state: expanded } = useSidebar();
6
+ </script>
7
+
1
8
  <template>
2
- <NuxtLink class="a-navbar-item">
3
- <slot />
9
+ <NuxtLink class="a-navbar-item" :class="{expanded}">
10
+ <a-icon :icon="icon" font-size="32px"/>
11
+ <slot v-if="expanded" />
4
12
  </NuxtLink>
5
13
  </template>
6
14
 
7
15
  <style scoped>
8
16
  .a-navbar-item {
9
17
  color: var(--dscl-nav-font-color, var(--dscl-light-font, var(--primary-white)));
10
- margin: 4px 16px;
18
+ margin: 4px 12px;
11
19
  display: flex;
12
20
  align-items: center;
21
+ gap: 4px;
13
22
  text-decoration: none;
14
23
  text-transform: capitalize;
15
24
  padding: 4px;
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <div class="a-nav-section" :class="{ active }">
3
- <NuxtLink class="a-nav-section--link" :to="application.url">
4
- <img v-if="application.img_src" :src="iconUrl" alt="icon">
5
- <span>{{ application.text.replace("_", " ") }}</span>
6
- <a-icon v-if="active" class="caret-icon" icon="16:carret-up" />
3
+ <NuxtLink class="a-nav-section--link" :to="active ? '' : application.url">
4
+ <img v-if="application.img_src" :src="active ? getActiveIcon(application.img_src) : application.img_src" alt="icon">
5
+ <span v-if="expanded">{{ application.text.replace("_", " ") }}</span>
6
+ <a-icon v-if="expanded && active" class="caret-icon" icon="16:carret-up" />
7
7
  </NuxtLink>
8
8
  <div class="a-nav-section--content">
9
9
  <slot />
@@ -12,18 +12,16 @@
12
12
  </template>
13
13
 
14
14
  <script setup lang="ts">
15
- import { computed } from 'vue';
16
-
17
- const props = defineProps<{
15
+ defineProps<{
18
16
  application: IApplication;
19
17
  active: boolean;
20
18
  }>();
21
19
 
22
- const iconUrl = computed(() =>
23
- props.active
24
- ? props.application.img_src?.replace(".svg", "_active.svg")
25
- : props.application.img_src,
26
- );
20
+ const { state: expanded } = useSidebar();
21
+
22
+ function getActiveIcon(src){
23
+ return src.replace(".svg", "_active.svg");
24
+ };
27
25
  </script>
28
26
 
29
27
  <style scoped>
@@ -31,9 +29,6 @@ const iconUrl = computed(() =>
31
29
  box-shadow: inset 0px -1px 0px 0px var(--dscl-nav-section-border-bottom-color, var(--purple-65));
32
30
  cursor: pointer;
33
31
  min-height: 48px;
34
- /* &--content {
35
- margin-bottom: 8px;
36
- } */
37
32
  }
38
33
  .a-nav-section.active {
39
34
  box-shadow: inset 0px -1px 0px 0px var(--dscl-nav-section-border-bottom-color, var(--purple-65));
@@ -19,11 +19,11 @@ const { toggleSidebar } = useSidebar();
19
19
  background: var(--purple-20);
20
20
  border: none;
21
21
  border-radius: 4px;
22
- padding: 8px 16px;
22
+ padding: 4px 8px;
23
23
  color: var(--purple);
24
24
  cursor: pointer;
25
25
  }
26
- .sidebar-toggle:focus {
26
+ .sidebar-toggle:focus-visible {
27
27
  outline: none;
28
28
  box-shadow: 0 0 0 2px var(--primary-white), 0 0 0 3px var(--purple);
29
29
  }
@@ -48,13 +48,13 @@ defineProps({
48
48
  border-top: 2px solid transparent;
49
49
  border-radius: 4px;
50
50
  }
51
- .menu-item:hover, .menu-item:focus, .menu-item.nuxt-link-exact-active, .menu-item.router-link-exact-active {
51
+ .menu-item:hover, .menu-item:focus-visible, .menu-item.nuxt-link-exact-active, .menu-item.router-link-exact-active {
52
52
  background-color: var(--purple-10);
53
53
  border-radius: 4px 4px 0px 0px;
54
54
  color: var(--purple);
55
55
  outline: none;
56
56
  }
57
- .menu-item:hover:after, .menu-item:focus:after, .menu-item.nuxt-link-exact-active:after, .menu-item.router-link-exact-active:after {
57
+ .menu-item:hover:after, .menu-item:focus-visible:after, .menu-item.nuxt-link-exact-active:after, .menu-item.router-link-exact-active:after {
58
58
  border-top: 2px solid var(--purple);
59
59
  }
60
60
  .menu-item.nuxt-link-exact-active, .menu-item.router-link-exact-active {
@@ -1,16 +1,21 @@
1
1
  <script setup lang="ts">
2
+ import { useDropdown, useAppConfig } from "#imports";
2
3
  import { ref } from "vue";
3
- import { useDropdown } from "#imports";
4
4
  import { vOnClickOutside } from "@vueuse/components";
5
5
 
6
6
  interface IUserDropdown {
7
7
  user: {
8
8
  name: string;
9
9
  avatar?: string;
10
+ email: string;
10
11
  };
11
- userDropdownOptions: Array<{ label: string; url: string; icon: string }>;
12
+ userDropdownOptions: Array<{ label: string; url: string; }>;
12
13
  }
13
14
 
15
+ const appConfig = useAppConfig();
16
+ const zIndex = computed(() => appConfig?.navigation?.zIndex || 100)
17
+
18
+
14
19
  const props = defineProps<IUserDropdown>();
15
20
  const dropdownTriggerRef = ref<HTMLDivElement>();
16
21
  const dropdownOptionsRef = ref<Array<HTMLDivElement>>();
@@ -29,7 +34,7 @@ const {
29
34
  );
30
35
 
31
36
  const emit = defineEmits<{
32
- 'select-option': [index: number]
37
+ "select-option": [index: number];
33
38
  }>();
34
39
 
35
40
  function handleSelectedClick(index: number) {
@@ -60,7 +65,7 @@ function handleKeydownAction($event: KeyboardEvent, index: number) {
60
65
  >
61
66
  <NavAvatar :name="user.name" :src="user.avatar" />
62
67
  <NavIconsUserDropdownMenu />
63
- <span class="sr-only">{{ $t('navigation.userDropdown') }}</span>
68
+ <span class="sr-only">{{ $t("navigation.userDropdown") }}</span>
64
69
  </div>
65
70
  <div
66
71
  v-show="active"
@@ -68,6 +73,17 @@ function handleKeydownAction($event: KeyboardEvent, index: number) {
68
73
  class="options-dropdown"
69
74
  role="listbox"
70
75
  >
76
+ <div class="user-info">
77
+ <span class="user-info-title">{{ $t("navigation.userDropdown") }}</span>
78
+ <div class="user-info-details">
79
+ <NavAvatar :name="user.name" :src="user.avatar" style="--size: 40px"/>
80
+ <div class="user-info-details-container">
81
+ <span class="user-info-name"> {{ user.name }} </span>
82
+ <span class="user-info-email"> {{ user.email }} </span>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ <hr>
71
87
  <div
72
88
  v-for="(option, idx) in userDropdownOptions"
73
89
  :key="option.label"
@@ -79,9 +95,9 @@ function handleKeydownAction($event: KeyboardEvent, index: number) {
79
95
  @keydown="handleKeydownAction($event, idx)"
80
96
  @click="handleSelectedClick(idx)"
81
97
  >
98
+ <!-- because of the the above handler, this component is never treated as a link and can't redirect natively? -->
82
99
  <NuxtLink class="option" :to="option.url">
83
100
  {{ option.label }}
84
- <a-icon :icon="option.icon" font-size="24px" />
85
101
  </NuxtLink>
86
102
  </div>
87
103
  </div>
@@ -106,13 +122,44 @@ function handleKeydownAction($event: KeyboardEvent, index: number) {
106
122
  align-items: center;
107
123
  cursor: pointer;
108
124
  }
109
- .header__dropdown:focus {
125
+ .header__dropdown:focus-visible {
110
126
  box-shadow: 0 0 0 2px var(--primary-white), 0 0 0 3px var(--purple);
111
127
  }
112
- .header__dropdown .avatar-container:focus {
128
+ .header__dropdown .avatar-container:focus-visible {
113
129
  outline: none;
114
130
  }
115
131
 
132
+ hr {
133
+ border: 0;
134
+ border-top: 1px solid var(--grey-20);
135
+ margin: 8px 0;
136
+ }
137
+
138
+ .user-info {
139
+ display: flex;
140
+ flex-direction: column;
141
+ gap: 12px;
142
+ padding: 8px;
143
+ }
144
+ .user-info .user-info-title {
145
+ font-weight: bold;
146
+ font-size: 12px;
147
+ color: var(--grey-60);
148
+ text-transform: uppercase;
149
+ }
150
+ .user-info .user-info-details {
151
+ display: flex;
152
+ gap: 4px;
153
+ }
154
+ .user-info .user-info-details .user-info-details-container {
155
+ display: flex;
156
+ flex-direction: column;
157
+ }
158
+ .user-info .user-info-details .user-info-details-container .user-info-email {
159
+ font-size: 12px;
160
+ color: var(--grey-50);
161
+ }
162
+
116
163
  .options-dropdown {
117
164
  min-height: 100px;
118
165
  position: absolute;
@@ -123,7 +170,7 @@ function handleKeydownAction($event: KeyboardEvent, index: number) {
123
170
  border-radius: 4px;
124
171
  box-shadow: 0px 6px 20px 0px rgba(0, 0, 0, 0.06);
125
172
  padding: 8px;
126
- z-index: 10;
173
+ z-index: v-bind(zIndex);
127
174
  }
128
175
  .options-dropdown .option-wrapper {
129
176
  padding: 8px;
@@ -3,8 +3,8 @@ export declare function useDropdown(options: Array<unknown>, dropdownOptionsRef:
3
3
  searchable: boolean;
4
4
  trackBy?: string;
5
5
  }): {
6
- active: Ref<boolean>;
7
- searchQuery: Ref<string>;
6
+ active: Ref<boolean, boolean>;
7
+ searchQuery: Ref<string, string>;
8
8
  toggleDropdown: ($event: KeyboardEvent | MouseEvent) => Promise<void>;
9
9
  openDropdown: () => void;
10
10
  closeDropdown: () => void;
@@ -50,6 +50,9 @@ export function useDropdown(options, dropdownOptionsRef, dropdownTriggerRef, con
50
50
  });
51
51
  }
52
52
  break;
53
+ case "ArrowLeft":
54
+ case "ArrowRight":
55
+ break;
53
56
  case " ":
54
57
  if (active.value) {
55
58
  closeDropdown();
@@ -141,6 +144,9 @@ export function useDropdown(options, dropdownOptionsRef, dropdownTriggerRef, con
141
144
  dropdownOptionsRef.value[index - 1].focus();
142
145
  });
143
146
  return index;
147
+ case "ArrowLeft":
148
+ case "ArrowRight":
149
+ break;
144
150
  case "Home":
145
151
  nextTick(() => {
146
152
  dropdownOptionsRef.value[0].focus();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apptegy/nuxt-navigation",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -26,24 +26,24 @@
26
26
  "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
27
27
  },
28
28
  "dependencies": {
29
- "@nuxt/kit": "^3.12.4",
30
- "@vueuse/components": "11.0.1",
29
+ "@nuxt/kit": "^3.13.1",
30
+ "@vueuse/components": "11.0.3",
31
31
  "lodash": "^4.17.21"
32
32
  },
33
33
  "devDependencies": {
34
- "@nuxt/devtools": "^1.3.14",
35
- "@nuxt/eslint-config": "^0.5.1",
34
+ "@nuxt/devtools": "^1.4.1",
35
+ "@nuxt/eslint-config": "^0.5.6",
36
36
  "@nuxt/module-builder": "^0.8.3",
37
- "@nuxt/schema": "^3.12.4",
37
+ "@nuxt/schema": "^3.13.1",
38
38
  "@nuxt/test-utils": "^3.14.1",
39
- "@types/node": "^20.16.1",
39
+ "@types/node": "^20.16.5",
40
40
  "changelogen": "^0.5.5",
41
- "eslint": "^9.9.0",
42
- "nuxt": "^3.12.4",
43
- "sass": "^1.77.8",
41
+ "eslint": "^9.9.1",
42
+ "nuxt": "^3.13.1",
43
+ "sass": "^1.78.0",
44
44
  "typescript": "^5.5.4",
45
45
  "vitest": "^1.6.0",
46
- "vue": "^3.4.38",
47
- "vue-tsc": "^2.0.29"
46
+ "vue": "^3.5.2",
47
+ "vue-tsc": "^2.1.6"
48
48
  }
49
49
  }