@asd20/ui-next 2.33.1 → 2.33.2

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,7 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.33.2](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.33.1...ui-next-v2.33.2) (2026-10-26)
4
+
3
5
  ## [2.33.1](https://github.com/academydistrict20/asd20-ui-next/compare/ui-next-v2.33.0...ui-next-v2.33.1) (2026-10-26)
4
6
 
5
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asd20/ui-next",
3
- "version": "2.33.1",
3
+ "version": "2.33.2",
4
4
  "private": false,
5
5
  "description": "ASD20 UI component library for Vue 3.",
6
6
  "license": "MIT",
@@ -97,26 +97,11 @@
97
97
  <div class="white-accent-band">
98
98
  <section
99
99
  ref="header"
100
- :class="headerClasses"
100
+ class="asd20-secondary-header"
101
101
  aria-label="Secondary message"
102
- :style="secondaryHeaderStyle"
103
102
  >
104
- <!-- Parallax background (masked by .asd20-secondary-header mask) -->
105
- <div
106
- class="secondary-parallax"
107
- aria-hidden="true"
108
- >
109
- <div class="secondary-parallax__layer secondary-parallax__base"></div>
110
- <div
111
- class="secondary-parallax__layer secondary-parallax__field"
112
- ></div>
113
- <div
114
- class="secondary-parallax__layer secondary-parallax__ribbons"
115
- ></div>
116
- </div>
117
-
118
103
  <asd20-messaging
119
- v-bind="secondaryMessageForDisplay"
104
+ v-bind="secondaryMessage"
120
105
  fullscreen
121
106
  ></asd20-messaging>
122
107
  </section>
@@ -141,181 +126,10 @@ export default {
141
126
  grid: { type: Boolean, default: false },
142
127
  forceDisplay: { type: Boolean, default: false },
143
128
  },
