Skip to content

Commit

Permalink
add sizeBasedOn prop to Image
Browse files Browse the repository at this point in the history
  • Loading branch information
jackiequach committed Nov 21, 2023
1 parent b7ebd52 commit 7cd5a61
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 103 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Currently, this repo is in Prerelease. When it is released, this project will ad

## Prerelease

### Adds

- Adds the `sizeBasedOn` prop to the `Image` component.

## 2.1.2 (November 9, 2023)

### Adds
Expand Down
21 changes: 16 additions & 5 deletions src/components/Image/Image.mdx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { ArgTypes, Canvas, Description, Meta, Source } from "@storybook/blocks";

import { changelogData } from "./imageChangelogData";
import ComponentChangelogTable from "../../utils/ComponentChangelogTable";
import * as ImageStories from "./Image.stories";
import Link from "../Link/Link";

<Meta of={ImageStories} />

# Image

| Component Version | DS Version |
| ----------------- | ---------- |
| Added | `0.0.6` |
| Latest | `2.0.0` |
| Component Version | DS Version |
| ----------------- | ------------ |
| Added | `0.0.6` |
| Latest | `Prerelease` |

## Table of Contents

Expand All @@ -23,6 +24,7 @@ import Link from "../Link/Link";
- {<Link href="#types" target="_self">Types</Link>}
- {<Link href="#html-attributes" target="_self">HTML Attributes</Link>}
- {<Link href="#lazy-loading" target="_self">Lazy Loading</Link>}
- {<Link href="#changelog" target="_self">Changelog</Link>}

## Overview

Expand Down Expand Up @@ -62,7 +64,12 @@ then an `img` element will be rendered with or without wrapper style divs.

Use the `size` prop to set the desired size with the `ImageSizes` enum.

In addition, the `sizeBasedOn` prop can be passed to determine whether the size
of the `Image` is updated based on either the `"height"` or `"width"`. By default,
the `sizeBasedOn` prop is set to `"width"`.

<Canvas of={ImageStories.Sizes} />
<Canvas of={ImageStories.SizesBasedOnHeight} />

## Aspect Ratios

