Repository: marigold-ui/marigold
Pull request #2328 (2022-08-18 09:22:16)

feat: add `fit` and `potision` props to `<Image>`

changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: a52fd4f8d9057bca632cb0fb95dbf234abca6532

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/master/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/marigold-ui/marigold/new/image-fit-position-props?filename=.changeset/light-windows-shop.md&value=---%0A%22%40marigold%2Fdocs%22%3A%20patch%0A%22%40marigold%2Fcomponents%22%3A%20patch%0A---%0A%0Afeat%3A%20add%20%60fit%60%20and%20%60potision%60%20props%20to%20%60%3CImage%3E%60%0A)



Patch:
diff --git a/.changeset/light-windows-shop.md b/.changeset/light-windows-shop.md
new file mode 100644
index 000000000..1f81e9d32
--- /dev/null
+++ b/.changeset/light-windows-shop.md
@@ -0,0 +1,6 @@
+---
+"@marigold/docs": minor
+"@marigold/components": minor
+---
+
+feat: add `fit` and `potision` props to `<Image>`
diff --git a/docs/content/components/image.mdx b/docs/content/components/image.mdx
index 8c69c27a6..9193c2133 100644
--- a/docs/content/components/image.mdx
+++ b/docs/content/components/image.mdx
@@ -12,9 +12,13 @@ import { Image } from '@marigold/components';
 
 ## Props
 
-| Property             | Type     | Default |
-| :------------------- | :------- | :------ |
-| `variant` (optional) | `string` |         |
+| Property              | Type     | Default |
+| :-------------------- | :------- | :------ |
+| `variant` (optional)  | `string` |         |
+| `size` (optional)     | `string` |         |
+| `alt`                 | `string` |         |
+| `fit` (optional)      | `TODO!`  |         |
+| `position` (optional) | `TODO!`  |         |
 
 ## Usage
 
diff --git a/packages/components/src/Image/Image.stories.tsx b/packages/components/src/Image/Image.stories.tsx
index 09642ae8e..c9eaafd5d 100644
--- a/packages/components/src/Image/Image.stories.tsx
+++ b/packages/components/src/Image/Image.stories.tsx
@@ -9,26 +9,46 @@ export default {
       control: {
         type: 'text',
       },
-      description: 'there is only one variant',
-      table: {
-        defaultValue: {
-          summary: 'fullWidth',
-        },
+      description: 'variant of the image',
+    },
+    size: {
+      control: {
+        type: 'text',
+      },
+      description: 'size of the image',
+    },
+    fit: {
+      control: {
+        type: 'select',
       },
+      options: [
+        '',
+        'contain',
+        'cover',
+        'fill',
+        'none',
+        'scale-down',
+        'inherit',
+        'initial',
+        'revert',
+        'revert-layer',
+        'unset',
+      ],
+      description: 'object fit value',
     },
-    alt: {
+    position: {
       control: {
         type: 'text',
       },
-      description: 'Description text for screenreaders',
+      description: 'object position value',
     },
   },
 } as Meta;
 
 export const Basic: ComponentStory<typeof Image> = args => (
   <Image
+    {...args}
     src="https://www.reservix.net/_Resources/Persistent/0e8f5885125940fdb2bc2d54840f497782f56584/Reservix_Logo_dtp_web_rgb_font_black_180704.png"
     alt="marigold_logo"
-    {...args}
   />
 );
diff --git a/packages/components/src/Image/Image.tsx b/packages/components/src/Image/Image.tsx
index 594d84449..fd77b2e2c 100755
--- a/packages/components/src/Image/Image.tsx
+++ b/packages/components/src/Image/Image.tsx
@@ -1,6 +1,6 @@
 import React from 'react';
 import { ComponentProps } from '@marigold/types';
-import { Box } from '../Box';
+import { Box, CSSObject } from '@marigold/system';
 import { ThemeExtension, useComponentStyles } from '@marigold/system';
 
 // Theme Extension
@@ -12,12 +12,26 @@ export interface ImageThemeExtension extends ThemeExtension<'Image'> {}
 export interface ImageProps extends ComponentProps<'img'> {
   variant?: string;
   size?: string;
+  fit?: CSSObject['objectFit'];
+  position?: CSSObject['objectPosition'];
   children?: never;
+  alt: string;
 }
 
 // Component
 // ---------------
