From ab544228addcd4d5b9481466dd60bad6fd9ab186 Mon Sep 17 00:00:00 2001 From: sowmyagunturi Date: Wed, 10 Sep 2025 12:21:05 +0530 Subject: [PATCH] fix: add role, tabIndex, and aria-label for Preview accessibility --- src/Preview.tsx | 127 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/src/Preview.tsx b/src/Preview.tsx index e5b06c74..bbe95e7b 100644 --- a/src/Preview.tsx +++ b/src/Preview.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +/*import React, { useState, useEffect } from 'react'; import type { PreviewProps } from './types'; @@ -122,3 +122,128 @@ const Preview = ({ }; export default Preview; +*/ + + +import React, { useState, useEffect } from 'react'; +import type { PreviewProps } from './types'; + +const ICON_SIZE = '64px'; +const cache: Record = {}; + +const Preview = ({ + src, + light, + oEmbedUrl, + onClickPreview, + playIcon, + previewTabIndex, + previewAriaLabel, +}: PreviewProps) => { + const [image, setImage] = useState(null); + + useEffect(() => { + if (!src || !light || !oEmbedUrl) return; + fetchImage({ src, light, oEmbedUrl }); + }, [src, light, oEmbedUrl]); + + const fetchImage = async ({ + src, + light, + oEmbedUrl, + }: { + src: string; + light: boolean | string | React.ReactElement; + oEmbedUrl: string; + }) => { + if (React.isValidElement(light)) return; + + if (typeof light === 'string') { + setImage(light); + return; + } + if (cache[src]) { + setImage(cache[src]); + return; + } + setImage(null); + + const response = await fetch(oEmbedUrl.replace('{url}', src)); + const data = await response.json(); + + if (data.thumbnail_url) { + const fetchedImage = data.thumbnail_url + .replace('height=100', 'height=480') + .replace('-d_295x166', '-d_640'); + setImage(fetchedImage); + cache[src] = fetchedImage; + } + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === 'Enter' || e.key === ' ') { + onClickPreview?.(e); + } + }; + + const handleClick = (e: React.MouseEvent) => { + onClickPreview?.(e); + }; + + const isElement = React.isValidElement(light); + + const flexCenter = { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }; + + const styles = { + preview: { + width: '100%', + height: '100%', + backgroundImage: image && !isElement ? `url(${image})` : undefined, + backgroundSize: 'cover', + backgroundPosition: 'center', + cursor: 'pointer', + ...flexCenter, + }, + shadow: { + background: 'radial-gradient(rgb(0, 0, 0, 0.3), rgba(0, 0, 0, 0) 60%)', + borderRadius: ICON_SIZE, + width: ICON_SIZE, + height: ICON_SIZE, + position: isElement ? 'absolute' as const : undefined, + ...flexCenter, + }, + playIcon: { + borderStyle: 'solid', + borderWidth: '16px 0 16px 26px', + borderColor: 'transparent transparent transparent white', + marginLeft: '7px', + }, + }; + + const defaultPlayIcon = ( +
+
+
+ ); + + return ( +
+ {isElement ? light : null} + {playIcon || defaultPlayIcon} +
+ ); +}; + +export default Preview;