@@ -24,15 +24,16 @@ import {
2424
2525// Constants here
2626const LCP_BLOCKS = [ 'hero' , 'logo-wall' ] ; // add your LCP blocks to the list
27+ const LONG_FORM_TEMPLATE_CLASSES = new Set ( [ 'docs-template' , 'guides-template' , 'blog-template' , 'skills-template' ] ) ;
28+ const LONG_FORM_TEMPLATE_METADATA = new Set ( [ 'docs' , 'documentation' , 'guide' , 'guides' , 'blog' , 'skills' ] ) ;
29+ const LONG_FORM_SCROLL_THRESHOLD = 0.35 ;
2730
2831const AUDIENCES = {
2932 mobile : ( ) => window . innerWidth < 600 ,
3033 desktop : ( ) => window . innerWidth >= 600 ,
3134 // define your custom audiences here as needed
3235} ;
3336
34- const LONG_FORM_TEMPLATES = [ 'docs-template' , 'guides-template' , 'blog-template' ] ;
35-
3637window . hlx . plugins . add ( 'performance' , {
3738 condition : ( ) => window . name . includes ( 'performance' ) ,
3839 load : 'eager' ,
@@ -185,36 +186,56 @@ export function addMessageBoxOnGuideTemplate(main) {
185186 main . append ( messageBox ) ;
186187}
187188
188- const isLongFormPage = ( ) => LONG_FORM_TEMPLATES
189- . some ( ( tplClass ) => document . body . classList . contains ( tplClass ) ) ;
189+ const isLongFormPage = ( ) => {
190+ const { body } = document ;
191+ if ( ! body ) return false ;
192+ const hasTemplateClass = [ ...LONG_FORM_TEMPLATE_CLASSES ]
193+ . some ( ( tplClass ) => body . classList . contains ( tplClass ) ) ;
194+ if ( hasTemplateClass ) return true ;
195+ const templateMetadata = getMetadata ( 'template' ) ;
196+ if ( ! templateMetadata ) return false ;
197+ return LONG_FORM_TEMPLATE_METADATA . has ( templateMetadata . toLowerCase ( ) ) ;
198+ } ;
190199
191200const hasScrollableLongFormContent = ( ) => {
192201 const scrollable = document . documentElement . scrollHeight - window . innerHeight ;
193- return scrollable > window . innerHeight * 0.35 ;
202+ return scrollable > window . innerHeight * LONG_FORM_SCROLL_THRESHOLD ;
194203} ;
195204
196205function initReadingProgress ( ) {
197206 if ( ! isLongFormPage ( ) || document . querySelector ( '.reading-progress' ) ) return ;
198207
199208 const progressBar = createTag ( 'div' , {
200209 class : 'reading-progress' ,
210+ role : 'progressbar' ,
211+ 'aria-label' : 'Reading progress' ,
212+ 'aria-valuemin' : '0' ,
213+ 'aria-valuemax' : '100' ,
214+ 'aria-valuenow' : '0' ,
215+ 'aria-hidden' : 'true' ,
216+ } ) ;
217+ const fill = createTag ( 'span' , {
218+ class : 'reading-progress-fill' ,
201219 'aria-hidden' : 'true' ,
202220 } ) ;
203- const fill = createTag ( 'span' , { class : 'reading-progress-fill' } ) ;
204221 progressBar . append ( fill ) ;
205222 document . body . prepend ( progressBar ) ;
206223
207224 const updateProgress = ( ) => {
208- const scrollable = document . documentElement . scrollHeight - window . innerHeight ;
225+ const scrollable = Math . max ( document . documentElement . scrollHeight - window . innerHeight , 0 ) ;
209226 const canScroll = scrollable > 0 ;
210227 const isLongEnough = hasScrollableLongFormContent ( ) ;
211- progressBar . classList . toggle ( 'is-hidden' , ! isLongEnough ) ;
212- if ( ! canScroll || ! isLongEnough ) {
228+ const shouldHide = ! canScroll || ! isLongEnough ;
229+ progressBar . classList . toggle ( 'is-hidden' , shouldHide ) ;
230+ progressBar . setAttribute ( 'aria-hidden' , shouldHide ? 'true' : 'false' ) ;
231+ if ( shouldHide ) {
213232 fill . style . transform = 'scaleX(0)' ;
233+ progressBar . setAttribute ( 'aria-valuenow' , '0' ) ;
214234 return ;
215235 }
216236 const progress = Math . min ( window . scrollY / scrollable , 1 ) ;
217237 fill . style . transform = `scaleX(${ progress } )` ;
238+ progressBar . setAttribute ( 'aria-valuenow' , `${ Math . round ( progress * 100 ) } ` ) ;
218239 } ;
219240
220241 updateProgress ( ) ;
@@ -232,6 +253,11 @@ function initReadingProgress() {
232253
233254 window . addEventListener ( 'scroll' , handleScroll , { passive : true } ) ;
234255 window . addEventListener ( 'resize' , updateProgress ) ;
256+
257+ if ( window . ResizeObserver && document . body ) {
258+ const resizeObserver = new ResizeObserver ( updateProgress ) ;
259+ resizeObserver . observe ( document . body ) ;
260+ }
235261}
236262
237263function initBackToTopButton ( ) {
@@ -249,6 +275,8 @@ function initBackToTopButton() {
249275 const label = createTag ( 'span' , { class : 'back-to-top-button-label' } , 'Back to top' ) ;
250276 button . append ( icon , label ) ;
251277 document . body . append ( button ) ;
278+ button . setAttribute ( 'aria-hidden' , 'true' ) ;
279+ button . setAttribute ( 'tabindex' , '-1' ) ;
252280
253281 const prefersReducedMotionQuery = window . matchMedia
254282 ? window . matchMedia ( '(prefers-reduced-motion: reduce)' )
@@ -281,15 +309,20 @@ function initBackToTopButton() {
281309 button . setAttribute ( 'tabindex' , '-1' ) ;
282310 return ;
283311 }
284- button . removeAttribute ( 'aria-hidden' ) ;
285- button . removeAttribute ( 'tabindex' ) ;
312+ button . setAttribute ( 'aria-hidden' , 'false ') ;
313+ button . setAttribute ( 'tabindex' , '0 ') ;
286314 const shouldShow = window . scrollY > window . innerHeight * 0.8 ;
287315 button . classList . toggle ( 'is-visible' , shouldShow ) ;
288316 } ;
289317
290318 toggleVisibility ( ) ;
291319 window . addEventListener ( 'scroll' , toggleVisibility , { passive : true } ) ;
292320 window . addEventListener ( 'resize' , toggleVisibility ) ;
321+
322+ if ( window . ResizeObserver && document . body ) {
323+ const resizeObserver = new ResizeObserver ( toggleVisibility ) ;
324+ resizeObserver . observe ( document . body ) ;
325+ }
293326}
294327
295328export function addHeadingAnchorLink ( elem ) {
0 commit comments