-export const Image = ({ variant, ...props }: ImageProps) => {
-  const styles = useComponentStyles('Image', { variant });
-  return <Box {...props} as="img" css={styles} />;
+export const Image = ({
+  variant,
+  size,
+  fit,
+  position,
+  ...props
+}: ImageProps) => {
+  const styles = useComponentStyles('Image', { variant, size });
+  const css: CSSObject = {
+    ...styles,
+    objectFit: fit,
+    objectPosition: position,
+  };
+  return <Box {...props} as="img" css={css} />;
 };


Test patch:
diff --git a/packages/components/src/Image/Image.test.tsx b/packages/components/src/Image/Image.test.tsx
index c26acb7c5..7145c0850 100644
--- a/packages/components/src/Image/Image.test.tsx
+++ b/packages/components/src/Image/Image.test.tsx
@@ -16,15 +16,35 @@ const theme = {
         fullWidth: {
           alignItems: 'center',
         },
+        cover: {
+          objectFit: 'cover',
+          position: 'center',
+        },
+      },
+      size: {
+        large: {
+          width: 1000,
+        },
       },
     },
   },
 };
 
-test('supports Image variant', () => {
+test('renders correct HTML element', () => {
   render(
     <ThemeProvider theme={theme}>
-      <Image data-testid="images" variant="fullWidth" />
+      <Image data-testid="default" alt="test image" />
+    </ThemeProvider>
+  );
+  const img = screen.getByTestId(/default/);
+
+  expect(img instanceof HTMLImageElement).toBeTruthy();
+});
+
+test('supports variant from theme', () => {
+  render(
+    <ThemeProvider theme={theme}>
+      <Image data-testid="images" variant="fullWidth" alt="test image" />
     </ThemeProvider>
   );
   const img = screen.getByTestId(/images/);
@@ -32,35 +52,60 @@ test('supports Image variant', () => {
   expect(img).toHaveStyle(`align-items: center`);
 });
 
-test('renders correct HTML element', () => {
+test('supports size from theme', () => {
   render(
     <ThemeProvider theme={theme}>
-      <Image data-testid="default" />
+      <Image data-testid="images" size="large" alt="test image" />
     </ThemeProvider>
   );
-  const img = screen.getByTestId(/default/);
+  const img = screen.getByTestId(/images/);
 
-  expect(img instanceof HTMLImageElement).toBeTruthy();
+  expect(img).toHaveStyle(`width: 1000px`);
 });
 
-test('accept alt', () => {
+test('set object fit via prop', () => {
+  render(<Image data-testid="images" alt="test image" fit="cover" />);
+
+  const img = screen.getByTestId(/images/);
+
+  expect(img).toHaveStyle(`object-fit: cover`);
+});
+
+test('set object position via prop', () => {
+  render(
+    <Image data-testid="images" alt="test image" position="left bottom" />
+  );
+
+  const img = screen.getByTestId(/images/);
+
+  expect(img).toHaveStyle(`object-position: left bottom`);
+});
+
+test('setting object position and fit via props overrides theme values', () => {
   render(
     <ThemeProvider theme={theme}>
-      <Image alt="altText" data-testid="default" />
+      <Image
+        data-testid="images"
+        alt="test image"
+        variant="cover"
+        fit="fill"
+        position="bottom"
+      />
     </ThemeProvider>
   );
-  const img = screen.getByTestId(/default/);
+  const img = screen.getByTestId(/images/);
 
-  expect(img.getAttribute('alt')).toEqual('altText');
+  expect(img).toHaveStyle(`object-fit: fill`);
+  expect(img).toHaveStyle(`object-position: bottom`);
 });
 
-test('accepts custom styles prop className', () => {
+test('accept alt', () => {
   render(
     <ThemeProvider theme={theme}>
-      <Image className="custom-class-name" data-testid="image" />
+      <Image alt="altText" data-testid="default" />
     </ThemeProvider>
   );
-  const image = screen.getByTestId(/image/);
+  const img = screen.getByTestId(/default/);
 
-  expect(image.className).toMatch('custom-class-name');
+  expect(img.getAttribute('alt')).toEqual('altText');
 });