@abgov/nx-adsp 13.18.0-beta.8 → 13.18.0-beta.9

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": "@abgov/nx-adsp",
3
- "version": "13.18.0-beta.8",
3
+ "version": "13.18.0-beta.9",
4
4
  "license": "Apache-2.0",
5
5
  "main": "src/index.js",
6
6
  "description": "Government of Alberta - Nx plugin for ADSP apps.",
@@ -172,7 +172,7 @@ from **`<%= goaImportPath %>`**, not hand-rolled markup:
172
172
 
173
173
  | Component | Purpose |
174
174
  |---|---|
175
- | `AppSideMenu` | `goa-work-side-menu`. Takes `heading`/`primaryItems`/`secondaryItems`/`accountItems` props (each item: `{ label, to?, icon?, badge?, current? }`) and emits `itemClick` — it doesn't know about routing or auth, so `App.vue` computes `current`/handles the click itself. `App.vue` currently only populates `accountItems` (a single Sign in/out item); add real nav items to `primaryItems`/`secondaryItems` as routes are added. Also owns the skip-to-main-content landmark for this layout — `AppLayout` deliberately doesn't duplicate it |
175
+ | `AppSideMenu` | `goa-work-side-menu`. Takes `heading`/`primaryItems`/`secondaryItems`/`accountItems` props (each item: `{ label, to?, icon?, badge?, current? }`) and emits `itemClick` — it doesn't know about routing or auth, so `App.vue` computes `current`/handles the click itself. `App.vue` currently only populates `accountItems` (a single Sign in/out item); add real nav items to `primaryItems`/`secondaryItems` as routes are added. Also owns the skip-to-main-content landmark for this layout — `AppLayout` deliberately doesn't duplicate it. Also takes an optional `#topbar` slot — a slim row above the routed content, for something like a notification bell; only renders when given content, unused by default |
176
176
  | `AppLayout` | The content gutter every view renders inside (see the key files table) |
177
177
  | `SessionExpiredBanner` | A `v-model:show` banner with `signIn`/`dismiss` emits. Bound to the `useSessionStore()` Pinia store (`src/stores/session.ts`), which `main.ts`'s `onAuthRefreshError` hook flips when the refresh token itself has expired |
178
178
 
@@ -1,9 +1,20 @@
1
1
  <script setup lang="ts">
2
+ import { useSlots } from 'vue';
3
+
2
4
  // The alternate top-level shell for staff-facing/internal apps (goa-work-side-menu),
3
5
  // used instead of AppHeader/AppFooter -- not together with them. Presentational only:
4
6
  // unlike the real GovAlta-Pronghorn source this is adapted from, active-route
5
7
  // highlighting and navigation are the caller's job (pass `current` on each item,
6
8
  // listen for `item-click`) so this component doesn't need vue-router as a dependency.
9
+ //
10
+ // The real reference source also has a slim in-content "topbar" row for
11
+ // module-registered header actions (e.g. a notification bell) -- there's no
12
+ // AppHeader/utilities slot in this layout to hold that kind of thing. Exposed
13
+ // here as a plain named slot (`#topbar`), not a module-registration system --
14
+ // that's app-specific plumbing, not something a shared, presentational
15
+ // component should own.
16
+ const slots = useSlots();
17
+
7
18
  interface AppSideMenuItem {
8
19
  label: string;
9
20
  to?: string;
@@ -63,6 +74,9 @@ const emit = defineEmits<{ itemClick: [item: AppSideMenuItem] }>();
63
74
  />
64
75
  </goa-work-side-menu>
65
76
  <main id="main-content" class="app-side-menu-content">
77
+ <div v-if="slots.topbar" class="app-side-menu-topbar">
78
+ <slot name="topbar" />
79
+ </div>
66
80
  <slot />
67
81
  </main>
68
82
  </div>
@@ -80,6 +94,15 @@ const emit = defineEmits<{ itemClick: [item: AppSideMenuItem] }>();
80
94
  overflow-y: auto;
81
95
  }
82
96
 
97
+ .app-side-menu-topbar {
98
+ display: flex;
99
+ justify-content: flex-end;
100
+ align-items: center;
101
+ gap: var(--goa-space-s, 0.75rem);
102
+ padding: var(--goa-space-xs, 0.5rem) var(--goa-space-m, 1rem);
103
+ border-bottom: 1px solid var(--goa-color-greyscale-100, #f1f1f1);
104
+ }
105
+
83
106
  .skip-link {
84
107
  position: absolute;
85
108
  left: -9999px;
@@ -76,6 +76,19 @@ describe('Vue Components Generator', () => {
76
76
  expect(agents).toContain('defineModel<boolean>');
77
77
  }, 30000);
78
78
 
79
+ it('AppSideMenu exposes an optional #topbar slot for header-action-style content', async () => {
80
+ await generator(host);
81
+
82
+ const sideMenu = host
83
+ .read('libs/vue-components/src/lib/patterns/AppSideMenu.vue')
84
+ .toString();
85
+ // Named slot, only rendered when actually given content -- no empty bar
86
+ // shows by default, matching the "unused by default" doc claim.
87
+ expect(sideMenu).toContain('<slot name="topbar" />');
88
+ expect(sideMenu).toContain('v-if="slots.topbar"');
89
+ expect(sideMenu).toContain('useSlots');
90
+ }, 30000);
91
+
79
92
  it('disables vue/no-deprecated-slot-attribute in flat config too, not just .eslintrc.json', async () => {
80
93
  // useFlatConfig() (from @nx/eslint) treats a root flat-config file's
81
94
  // presence as authoritative, regardless of the installed ESLint version —