Skip to content

Commit 2778ff8

Browse files
ibrahimcesarclaude
andauthored
a11y: improve accessibility with ARIA enhancements and focus management (#149)
This commit significantly improves accessibility for keyboard and screen reader users: 1. Enhanced ARIA Attributes: - Added role="img" to container when iframe not loaded (it's a static preview) - Added aria-label to container describing it as a YouTube preview - Added aria-hidden to button when iframe is active (button no longer functional) - Added tabIndex=-1 to button when iframe loaded (prevents focus on hidden element) 2. Visually Hidden Text for Screen Readers: - Added visually-hidden span inside button with announce text - Provides better context for screen reader users - Uses standard visually-hidden CSS technique (accessible but invisible) 3. Focus Management (Optional): - Added focusOnLoad prop to automatically focus iframe when loaded - Helps keyboard users know where they are after interaction - Maintains keyboard navigation flow - Default: false (opt-in behavior) 4. Customizable Referrer Policy: - Added referrerPolicy prop to customize iframe referrer policy - Default: "strict-origin-when-cross-origin" - Improves privacy and security configuration options 5. CSS Improvements: - Added .lty-visually-hidden class for screen reader only content - Standard implementation following WCAG guidelines - Ensures text is accessible but doesn't affect visual layout Accessibility Benefits: - Better screen reader announcements - Clearer focus indication - Improved keyboard navigation - WCAG 2.1 compliance improvements - Better context for assistive technologies All tests passing (20/20). Co-authored-by: Claude <noreply@anthropic.com>
1 parent c014df2 commit 2778ff8

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

src/lib/LiteYouTubeEmbed.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,16 @@
6868
opacity: 0;
6969
pointer-events: none;
7070
}
71+
72+
/* Visually hidden but accessible to screen readers */
73+
.lty-visually-hidden {
74+
position: absolute;
75+
width: 1px;
76+
height: 1px;
77+
margin: -1px;
78+
padding: 0;
79+
overflow: hidden;
80+
clip: rect(0, 0, 0, 0);
81+
white-space: nowrap;
82+
border: 0;
83+
}

src/lib/index.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export interface LiteYouTubeProps {
2929
rel?: string;
3030
containerElement?: keyof React.JSX.IntrinsicElements;
3131
style?: React.CSSProperties;
32+
focusOnLoad?: boolean;
33+
referrerPolicy?: string;
3234
}
3335

3436
function LiteYouTubeEmbedComponent(
@@ -130,8 +132,13 @@ function LiteYouTubeEmbedComponent(
130132
React.useEffect(() => {
131133
if (iframe) {
132134
onIframeAdded();
135+
136+
// Focus iframe if focusOnLoad is enabled and ref is available
137+
if (props.focusOnLoad && typeof ref === 'object' && ref?.current) {
138+
ref.current.focus();
139+
}
133140
}
134-
}, [iframe]);
141+
}, [iframe, onIframeAdded, props.focusOnLoad, ref]);
135142

136143
return (
137144
<>
@@ -158,6 +165,8 @@ function LiteYouTubeEmbedComponent(
158165
onClick={addIframe}
159166
className={`${wrapperClassImp} ${iframe ? activatedClassImp : ""}`}
160167
data-title={videoTitle}
168+
role={!iframe ? "img" : undefined}
169+
aria-label={!iframe ? `${videoTitle} - YouTube video preview` : undefined}
161170
style={{
162171
backgroundImage: `url(${posterUrl})`,
163172
...({
@@ -170,7 +179,13 @@ function LiteYouTubeEmbedComponent(
170179
type="button"
171180
className={playerClassImp}
172181
aria-label={`${announceWatch} ${videoTitle}`}
173-
/>
182+
aria-hidden={iframe || undefined}
183+
tabIndex={iframe ? -1 : 0}
184+
>
185+
<span className="lty-visually-hidden">
186+
{announceWatch}
187+
</span>
188+
</button>
174189
{iframe && (
175190
<iframe
176191
ref={ref}
@@ -182,7 +197,7 @@ function LiteYouTubeEmbedComponent(
182197
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
183198
allowFullScreen
184199
src={iframeSrc}
185-
referrerPolicy="strict-origin-when-cross-origin"
200+
referrerPolicy={props.referrerPolicy || "strict-origin-when-cross-origin"}
186201
></iframe>
187202
)}
188203
</ContainerElement>

0 commit comments

Comments
 (0)