Skip to content

Commit effbbc4

Browse files
committed
Adding configurable styles, key for images, and visibility of captions
1 parent 33898bd commit effbbc4

File tree

6 files changed

+131
-35
lines changed

6 files changed

+131
-35
lines changed

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ function App() {
8888
- `alt`: (**Required**) The image's [alternative text](https://webaim.org/techniques/alttext).
8989
- `caption`: (**Optional**) The [image's description](https://www.studysmarter.co.uk/explanations/english/blog/image-caption).
9090
- `src`: (**Required**) The image's [URL](https://codesweetly.com/web-address-url).
91+
- `key`: (**Optional**) The [key](https://react.dev/learn/rendering-lists) for the button wrapping the image.
9192

9293
</td>
9394
</tr>
@@ -133,6 +134,41 @@ function App() {
133134

134135
</td>
135136
</tr>
137+
<tr>
138+
<td>
139+
140+
`captionVisible`
141+
142+
</td>
143+
<td>boolean</td>
144+
<td><code>false</code></td>
145+
<td>
146+
147+
(**Optional**) Wether to permanently show image captions, or have them
148+
ease in.
149+
150+
</td>
151+
</tr>
152+
<tr>
153+
<td>
154+
155+
`styles`
156+
157+
</td>
158+
<td>ImageGalleryStylesType</td>
159+
<td><code>undefined</code></td>
160+
<td>
161+
162+
(**Optional**) Styles to override default styles with (can optionally include
163+
any of: `galleryContainerStyle`, `imageBtnStyle`, `imageContainerStyle`,
164+
`imageStyle`, `imageCaptionStyle`, `modalContainerStyle`,
165+
`modalSlideNumberStyle`, `modalToolbarStyle`, `modalToolbarBtnStyle`,
166+
`modalSlideShowSectionStyle`, `modalImageStyle`, `modalSlideBtnStyle`.)
167+
168+
169+
</td>
170+
</tr>
171+
136172
</tbody>
137173
</table>
138174

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"build:esm": "tsc",
1414
"build:cjs": "tsc --module commonjs --outDir dist/cjs",
1515
"release": "dotenv release-it --",
16-
"test": "jest --config jest.config.ts"
16+
"test": "jest --config jest.config.ts",
17+
"watch": "tsc --watch"
1718
},
1819
"files": [
1920
"./dist"

src/ImageGallery.test.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,28 @@ const imagesArray = [
6666
},
6767
];
6868

69+
const imagesWithKeyArray = [
70+
{
71+
alt: "Image1's alt text",
72+
caption: "Image1's description",
73+
src: "https://cdn.pixabay.com/photo/2023/05/25/22/07/river-8018379_1280.jpg",
74+
key: "image_1"
75+
},
76+
{
77+
alt: "Image2's alt text",
78+
caption: "Image2's description",
79+
src: "https://cdn.pixabay.com/photo/2023/05/21/11/45/flowers-8008392_1280.jpg",
80+
key: "image_2"
81+
},
82+
{
83+
alt: "Image3's alt text",
84+
caption: "Image3's description",
85+
src: "https://cdn.pixabay.com/photo/2020/09/14/15/10/birch-tree-5571242_1280.png",
86+
key: "image_3"
87+
}
88+
];
89+
90+
6991
test("image gallery renders correctly", () => {
7092
render(
7193
<ImageGallery
@@ -76,3 +98,21 @@ test("image gallery renders correctly", () => {
7698
/>
7799
);
78100
});
101+
102+
test("image gallery renders correctly with styles and visible captions", () => {
103+
const imageContainerStyle: React.CSSProperties = {
104+
margin: `0 0 0`,
105+
position: "relative",
106+
};
107+
108+
render(
109+
<ImageGallery
110+
imagesInfoArray={imagesWithKeyArray}
111+
columnCount={1}
112+
columnWidth={300}
113+
gapSize={2}
114+
styles={ { imageContainerStyle } }
115+
captionVisible={true}
116+
/>
117+
);
118+
});

src/ImageGallery.tsx

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,37 @@
11
import React, { ReactElement, useRef, useState, useEffect } from "react";
2-
import { ImageGalleryPropsType } from "./ImageGallery.types";
3-
import { imageGalleryStyles } from "./imageGalleryStyles";
2+
import { ImageGalleryImageType, ImageGalleryPropsType } from "./ImageGallery.types";
3+
import { imageGalleryStyles } from "./ImageGalleryStyles";
4+
5+
export type { ImageGalleryImageType };
46

57
export function ImageGallery({
68
imagesInfoArray,
79
columnCount = "auto",
810
columnWidth = 230,
911
gapSize = 24,
12+
captionVisible = false,
13+
styles = undefined
1014
}: ImageGalleryPropsType) {
1115
const [imageSrc, setImageSrc] = useState("");
1216
const [slideNumber, setSlideNumber] = useState(1);
1317
const [showModalControls, setShowModalControls] = useState(false);
1418
const [fullscreen, setFullscreen] = useState(false);
1519
const dialogRef = useRef<HTMLDialogElement | null>(null);
1620
const lightboxRef = useRef<HTMLElement | null>(null);
17-
18-
const galleryContainerStyle = imageGalleryStyles(
19-
columnCount,
20-
columnWidth,
21-
gapSize
22-
).galleryContainerStyle;
23-
const imageBtnStyle = imageGalleryStyles().imageBtnStyle;
24-
const imageContainerStyle = imageGalleryStyles(
25-
undefined,
26-
undefined,
27-
gapSize
28-
).imageContainerStyle;
29-
const imageStyle = imageGalleryStyles().imageStyle;
30-
const imageCaptionStyle = imageGalleryStyles().imageCaptionStyle;
31-
const modalContainerStyle = imageGalleryStyles().modalContainerStyle;
32-
const modalSlideNumberStyle = imageGalleryStyles().modalSlideNumberStyle;
33-
const modalToolbarStyle = imageGalleryStyles().modalToolbarStyle;
34-
const modalToolbarBtnStyle = imageGalleryStyles().modalToolbarBtnStyle;
35-
const modalSlideShowSectionStyle =
36-
imageGalleryStyles().modalSlideShowSectionStyle;
37-
const modalImageStyle = imageGalleryStyles().modalImageStyle;
38-
const modalSlideBtnStyle = imageGalleryStyles().modalSlideBtnStyle;
21+
const defaultStyles = imageGalleryStyles(columnCount, columnWidth, gapSize, captionVisible);
22+
const galleryStyles = { ...defaultStyles, ...styles };
23+
const galleryContainerStyle = galleryStyles.galleryContainerStyle;
24+
const imageContainerStyle = galleryStyles.imageContainerStyle;
25+
const imageBtnStyle = galleryStyles.imageBtnStyle;
26+
const imageStyle = galleryStyles.imageStyle;
27+
const imageCaptionStyle = galleryStyles.imageCaptionStyle;
28+
const modalContainerStyle = galleryStyles.modalContainerStyle;
29+
const modalSlideNumberStyle = galleryStyles.modalSlideNumberStyle;
30+
const modalToolbarStyle = galleryStyles.modalToolbarStyle;
31+
const modalToolbarBtnStyle = galleryStyles.modalToolbarBtnStyle;
32+
const modalSlideShowSectionStyle = galleryStyles.modalSlideShowSectionStyle;
33+
const modalImageStyle = galleryStyles.modalImageStyle;
34+
const modalSlideBtnStyle = galleryStyles.modalSlideBtnStyle;
3935

4036
function handleImageContainerMouseEnter(
4137
e: React.MouseEvent<HTMLElement, MouseEvent>
@@ -129,15 +125,15 @@ export function ImageGallery({
129125
<button
130126
type="button"
131127
style={imageBtnStyle}
132-
key={crypto.randomUUID()}
128+
key={item.key ?? crypto.randomUUID()}
133129
onKeyDown={(e) =>
134130
e.key === "Enter" && openLightboxOnSlide(item.src, index + 1)
135131
}
136132
>
137133
<figure
138134
style={imageContainerStyle}
139-
onMouseEnter={(e) => handleImageContainerMouseEnter(e)}
140-
onMouseLeave={(e) => handleImageContainerMouseLeave(e)}
135+
onMouseEnter={(e) => !captionVisible ? handleImageContainerMouseEnter(e) : undefined}
136+
onMouseLeave={(e) => !captionVisible ? handleImageContainerMouseLeave(e) : undefined}
141137
>
142138
<img
143139
alt={item.alt}

src/ImageGallery.types.tsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,30 @@
1-
export interface ImageGalleryPropsType {
2-
imagesInfoArray: Array<{
1+
export interface ImageGalleryStylesType {
2+
galleryContainerStyle?: React.CSSProperties;
3+
imageBtnStyle?: React.CSSProperties;
4+
imageContainerStyle?: React.CSSProperties;
5+
imageStyle?: React.CSSProperties;
6+
imageCaptionStyle?: React.CSSProperties;
7+
modalContainerStyle?: React.CSSProperties;
8+
modalSlideNumberStyle?: React.CSSProperties;
9+
modalToolbarStyle?: React.CSSProperties;
10+
modalToolbarBtnStyle?: React.CSSProperties;
11+
modalSlideShowSectionStyle?: React.CSSProperties;
12+
modalImageStyle?: React.CSSProperties;
13+
modalSlideBtnStyle?: React.CSSProperties;
14+
}
15+
16+
export interface ImageGalleryImageType {
317
alt: string;
418
caption?: string;
519
src: string;
6-
}>;
20+
key?: string;
21+
}
22+
23+
export interface ImageGalleryPropsType {
24+
imagesInfoArray: ImageGalleryImageType[];
725
columnCount?: string | number;
826
columnWidth?: string | number;
927
gapSize?: number;
28+
styles?: ImageGalleryStylesType;
29+
captionVisible?: boolean;
1030
}

src/ImageGalleryStyles.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import { ImageGalleryStylesType } from "./ImageGallery.types";
2+
13
export function imageGalleryStyles(
24
columnCount?: string | number,
35
columnWidth?: string | number,
4-
gapSize?: number
5-
) {
6+
gapSize?: number,
7+
captionVisible?: boolean
8+
) : ImageGalleryStylesType {
69
const galleryContainerStyle: React.CSSProperties = {
710
columnCount,
811
columnWidth: `${columnWidth}px`,
@@ -24,8 +27,8 @@ export function imageGalleryStyles(
2427
cursor: "pointer",
2528
};
2629
const imageCaptionStyle: React.CSSProperties = {
27-
opacity: 0,
28-
transition: "opacity 1s ease-in-out",
30+
opacity: captionVisible ? 1 : 0,
31+
transition: captionVisible ? undefined : "opacity 1s ease-in-out",
2932
position: "absolute",
3033
bottom: 0,
3134
zIndex: "1000",

0 commit comments

Comments
 (0)