@apptegy/nuxt-navigation 0.1.68 → 0.1.70

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.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "nuxt": ">=3.0.0"
5
5
  },
6
6
  "configKey": "@apptegy/nuxt-navigation",
7
- "version": "0.1.68",
7
+ "version": "0.1.70",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.1",
10
10
  "unbuild": "unknown"
@@ -21,13 +21,7 @@ type __VLS_Slots = {} & {
21
21
  } & {
22
22
  'user-controls'?: (props: typeof __VLS_5) => any;
23
23
  };
24
- declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
25
- "selected-option": (...args: any[]) => void;
26
- "user-logout": (...args: any[]) => void;
27
- }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
28
- "onSelected-option"?: ((...args: any[]) => any) | undefined;
29
- "onUser-logout"?: ((...args: any[]) => any) | undefined;
30
- }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
24
+ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, any, string, import("vue").PublicProps, any, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
31
25
  declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
32
26
  export default _default;
33
27
  type __VLS_WithSlots<T, S> = T & {
@@ -1,9 +1,10 @@
1
1
  <template>
2
- <div class="help-btn-wrapper">
2
+ <div class="help-btn-wrapper" :class="{ 'collapsed': collapsed }">
3
3
  <button
4
4
  v-if="schoolWebsite"
5
5
  :id="'school-website'"
6
6
  class="help-articles-btn"
7
+ :class="{ 'collapsed': collapsed }"
7
8
  :aria-label="$t('navigation.website')"
8
9
  @click="goToWebsite"
9
10
  >
@@ -17,7 +18,8 @@
17
18
  :class="[
18
19
  'help-articles-btn',
19
20
  !isDropdown && 'help-btn',
20
- isRoomsUser && `help-btn-${userRoomsRole}`
21
+ isRoomsUser && `help-btn-${userRoomsRole}`,
22
+ collapsed && 'collapsed'
21
23
  ]"
22
24
  :aria-label="isDropdown ? $t('navigation.helpCenter') : $t('navigation.helpArticles')"
23
25
  @click="expandDropdown"
@@ -29,7 +31,7 @@
29
31
  <button
30
32
  v-if="settingsRoute"
31
33
  :id="!isDropdown && 'help-btn'"
32
- :class="['help-articles-btn', !isDropdown && 'help-btn']"
34
+ :class="['help-articles-btn', !isDropdown && 'help-btn', collapsed && 'collapsed']"
33
35
  :aria-label="$t('navigation.accountSettings')"
34
36
  @click="goToSettings"
35
37
  >
@@ -50,7 +52,8 @@ const props = defineProps({
50
52
  helpArticleOptions: { type: Array, required: true, default: () => [] },
51
53
  settingsRoute: { type: String, required: true, default: "" },
52
54
  schoolWebsite: { type: String, required: true, default: "" },
53
- showHelpArticles: { type: Boolean, required: true, default: false }
55
+ showHelpArticles: { type: Boolean, required: true, default: false },
56
+ collapsed: { type: Boolean, required: true }
54
57
  });
55
58
  const { state: expandedSidebar } = useSidebar();
56
59
  const expanded = ref(false);
@@ -93,6 +96,11 @@ async function goToWebsite() {
93
96
  text-transform: uppercase;
94
97
  padding-left: 8px;
95
98
  }
