@asd20/ui-next 2.27.2 → 2.28.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.28.1](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.28.0...ui-next-v2.28.1) (2026-10-02)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * allow an intro message on the handbook page; fix unnecessary focus outlines ([e8c8e09](https://github.com/academydistrict20/asd20-ui-next/commit/e8c8e0965f1f4cef4eb2b8ffa9aacb9b82c0ccc0))
9
+
10
+ # [2.28.0](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.27.2...ui-next-v2.28.0) (2026-10-02)
11
+
12
+
13
+ ### Features
14
+
15
+ * add handbook template ([ceef718](https://github.com/academydistrict20/asd20-ui-next/commit/ceef718735afda7dac57b80f4bf9f2e7e868c604))
16
+
3
17
  ## [2.27.2](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.27.1...ui-next-v2.27.2) (2026-10-01)
4
18
 
5
19
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asd20/ui-next",
3
- "version": "2.27.2",
3
+ "version": "2.28.1",
4
4
  "private": false,
5
5
  "description": "ASD20 UI component library for Vue 3.",
6
6
  "license": "MIT",
@@ -0,0 +1,340 @@
1
+ <template>
2
+ <div class="asd20-template-handbook">
3
+ <asd20-skip-to to="#handbook-content" />
4
+
5
+ <asd20-site-navigation
6
+ v-bind="siteNavigationSearchProps"
7
+ :navigation="navigation"
8
+ :action-items="actionItems"
9
+ :menu-open="menuOpen"
10
+ :search-open="searchOpen"
11
+ :organization="organization"
12
+ :organization-options="organizationOptions"
13
+ @update:menuOpen="$emit('update:menuOpen', $event)"
14
+ @update:searchOpen="$emit('update:searchOpen', $event)"
15
+ />
16
+
17
+ <asd20-notification-group
18
+ :notifications="activeNotificationsByType.banner"
19
+ group-type="banner"
20
+ @dismiss="$emit('dismiss-notification', $event)"
21
+ @toggle-all="$emit('toggle-all')"
22
+ />
23
+
24
+ <asd20-page-header
25
+ :heading="title"
26
+ :lead="handbookLead"
27
+ :organization="organization"
28
+ :organization-options="organizationOptions"
29
+ :breadcrumb-links="breadcrumbLinks"
30
+ :language-code="languageCode"
31
+ @update:languageCode="$emit('update:languageCode', $event)"
32
+ >
33
+ <template #top>
34
+ <asd20-notification-group
35
+ class="asd20-notification-group--floating"
36
+ :notifications="activeNotificationsByType.floating"
37
+ :total-dismissed-notifications="totalDismissedNotifications"
38
+ group-type="floating"
39
+ @dismiss="$emit('dismiss-notification', $event)"
40
+ @toggle-all="$emit('toggle-all')"
41
+ />
42
+ </template>
43
+ </asd20-page-header>
44
+
45
+ <asd20-notification-group
46
+ :notifications="activeNotificationsByType.inline"
47
+ group-type="inline"
48
+ @dismiss="$emit('dismiss-notification', $event)"
49
+ @toggle-all="$emit('toggle-all')"
50
+ />
51
+
52
+ <main
53
+ id="handbook-content"
54
+ class="asd20-template-handbook__layout"
55
+ tabindex="-1"
56
+ >
57
+ <nav
58
+ class="asd20-template-handbook__index"
59
+ aria-label="Handbook topics"
60
+ >
61
+ <button
62
+ class="asd20-template-handbook__index-toggle"
63
+ type="button"
64
+ :aria-expanded="topicsOpen"
65
+ aria-controls="handbook-topics"
66
+ @click="topicsOpen = !topicsOpen"
67
+ >
68
+ Topics
69
+ </button>
70
+ <h2 class="asd20-template-handbook__index-heading">
71
+ Topics
72
+ </h2>
73
+ <ol
74
+ id="handbook-topics"
75
+ :class="{ 'is-open': topicsOpen }"
76
+ >
77
+ <li
78
+ v-for="message in topicMessages"
79
+ :key="message.id"
80
+ >
81
+ <button
82
+ type="button"
83
+ :aria-current="activeMessage && activeMessage.id === message.id ? 'true' : null"
84
+ @click="selectTopic(message.id)"
85
+ >
86
+ {{ message.heading || message.title }}
87
+ </button>
88
+ </li>
89
+ </ol>
90
+ </nav>
91
+
92
+ <article
93
+ v-for="message in topicMessages"
94
+ :key="message.id"
95
+ class="asd20-template-handbook__topic"
96
+ :class="{ 'is-active': activeMessage && activeMessage.id === message.id }"
97
+ >
98
+ <h2>
99
+ {{ message.heading || message.title }}
100
+ </h2>
101
+ <div
102
+ v-if="topicSummary(message)"
103
+ class="asd20-template-handbook__summary"
104
+ v-html="topicSummary(message)"
105
+ />
106
+ <hr
107
+ v-if="topicSummary(message)"
108
+ class="asd20-template-handbook__summary-divider"
109
+ />
110
+ <asd20-messaging
111
+ v-bind="message"
112
+ heading=""
113
+ short-description=""
114
+ detail-link=""
115
+ />
116
+ </article>
117
+ <p v-if="!topicMessages.length">
118
+ No handbook topics are available yet.
119
+ </p>
120
+ </main>
121
+
122
+ <asd20-quicklinks-menu :quick-links="quickLinks" />
123
+ <asd20-page-footer
124
+ :organization="organization"
125
+ :social-links="socialLinks"
126
+ :disclosure-links="disclosureLinks"
127
+ :website-logo-props="websiteLogoProps"
128
+ :website-logo-props2="websiteLogoProps2"
129
+ />
130
+ </div>
131
+ </template>
132
+
133
+ <script>
134
+ import Asd20SkipTo from '../../../components/atoms/Asd20SkipTo'
135
+ import Asd20Messaging from '../../../components/atoms/Asd20Messaging'
136
+ import Asd20PageHeader from '../../../components/organisms/Asd20PageHeader'
137
+ import Asd20SiteNavigation from '../../../components/organisms/Asd20SiteNavigation'
138
+ import Asd20NotificationGroup from '../../../components/organisms/Asd20NotificationGroup'
139
+ import Asd20QuicklinksMenu from '../../../components/organisms/Asd20QuicklinksMenu'
140
+ import Asd20PageFooter from '../../../components/organisms/Asd20PageFooter'
141
+ import pageTemplateMixin from '../../../mixins/pageTemplateMixin'
142
+
143
+ export default {
144
+ name: 'Asd20HandbookTemplate',
145
+ components: {
146
+ Asd20SkipTo,
147
+ Asd20Messaging,
148
+ Asd20PageHeader,
149
+ Asd20SiteNavigation,
150
+ Asd20NotificationGroup,
151
+ Asd20QuicklinksMenu,
152
+ Asd20PageFooter,
153
+ },
154
+ mixins: [pageTemplateMixin],
155
+ data: () => ({
156
+ selectedMessageId: null,
157
+ topicsOpen: false,
158
+ }),
159
+ computed: {
160
+ handbookLead() {
161
+ return this.firstMessage?.shortDescription || this.firstMessage?.summary || this.metaDescription
162
+ },
163
+ topicMessages() {
164
+ return this.messages.slice(1)
165
+ },
166
+ activeMessage() {
167
+ return this.topicMessages.find(message => message.id === this.selectedMessageId)
168
+ || this.topicMessages[0]
169
+ || null
170
+ },
171
+ },
172
+ methods: {
173
+ topicSummary(message) {
174
+ return message.shortDescription || message.summary || ''
175
+ },
176
+ selectTopic(messageId) {
177
+ this.selectedMessageId = messageId
178
+ this.topicsOpen = false
179
+ },
180
+ },
181
+ }
182
+ </script>
183
+
184
+ <style src="../../../design/tokens.css"></style>
185
+
186
+ <style lang="scss">
187
+ @use '../../../design/template-stack' as *;
188
+
189
+ .asd20-template-handbook {
190
+ @include typography;
191
+ @include template;
192
+ display: flex;
193
+ flex-direction: column;
194
+ flex-grow: 1;
195
+ min-width: 0;
196
+ margin-top: space(2.25);
197
+
198
+ &__layout {
199
+ display: grid;
200
+ grid-template-columns: minmax(0, 1fr);
201
+ gap: space(2);
202
+ min-width: 0;
203
+ padding: space(2) space(1);
204
+ }
205
+
206
+ &__layout:focus:not(.asd20-tab):not([role='tab']):not(.asd20-focus-trap) {
207
+ outline: none;
208
+ box-shadow: none !important;
209
+ }
210
+
211
+ &__summary {
212
+ @include asd20-font(0.75, var(--website-typography__font-family-body), 1.5);
213
+ margin-bottom: space(0.5);
214
+ }
215
+
216
+ &__summary-divider {
217
+ margin: 0 0 space(1);
218
+ border: 0;
219
+ border-top: 1px solid currentColor;
220
+ opacity: 0.25;
221
+ }
222
+
223
+ &__index ol {
224
+ display: none;
225
+ list-style: none;
226
+ margin: 0;
227
+ padding: 0;
228
+ }
229
+
230
+ &__index ol.is-open {
231
+ display: block;
232
+ }
233
+
234
+ &__index-heading {
235
+ display: none;
236
+ }
237
+
238
+ &__index button {
239
+ font: inherit;
240
+ text-align: start;
241
+ cursor: pointer;
242
+ }
243
+
244
+ &__index li button {
245
+ display: block;
246
+ width: 100%;
247
+ min-height: 44px;
248
+ padding: space(0.5);
249
+ border: 0;
250
+ border-left: 3px solid transparent;
251
+ background: transparent;
252
+ color: inherit;
253
+ }
254
+
255
+ &__index li button:hover,
256
+ &__index li button:focus-visible {
257
+ background: var(--color__tertiary-t50);
258
+ }
259
+
260
+ &__index li button[aria-current='true'] {
261
+ border-left-color: var(--color__primary);
262
+ background: var(--color__tertiary-t50);
263
+ font-weight: bold;
264
+ }
265
+
266
+ &__index-toggle {
267
+ width: 100%;
268
+ min-height: 44px;
269
+ padding: space(0.5);
270
+ border: 1px solid var(--color__primary);
271
+ border-radius: 0.25rem;
272
+ background: var(--color__tertiary-t50);
273
+ color: var(--color__primary);
274
+ font-weight: bold;
275
+ }
276
+
277
+ &__topic {
278
+ min-width: 0;
279
+ }
280
+
281
+ &__topic:not(.is-active) {
282
+ display: none;
283
+ }
284
+ }
285
+
286
+ @media (min-width: 768px) {
287
+ .asd20-template-handbook {
288
+ &__layout {
289
+ grid-template-columns: minmax(12rem, 16rem) minmax(0, 1fr);
290
+ gap: space(3);
291
+ padding: space(3);
292
+ }
293
+
294
+ &__index {
295
+ position: sticky;
296
+ top: space(2);
297
+ align-self: start;
298
+ max-height: calc(100vh - 4rem);
299
+ overflow-y: auto;
300
+ }
301
+
302
+ &__index-heading,
303
+ &__index ol {
304
+ display: block;
305
+ }
306
+
307
+ &__index-toggle {
308
+ display: none;
309
+ }
310
+ }
311
+ }
312
+
313
+ @media (min-width: 1024px) {
314
+ .asd20-template-handbook {
315
+ margin-left: space(3);
316
+ margin-top: 0;
317
+ }
318
+ }
319
+
320
+ @media print {
321
+ .asd20-template-handbook {
322
+ &__index {
323
+ display: none;
324
+ }
325
+
326
+ &__layout {
327
+ display: block;
328
+ }
329
+
330
+ &__topic,
331
+ &__topic:not(.is-active) {
332
+ display: block;
333
+ }
334
+
335
+ &__topic {
336
+ break-inside: avoid-page;
337
+ }
338
+ }
339
+ }
340
+ </style>
package/templates.js CHANGED
@@ -16,6 +16,7 @@ export { default as Asd20DistrictHomeTemplate } from './src/components/templates
16
16
  export { default as Asd20DistrictVideoTemplate } from './src/components/templates/Asd20DistrictVideoTemplate/index.vue'
17
17
  export { default as Asd20FileListPageTemplate } from './src/components/templates/Asd20FileListPageTemplate/index.vue'
18
18
  export { default as Asd20GroupFeatureTemplate } from './src/components/templates/Asd20GroupFeatureTemplate/index.vue'
19
+ export { default as Asd20HandbookTemplate } from './src/components/templates/Asd20HandbookTemplate/index.vue'
19
20
  export { default as Asd20LoginsTemplate } from './src/components/templates/Asd20LoginsTemplate/index.vue'
20
21
  export { default as Asd20PeopleFeatureTemplate } from './src/components/templates/Asd20PeopleFeatureTemplate/index.vue'
21
22
  export { default as Asd20ProfileTemplate } from './src/components/templates/Asd20ProfileTemplate/index.vue'