144
- data() {
145
- return {
146
- isTouchCapableDevice: false,
147
- parallaxEnabled: false,
148
- intersectionObserver: null,
149
- parallaxRaf: null,
150
- handleScroll: null,
151
- handleResize: null,
152
- }
153
- },
154
129
  computed: {
155
- shouldUseParallax() {
156
- return !this.isTouchCapableDevice
157
- },
158
- headerClasses() {
159
- return {
160
- 'asd20-secondary-header': true,
161
- 'asd20-secondary-header--desktop-background':
162
- this.hasSecondaryHeaderImage,
163
- 'asd20-secondary-header--parallax-enabled-background':
164
- this.hasSecondaryHeaderImage && this.shouldUseParallax,
165
- 'asd20-secondary-header--hide-desktop-image':
166
- !this.shouldShowDesktopInlineImage,
167
- }
168
- },
169
130
  secondaryMessage() {
170
131
  return Array.isArray(this.messages) ? this.messages[1] || {} : {}
171
132
  },
172
- secondaryMessageImages() {
173
- return Array.isArray(this.secondaryMessage.images)
174
- ? this.secondaryMessage.images
175
- : []
176
- },
177
- secondaryHeaderImageObject() {
178
- return (
179
- this.secondaryMessageImages.find(image => image && image.isCover) ||
180
- this.secondaryMessageImages[0] ||
181
- null
182
- )
183
- },
184
- secondaryHeaderImage() {
185
- return this.resolveMessageImageUrl(this.secondaryHeaderImageObject)
186
- },
187
- hasSecondaryHeaderImage() {
188
- return Boolean(this.secondaryHeaderImage)
189
- },
190
- shouldShowDesktopInlineImage() {
191
- return Boolean(
192
- this.secondaryHeaderImageObject && this.secondaryHeaderImageObject.isCover
193
- )
194
- },
195
- secondaryMessageForDisplay() {
196
- if (!this.secondaryHeaderImageObject) return this.secondaryMessage
197
-
198
- return {
199
- ...this.secondaryMessage,
200
- images: [
201
- {
202
- ...this.secondaryHeaderImageObject,
203
- isCover: true,
204
- },
205
- ],
206
- }
207
- },
208
- secondaryHeaderStyle() {
209
- if (!this.hasSecondaryHeaderImage) return {}
210
-
211
- return {
212
- '--secondary-header-image': `url("${this.secondaryHeaderImage}")`,
213
- }
214
- },
215
- },
216
- mounted() {
217
- if (typeof window !== 'undefined') {
218
- this.isTouchCapableDevice = Boolean(
219
- window.matchMedia?.('(pointer: coarse)').matches ||
220
- window.navigator?.maxTouchPoints > 0
221
- )
222
- }
223
-
224
- // Respect reduced motion
225
- const prefersReduced =
226
- typeof window !== 'undefined' &&
227
- window.matchMedia &&
228
- window.matchMedia('(prefers-reduced-motion: reduce)').matches
229
-
230
- if (prefersReduced || !this.shouldUseParallax) return
231
-
232
- this.handleScroll = () => this.scheduleParallaxUpdate()
233
- this.handleResize = () => this.scheduleParallaxUpdate()
234
-
235
- // Only animate when the header is in view
236
- if (typeof window !== 'undefined' && 'IntersectionObserver' in window) {
237
- this.intersectionObserver = new IntersectionObserver(
238
- entries => {
239
- const entry = entries && entries[0]
240
- if (!entry) return
241
- if (entry.isIntersecting) this.enableParallax()
242
- else this.disableParallax()
243
- },
244
- { root: null, threshold: 0.01 }
245
- )
246
-
247
- if (this.$refs.header) this.intersectionObserver.observe(this.$refs.header)
248
- } else {
249
- // Fallback: just enable
250
- this.enableParallax()
251
- }
252
-
253
- // Initial set
254
- this.scheduleParallaxUpdate()
255
- },
256
- beforeUnmount() {
257
- this.teardownParallax()
258
- },
259
- methods: {
260
- resolveMessageImageUrl(image) {
261
- if (!image) return ''
262
-
263
- const imageFiles = Array.isArray(image.files) ? image.files : []
264
- const fullImage = imageFiles.find(file => file.name === 'full')
265
- return fullImage ? fullImage.url : image.url || ''
266
- },
267
- teardownParallax() {
268
- this.disableParallax()
269
- if (this.intersectionObserver) this.intersectionObserver.disconnect()
270
- this.intersectionObserver = null
271
- },
272
- enableParallax() {
273
- if (this.parallaxEnabled) return
274
- this.parallaxEnabled = true
275
- window.addEventListener('scroll', this.handleScroll, { passive: true })
276
- window.addEventListener('resize', this.handleResize, { passive: true })
277
- this.scheduleParallaxUpdate()
278
- },
279
- disableParallax() {
280
- if (!this.parallaxEnabled) return
281
- this.parallaxEnabled = false
282
- window.removeEventListener('scroll', this.handleScroll)
283
- window.removeEventListener('resize', this.handleResize)
284
- if (this.parallaxRaf) cancelAnimationFrame(this.parallaxRaf)
285
- this.parallaxRaf = null
286
- },
287
- scheduleParallaxUpdate() {
288
- if (!this.parallaxEnabled) return
289
- if (this.parallaxRaf) return
290
- this.parallaxRaf = requestAnimationFrame(() => {
291
- this.parallaxRaf = null
292
- this.updateParallax()
293
- })
294
- },
295
- updateParallax() {
296
- const el = this.$refs.header
297
- if (!el) return
298
-
299
- const rect = el.getBoundingClientRect()
300
- const vh = window.innerHeight || 1
301
-
302
- // Progress through viewport: 0 (below) -> 1 (above)
303
- // We keep it gentle and clamp
304
- const mid = rect.top + rect.height * 0.25
305
- const tRaw = 1 - mid / vh
306
- const t = Math.max(0, Math.min(1, tRaw * 1.25))
307
- const t2 = Math.max(0, Math.min(1, tRaw * 1.25)) // field
308
- const t3 = Math.max(0, Math.min(1, tRaw * 1.6)) // ribbons
309
-
310
- // Subtle movement only (px)
311
- const y1 = (t - 0.5) * 22 // base
312
- const y2 = (t2 - 0.5) * 60 // field
313
- const y3 = (t3 - 0.5) * 40 // ribbons
314
-
315
- el.style.setProperty('--secondary-parallax-y1', `${y1}px`)
316
- el.style.setProperty('--secondary-parallax-y2', `${y2}px`)
317
- el.style.setProperty('--secondary-parallax-y3', `${y3}px`)
318
- },
319
133
  },
