Fix: Ensure carousel focuses on wrapper (#36649)

pull/36650/head
Echo 5 days ago committed by GitHub
parent f3d9a4ed44
commit 28cb345131
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -90,9 +90,8 @@ export const Carousel = <
const slide = wrapperRef.current?.children[newIndex]; const slide = wrapperRef.current?.children[newIndex];
if (slide) { if (slide) {
setCurrentSlideHeight(slide.scrollHeight); setCurrentSlideHeight(slide.scrollHeight);
onChangeSlide?.(newIndex, slide);
if (slide instanceof HTMLElement) { if (slide instanceof HTMLElement) {
slide.focus({ preventScroll: true }); onChangeSlide?.(newIndex, slide);
} }
} }
@ -134,9 +133,13 @@ export const Carousel = <
); );
const handlePrev = useCallback(() => { const handlePrev = useCallback(() => {
handleSlideChange(-1); handleSlideChange(-1);
// We're focusing on the wrapper as the child slides can potentially be inert.
// Because of that, only the active slide can be focused anyway.
wrapperRef.current?.focus();
}, [handleSlideChange]); }, [handleSlideChange]);
const handleNext = useCallback(() => { const handleNext = useCallback(() => {
handleSlideChange(1); handleSlideChange(1);
wrapperRef.current?.focus();
}, [handleSlideChange]); }, [handleSlideChange]);
const intl = useIntl(); const intl = useIntl();
@ -172,6 +175,11 @@ export const Carousel = <
className={`${classNamePrefix}__slides`} className={`${classNamePrefix}__slides`}
ref={wrapperRef} ref={wrapperRef}
style={wrapperStyles} style={wrapperStyles}
aria-label={intl.formatMessage(messages.slide, {
current: slideIndex + 1,
max: items.length,
})}
tabIndex={-1}
> >
{items.map((itemsProps, index) => ( {items.map((itemsProps, index) => (
<CarouselSlideWrapper<SlideProps> <CarouselSlideWrapper<SlideProps>
@ -184,10 +192,6 @@ export const Carousel = <
active: index === slideIndex, active: index === slideIndex,
})} })}
active={index === slideIndex} active={index === slideIndex}
label={intl.formatMessage(messages.slide, {
current: index + 1,
max: items.length,
})}
/> />
))} ))}
</animated.div> </animated.div>
@ -201,7 +205,6 @@ type CarouselSlideWrapperProps<SlideProps extends CarouselSlideProps> = {
active: boolean; active: boolean;
item: SlideProps; item: SlideProps;
index: number; index: number;
label: string;
} & Pick<CarouselProps<SlideProps>, 'renderItem'>; } & Pick<CarouselProps<SlideProps>, 'renderItem'>;
const CarouselSlideWrapper = <SlideProps extends CarouselSlideProps>({ const CarouselSlideWrapper = <SlideProps extends CarouselSlideProps>({
@ -211,7 +214,6 @@ const CarouselSlideWrapper = <SlideProps extends CarouselSlideProps>({
renderItem, renderItem,
item, item,
index, index,
label,
}: CarouselSlideWrapperProps<SlideProps>) => { }: CarouselSlideWrapperProps<SlideProps>) => {
const handleRef = useCallback( const handleRef = useCallback(
(instance: HTMLDivElement | null) => { (instance: HTMLDivElement | null) => {
@ -233,9 +235,7 @@ const CarouselSlideWrapper = <SlideProps extends CarouselSlideProps>({
className={className} className={className}
role='group' role='group'
aria-roledescription='slide' aria-roledescription='slide'
aria-label={label}
inert={active ? undefined : ''} inert={active ? undefined : ''}
tabIndex={-1}
data-index={index} data-index={index}
> >
{children} {children}

Loading…
Cancel
Save