Skip to content

Commit 5ac95a1

Browse files
authored
fix: show image fallbacks in image gallery modal (#2212)
1 parent 38f2363 commit 5ac95a1

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

src/components/Gallery/ModalGallery.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useMemo } from 'react';
2-
import ImageGallery from 'react-image-gallery';
2+
import ImageGallery, { ReactImageGalleryItem } from 'react-image-gallery';
3+
import { BaseImage } from './BaseImage';
34
import { useTranslationContext } from '../../context';
45

56
import type { Attachment } from 'stream-chat';
@@ -14,6 +15,16 @@ export type ModalGalleryProps<
1415
index?: number;
1516
};
1617

18+
const onError: React.ReactEventHandler<HTMLImageElement> = (e) => {
19+
// Prevent having alt attribute on img as the img takes the height of the alt text
20+
// instead of the CSS / element width & height when the CSS mask (fallback) is applied.
21+
(e.target as HTMLImageElement).alt = '';
22+
};
23+
24+
const renderItem = ({ original, originalAlt }: ReactImageGalleryItem) => (
25+
<BaseImage alt={originalAlt} className='image-gallery-image' onError={onError} src={original} />
26+
);
27+
1728
export const ModalGallery = <
1829
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
1930
>(
@@ -38,6 +49,7 @@ export const ModalGallery = <
3849
return (
3950
<ImageGallery
4051
items={formattedArray}
52+
renderItem={renderItem}
4153
showIndex={true}
4254
showPlayButton={false}
4355
showThumbnails={false}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react';
2+
import { act, fireEvent, render, screen } from '@testing-library/react';
3+
import '@testing-library/jest-dom';
4+
5+
import { ModalGallery } from '../ModalGallery';
6+
import { TranslationProvider } from '../../../context';
7+
import { generateImageAttachment } from '../../../mock-builders';
8+
9+
const images = Array.from({ length: 3 }, generateImageAttachment);
10+
11+
const t = (val) => val;
12+
const BASE_IMAGE_TEST_ID = 'str-chat__base-image';
13+
const getImages = () => screen.queryAllByTestId(BASE_IMAGE_TEST_ID);
14+
15+
const renderComponent = (props = {}) =>
16+
render(
17+
<TranslationProvider value={{ t }}>
18+
<ModalGallery {...props} />
19+
</TranslationProvider>,
20+
);
21+
22+
describe('ModalGallery', () => {
23+
it('uses BaseImage component to display images', () => {
24+
const { container } = renderComponent({ images });
25+
expect(container.querySelectorAll('.str-chat__base-image')).toHaveLength(images.length);
26+
});
27+
it('displays image fallback on error', () => {
28+
const { container } = renderComponent({ images });
29+
const imageElements = getImages();
30+
act(() => {
31+
imageElements.forEach((element) => fireEvent.error(element));
32+
});
33+
34+
const fallbacks = container.querySelectorAll('.str-chat__base-image--load-failed');
35+
expect(fallbacks).toHaveLength(images.length);
36+
fallbacks.forEach((fallback) => {
37+
expect(fallback.alt).toBe('');
38+
});
39+
});
40+
});

0 commit comments

Comments
 (0)