99
+ .help-btn-wrapper.collapsed {
100
+ justify-content: center;
101
+ flex-direction: column;
102
+ padding-left: 0;
103
+ }
96
104
  .help-btn-wrapper .help-articles-btn {
97
105
  cursor: pointer;
98
106
  display: flex;
@@ -112,6 +120,9 @@ async function goToWebsite() {
112
120
  min-width: 32px;
113
121
  width: 32px;
114
122
  }
123
+ .help-btn-wrapper .help-articles-btn.collapsed {
124
+ padding: 10px 0px;
125
+ }
115
126
  .help-btn-wrapper .help-btn-actions {
116
127
  visibility: hidden;
117
128
  max-height: 0px;
@@ -3,6 +3,7 @@ interface IHelpArticlesProps {
3
3
  settingsRoute: string;
4
4
  schoolWebsite: string;
5
5
  showHelpArticles: boolean;
6
+ collapsed: boolean;
6
7
  }
7
8
  declare const _default: import("vue").DefineComponent<IHelpArticlesProps, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<IHelpArticlesProps> & Readonly<{}>, {
8
9
  helpArticleOptions: Array<unknown>;
@@ -5,8 +5,8 @@
5
5
  aria-label="Main"
6
6
  :class="{ expanded }"
7
7
  :style="getBrandingStyles"
8
- @mouseenter="onHover"
9
- @mouseleave="onHoverLeave"
8
+ @mouseenter="!lockedExpanded && onHover()"
9
+ @mouseleave="!lockedExpanded && onHoverLeave()"
10
10
  >
11
11
  <a
12
12
  :href="`#${skipToContent}`"
@@ -17,24 +17,35 @@
17
17
  </a>
18
18
  <div :class="['navbar--wrapper', fixed && 'fixed']" >
19
19
  <div class="navbar--header">
20
- <div class="header-actions">
20
+ <div :class="['header-actions', { 'collapsed': !expanded && !isMobile }]">
21
21
  <NuxtLink v-if="expanded" class="no-link-style" :to="homepageUrl">
22
22
  <slot name="logo">
23
- <div class="navbar--logo">
24
- <img v-if="brandLogo" :src="brandLogo" :alt="$t('navigation.brandLogoAlt')">
25
- <component
26
- :is="ApptegyLogo"
27
- v-else
28
- :alt="$t('navigation.brandLogoAlt')"
29
- :use-light-logo="isAdmin || Object.values(getBrandingStyles).length === 0"
30
- />
31
- <div v-if="!brand?.hide_school_name">
32
- <div class="school-name"> {{ brand?.school_name }} </div>
33
- <div v-if="brand?.school_tag_line" class="school-tag">{{ brand.school_tag_line }}</div>
34
- </div>
23
+ <div class="navbar--logo">
24
+ <img v-if="brandLogo" :src="brandLogo" :alt="$t('navigation.brandLogoAlt')">
25
+ <component
26
+ :is="ApptegyLogo"
27
+ v-else
28
+ :alt="$t('navigation.brandLogoAlt')"
29
+ :use-light-logo="isAdmin || Object.values(getBrandingStyles).length === 0"
30
+ />
31
+ <div v-if="!brand?.hide_school_name">
32
+ <div class="school-name"> {{ brand?.school_name }} </div>
33
+ <div v-if="brand?.school_tag_line" class="school-tag">{{ brand.school_tag_line }}</div>
34
+ </div>
35
35
  </div>
36
36
  </slot>
37
37
  </NuxtLink>
38
+ <div v-if="!isMobile && showCollapseButton">
39
+ <button v-if="lockedExpanded && !allowCollapse" class="hamburger-button" @click="closeSidebar">
40
+ <a-icon icon="24:hamburger" />
41
+ </button>
42
+ <button v-if="!lockedExpanded && allowCollapse && expanded" class="hamburger-button" @click="lockSidebar">
43
+ <a-icon icon="24:lock-unlocked" />
44
+ </button>
45
+ <button v-if="!lockedExpanded && allowCollapse && !expanded" class="hamburger-button">
46
+ <a-icon icon="24:hamburger" />
47
+ </button>
48
+ </div>
38
49
  </div>
39
50
  <slot name="switcher" />
40
51
  </div>
@@ -42,8 +53,10 @@
42
53
  <ul class="navbar-applications">
43
54
  <li v-for="application of applications" :key="application.id">
44
55
  <NavSidebarSection
56
+ v-if="expanded || currentApplication === application.text || isMobile"
45
57
  :application="application"
46
58
  :active="currentApplication === application.text"
59
+ :collapsed="!expanded && !isMobile"
47
60
  >
48
61
  <slot v-if="currentApplication === application.text" />
49
62
  </NavSidebarSection>
@@ -56,6 +69,7 @@
56
69
  :help-article-options="helpArticleOptions"
57
70
  :settings-route="settingsRoute"
58
71
  :school-website="schoolWebsite"
72
+ :collapsed="!expanded && !isMobile"
59
73
  />
60
74
  <NavImpersonateInfoPanel
61
75
  v-if="impersonatedUser.show"
@@ -65,7 +79,7 @@
65
79
  <slot name="logo">
66
80
  <template v-if="brand">
67
81
  <NuxtLink v-if="expanded ? logo.src : logo.iconSrc" :to="homepageUrl">
68
- <div class="navbar--footer-logo">
82
+ <div v-if="!isMobile && expanded" class="navbar--footer-logo">
69
83
  <img :src="expanded ? logo.src : logo.iconSrc" :alt="logo.alt || $t('navigation.logoAlt')">
70
84
  </div>
71
85
  </NuxtLink>
@@ -79,6 +93,7 @@
79
93
  <script setup>
80
94
  import { useSidebar, useBranding, useNuxtApp, ref, watch } from "#imports";
81
95
  import ApptegyLogo from "./Icons/ApptegyLogo.vue";
96
+ import { useBreakpoints, breakpointsTailwind } from "@vueuse/core";
82
97
  const { $t } = useNuxtApp();
83
98
  const props = defineProps({
84
99
  clientId: { type: Number, required: true, default: void 0 },
@@ -104,28 +119,40 @@ const props = defineProps({
104
119
  fixed: { type: Boolean, required: false, default: false },
105
120
  isAdmin: { type: Boolean, required: false, default: false },
106
121
  settingsRoute: { type: String, required: true, default: "" },
107
- schoolWebsite: { type: String, required: true, default: "" }
122
+ schoolWebsite: { type: String, required: true, default: "" },
123
+ showCollapseButton: { type: Boolean, required: false }
108
124
  });
109
125
  const emit = defineEmits(["toggle-expand"]);
110
126
  const { state: expanded } = useSidebar();
111
127
  const { brand, getBrandingStyles } = await useBranding(props.clientId);
112
128
  const brandLogo = ref(brand.value?.logo_light);
129
+ const breakpoints = useBreakpoints(breakpointsTailwind);
130
+ const isMobile = breakpoints.smaller("md");
131
+ const lockedExpanded = ref(true);
132
+ const allowCollapse = ref(false);
113
133
  watch(expanded, (value) => {
114
134
  emit("toggle-expand", value ? 264 : 64);
115
135
  });
116
- let expandedTimer = null;
117
136
  function onHover() {
118
137
  if (!expanded.value) {
119
- expandedTimer = setTimeout(() => {
120
- expanded.value = true;
121
- }, 280);
138
+ expanded.value = true;
122
139
  }
123
140
  }
124
141
  function onHoverLeave() {
125
- if (!expanded.value) {
126
- clearTimeout(expandedTimer);
142
+ if (expanded.value) {
143
+ expanded.value = false;
127
144
  }
128
145
  }
146
+ function closeSidebar() {
147
+ expanded.value = false;
148
+ lockedExpanded.value = false;
149
+ allowCollapse.value = true;
150
+ }
151
+ function lockSidebar() {
152
+ lockedExpanded.value = true;
153
+ expanded.value = true;
154
+ allowCollapse.value = false;
155
+ }
129
156
  </script>
130
157
 
131
158
  <style scoped>
@@ -156,6 +183,7 @@ function onHoverLeave() {
156
183
  border-right: 1px solid #DFDFDF;
157
184
  height: 100%;
158
185
  overflow-y: auto;
186
+ overflow-x: hidden;
159
187
  }
160
188
  .navbar--wrapper.fixed {
161
189
  position: fixed;
@@ -178,6 +206,9 @@ function onHoverLeave() {
178
206
  justify-content: space-between;
179
207
  box-sizing: border-box;
180
208
  }
209
+ .navbar--header .header-actions.collapsed {
210
+ justify-content: center;
211
+ }
181
212
  .navbar--logo {
182
213
  display: flex;
183
214
  align-items: center;
@@ -266,4 +297,18 @@ function onHoverLeave() {
266
297
  color: inherit;
267
298
  max-width: 200px;
268
299
  }
300
+ .navbar .hamburger-button {
301
+ background: none;
302
+ border: none;
303
+ cursor: pointer;
304
+ padding: 0;
305
+ margin: 0;
306
+ display: flex;
307
+ align-items: center;
308
+ }
309
+ .navbar .hamburger-button svg {
310
+ cursor: pointer;
311
+ height: 24px;
312
+ width: 24px;
313
+ }
269
314
  </style>
@@ -19,16 +19,17 @@ interface ISidebarProps {
19
19
  isAdmin?: boolean;
20
20
  settingsRoute: string;
21
21
  schoolWebsite: string;
22
+ showCollapseButton?: boolean;
22
23
  }
23
- declare var __VLS_6: {}, __VLS_13: {}, __VLS_20: {}, __VLS_32: {};
24
+ declare var __VLS_6: {}, __VLS_28: {}, __VLS_35: {}, __VLS_47: {};
24
25
  type __VLS_Slots = {} & {
25
26
  logo?: (props: typeof __VLS_6) => any;
26
27
  } & {
27
- switcher?: (props: typeof __VLS_13) => any;
28
+ switcher?: (props: typeof __VLS_28) => any;
28
29
  } & {
29
- default?: (props: typeof __VLS_20) => any;
30
+ default?: (props: typeof __VLS_35) => any;
30
31
  } & {
31
- logo?: (props: typeof __VLS_32) => any;
32
+ logo?: (props: typeof __VLS_47) => any;
32
33
  };
33
34
  declare const __VLS_component: import("vue").DefineComponent<ISidebarProps, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
34
35
  "toggle-expand": (width: number) => any;
@@ -3,16 +3,20 @@ import { useSidebar, computed, resolveComponent } from "#imports";
3
3
  const props = defineProps({
4
4
  icon: { type: String, required: false },
5
5
  active: { type: Boolean, required: false },
6
- as: { type: String, required: false }
6
+ as: { type: String, required: false },
7
+ name: { type: String, required: false }
7
8
  });
8
9
  const { state: expanded } = useSidebar();
9
10
  const component = computed(() => props.as || resolveComponent("NuxtLink"));
10
11
  </script>
11
12
 
12
13
  <template>
13
- <component :is="component" class="a-navbar-item" :class="{ expanded, active }">
14
+ <component :is="component" class="a-navbar-item" :class="{ expanded, active, collapsed: !expanded }">
14
15
  <slot name="icon">
16
+ <a-tooltip v-if="!expanded" :label="name" position="right" size="small">
15
17
  <a-icon class="icon" :icon="icon" font-size="24px"/>
18
+ </a-tooltip>
19
+ <a-icon v-else class="icon" :icon="icon" font-size="24px"/>
16
20
  </slot>
17
21
  <slot v-if="expanded" />
18
22
  </component>
@@ -32,6 +36,11 @@ const component = computed(() => props.as || resolveComponent("NuxtLink"));
32
36
  border-radius: 8px;
33
37
  user-select: none;
34
38
  }
39
+ .a-navbar-item.collapsed {
40
+ justify-content: center;
41
+ margin: 8px;
42
+ cursor: pointer;
43
+ }
35
44
  .a-navbar-item:focus-visible {
36
45
  outline: var(--orange) auto 2px;
37
46
  outline-offset: 0px;
@@ -2,12 +2,13 @@ type __VLS_Props = {
2
2
  icon?: string;
3
3
  active?: boolean;
4
4
  as?: string;
5
+ name?: string;
5
6
  };
6
- declare var __VLS_7: {}, __VLS_14: {};
7
+ declare var __VLS_7: {}, __VLS_24: {};
7
8
  type __VLS_Slots = {} & {
8
9
  icon?: (props: typeof __VLS_7) => any;
9
10
  } & {
10
- default?: (props: typeof __VLS_14) => any;
11
+ default?: (props: typeof __VLS_24) => any;
11
12
  };
12
13
  declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
14
  declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="a-nav-section" :class="{ active }">
3
- <NuxtLink class="a-nav-section--link" :to="active ? '' : application.url" :aria-label="appText">
3
+ <NuxtLink v-if="!collapsed" class="a-nav-section--link" :to="active ? '' : application.url" :aria-label="appText">
4
4
  <span v-if="expanded">{{ appText }}</span>
5
5
  <a-icon v-if="expanded && active" :class="['caret-icon', { 'collapse': !isOpen }]" icon="16:carret-up" @click="isOpen = !isOpen" />
6
6
  <a-icon v-if="expanded && !active" :class="['caret-icon', { 'collapse': !isOpen }]" icon="16:carret-down" @click="isOpen = !isOpen" />
@@ -16,7 +16,8 @@ import { useSidebar, computed, ref } from "#imports";
16
16
  import icons from "../../assets/iconPaths.json";
17
17
  const props = defineProps({
18
18
  application: { type: Object, required: true },
19
- active: { type: Boolean, required: true }
19
+ active: { type: Boolean, required: true },
20
+ collapsed: { type: Boolean, required: true }
20
21
  });
21
22
  const appText = computed(() => props.application.text.replace("_", " "));
22
23
  const { state: expanded } = useSidebar();
@@ -2,6 +2,7 @@ import type { IApplication } from "../../types/index.js";
2
2
  type __VLS_Props = {
3
3
  application: IApplication;
4
4
  active: boolean;
5
+ collapsed: boolean;
5
6
  };
6
7
  declare var __VLS_22: {};
7
8
  type __VLS_Slots = {} & {
@@ -1,5 +1,5 @@
1
1
  export declare function useSidebar(): {
2
- state: any;
2
+ state: import("vue").Ref<boolean, boolean>;
3
3
  toggleSidebar: () => void;
4
4
  sidebarWidth: import("vue").ComputedRef<"264px" | "0px">;
5
5
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apptegy/nuxt-navigation",
3
- "version": "0.1.68",
3
+ "version": "0.1.70",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -27,24 +27,23 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@apptegy/nuxt-intl": "^2.4.2",
30
- "@nuxt/kit": "^3.17.0",
31
- "@vueuse/components": "^12.0.0",
32
- "@vueuse/core": "^12.0.0"
30
+ "@nuxt/kit": "catalog:",
31
+ "@vueuse/components": "catalog:shared",
32
+ "@vueuse/core": "catalog:shared"
33
33
  },
34
34
  "devDependencies": {
35
- "@nuxt/devtools": "^2.6.2",
36
- "@nuxt/eslint-config": "^1.6.0",
37
- "@nuxt/module-builder": "^1.0.1",
38
- "@nuxt/schema": "^3.17.0",
39
- "@nuxt/test-utils": "^3.17.0",
40
- "@types/node": "^22.0.0",
41
- "eslint": "^9.31.0",
42
- "nuxt": "^3.17.0",
43
- "sass": "^1.89.2",
44
- "typescript": "~5.8.0",
45
- "vitest": "^3.2.4",
46
- "vue": "^3.5.13",
47
- "vue-tsc": "^3.0.3"
48
- },
49
- "gitHead": "f2b6d8385d69cf522eb52430455fb61b4e43a9d4"
35
+ "@nuxt/devtools": "catalog:",
36
+ "@nuxt/eslint-config": "catalog:",
37
+ "@nuxt/module-builder": "catalog:",
38
+ "@nuxt/schema": "catalog:",
39
+ "@nuxt/test-utils": "catalog:",
40
+ "@types/node": "catalog:",
41
+ "eslint": "catalog:",
42
+ "nuxt": "catalog:",
43
+ "sass": "catalog:",
44
+ "typescript": "catalog:",
45
+ "vitest": "catalog:",
46
+ "vue": "catalog:",
47
+ "vue-tsc": "catalog:"
48
+ }
50
49
  }