@abgov/nx-adsp 13.17.1 → 13.18.0-beta.1

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.
Files changed (21) hide show
  1. package/package.json +1 -1
  2. package/src/generators/vue-app/files/AGENTS.md__tmpl__ +23 -6
  3. package/src/generators/vue-app/files/src/App.vue__tmpl__ +6 -10
  4. package/src/generators/vue-app/vue-app.js +3 -0
  5. package/src/generators/vue-app/vue-app.js.map +1 -1
  6. package/src/generators/vue-app/vue-app.spec.ts +38 -11
  7. package/src/generators/vue-components/files/AGENTS.md__tmpl__ +44 -14
  8. package/src/generators/vue-components/files/src/index.ts__tmpl__ +23 -12
  9. package/src/generators/vue-components/files/src/lib/patterns/AppFooter.vue__tmpl__ +14 -0
  10. package/src/generators/vue-components/files/src/lib/patterns/AppHeader.vue__tmpl__ +19 -0
  11. package/src/generators/{vue-app/files/src/components → vue-components/files/src/lib/patterns}/AppLayout.vue__tmpl__ +17 -0
  12. package/src/generators/vue-components/files/src/lib/patterns/SessionExpiredBanner.vue__tmpl__ +26 -0
  13. package/src/generators/vue-components/files/src/vue-components.spec.ts__tmpl__ +15 -4
  14. package/src/generators/vue-components/vue-components.spec.ts +14 -3
  15. /package/src/generators/vue-components/files/src/lib/{GoabButton.vue__tmpl__ → primitives/GoabButton.vue__tmpl__} +0 -0
  16. /package/src/generators/vue-components/files/src/lib/{GoabCheckbox.vue__tmpl__ → primitives/GoabCheckbox.vue__tmpl__} +0 -0
  17. /package/src/generators/vue-components/files/src/lib/{GoabDropdown.vue__tmpl__ → primitives/GoabDropdown.vue__tmpl__} +0 -0
  18. /package/src/generators/vue-components/files/src/lib/{GoabInput.vue__tmpl__ → primitives/GoabInput.vue__tmpl__} +0 -0
  19. /package/src/generators/vue-components/files/src/lib/{GoabModal.vue__tmpl__ → primitives/GoabModal.vue__tmpl__} +0 -0
  20. /package/src/generators/vue-components/files/src/lib/{GoabRadioGroup.vue__tmpl__ → primitives/GoabRadioGroup.vue__tmpl__} +0 -0
  21. /package/src/generators/vue-components/files/src/lib/{GoabTextarea.vue__tmpl__ → primitives/GoabTextarea.vue__tmpl__} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/nx-adsp",
3
- "version": "13.17.1",
3
+ "version": "13.18.0-beta.1",
4
4
  "license": "Apache-2.0",
5
5
  "main": "src/index.js",
6
6
  "description": "Government of Alberta - Nx plugin for ADSP apps.",
@@ -31,8 +31,7 @@ executors read options from `project.json` and do not prompt.
31
31
  | File | Purpose |
32
32
  |------|---------|
33
33
  | `src/main.ts` | Entry — registers Pinia, Router, and Keycloak plugin |
34
- | `src/App.vue` | Shell — nav header with sign-in/out, hero banner, `<RouterView>` wrapped in `AppLayout` |
35
- | `src/components/AppLayout.vue` | Shared content gutter (centered, max-width, token padding). Every view lands inside it — no per-view spacing to add. Width via route meta `layout` |
34
+ | `src/App.vue` | Shell — `AppHeader` with sign-in/out in its `utilities` slot, hero banner, `<RouterView>` wrapped in `AppLayout`, `AppFooter` |
36
35
  | `src/router/index.ts` | Routes — `/protected` guarded with `requiresAuth` meta |
37
36
  | `src/views/HomeView.vue` | Public page — calls public and private APIs |
38
37
  | `src/views/ProtectedView.vue` | Authenticated page — shows user info from token |
@@ -151,10 +150,28 @@ the design system supports still works. For components without a wrapper, use th
151
150
  across every Vue app in this workspace — fix or extend a wrapper once in
152
151
  `libs/vue-components` (or run `nx g @abgov/nx-adsp:vue-components` to restore it).
153
152
 