320
134
  }
321
135
  </script>
@@ -344,13 +158,14 @@ export default {
344
158
  }
345
159
 
346
160
  .asd20-secondary-header {
347
- --secondary-header-image: none;
348
161
  position: relative;
349
162
  display: flex;
350
163
  flex-shrink: 0;
351
164
  flex-direction: column;
352
165
  color: var(--website-homepage-header__secondary-foreground-color);
353
- background: var(--website-homepage-header__secondary-background-color);
166
+ // CommCenter supplies a full background shorthand (image, position, size, repeat).
167
+ background: var(--website-homepage-header__secondary-background-style, none);
168
+ background-color: var(--website-homepage-header__secondary-background-color);
354
169
  padding: space(1) 0 0 0;
355
170
 
356
171
  mask: url(#secondary-header-mask-mobile);
@@ -358,7 +173,6 @@ export default {
358
173
  mask-size: 100% 100%;
359
174
  -webkit-mask-size: 100% 100%;
360
175
 
361
- /* Ensure content stays above the parallax layers */
362
176
  .asd20-messaging {
363
177
  position: relative;
364
178
  z-index: 2;
@@ -367,94 +181,6 @@ export default {
367
181
  flex-direction: column;
368
182
  }
369
183
 
370
- /* Parallax background container */
371
- .secondary-parallax {
372
- position: absolute;
373
- inset: 0;
374
- z-index: 1;
375
- pointer-events: none;
376
- overflow: hidden; /* mask will clip, but this avoids any edge artifacts */
377
- }
378
-
379
- .secondary-parallax__layer {
380
- position: absolute;
381
- inset: -10% -10% -10% -10%;
382
- transform: translate3d(0, 0, 0);
383
- will-change: transform;
384
- }
385
-
386
- /* Layer 1: base gradient glow */
387
- .secondary-parallax__base {
388
- transform: translate3d(0, var(--secondary-parallax-y1, 0px), 0);
389
- background: radial-gradient(
390
- 800px 520px at 90% 90%,
391
- rgba(255, 255, 255, 0.55) 0%,
392
- rgba(255, 255, 255, 0.22) 0%,
393
- rgba(255, 255, 255, 0) 0%
394
- ),
395
- linear-gradient(
396
- 90deg,
397
- rgba(12, 36, 86, 0.95) 0%,
398
- rgba(12, 36, 86, 0.85) 35%,
399
- rgba(12, 36, 86, 0.25) 100%
400
- );
401
- /* linear-gradient(*/
402
- /* 90deg,*/
403
- /* rgba(12, 36, 86, 0.95) 0%,*/
404
- /* rgba(24, 74, 160, 0.6) 85%,*/
405
- /* rgba(112, 160, 230, 0.85) 100%*/
406
- /* );*/
407
- }
408
-
409
- /* Layer 2: soft wave fields (broad arcs) */
410
- .secondary-parallax__field {
411
- transform: translate3d(0px, var(--secondary-parallax-y2, 0px), 0)
412
- rotate(-5deg);
413
- background: radial-gradient(
414
- 280% 155% at 20% 110%,
415
- rgba(255, 255, 255, 0) 0%,
416
- rgba(255, 255, 255, 0) 62%,
417
- rgba(188, 220, 250, 0.95) 70%,
418
- rgba(255, 255, 255, 0) 72%
419
- );
420
- filter: none;
421
- opacity: 0.9;
422
- mask-image: linear-gradient(
423
- 90deg,
424
- rgba(0, 0, 0, 0.85) 0%,
425
- rgba(0, 0, 0, 1) 85%
426
- );
427
- -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,0.85) 0%, rgba(0,0,0,1) 85%);
428
- }
429
-
430
- /* Layer 3: highlight ribbons (brighter curves) */
431
- .secondary-parallax__ribbons {
432
- transform: translate3d(0, var(--secondary-parallax-y3, 0px), 0)
433
- rotate(-3deg);
434
- background: radial-gradient(
435
- 260% 160% at 50% 110%,
436
- rgba(255, 255, 255, 0) 0%,
437
- rgba(255, 255, 255, 0) 60%,
438
- rgba(255, 255, 255, 0.9) 64%,
439
- rgba(255, 255, 255, 0) 70%
440
- );
441
- opacity: 0.9;
442
- filter: none;
443
- mask-image: linear-gradient(
444
- 90deg,
445
- rgba(0, 0, 0, 0.3) 0%,
446
- rgba(0, 0, 0, 1) 70%
447
- );
448
- -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,0.3) 0%, rgba(0,0,0,1) 70%);
449
- }
450
-
451
- /* Reduced motion: lock the layers */
452
- @media (prefers-reduced-motion: reduce) {
453
- .secondary-parallax__layer {
454
- transform: none !important;
455
- }
456
- }
457
-
458
184
  & :deep(.message-image) {
459
185
  order: 2;
460
186
  border-top: none !important;
@@ -484,6 +210,15 @@ export default {
484
210
  padding: space(1) space(1) space(1) space(1);
485
211
  }
486
212
 
213
+ & :deep(.asd20-messaging__button-group) {
214
+ display: grid;
215
+ grid-template-columns: minmax(0, 1fr);
216
+ gap: space(0.5);
217
+ width: 70vw;
218
+ max-width: 100%;
219
+ margin: space(0.5) auto;
220
+ }
221
+
487
222
  & :deep(.asd20-button) {
488
223
  @include asd20-font(
489
224
  0.75,
@@ -492,8 +227,10 @@ export default {
492
227
  700
493
228
  );
494
229
  flex-direction: column;
495
- width: 70vw;
496
- margin: space(0.5) auto !important;
230
+ box-sizing: border-box;
231
+ min-width: 0;
232
+ width: 100%;
233
+ margin: 0 !important;
497
234
  color: var(--website-homepage-header__secondary-button-foreground-color);
498
235
  background: var(
499
236
  --website-homepage-header__secondary-button-background-color
@@ -505,6 +242,9 @@ export default {
505
242
  z-index: 2;
506
243
  overflow: hidden;
507
244
  }
245
+ & :deep(.asd20-button__label) {
246
+ overflow-wrap: anywhere;
247
+ }
508
248
  & :deep(.asd20-button)::before {
509
249
  content: '';
510
250
  position: absolute;
@@ -542,9 +282,9 @@ export default {
542
282
  & :deep(.lead) {
543
283
  width: 100%;
544
284
  }
545
- & :deep(.asd20-button) {
285
+ & :deep(.asd20-messaging__button-group) {
546
286
  width: 50vw;
547
- margin: space(0.5) space(0.5) 0 0 !important;
287
+ margin-inline: 0;
548
288
  }
549
289
  }
550
290
  }
@@ -575,14 +315,8 @@ export default {
575
315
  }
576
316
 
577
317
  @media (min-width: 1024px) {
578
- .asd20-secondary-header--desktop-background {
318
+ .asd20-secondary-header {
579
319
  padding: space(3) space(3) space(2) space(3);
580
- background-color: var(--website-homepage-header__secondary-background-color);
581
- background-image: var(--secondary-header-image);
582
- background-position: center;
583
- background-repeat: no-repeat;
584
- background-size: cover;
585
- background-attachment: scroll;
586
320
  padding-top: 70px;
587
321
 
588
322
  mask: url(#secondary-header-mask-desktop);
@@ -607,6 +341,11 @@ export default {
607
341
  border-bottom: none;
608
342
  }
609
343
 
344
+ & :deep(.asd20-messaging__button-group) {
345
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
346
+ width: 100%;
347
+ }
348
+
610
349
  & :deep(.asd20-button) {
611
350
  @include asd20-font(
612
351
  0.75,
@@ -615,8 +354,6 @@ export default {
615
354
  700
616
355
  );
617
356
  flex-direction: row;
618
- width: inherit;
619
- margin: space(0.5) space(0.5) 0 0 !important;
620
357
  padding: space(0.5) space(1.5);
621
358
  }
622
359
 
@@ -634,64 +371,17 @@ export default {
634
371
  }
635
372
  }
636
373
 
637
- .asd20-secondary-header--desktop-background .secondary-parallax {
638
- display: block;
639
- }
640
-
641
- .asd20-secondary-header--desktop-background .secondary-parallax__field,
642
- .asd20-secondary-header--desktop-background .secondary-parallax__ribbons {
643
- display: none;
644
- }
645
-
646
- .asd20-secondary-header--parallax-enabled-background {
647
- background-attachment: fixed;
648
- }
649
-
650
- .asd20-secondary-header--parallax-enabled-background .secondary-parallax__field,
651
- .asd20-secondary-header--parallax-enabled-background .secondary-parallax__ribbons {
652
- display: block;
653
- }
654
-
655
- .asd20-secondary-header--parallax-enabled-background .secondary-parallax__field {
656
- transform: translate3d(0px, var(--secondary-parallax-y2, 0px), 0)
657
- rotate(-5deg);
658
- filter: none;
659
- opacity: 0.9;
660
- mask-image: linear-gradient(
661
- 90deg,
662
- rgba(0, 0, 0, 0.85) 0%,
663
- rgba(0, 0, 0, 1) 85%
664
- );
665
- -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,0.85) 0%, rgba(0,0,0,1) 85%);
666
- }
667
-
668
- .asd20-secondary-header--parallax-enabled-background .secondary-parallax__ribbons {
669
- transform: translate3d(0, var(--secondary-parallax-y3, 0px), 0)
670
- rotate(-3deg);
671
- background: radial-gradient(
672
- 180% 160% at 40% 110%,
673
- rgba(255, 255, 255, 0) 0%,
674
- rgba(255, 255, 255, 0) 60%,
675
- rgba(255, 255, 255, 0.9) 64%,
676
- rgba(255, 255, 255, 0) 70%
677
- );
678
- opacity: 0.9;
679
- filter: none;
680
- mask-image: linear-gradient(
681
- 90deg,
682
- rgba(0, 0, 0, 0.3) 0%,
683
- rgba(0, 0, 0, 1) 70%
684
- );
685
- -webkit-mask-image: linear-gradient(90deg, rgba(0,0,0,0.3) 0%, rgba(0,0,0,1) 70%);
686
- }
687
-
688
- .asd20-secondary-header--desktop-background.asd20-secondary-header--hide-desktop-image {
689
- & :deep(.asd20-messaging--fullscreen > .message-image) {
690
- display: none;
374
+ }
375
+ @media (min-width: 1025px) {
376
+ .asd20-secondary-header {
377
+ & :deep(.asd20-messaging__button-group) {
378
+ display: flex;
379
+ flex-wrap: wrap;
691
380
  }
692
381
 
693
- & :deep(.asd20-messaging--fullscreen > .asd20-messaging__content) {
694
- max-width: 60%;
382
+ & :deep(.asd20-button) {
383
+ width: fit-content;
384
+ max-width: 100%;
695
385
  }
696
386
  }
697
387
  }