Repository: marigold-ui/marigold
Pull request #2805 (2023-02-20 19:58:09)

feat: introduce `<Inset>` component

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

Latest commit: a78bd66194bf44cb70c0d8d50fe5a12aecba868a

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/inset-component?filename=.changeset/perfect-camels-watch.md&value=---%0A%22%40marigold%2Fdocs%22%3A%20patch%0A%22%40marigold%2Fcomponents%22%3A%20patch%0A---%0A%0Afeat%3A%20introduce%20%60%3CInset%3E%60%20component%0A)


codecov[bot]: # [Codecov](https://codecov.io/gh/marigold-ui/marigold/pull/2805?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui) Report
> Merging [#2805](https://codecov.io/gh/marigold-ui/marigold/pull/2805?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui) (a78bd66) into [main](https://codecov.io/gh/marigold-ui/marigold/commit/1894e6f3c57d2ca6232c4a6f7767b9c3fb899019?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui) (1894e6f) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/marigold-ui/marigold/pull/2805/graphs/tree.svg?width=650&height=150&src=pr&token=YIIcKX7TZu&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui)](https://codecov.io/gh/marigold-ui/marigold/pull/2805?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui)

```diff
@@            Coverage Diff            @@
##              main     #2805   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          101       102    +1     
  Lines         1182      1186    +4     
  Branches       209       210    +1     
=========================================
+ Hits          1182      1186    +4     
```

| Flag | Coverage Δ | |
|---|---|---|
| components | `100.00% <100.00%> (ø)` | |
| system | `100.00% <100.00%> (ø)` | |
| tokens | `100.00% <100.00%> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/marigold-ui/marigold/pull/2805?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui) | Coverage Δ | |
|---|---|---|
| [packages/components/src/Inset/Inset.tsx](https://codecov.io/gh/marigold-ui/marigold/pull/2805?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui#diff-cGFja2FnZXMvY29tcG9uZW50cy9zcmMvSW5zZXQvSW5zZXQudHN4) | `100.00% <100.00%> (ø)` | |
| [packages/components/src/Stack/Stack.tsx](https://codecov.io/gh/marigold-ui/marigold/pull/2805?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui#diff-cGFja2FnZXMvY29tcG9uZW50cy9zcmMvU3RhY2svU3RhY2sudHN4) | `100.00% <100.00%> (ø)` | |

sarahgm: @sebald  changeset?
sebald: > @sebald changeset?

@sarahgm added

Patch:
diff --git a/.changeset/perfect-camels-watch.md b/.changeset/perfect-camels-watch.md
new file mode 100644
index 000000000..6d1821c7f
--- /dev/null
+++ b/.changeset/perfect-camels-watch.md
@@ -0,0 +1,6 @@
+---
+"@marigold/docs": minor
+"@marigold/components": minor 
+---
+
+feat: introduce `<Inset>` component
diff --git a/docs/src/demos/components/Inset/index.ts b/docs/src/demos/components/Inset/index.ts
new file mode 100644
index 000000000..ebec92423
--- /dev/null
+++ b/docs/src/demos/components/Inset/index.ts
@@ -0,0 +1,3 @@
+export * from './inset-basic.demo';
+export * from './inset-equal.demo';
+export * from './inset-hv.demo';
diff --git a/docs/src/demos/components/Inset/inset-basic.demo.tsx b/docs/src/demos/components/Inset/inset-basic.demo.tsx
new file mode 100644
index 000000000..51c0c002e
--- /dev/null
+++ b/docs/src/demos/components/Inset/inset-basic.demo.tsx
@@ -0,0 +1,20 @@
+import { Headline, Inset, Stack, Text } from '@marigold/components';
+
+export const BasicInset = () => (
+  <Inset space="medium">
+    <Stack space="small">
+      <Headline level="2">Interesting facts about Marigolds</Headline>
+      <Text>
+        Marigolds are flowering plants of the genus Tagetes of the sunflower
+        family Asteraceae.
+      </Text>
+      <Text>There are 56 species of marigolds.</Text>
+      <Text>
+        Their habitats are shores, ponds, springs, quiet waters in streams,
+        ditches, wetlands, wet meadows, waterside swamps and meadows which are
+        prone to flooding, damp hollows in broad-leaved forests, snow-bed sites,
+        sometimes underwater.
+      </Text>
+    </Stack>
+  </Inset>
+);
diff --git a/docs/src/demos/components/Inset/inset-equal.demo.tsx b/docs/src/demos/components/Inset/inset-equal.demo.tsx
new file mode 100644
index 000000000..5d6dbe975
--- /dev/null
+++ b/docs/src/demos/components/Inset/inset-equal.demo.tsx
@@ -0,0 +1,9 @@
+import { Inset } from '@marigold/components';
+
+export const InsetEqualSpaceDemo = () => (
+  <Inset space="large">
+    Marigold has oblong and lanceolate leaves with whole margins. Some varieties
+    of marigold have leaves with toothed edges. Leaves are spirally arranged on
+    the branches.
+  </Inset>
+);
diff --git a/docs/src/demos/components/Inset/inset-hv.demo.tsx b/docs/src/demos/components/Inset/inset-hv.demo.tsx
new file mode 100644
index 000000000..4a7179a1e
--- /dev/null
+++ b/docs/src/demos/components/Inset/inset-hv.demo.tsx
@@ -0,0 +1,10 @@
+import { Inset } from '@marigold/components';
+
+export const InsetDifferentSpaceDemo = () => (
+  <Inset spaceY="small" spaceX="large">
+    Marigold is usually yellow, orange, red and maroon in color. Each flower
+    consists of large number of petals that overlap. Biggest petals are located
+    on a periphery and smallest in a center of a flower. Flowers contain both
+    male (stamen) and female (pistil) reproductive organs.
+  </Inset>
+);
diff --git a/docs/src/demos/components/index.ts b/docs/src/demos/components/index.ts
index 734ec3912..815d83d99 100644
--- a/docs/src/demos/components/index.ts
+++ b/docs/src/demos/components/index.ts
@@ -27,6 +27,7 @@ export * from './Icon';
 export * from './Image';
 export * from './Inline';
 export * from './Input';
+export * from './Inset';
 export * from './Label';
 export * from './Link';
 export * from './List';
diff --git a/docs/src/pages/components/inset.mdx b/docs/src/pages/components/inset.mdx
new file mode 100644
index 000000000..86897ff1d
--- /dev/null
+++ b/docs/src/pages/components/inset.mdx
@@ -0,0 +1,69 @@
+---
+title: Inset
+group: Layout
+github: https://github.com/marigold-ui/marigold/blob/main/packages/components/src/Inset/Inset.tsx
+edit: https://github.com/marigold-ui/marigold/blob/main/docs/src/pages/components/inset.mdx
+caption: Component to add spacing to children.
+badge: new
+---
+
+The `<Inset>` component is a layout component that acts as a container which adds spacing around its children. It can either add equal spacing to all sides (`space`) or add horizontal (`spaceX`) and vertical (`spaceY`) spacing sepretaly.
+
+The component should be used whenever you need to add some whitespace around elements. For example, around a form or inside a [`<Card>`](/components/card/).
+
+<Preview>
+  <BasicInset />
+</Preview>
+
+## Usage
+
+### Import
+
+To import the component you just have to use this code below.
+
+```tsx
+import { Inset } from '@marigold/components';
+```
+
+### Props
+
+<PropsTable
+  props={[
+    {
+      property: 'space',
+      type: 'ResponsiveStyleValue<string>',
+      description: 'Space on all sides',
+      default: 'none',
+    },
+    {
+      property: 'spaceX',
+      type: 'ResponsiveStyleValue<string>',
+      description: 'Horizontal space',
+      default: 'none',
+    },
+    {
+      property: 'spaceY',
+      type: 'ResponsiveStyleValue<string>',
+      description: 'Vertical space',
+      default: 'none',
+    },
+  ]}
+/>
+
+## Examples
+
+### Equal Spacing
+
+In order to add equal spacing to all sides use the `space` property like shown below.
+
+```tsx preview file=components/Inset/inset-equal.demo.tsx
+
+```
+
+### Horzintal and vertical Spacing
+
+If you need to only set horizontal or vertical spacing, or want a different horizontal and vertical spacing, use the `spaceX` and `spaceY` respectively.
+
+```tsx preview file=components/Inset/inset-hv.demo.tsx
+
+```
diff --git a/packages/components/src/Inset/Inset.stories.tsx b/packages/components/src/Inset/Inset.stories.tsx
new file mode 100644
index 000000000..b6d2917bd
--- /dev/null
+++ b/packages/components/src/Inset/Inset.stories.tsx
@@ -0,0 +1,52 @@
+import React from 'react';
+import type { Meta, ComponentStory } from '@storybook/react';
+
+import { Inset } from '../Inset';
+import { Text } from '../Text';
+import isChromatic from 'chromatic';
+
+export default {
+  title: 'Components/Inset',
+  argTypes: {
+    space: {
+      control: {
+        type: 'select',
+      },
+      options: ['small', 'medium', 'large'],
+      description: 'set padding on all sides',
+    },
+    spaceX: {
+      control: {
+        type: 'select',
+      },
+      options: ['small', 'medium', 'large'],
+      description: 'set padding on left and right side',
+    },
+    spaceY: {
+      control: {
+        type: 'select',
+      },
+      options: ['small', 'medium', 'large'],
+      description: 'set padding on top and bottom side',
+    },
+  },
+} as Meta;
+
+export const Basic: ComponentStory<typeof Inset> = args => (
+  <Inset {...args}>
+    <Text>
+      It is a dark time for the Rebellion. Although the Death Star has been
+      destroyed, Imperial troops have driven the Rebel forces from their hidden
+      base and pursued them across the galaxy. Evading the dreaded Imperial
+      Starfleet, a group of freedom fighters led by Luke Skywalker has
+      established a new secret base on the remote ice world of Hoth. The evil
+      lord Darth Vader, obsessed with finding young Skywalker, has dispatched
+      thousands of remote probes into the far reaches of space....
+    </Text>
+  </Inset>
+);
+
+Basic.parameters = {
+  chromatic: { viewports: [320, 1200] },
+  theme: isChromatic() ? 'b2b' : 'stacked',
+};
diff --git a/packages/components/src/Inset/Inset.tsx b/packages/components/src/Inset/Inset.tsx
new file mode 100644
index 000000000..97c013481
--- /dev/null
+++ b/packages/components/src/Inset/Inset.tsx
@@ -0,0 +1,20 @@
+import React, { ReactNode } from 'react';
+import { Box, ResponsiveStyleValue } from '@marigold/system';
+
+export type InsetProps =
+  | {
+      children: ReactNode;
+      space?: never;
+      spaceX?: ResponsiveStyleValue<string>;
+      spaceY?: ResponsiveStyleValue<string>;
+    }
+  | {
+      children: ReactNode;
+      space?: ResponsiveStyleValue<string>;
+      spaceX?: never;
+      spaceY?: never;
+    };
+
+export const Inset = ({ space, spaceX, spaceY, children }: InsetProps) => (
+  <Box css={space ? { p: space } : { px: spaceX, py: spaceY }}>{children}</Box>
+);
diff --git a/packages/components/src/Inset/index.ts b/packages/components/src/Inset/index.ts
new file mode 100644
index 000000000..167e0d25e
--- /dev/null
+++ b/packages/components/src/Inset/index.ts
@@ -0,0 +1,1 @@
+export * from './Inset';
diff --git a/packages/components/src/Stack/Stack.tsx b/packages/components/src/Stack/Stack.tsx
index 69caab6b8..c04ca0c88 100755
--- a/packages/components/src/Stack/Stack.tsx
+++ b/packages/components/src/Stack/Stack.tsx
@@ -1,7 +1,5 @@
 import React, { ReactNode } from 'react';
-import { ResponsiveStyleValue } from '@marigold/system';
-
-import { Box } from '../Box';
+import { Box, ResponsiveStyleValue } from '@marigold/system';
 
 const ALIGNMENT_X = {
   none: 'initial',
diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts
index 5b911bc79..5f2a6dd71 100644
--- a/packages/components/src/index.ts
+++ b/packages/components/src/index.ts
@@ -22,6 +22,7 @@ export * from './Headline';
 export * from './Image';
 export * from './Inline';
 export * from './Input';
+export * from './Inset';
 export * from './Label';
 export * from './Link';
 export * from './List';


Test patch:
diff --git a/packages/components/src/Inset/Inset.test.tsx b/packages/components/src/Inset/Inset.test.tsx
new file mode 100644
index 000000000..f5de9f6dd
--- /dev/null
+++ b/packages/components/src/Inset/Inset.test.tsx
@@ -0,0 +1,88 @@
+/* eslint-disable testing-library/no-node-access */
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import { ThemeProvider } from '@marigold/system';
+import { Text } from '../Text';
+
+import { Inset } from './Inset';
+
+const theme = {
+  space: {
+    none: 0,
+    small: 2,
+    medium: 4,
+    large: 8,
+  },
+};
+
+test('does not have a default spacing', () => {
+  render(
+    <ThemeProvider theme={theme}>
+      <Inset>
+        <Text>first</Text>
+        <Text>second</Text>
+      </Inset>
+    </ThemeProvider>
+  );
+  const inset = screen.getByText('first').parentElement;
+  expect(inset).not.toHaveStyle(`padding: 0`);
+  expect(inset).not.toHaveStyle(`padding-top: 0`);
+  expect(inset).not.toHaveStyle(`padding-left: 0`);
+});
+
+test('allows to add spacing equally on all sides', () => {
+  render(
+    <ThemeProvider theme={theme}>
+      <Inset space="small">
+        <Text>first</Text>
+        <Text>second</Text>
+      </Inset>
+    </ThemeProvider>
+  );
+  const inset = screen.getByText('first').parentElement;
+  expect(inset).toHaveStyle(`padding: ${theme.space.small}px`);
+});
+
+test('allows to add horizontal spacing', () => {
+  render(
+    <ThemeProvider theme={theme}>
+      <Inset spaceX="medium">
+        <Text>first</Text>
+        <Text>second</Text>
+      </Inset>
+    </ThemeProvider>
+  );
+  const inset = screen.getByText('first').parentElement;
+  expect(inset).toHaveStyle(`padding-left: ${theme.space.medium}px`);
+  expect(inset).toHaveStyle(`padding-right: ${theme.space.medium}px`);
+});
+
+test('allows to add vertical spacing', () => {
+  render(
+    <ThemeProvider theme={theme}>
+      <Inset spaceY="large">
+        <Text>first</Text>
+        <Text>second</Text>
+      </Inset>
+    </ThemeProvider>
+  );
+  const inset = screen.getByText('first').parentElement;
+  expect(inset).toHaveStyle(`padding-top: ${theme.space.large}px`);
+  expect(inset).toHaveStyle(`padding-bottom: ${theme.space.large}px`);
+});
+
+test('allows to add different vertical/horizontal spacing', () => {
+  render(
+    <ThemeProvider theme={theme}>
+      <Inset spaceX="large" spaceY="small">
+        <Text>first</Text>
+        <Text>second</Text>
+      </Inset>
+    </ThemeProvider>
+  );
+  const inset = screen.getByText('first').parentElement;
+  expect(inset).toHaveStyle(`padding-left: ${theme.space.large}px`);
+  expect(inset).toHaveStyle(`padding-right: ${theme.space.large}px`);
+  expect(inset).toHaveStyle(`padding-top: ${theme.space.small}px`);
+  expect(inset).toHaveStyle(`padding-bottom: ${theme.space.small}px`);
+});
diff --git a/packages/components/src/Stack/Stack.test.tsx b/packages/components/src/Stack/Stack.test.tsx
index f0f263698..0fe15db03 100644
--- a/packages/components/src/Stack/Stack.test.tsx
+++ b/packages/components/src/Stack/Stack.test.tsx
@@ -26,7 +26,7 @@ test('default space is "none"', () => {
       </Stack>
     </ThemeProvider>
   );
-  const first = screen.getByText(/first/).parentElement;
+  const first = screen.getByText('first').parentElement;
   expect(first).toHaveStyle(`gap: 0`);
 });