Expand Down Expand Up @@ -130,3 +137,7 @@ Resources:
- [Browser-level image lazy-loading for the web](https://web.dev/browser-level-image-lazy-loading/)

<Canvas of={ImageStories.LazyLoading} />

## Changelog

<ComponentChangelogTable changelogData={changelogData} />
137 changes: 65 additions & 72 deletions src/components/Image/Image.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { withDesign } from "storybook-addon-designs";
import Heading from "../Heading/Heading";
import Image, {
imageRatiosArray,
imageSizeBasedOnArray,
imageSizesArray,
imageTypesArray,
} from "./Image";
Expand Down Expand Up @@ -43,6 +44,11 @@ const meta: Meta<typeof Image> = {
options: imageSizesArray,
table: { defaultValue: { summary: "default" } },
},
sizeBasedOn: {
control: { type: "radio" },
options: imageSizeBasedOnArray,
table: { defaultValue: { summary: "width" } },
},
src: {
description:
"The src attribute is required, and contains the path to the image you want to embed.",
Expand All @@ -53,6 +59,60 @@ const meta: Meta<typeof Image> = {
export default meta;
type Story = StoryObj<typeof Image>;

const imageRow = (opts: any = {}) => {
// We'll use this setup function to render all the images in a list item.
// Some images display better with a dark background.
const styles: any = { textAlign: "center" };
const { size = "large", displayValue, sizeBasedOn = "width", id } = opts;

return (
<Box style={styles} key={id}>
<Heading id={id} level="h4" size="heading6" text={size} />
<Image
alt="Alt text"
caption={displayValue}
size={size}
sizeBasedOn={sizeBasedOn}
src="//placekitten.com/400/300"
/>
</Box>
);
};

const allVStack = (items) => {
return <VStack spacing="l">{items}</VStack>;
};

const imageSizeValues = [
{ size: "xxxsmall", display: "32px", id: "ExtraExtraExtraSmall" },
{ size: "xxsmall", display: "64px", id: "ExtraExtraSmall" },
{ size: "xsmall", display: "96px", id: "ExtraSmall" },
{ size: "small", display: "165px", id: "Small" },
{ size: "medium", display: "225px", id: "Medium" },
{ size: "large", display: "360px", id: "Large" },
{ size: "default", display: "100%", id: "Default" },
];

const sizes = [];
const sizesBasedOnHeight = [];

for (const imageValue of imageSizeValues) {
sizes.push(
imageRow({
size: imageValue.size,
displayValue: imageValue.display,
id: imageValue.id,
})
);
sizesBasedOnHeight.push(
imageRow({
size: imageValue.size,
displayValue: imageValue.display,
id: imageValue.id,
sizeBasedOn: "height",
})
);
}
/**
* Main Story for the Image component. This must contains the `args`
* and `parameters` properties in this object.
Expand All @@ -70,6 +130,7 @@ export const WithControls: Story = {
credit: "Image credit",
imageType: "default",
size: "medium",
sizeBasedOn: "width",
src: "//placekitten.com/400/300",
},
render: (args) => <Image {...args} />,
Expand Down Expand Up @@ -105,78 +166,10 @@ export const FigureAndFigcaption: Story = {
render: (args) => <Image {...args} />,
};
export const Sizes: Story = {
render: () => (
<VStack spacing="l">
<Box textAlign="center">
<Heading
id="ExtraExtraExtraSmall"
level="h4"
size="heading6"
text="xxxsmall"
/>
<Image
alt="Alt text"
caption="32px"
size="xxxsmall"
src="//placekitten.com/400/300"
/>
</Box>
<Box textAlign="center">
<Heading
id="ExtraExtraSmall"
level="h4"
size="heading6"
text="xxsmall"
/>
<Image
alt="Alt text"
caption="64px"
size="xxsmall"
src="//placekitten.com/400/300"
/>
</Box>
<Box textAlign="center">
<Heading id="ExtraSmall" level="h4" size="heading6" text="xsmall" />
<Image
alt="Alt text"
caption="96px"
size="xsmall"
src="//placekitten.com/400/300"
/>
</Box>
<Box textAlign="center">
<Heading id="Small" level="h4" size="heading6" text="small" />
<Image
alt="Alt text"
caption="165px"
size="small"
src="//placekitten.com/400/300"
/>
</Box>
<Box textAlign="center">
<Heading id="Medium" level="h4" size="heading6" text="medium" />
<Image
alt="Alt text"
caption="225px"
size="medium"
src="//placekitten.com/400/300"
/>
</Box>
<Box textAlign="center">
<Heading id="Large" level="h4" size="heading6" text="large" />
<Image
alt="Alt text"
caption="360px"
size="large"
src="//placekitten.com/400/300"
/>
</Box>
<Box textAlign="center" width="100%">
<Heading id="Default" level="h4" size="heading6" text="default" />
<Image alt="Alt text" caption="100%" src="//placekitten.com/400/300" />
</Box>
</VStack>
),
render: () => allVStack(sizes),
};
export const SizesBasedOnHeight: Story = {
render: () => allVStack(sizesBasedOnHeight),
};

const imageBlockStyles = {
Expand Down
10 changes: 10 additions & 0 deletions src/components/Image/Image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ export const imageSizesArray = [
"large",
] as const;
export const imageTypesArray = ["default", "circle"] as const;
export const imageSizeBasedOnArray = ["height", "width"] as const;
export type ImageRatios = typeof imageRatiosArray[number];
export type ImageSizes = typeof imageSizesArray[number];
export type ImageTypes = typeof imageTypesArray[number];
export type ImageSizeBasedOn = typeof imageSizeBasedOnArray[number];

// Used for components that have an `imageProps` prop.
export interface ComponentImageProps extends Partial<HTMLImageElement> {
Expand Down Expand Up @@ -67,6 +69,8 @@ interface ImageWrapperProps {
aspectRatio?: ImageRatios;
/** Optional value to control the size of the image */
size?: ImageSizes;
/** Sets the image size based on the width or height. Width by default. */
sizeBasedOn?: ImageSizeBasedOn;
}

export interface ImageProps
Expand Down Expand Up @@ -100,11 +104,13 @@ const ImageWrapper = chakra(
children,
aspectRatio = "original",
size = "default",
sizeBasedOn = "width",
...rest
} = props;
const styles = useMultiStyleConfig("CustomImageWrapper", {
ratio: aspectRatio,
size,
sizeBasedOn,
});
return (
<Box
Expand Down Expand Up @@ -135,6 +141,7 @@ export const Image = chakra(
imageType = "default",
isLazy = false,
size = "default",
sizeBasedOn = "width",
src,
...rest
} = props;
Expand All @@ -149,7 +156,9 @@ export const Image = chakra(
const useImageWrapper = aspectRatio !== "original";
const styles = useMultiStyleConfig("CustomImage", {
variant: imageType,
ratio: aspectRatio,
size,
sizeBasedOn,
});
let imageComponent: JSX.Element | null = null;
let lazyRef = undefined;
Expand Down Expand Up @@ -196,6 +205,7 @@ export const Image = chakra(
aspectRatio={aspectRatio}
className={className}
size={size}
sizeBasedOn={sizeBasedOn}
{...(caption || credit ? {} : rest)}
>
{imageComponent}
Expand Down
19 changes: 19 additions & 0 deletions src/components/Image/imageChangelogData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/** This data is used to populate the ComponentChangelogTable component.
*
* date: string (when adding new entry during development, set value as "Prerelease")
* version: string (when adding new entry during development, set value as "Prerelease")
* type: "Bug Fix" | "New Feature" | "Update";
* affects: array["Accessibility" | "Documentation" | "Functionality" | "Styles"];
* notes: array (will render as a bulleted list, add one array element for each list element)
*/
import { ChangelogData } from "../../utils/ComponentChangelogTable";

export const changelogData: ChangelogData[] = [
{
date: "2023-11-09",
version: "2.1.2",
type: "Update",
affects: ["Documentation", "Functionality", "Styles"],
notes: ["Adds `sizeBasedOn` prop to the `Logo` component."],
},
];
Loading

0 comments on commit 7cd5a61

Please sign in to comment.