From 9fd3eaed3df9502e16797cbb2c6f814085c6d6b1 Mon Sep 17 00:00:00 2001 From: Brad Simpson Date: Thu, 4 Jun 2026 13:56:34 -0600 Subject: [PATCH 1/2] Fix: add aria-label to iframe for screen readers (fixes #55) --- js/adapt-vimeo.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/js/adapt-vimeo.js b/js/adapt-vimeo.js index 81202fb..0b2140e 100644 --- a/js/adapt-vimeo.js +++ b/js/adapt-vimeo.js @@ -28,7 +28,25 @@ class Vimeo extends ComponentView { setupPlayer() { this.vimeoView = this.addSubview(VimeoView, this.model.get('_media')); - this.listenToOnce(this.vimeoView, 'ready', this.setReadyStatus); + this.listenToOnce(this.vimeoView, 'ready', this.onVimeoViewReady); + } + + onVimeoViewReady() { + this.setIframeAriaLabel(); + this.setReadyStatus(); + } + + /** + * Give the player iframe an author-controlled, localisable accessible name. + * The Vimeo library otherwise only sets a `title` from the video's own + * Vimeo title, which authors cannot control or localise. + */ + setIframeAriaLabel() { + const ariaLabel = this.model.get('displayTitle') || this.model.get('title'); + if (!ariaLabel) return; + const iframe = this.vimeoView.player?.element; + if (!iframe) return; + iframe.setAttribute('aria-label', ariaLabel); } setupEventListeners() { From 88872c50838f4bad8f2545e821bcf4beec166cc4 Mon Sep 17 00:00:00 2001 From: Brad Simpson Date: Fri, 17 Jul 2026 11:01:37 -0600 Subject: [PATCH 2/2] Fix: reference visible title heading via aria-labelledby (#55) When displayTitle is set the player iframe now references the visible component heading (#{_id}-heading) with aria-labelledby instead of duplicating the string in aria-label. Falls back to aria-label with the non-visible title field when displayTitle is empty. Aligns with adapt-youtube#48. Co-Authored-By: Claude Opus 4.8 (1M context) --- js/adapt-vimeo.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/js/adapt-vimeo.js b/js/adapt-vimeo.js index 0b2140e..df37555 100644 --- a/js/adapt-vimeo.js +++ b/js/adapt-vimeo.js @@ -32,7 +32,7 @@ class Vimeo extends ComponentView { } onVimeoViewReady() { - this.setIframeAriaLabel(); + this.setIframeAccessibleName(); this.setReadyStatus(); } @@ -40,13 +40,21 @@ class Vimeo extends ComponentView { * Give the player iframe an author-controlled, localisable accessible name. * The Vimeo library otherwise only sets a `title` from the video's own * Vimeo title, which authors cannot control or localise. + * + * When a displayTitle is set it renders as a visible component heading, so + * the iframe references that heading via aria-labelledby rather than + * duplicating the string. Otherwise the non-visible title field is used + * directly as an aria-label. Mirrors adapt-youtube#48. */ - setIframeAriaLabel() { - const ariaLabel = this.model.get('displayTitle') || this.model.get('title'); - if (!ariaLabel) return; + setIframeAccessibleName() { const iframe = this.vimeoView.player?.element; if (!iframe) return; - iframe.setAttribute('aria-label', ariaLabel); + if (this.model.get('displayTitle')) { + iframe.setAttribute('aria-labelledby', `${this.model.get('_id')}-heading`); + return; + } + const title = this.model.get('title'); + if (title) iframe.setAttribute('aria-label', title); } setupEventListeners() {