154
- > **Interim:** these wrappers are a stopgap until GoA DS ships an official
155
- > `@abgov/vue-components`. When it lands, delete the `vue-components` lib and
156
- > repoint imports at that package — the names/props are intended to match, so
157
- > it's a scope swap.
153
+ > **Interim:** these wrappers (`libs/vue-components/src/lib/primitives/`) are a
154
+ > stopgap until GoA DS ships an official `@abgov/vue-components`. When it lands,
155
+ > delete `primitives/` and repoint imports at that package — the names/props are
156
+ > intended to match, so it's a scope swap. This does **not** apply to the
157
+ > `AppHeader`/`AppLayout`/`AppFooter`/`SessionExpiredBanner` shell components
158
+ > below — those live in the same library's `patterns/` folder and are permanent
159
+ > (app-shell composition has no equivalent in a design-system package).
160
+
161
+ ### App shell components
162
+
163
+ `App.vue` is built from four shared components imported from
164
+ **`<%= goaImportPath %>`**, not hand-rolled markup:
165
+
166
+ | Component | Purpose |
167
+ |---|---|
168
+ | `AppHeader` | `goa-microsite-header` + `goa-app-header`. Takes a `heading` prop; put account/sign-in actions in its `utilities` slot (a bare child with no slot is silently dropped by `goa-app-header`) |
169
+ | `AppLayout` | The content gutter every view renders inside (see the key files table). Also renders the skip-to-main-content link |
170
+ | `AppFooter` | `goa-app-footer` with the standard GoA nav/meta links (Services/Contact/Terms of Use, Privacy/Disclaimer/Accessibility) |
171
+ | `SessionExpiredBanner` | A `v-model:show` banner with `signIn`/`dismiss` emits — available in the shared library, not yet wired into this app's `App.vue`. Wiring it to a real Keycloak session-expiry signal needs an `onAuthLogout` callback added to `main.ts`'s Keycloak plugin config; do that before using it |
172
+
173
+ These are shared across every Vue app in this workspace — fix or extend one once
174
+ in `libs/vue-components/src/lib/patterns/`, the same way as the `Goab*` wrappers.
158
175
 
159
176
  ## Adding a view
160
177
 
@@ -2,7 +2,7 @@
2
2
  import { computed } from 'vue';
3
3
  import { useKeycloak } from '@dsb-norge/vue-keycloak-js';
4
4
  import { RouterView, useRoute } from 'vue-router';
5
- import AppLayout from './components/AppLayout.vue';
5
+ import { AppHeader, AppLayout, AppFooter } from '<%= goaImportPath %>';
6
6
 
7
7
  // Keep the reactive instance — do NOT destructure. useKeycloak() returns a
8
8
  // readonly(reactive()); destructuring snapshots each field at setup time, so
