Skip to content

Commit

Permalink
Adding configurable styles, key for images, and visibility of captions
Browse files Browse the repository at this point in the history
  • Loading branch information
mariano committed Oct 3, 2024
1 parent 33898bd commit effbbc4
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 35 deletions.
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ function App() {
- `alt`: (**Required**) The image's [alternative text](https://webaim.org/techniques/alttext).
- `caption`: (**Optional**) The [image's description](https://www.studysmarter.co.uk/explanations/english/blog/image-caption).
- `src`: (**Required**) The image's [URL](https://codesweetly.com/web-address-url).
- `key`: (**Optional**) The [key](https://react.dev/learn/rendering-lists) for the button wrapping the image.

</td>
</tr>
Expand Down Expand Up @@ -133,6 +134,41 @@ function App() {

</td>
</tr>
<tr>
<td>

`captionVisible`

</td>
<td>boolean</td>
<td><code>false</code></td>
<td>

(**Optional**) Wether to permanently show image captions, or have them
ease in.

</td>
</tr>
<tr>
<td>

`styles`

</td>
<td>ImageGalleryStylesType</td>
<td><code>undefined</code></td>
<td>

(**Optional**) Styles to override default styles with (can optionally include
any of: `galleryContainerStyle`, `imageBtnStyle`, `imageContainerStyle`,
`imageStyle`, `imageCaptionStyle`, `modalContainerStyle`,
`modalSlideNumberStyle`, `modalToolbarStyle`, `modalToolbarBtnStyle`,
`modalSlideShowSectionStyle`, `modalImageStyle`, `modalSlideBtnStyle`.)


</td>
</tr>

</tbody>
</table>

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"build:esm": "tsc",
"build:cjs": "tsc --module commonjs --outDir dist/cjs",
"release": "dotenv release-it --",
"test": "jest --config jest.config.ts"
"test": "jest --config jest.config.ts",
"watch": "tsc --watch"
},
"files": [
"./dist"
Expand Down
40 changes: 40 additions & 0 deletions src/ImageGallery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,28 @@ const imagesArray = [
},
];

const imagesWithKeyArray = [
{
alt: "Image1's alt text",
caption: "Image1's description",
src: "https://cdn.pixabay.com/photo/2023/05/25/22/07/river-8018379_1280.jpg",
key: "image_1"
},
{
alt: "Image2's alt text",
caption: "Image2's description",
src: "https://cdn.pixabay.com/photo/2023/05/21/11/45/flowers-8008392_1280.jpg",
key: "image_2"
},
{
alt: "Image3's alt text",
caption: "Image3's description",
src: "https://cdn.pixabay.com/photo/2020/09/14/15/10/birch-tree-5571242_1280.png",
key: "image_3"
}
];


test("image gallery renders correctly", () => {
render(
<ImageGallery
Expand All @@ -76,3 +98,21 @@ test("image gallery renders correctly", () => {
/>
);
});

test("image gallery renders correctly with styles and visible captions", () => {
const imageContainerStyle: React.CSSProperties = {
margin: `0 0 0`,
position: "relative",
};

render(
<ImageGallery
imagesInfoArray={imagesWithKeyArray}
columnCount={1}
columnWidth={300}
gapSize={2}
styles={ { imageContainerStyle } }
captionVisible={true}
/>
);
});
50 changes: 23 additions & 27 deletions src/ImageGallery.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,37 @@
import React, { ReactElement, useRef, useState, useEffect } from "react";
import { ImageGalleryPropsType } from "./ImageGallery.types";
import { imageGalleryStyles } from "./imageGalleryStyles";
import { ImageGalleryImageType, ImageGalleryPropsType } from "./ImageGallery.types";
import { imageGalleryStyles } from "./ImageGalleryStyles";

export type { ImageGalleryImageType };

export function ImageGallery({
imagesInfoArray,
columnCount = "auto",
columnWidth = 230,
gapSize = 24,
captionVisible = false,
styles = undefined
}: ImageGalleryPropsType) {
const [imageSrc, setImageSrc] = useState("");
const [slideNumber, setSlideNumber] = useState(1);
const [showModalControls, setShowModalControls] = useState(false);
const [fullscreen, setFullscreen] = useState(false);
const dialogRef = useRef<HTMLDialogElement | null>(null);
const lightboxRef = useRef<HTMLElement | null>(null);

const galleryContainerStyle = imageGalleryStyles(
columnCount,
columnWidth,
gapSize
).galleryContainerStyle;
const imageBtnStyle = imageGalleryStyles().imageBtnStyle;
const imageContainerStyle = imageGalleryStyles(
undefined,
undefined,
gapSize
).imageContainerStyle;
const imageStyle = imageGalleryStyles().imageStyle;
const imageCaptionStyle = imageGalleryStyles().imageCaptionStyle;
const modalContainerStyle = imageGalleryStyles().modalContainerStyle;
const modalSlideNumberStyle = imageGalleryStyles().modalSlideNumberStyle;
const modalToolbarStyle = imageGalleryStyles().modalToolbarStyle;
const modalToolbarBtnStyle = imageGalleryStyles().modalToolbarBtnStyle;
const modalSlideShowSectionStyle =
imageGalleryStyles().modalSlideShowSectionStyle;
const modalImageStyle = imageGalleryStyles().modalImageStyle;
const modalSlideBtnStyle = imageGalleryStyles().modalSlideBtnStyle;
const defaultStyles = imageGalleryStyles(columnCount, columnWidth, gapSize, captionVisible);
const galleryStyles = { ...defaultStyles, ...styles };
const galleryContainerStyle = galleryStyles.galleryContainerStyle;
const imageContainerStyle = galleryStyles.imageContainerStyle;
const imageBtnStyle = galleryStyles.imageBtnStyle;
const imageStyle = galleryStyles.imageStyle;
const imageCaptionStyle = galleryStyles.imageCaptionStyle;
const modalContainerStyle = galleryStyles.modalContainerStyle;
const modalSlideNumberStyle = galleryStyles.modalSlideNumberStyle;
const modalToolbarStyle = galleryStyles.modalToolbarStyle;
const modalToolbarBtnStyle = galleryStyles.modalToolbarBtnStyle;
const modalSlideShowSectionStyle = galleryStyles.modalSlideShowSectionStyle;
const modalImageStyle = galleryStyles.modalImageStyle;
const modalSlideBtnStyle = galleryStyles.modalSlideBtnStyle;

function handleImageContainerMouseEnter(
e: React.MouseEvent<HTMLElement, MouseEvent>
Expand Down Expand Up @@ -129,15 +125,15 @@ export function ImageGallery({
<button
type="button"
style={imageBtnStyle}
key={crypto.randomUUID()}
key={item.key ?? crypto.randomUUID()}
onKeyDown={(e) =>
e.key === "Enter" && openLightboxOnSlide(item.src, index + 1)
}
>
<figure
style={imageContainerStyle}
onMouseEnter={(e) => handleImageContainerMouseEnter(e)}
onMouseLeave={(e) => handleImageContainerMouseLeave(e)}
onMouseEnter={(e) => !captionVisible ? handleImageContainerMouseEnter(e) : undefined}
onMouseLeave={(e) => !captionVisible ? handleImageContainerMouseLeave(e) : undefined}
>
<img
alt={item.alt}
Expand Down
26 changes: 23 additions & 3 deletions src/ImageGallery.types.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
export interface ImageGalleryPropsType {
imagesInfoArray: Array<{
export interface ImageGalleryStylesType {
galleryContainerStyle?: React.CSSProperties;
imageBtnStyle?: React.CSSProperties;
imageContainerStyle?: React.CSSProperties;
imageStyle?: React.CSSProperties;
imageCaptionStyle?: React.CSSProperties;
modalContainerStyle?: React.CSSProperties;
modalSlideNumberStyle?: React.CSSProperties;
modalToolbarStyle?: React.CSSProperties;
modalToolbarBtnStyle?: React.CSSProperties;
modalSlideShowSectionStyle?: React.CSSProperties;
modalImageStyle?: React.CSSProperties;
modalSlideBtnStyle?: React.CSSProperties;
}

export interface ImageGalleryImageType {
alt: string;
caption?: string;
src: string;
}>;
key?: string;
}

export interface ImageGalleryPropsType {
imagesInfoArray: ImageGalleryImageType[];
columnCount?: string | number;
columnWidth?: string | number;
gapSize?: number;
styles?: ImageGalleryStylesType;
captionVisible?: boolean;
}
11 changes: 7 additions & 4 deletions src/ImageGalleryStyles.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { ImageGalleryStylesType } from "./ImageGallery.types";

export function imageGalleryStyles(
columnCount?: string | number,
columnWidth?: string | number,
gapSize?: number
) {
gapSize?: number,
captionVisible?: boolean
) : ImageGalleryStylesType {
const galleryContainerStyle: React.CSSProperties = {
columnCount,
columnWidth: `${columnWidth}px`,
Expand All @@ -24,8 +27,8 @@ export function imageGalleryStyles(
cursor: "pointer",
};
const imageCaptionStyle: React.CSSProperties = {
opacity: 0,
transition: "opacity 1s ease-in-out",
opacity: captionVisible ? 1 : 0,
transition: captionVisible ? undefined : "opacity 1s ease-in-out",
position: "absolute",
bottom: 0,
zIndex: "1000",
Expand Down

0 comments on commit effbbc4

Please sign in to comment.