Repository: marigold-ui/marigold (ts)

Issue:
Text in full-width button is not centered
## Description

Button with `fullWidth` prop set has its text not centered. Tried on Chrome 104, macOS.

## How to reproduce

```
<Button
    variant="primary"
    size="small"
    fullWidth>
    Einloggen
</Button>
```

<img width="435" alt="Bildschirmfoto 2022-08-18 um 12 50 33" src="https://user-images.githubusercontent.com/531872/185382196-d26aad85-75bd-41b2-bac3-88d009e27eb8.png">



Pull request description:
fix: justify content in `<Button>`
closes #2329

Patch:
diff --git a/.changeset/chilly-needles-move.md b/.changeset/chilly-needles-move.md
new file mode 100644
index 000000000..67d2a6a5b
--- /dev/null
+++ b/.changeset/chilly-needles-move.md
@@ -0,0 +1,5 @@
+---
+"@marigold/components": patch
+---
+
+fix: justify content in `<Button>`
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/Button/Button.stories.tsx b/packages/components/src/Button/Button.stories.tsx
index 1210b0f4c..494e4f841 100644
--- a/packages/components/src/Button/Button.stories.tsx
+++ b/packages/components/src/Button/Button.stories.tsx
@@ -64,6 +64,10 @@ export const AsProp: ComponentStory<typeof Button> = args => (
   <Button {...args} as="a" href="https://reservix.net" />
 );
 
+export const FullWidth: ComponentStory<typeof Button> = args => (
+  <Button {...args} fullWidth />
+);
+
 export const PassThroughProps: ComponentStory<typeof Button> = args => {
   const [isHovered, setHovered] = useState(false);
   return (
diff --git a/packages/components/src/Button/Button.tsx b/packages/components/src/Button/Button.tsx
index 9284e1e28..17812f2a8 100644
--- a/packages/components/src/Button/Button.tsx
+++ b/packages/components/src/Button/Button.tsx
@@ -95,6 +95,7 @@ export const Button: PolymorphicComponentWithRef<ButtonOwnProps, 'button'> =
           __baseCSS={{
             display: 'inline-flex',
             alignItems: 'center',
+            justifyContent: 'center',
             gap: '0.5ch',
             cursor: disabled ? 'not-allowed' : 'pointer',
             width: fullWidth ? '100%' : undefined,
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/Button/Button.test.tsx b/packages/components/src/Button/Button.test.tsx
index cdcc4b0e4..b8e1e8b42 100644
--- a/packages/components/src/Button/Button.test.tsx
+++ b/packages/components/src/Button/Button.test.tsx
@@ -49,6 +49,18 @@ const theme = {
   },
 };
 
+test('sets some base styles', () => {
+  render(<Button>button</Button>);
+  const button = screen.getByText(/button/);
+
+  expect(button).toHaveStyle({
+    display: 'inline-flex',
+    alignItems: 'center',
+    justifyContent: 'center',
+    gap: '0.5ch',
+  });
+});
+
 test('supports base style', () => {
   render(
     <ThemeProvider theme={theme}>
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');
 });