@@ -22,13 +22,8 @@ function logout() { kc.keycloak?.logout({ redirectUri: window.location.origin })
22
22
  </script>
23
23
 
24
24
  <template>
25
- <goa-microsite-header type="alpha" />
26
- <goa-app-header url="/" heading="<%= projectName %>">
27
- <!-- goa-app-header only renders content placed in a named slot — the
28
- "utilities" slot is where GoA's own design system docs put
29
- account/sign-in actions (as opposed to "navigation" for nav links).
30
- A bare child with no slot attribute renders nothing. -->
31
- <div slot="utilities">
25
+ <AppHeader heading="<%= projectName %>">
26
+ <template #utilities>
32
27
  <goa-button-group alignment="end">
33
28
  <span v-if="kc.authenticated && kc.fullName">{{ kc.fullName }}</span>
34
29
  <!-- Gate on !authenticated only, never on `ready`: with no load-time SSO
@@ -41,12 +36,13 @@ function logout() { kc.keycloak?.logout({ redirectUri: window.location.origin })
41
36
  Sign out
42
37
  </goa-button>
43
38
  </goa-button-group>
44
- </div>
45
- </goa-app-header>
39
+ </template>
40
+ </AppHeader>
46
41
  <goa-hero-banner heading="<%= projectName %>" backgroundurl="/assets/banner.jpg" />
47
42
  <AppLayout :variant="layout">
48
43
  <RouterView />
49
44
  </AppLayout>
45
+ <AppFooter />
50
46
  </template>
51
47
 
52
48
  <style>
@@ -122,6 +122,9 @@ function default_1(host, options) {
122
122
  'src/app/App.spec.ts',
123
123
  'src/app/NxWelcome.vue',
124
124
  'src/components/HelloWorld.vue',
125
+ // AppLayout now lives in the shared vue-components lib (patterns/) —
126
+ // remove a stale copy from an app scaffolded before that move.
127
+ 'src/components/AppLayout.vue',
125
128
  'src/views/AboutView.vue',
126
129
  'vite.config.mts',
127
130
  ]) {
@@ -1 +1 @@
1
- {"version":3,"file":"vue-app.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/vue-app/vue-app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vue-app.js","sourceRoot":"","sources":["../../../../../../packages/nx-adsp/src/generators/vue-app/vue-app.ts"],"names":[],"mappings":"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"}
@@ -116,15 +116,16 @@ describe('Vue App Generator', () => {
116
116
  it('wraps views in a shared AppLayout gutter (not a bare tag selector)', async () => {
117
117
  await generator(host, options);
118
118
 
119
- // Shared layout component provides the content gutter for every view.
120
- expect(host.exists('apps/test/src/components/AppLayout.vue')).toBeTruthy();
121
- const layout = host
122
- .read('apps/test/src/components/AppLayout.vue')
123
- .toString();
119
+ // Layout is a pattern component in the shared lib, not copied into the app.
120
+ const layoutPath = 'libs/vue-components/src/lib/patterns/AppLayout.vue';
121
+ expect(host.exists(layoutPath)).toBeTruthy();
122
+ const layout = host.read(layoutPath).toString();
124
123
  // Three named width variants, token-driven padding.
125
124
  expect(layout).toContain('form-content');
126
125
  expect(layout).toContain('wide-content');
127
126
  expect(layout).toContain('--goa-space');
127
+ // Skip-to-main-content link for keyboard/screen-reader users.
128
+ expect(layout).toContain('href="#main-content"');
128
129
 
129
130
  // App.vue uses AppLayout and no longer relies on the `main > section` gutter
130
131
  // (which silently failed when a view's top-level tag wasn't <section>).
@@ -137,7 +138,7 @@ describe('Vue App Generator', () => {
137
138
  await generator(host, options);
138
139
 
139
140
  // Wrappers live in a shared workspace lib, not copied into the app.
140
- const base = 'libs/vue-components/src/lib';
141
+ const primitives = 'libs/vue-components/src/lib/primitives';
141
142
  for (const name of [
142
143
  'GoabInput',
143
144
  'GoabTextarea',
@@ -147,12 +148,12 @@ describe('Vue App Generator', () => {
147
148
  'GoabButton',
148
149
  'GoabModal',
149
150
  ]) {
150
- expect(host.exists(`${base}/${name}.vue`)).toBeTruthy();
151
+ expect(host.exists(`${primitives}/${name}.vue`)).toBeTruthy();
151
152
  }
152
153
  expect(host.exists('apps/test/src/components/goa')).toBeFalsy();
153
154
 
154
155
  // Real v-model wiring: bind :value and read the new value off the GoA event.
155
- const input = host.read(`${base}/GoabInput.vue`).toString();
156
+ const input = host.read(`${primitives}/GoabInput.vue`).toString();
156
157
  expect(input).toContain('defineModel');
157
158
  expect(input).toContain('.detail.value');
158
159
 
@@ -163,6 +164,25 @@ describe('Vue App Generator', () => {
163
164
  expect(agents).toContain('/vue-components');
164
165
  }, 30000);
165
166
 
167
+ it('provisions the shared app-shell pattern components and App.vue imports them', async () => {
168
+ await generator(host, options);
169
+
170
+ const patterns = 'libs/vue-components/src/lib/patterns';
171
+ for (const name of [
172
+ 'AppLayout',
173
+ 'AppHeader',
174
+ 'AppFooter',
175
+ 'SessionExpiredBanner',
176
+ ]) {
177
+ expect(host.exists(`${patterns}/${name}.vue`)).toBeTruthy();
178
+ }
179
+
180
+ const app = host.read('apps/test/src/App.vue').toString();
181
+ expect(app).toContain("import { AppHeader, AppLayout, AppFooter } from '@proj/vue-components';");
182
+ expect(app).toContain('<AppHeader heading="test">');
183
+ expect(app).toContain('<AppFooter />');
184
+ }, 30000);
185
+
166
186
  it('inits Keycloak with no hidden iframes so init never hangs', async () => {
167
187
  await generator(host, options);
168
188
  // Strip // comments — they legitimately reference the disabled iframe options
@@ -255,11 +275,18 @@ describe('Vue App Generator', () => {
255
275
  // goa-app-header (v2) only renders content placed in a named slot — GoA's
256
276
  // own design system docs put account/sign-in actions in "utilities" (vs.
257
277
  // "navigation" for nav links). A bare child with no slot attribute
258
- // renders nothing, silently dropping the sign-in button. Regression
259
- // guard for exactly that gap.
278
+ // renders nothing, silently dropping the sign-in button. AppHeader (the
279
+ // shared pattern component) owns the native `slot="utilities"` div; App.vue
280
+ // just feeds its named Vue slot. Regression guard for exactly that gap,
281
+ // now spanning both files since AppHeader was extracted out of App.vue.
260
282
  await generator(host, options);
283
+ const appHeader = host
284
+ .read('libs/vue-components/src/lib/patterns/AppHeader.vue')
285
+ .toString();
286
+ expect(appHeader).toMatch(/<div[^>]*slot="utilities"[^>]*>[\s\S]*<slot name="utilities"/);
287
+
261
288
  const app = host.read('apps/test/src/App.vue').toString();
262
- expect(app).toMatch(/<div slot="utilities">[\s\S]*<goa-button-group/);
289
+ expect(app).toMatch(/<template #utilities>[\s\S]*<goa-button-group/);
263
290
  }, 30000);
264
291
 
265
292
  it('removes the @nx/vue demo scaffold and ships a passing App test', async () => {
@@ -1,16 +1,25 @@
1
- # AGENTS.md — vue-components (GoA Design System Vue wrappers)
1
+ # AGENTS.md — vue-components (GoA Design System Vue wrappers + app shell)
2
2
 
3
- A shared, workspace-local library of thin Vue wrappers over the GoA Design System
4
- `goa-*` web components (`@abgov/web-components`). Every Vue app in this workspace
5
- imports these instead of carrying its own copy. Generated by
3
+ A shared, workspace-local library with two distinct kinds of content every Vue
4
+ app in this workspace imports both instead of carrying its own copy. Generated by
6
5
  `@abgov/nx-adsp:vue-components`.
7
6
 
8
- > **⚠️ Interim library do not invest in it as permanent.** It exists only
9
- > because GoA DS has not yet published an official Vue wrapper package. When
10
- > `@abgov/vue-components` ships, delete this library and repoint imports at it
7
+ | Folder | Contains | Lifespan |
8
+ |---|---|---|
9
+ | `src/lib/primitives/` | Thin `v-model`/idiomatic-event wrappers over individual `goa-*` elements (`GoabInput`, `GoabButton`, …) | **Interim** see below |
10
+ | `src/lib/patterns/` | Composite, app-shell components (`AppLayout`, `AppHeader`, `AppFooter`, `SessionExpiredBanner`) | **Permanent** |
11
+
12
+ > **⚠️ `primitives/` is interim — do not invest in it as permanent.** It exists
13
+ > only because GoA DS has not yet published an official Vue wrapper package. When
14
+ > `@abgov/vue-components` ships, delete `primitives/` and repoint imports at it —
11
15
  > the component names and props are deliberately kept matching, so it should be a
12
16
  > scope swap, not a rewrite. Don't add features here that would make that swap
13
17
  > harder (see "Don't" below).
18
+ >
19
+ > **`patterns/` is not part of that swap.** App-shell composition (layout,
20
+ > header, footer, banners) has no equivalent in an official design-system
21
+ > package — a design system ships primitives, not your app's shell. Nothing in
22
+ > `patterns/` is deleted when `primitives/` is.
14
23
 
15
24
  ## What these wrappers do (and why they're needed)
16
25
 
@@ -45,7 +54,7 @@ Most value elements put the value on `detail.value`; some carry extra keys
45
54
  (dropdown adds `label`, radio-group adds `labels`) you can ignore unless you need
46
55
  them. Always confirm against the component's page — see below.
47
56
 
48
- ## Wrapping a new component
57
+ ## Wrapping a new component (`primitives/`)
49
58
 
50
59
  ### 1. Find the event contract
51
60
 
@@ -129,14 +138,35 @@ Don't re-declare props you don't transform — let them fall through. `name` in
129
138
  particular is required by most `goa-*` form elements (it's echoed in the event
130
139
  detail); just leave it to fall through from the caller.
131
140
 
141
+ ## Building a pattern component (`patterns/`)
142
+
143
+ A pattern component is app-shell composition — layout, header/footer chrome,
144
+ banners — not a single-element wrapper. Existing examples: `AppLayout`,
145
+ `AppHeader`, `AppFooter`, `SessionExpiredBanner`.
146
+
147
+ - It's fine to compose `primitives/` wrappers inside a pattern component (e.g.
148
+ `SessionExpiredBanner` uses `GoabButton`) — import them with a relative path
149
+ (`../primitives/GoabButton.vue`), not the package's own public import path.
150
+ - Stay presentational: accept data and behavior via props/`v-model`/`emit`, don't
151
+ fetch data, call routing APIs, or encode business rules. A pattern component
152
+ used by every app in the workspace can't assume any one app's routes or
153
+ domain — that belongs in the app that uses it (see `SessionExpiredBanner`'s own
154
+ comment for a live example: the component renders the banner, but which
155
+ Keycloak hook flips `show` is main.ts's job, in the consuming app).
156
+ - `export` it from `src/index.ts` under the "patterns" group, with a one-line
157
+ purpose comment in this file's app-shell components table (mirrored in each
158
+ consuming generator's own `AGENTS.md`, e.g. `vue-app/files/AGENTS.md__tmpl__`).
159
+
132
160
  ## Don't
133
161
 
134
- - **Don't build net-new visual components or design primitives here.** That's GoA
135
- DS's job; this library is only *choreography* (adding `v-model`/idiomatic events
136
- to elements that already exist). New primitives would have no home in
137
- `@abgov/vue-components` and would block the swap.
138
- - **Don't add app-specific logic** (fetching, routing, business rules) — this is
139
- shared across every app in the workspace. Keep wrappers presentational.
162
+ - **Don't add new `goa-*` element wrappers to `patterns/`, or new composite
163
+ components to `primitives/`.** Single-element wrappers belong in
164
+ `primitives/` (interim, deleted on the `@abgov/vue-components` swap);
165
+ composites belong in `patterns/` (permanent). Putting one in the wrong folder
166
+ either blocks that swap or gets deleted by it.
167
+ - **Don't add app-specific logic** anywhere in this library (fetching, routing,
168
+ business rules) — it's shared across every app in the workspace. Keep every
169
+ component, wrapper or pattern, presentational.
140
170
 
141
171
  ## Testing
142
172
 
@@ -1,12 +1,23 @@
1
- // GoA Design System Vue wrappers INTERIM shared library.
2
- // These add v-model / idiomatic events over the framework-agnostic goa-* custom
3
- // elements. Remove this library and import from @abgov/vue-components once GoA DS
4
- // publishes it (see the repo's UX view-patterns spec, foundational gap #2) — the
5
- // component names/props are intended to match, so it should be a scope swap.
6
- export { default as GoabInput } from './lib/GoabInput.vue';
7
- export { default as GoabTextarea } from './lib/GoabTextarea.vue';
8
- export { default as GoabDropdown } from './lib/GoabDropdown.vue';
9
- export { default as GoabCheckbox } from './lib/GoabCheckbox.vue';
10
- export { default as GoabRadioGroup } from './lib/GoabRadioGroup.vue';
11
- export { default as GoabButton } from './lib/GoabButton.vue';
12
- export { default as GoabModal } from './lib/GoabModal.vue';
1
+ // GoA Design System Vue wrappers, shared across every Vue app in this workspace.
2
+ //
3
+ // primitives/ thin v-model/idiomatic-event wrappers over individual goa-*
4
+ // elements. INTERIM: once GoA DS publishes an official @abgov/vue-components,
5
+ // delete these files and repoint imports at it names/props are kept
6
+ // matching, so it's a scope swap, not a rewrite.
7
+ //
8
+ // patterns/ composite, app-shell components (layout, header, footer, ...).
9
+ // PERMANENT: these have no equivalent in an official design-system package
10
+ // (that's app-shell composition, not a design-system primitive) and are not
11
+ // deleted when primitives/ is.
12
+ export { default as GoabInput } from './lib/primitives/GoabInput.vue';
13
+ export { default as GoabTextarea } from './lib/primitives/GoabTextarea.vue';
14
+ export { default as GoabDropdown } from './lib/primitives/GoabDropdown.vue';
15
+ export { default as GoabCheckbox } from './lib/primitives/GoabCheckbox.vue';
16
+ export { default as GoabRadioGroup } from './lib/primitives/GoabRadioGroup.vue';
17
+ export { default as GoabButton } from './lib/primitives/GoabButton.vue';
18
+ export { default as GoabModal } from './lib/primitives/GoabModal.vue';
19
+
20
+ export { default as AppLayout } from './lib/patterns/AppLayout.vue';
21
+ export { default as AppHeader } from './lib/patterns/AppHeader.vue';
22
+ export { default as AppFooter } from './lib/patterns/AppFooter.vue';
23
+ export { default as SessionExpiredBanner } from './lib/patterns/SessionExpiredBanner.vue';
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <goa-app-footer>
3
+ <goa-app-footer-nav-section slot="nav" heading="Resources">
4
+ <a href="https://alberta.ca/services.aspx">Services</a>
5
+ <a href="https://alberta.ca/contact.aspx">Contact</a>
6
+ <a href="https://alberta.ca/terms-of-use.aspx">Terms of Use</a>
7
+ </goa-app-footer-nav-section>
8
+ <goa-app-footer-meta-section slot="meta">
9
+ <a href="https://alberta.ca/security-and-privacy.aspx">Privacy</a>
10
+ <a href="https://alberta.ca/disclaimer.aspx">Disclaimer</a>
11
+ <a href="https://alberta.ca/accessibility.aspx">Accessibility</a>
12
+ </goa-app-footer-meta-section>
13
+ </goa-app-footer>
14
+ </template>
@@ -0,0 +1,19 @@
1
+ <script setup lang="ts">
2
+ import { useSlots } from 'vue';
3
+
4
+ defineProps<{ heading: string }>();
5
+ const slots = useSlots();
6
+ </script>
7
+
8
+ <template>
9
+ <goa-microsite-header type="alpha" />
10
+ <goa-app-header url="/" :heading="heading">
11
+ <!-- goa-app-header only renders content placed in a named slot — the
12
+ "utilities" slot is where GoA's own design system docs put
13
+ account/sign-in actions (as opposed to "navigation" for nav links).
14
+ A bare child with no slot attribute renders nothing. -->
15
+ <div v-if="slots.utilities" slot="utilities">
16
+ <slot name="utilities" />
17
+ </div>
18
+ </goa-app-header>
19
+ </template>
@@ -14,6 +14,7 @@ withDefaults(defineProps<{ variant?: 'page' | 'wide' | 'form' }>(), {
14
14
  </script>
15
15
 
16
16
  <template>
17
+ <a class="skip-link" href="#main-content">Skip to main content</a>
17
18
  <main id="main-content">
18
19
  <div :class="`${variant}-content`">
19
20
  <slot />
@@ -22,6 +23,22 @@ withDefaults(defineProps<{ variant?: 'page' | 'wide' | 'form' }>(), {
22
23
  </template>
23
24
 
24
25
  <style scoped>
26
+ /* Visually hidden until focused (e.g. via Tab from the top of the page) — lets
27
+ keyboard/screen-reader users jump past the header straight to the content. */
28
+ .skip-link {
29
+ position: absolute;
30
+ left: -9999px;
31
+ top: 0;
32
+ z-index: 100;
33
+ padding: var(--goa-space-s, 0.5rem) var(--goa-space-m, 1rem);
34
+ background: var(--goa-color-interactive-default, #0070c4);
35
+ color: #fff;
36
+ }
37
+
38
+ .skip-link:focus {
39
+ left: var(--goa-space-m, 1rem);
40
+ }
41
+
25
42
  .page-content,
26
43
  .wide-content,
27
44
  .form-content {
@@ -0,0 +1,26 @@
1
+ <script setup lang="ts">
2
+ // Presentational only — not yet wired to a real Keycloak session-expiry signal
3
+ // by any generator. @dsb-norge/vue-keycloak-js has no reactive "expired" field
4
+ // on the useKeycloak() instance; the closest real hook is the `onAuthLogout`
5
+ // callback configured at plugin-install time in main.ts. Wiring that up is a
6
+ // separate change (new shared reactive state + main.ts plumbing); this
7
+ // component just renders the banner once some caller flips `show`.
8
+ import GoabButton from '../primitives/GoabButton.vue';
9
+
10
+ const show = defineModel<boolean>('show', { default: false });
11
+ const emit = defineEmits<{ signIn: []; dismiss: [] }>();
12
+ </script>
13
+
14
+ <template>
15
+ <div v-if="show" class="session-expired-banner">
16
+ <goa-callout type="emergency" heading="Session expired">
17
+ <p>Your session has expired. Sign in again to continue.</p>
18
+ <goa-spacer vspacing="s" />
19
+ <goa-button-group gap="relaxed">
20
+ <GoabButton type="primary" @click="emit('signIn')">Sign in</GoabButton>
21
+ <GoabButton type="tertiary" @click="emit('dismiss')">Dismiss</GoabButton>
22
+ </goa-button-group>
23
+ </goa-callout>
24
+ <goa-spacer vspacing="m" />
25
+ </div>
26
+ </template>
@@ -1,11 +1,11 @@
1
1
  import { describe, it, expect } from 'vitest';
2
2
  import * as lib from './index';
3
3
 
4
- // Smoke test: the barrel resolves and every wrapper SFC compiles under the test
5
- // runner. It also gives the library a test target with real content, so
6
- // `nx test vue-components` doesn't fail on "no test files found".
4
+ // Smoke test: the barrel resolves and every wrapper/pattern SFC compiles under
5
+ // the test runner. It also gives the library a test target with real content,
6
+ // so `nx test vue-components` doesn't fail on "no test files found".
7
7
  describe('vue-components', () => {
8
- it('exports every GoA wrapper', () => {
8
+ it('exports every GoA primitive wrapper', () => {
9
9
  for (const name of [
10
10
  'GoabInput',
11
11
  'GoabTextarea',
@@ -18,4 +18,15 @@ describe('vue-components', () => {
18
18
  expect(lib[name as keyof typeof lib]).toBeTruthy();
19
19
  }
20
20
  });
21
+
22
+ it('exports every app-shell pattern component', () => {
23
+ for (const name of [
24
+ 'AppLayout',
25
+ 'AppHeader',
26
+ 'AppFooter',
27
+ 'SessionExpiredBanner',
28
+ ]) {
29
+ expect(lib[name as keyof typeof lib]).toBeTruthy();
30
+ }
31
+ });
21
32
  });
@@ -23,7 +23,7 @@ describe('Vue Components Generator', () => {
23
23
  const config = readProjectConfiguration(host, 'vue-components');
24
24
  expect(config.root).toBe('libs/vue-components');
25
25
 
26
- const base = 'libs/vue-components/src/lib';
26
+ const primitives = 'libs/vue-components/src/lib/primitives';
27
27
  for (const name of [
28
28
  'GoabInput',
29
29
  'GoabTextarea',
@@ -33,10 +33,21 @@ describe('Vue Components Generator', () => {
33
33
  'GoabButton',
34
34
  'GoabModal',
35
35
  ]) {
36
- expect(host.exists(`${base}/${name}.vue`)).toBeTruthy();
36
+ expect(host.exists(`${primitives}/${name}.vue`)).toBeTruthy();
37
+ }
38
+ // Permanent app-shell pattern components live alongside the interim wrappers.
39
+ const patterns = 'libs/vue-components/src/lib/patterns';
40
+ for (const name of [
41
+ 'AppLayout',
42
+ 'AppHeader',
43
+ 'AppFooter',
44
+ 'SessionExpiredBanner',
45
+ ]) {
46
+ expect(host.exists(`${patterns}/${name}.vue`)).toBeTruthy();
37
47
  }
38
48
  const index = host.read('libs/vue-components/src/index.ts').toString();
39
49
  expect(index).toContain('export { default as GoabInput }');
50
+ expect(index).toContain('export { default as AppLayout }');
40
51
  expect(index).toContain('@abgov/vue-components'); // interim marker
41
52
 
42
53
  // Ships a spec so the vitest test target isn't empty (vitest exits non-zero
@@ -79,7 +90,7 @@ describe('Vue Components Generator', () => {
79
90
  await generator(host);
80
91
  await expect(generator(host)).resolves.not.toThrow();
81
92
  expect(
82
- host.exists('libs/vue-components/src/lib/GoabInput.vue'),
93
+ host.exists('libs/vue-components/src/lib/primitives/GoabInput.vue'),
83
94
  ).toBeTruthy();
84
95
  }, 30000);
85
96