Repository: marigold-ui/marigold
Pull request #1928 (2022-03-29 12:32:51)

feat(comp): improve Container component
#1860 

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

Latest commit: 0c9b123258826f763511b8943115dde1e94c22c7

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/container-improvement?filename=.changeset/eighty-sloths-brush.md&value=---%0A%22%40marigold%2Fdocs%22%3A%20patch%0A%22%40marigold%2Fcomponents%22%3A%20patch%0A---%0A%0Afeat(comp)%3A%20improve%20Container%20component%0A)



Patch:
diff --git a/.changeset/eighty-sloths-brush.md b/.changeset/eighty-sloths-brush.md
new file mode 100644
index 000000000..459d019d9
--- /dev/null
+++ b/.changeset/eighty-sloths-brush.md
@@ -0,0 +1,6 @@
+---
+"@marigold/docs": minor
+"@marigold/components": minor
+---
+
+feat(comp): improve Container component
diff --git a/docs/content/components/container.mdx b/docs/content/components/container.mdx
index c887f167d..569ba3bcf 100644
--- a/docs/content/components/container.mdx
+++ b/docs/content/components/container.mdx
@@ -8,29 +8,26 @@ import { Box, Container, Text } from '@marigold/components';
 
 ## Description
 
-Containers width is based on used font and is optimized for readability. You can use `header`or `content`as content type and set the `maxWidth` to `small`, `medium` or `large`.
-
-<Box
-  as={Container}
-  border="1px solid #ced4da"
-  bg="#e9ecef"
-  height="100px"
-  p="xsmall"
-  contentType="header"
->
-  <Text as="h5" variant="headline5">
-    Container header
-  </Text>
-</Box>
-<br />
-<Box
-  as={Container}
-  border="1px solid #ced4da"
-  bg="#e9ecef"
-  height="100px"
-  p="xsmall"
->
-  <Text>Container content</Text>
+Containers width is based on used font and is optimized for readability. You can use `header` or `content` as content type and set the `size` prop to `small`, `medium` or `large`.
+
+<Box border="1px solid #ced4da" bg="#e9ecef" p="xsmall">
+  <Box
+    as={Container}
+    contentType="header"
+    align="center"
+    alignContainer="center"
+  >
+    <Text as="h2" variant="headline2">
+      Container header
+    </Text>
+  </Box>
+  <Box as={Container} align="center" alignContainer="center">
+    <Text>
+      The container content is for example a long text to present information.
+      In this case it is an unnecessary text that is only used to fill the width
+      of the container content. Thank you for reading this.
+    </Text>
+  </Box>
 </Box>
 <br />
 
@@ -40,11 +37,12 @@ import { Container } from '@marigold/components';
 
 ## Props
 
-| Property      | Type                   | Default   |
-| :------------ | :--------------------- | :-------- |
-| `contentType` | `content, header`      | `content` |
-| `size`        | `small, medium, large` | `medium`  |
-| `align`       | `left, center, right`  | `left`    |
+| Property         | Type                   | Default   |
+| :--------------- | :--------------------- | :-------- |
+| `contentType`    | `content, header`      | `content` |
+| `size`           | `small, medium, large` | `medium`  |
+| `align`          | `left, center, right`  | `left`    |
+| `alignContainer` | `left, center, right`  | `left`    |
 
 ## Examples
 
@@ -77,7 +75,7 @@ Container header small, medium & large
 Container content small, medium & large
 
 ```tsx
-<Container size="small">
+<Container size="small" alignContainer="center">
   <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
@@ -87,7 +85,7 @@ Container content small, medium & large
 ```
 
 ```tsx
-<Container>
+<Container alignContainer="center">
   <Text>
     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
@@ -97,7 +95,7 @@ Container content small, medium & large
 ```
 
 ```tsx
-<Container size="large">
+<Container size="large" alignContainer="center">
   <Text>
     The evil lord Darth Vader, obsessed with finding young Skywalker, has
     dispatched thousands of remote probes into the far reaches of space....
@@ -110,7 +108,13 @@ Container content small, medium & large
 In some cases, the width of the content can be smaller than the container's width. You can use the align prop to align the content left, center or right.
 
 ```tsx
-<Box as={Container} bg="blue10" align="center" p="small">
+<Box
+  as={Container}
+  bg="blue10"
+  align="center"
+  alignContainer="center"
+  p="small"
+>
   <Text as="h2" variant="headline2">
     Star Wars - The Empire Strikes Back
   </Text>
diff --git a/packages/components/src/Container/Container.stories.tsx b/packages/components/src/Container/Container.stories.tsx
index 128138b33..19935e6d9 100644
--- a/packages/components/src/Container/Container.stories.tsx
+++ b/packages/components/src/Container/Container.stories.tsx
@@ -37,7 +37,19 @@ export default {
         type: 'select',
       },
       options: ['left', 'center', 'right'],
-      description: 'choose between left, center and right alignment',
+      description: 'choose between left, center and right items alignment',
+      table: {
+        defaultValue: {
+          summary: 'left',
+        },
+      },
+    },
+    alignContainer: {
+      control: {
+        type: 'select',
+      },
+      options: ['left', 'center', 'right'],
+      description: 'choose between left, center and right container alignment',
       table: {
         defaultValue: {
           summary: 'left',
diff --git a/packages/components/src/Container/Container.tsx b/packages/components/src/Container/Container.tsx
index 962841040..fe5a384e8 100755
--- a/packages/components/src/Container/Container.tsx
+++ b/packages/components/src/Container/Container.tsx
@@ -8,6 +8,7 @@ export interface ContainerProps extends ComponentProps<'div'> {
   contentType?: 'content' | 'header';
   size?: keyof typeof tokenSize.content | keyof typeof tokenSize.header;
   align?: 'left' | 'right' | 'center';
+  alignContainer?: 'left' | 'right' | 'center';
 }
 
 const ALIGNMENT = {
@@ -20,17 +21,36 @@ export const Container: React.FC<ContainerProps> = ({
   contentType = 'content',
   size = 'medium',
   align = 'left',
+  alignContainer = 'left',
   children,
   ...props
-}) => (
-  <Box
-    display="grid"
-    maxWidth={tokenSize[contentType][size]}
-    css={{
-      placeItems: ALIGNMENT[align],
-    }}
-    {...props}
-  >
-    {children}
-  </Box>
-);
+}) => {
+  const maxWidth = tokenSize[contentType][size];
+
+  let gridTemplateColumns = `${maxWidth} 1fr 1fr`;
+  let gridColumn = 1;
+  if (alignContainer === 'center') {
+    gridTemplateColumns = `1fr ${maxWidth} 1fr`;
+    gridColumn = 2;
+  }
+  if (alignContainer === 'right') {
+    gridTemplateColumns = `1fr 1fr ${maxWidth}`;
+    gridColumn = 3;
+  }
+
+  return (
+    <Box
+      display="grid"
+      css={{
+        gridTemplateColumns: gridTemplateColumns,
+        placeItems: ALIGNMENT[align],
+        '> *': {
+          gridColumn: gridColumn,
+        },
+      }}
+      {...props}
+    >
+      {children}
+    </Box>
+  );
+};


Test patch:
diff --git a/packages/components/src/Container/Container.test.tsx b/packages/components/src/Container/Container.test.tsx
index bd2eb6b11..a7541f465 100644
--- a/packages/components/src/Container/Container.test.tsx
+++ b/packages/components/src/Container/Container.test.tsx
@@ -11,7 +11,7 @@ test('supports default contentType content', () => {
     </Container>
   );
   const container = screen.getByTestId(/container/);
-  expect(container).toHaveStyle(`maxWidth: 45ch`);
+  expect(container).toHaveStyle(`gridTemplateColumns: 45ch 1fr 1fr`);
 });
 
 test('supports contentType header', () => {
@@ -21,7 +21,7 @@ test('supports contentType header', () => {
     </Container>
   );
   const container = screen.getByTestId(/container/);
-  expect(container).toHaveStyle(`maxWidth: 25ch`);
+  expect(container).toHaveStyle(`gridTemplateColumns: 25ch 1fr 1fr`);
 });
 
 test('supports default size', () => {
@@ -31,7 +31,7 @@ test('supports default size', () => {
     </Container>
   );
   const container = screen.getByTestId(/container/);
-  expect(container).toHaveStyle(`maxWidth: 45ch`);
+  expect(container).toHaveStyle(`gridTemplateColumns: 45ch 1fr 1fr`);
 });
 
 test('supports size small', () => {
@@ -41,7 +41,7 @@ test('supports size small', () => {
     </Container>
   );
   const container = screen.getByTestId(/container/);
-  expect(container).toHaveStyle(`maxWidth: 20ch`);
+  expect(container).toHaveStyle(`gridTemplateColumns: 20ch 1fr 1fr`);
 });
 
 test('supports size large', () => {
@@ -51,7 +51,7 @@ test('supports size large', () => {
     </Container>
   );
   const container = screen.getByTestId(/container/);
-  expect(container).toHaveStyle(`maxWidth: 60ch`);
+  expect(container).toHaveStyle(`gridTemplateColumns: 60ch 1fr 1fr`);
 });
 
 test('supports size and contentType', () => {
@@ -61,7 +61,7 @@ test('supports size and contentType', () => {
     </Container>
   );
   const container = screen.getByTestId(/container/);
-  expect(container).toHaveStyle(`maxWidth: 35ch`);
+  expect(container).toHaveStyle(`gridTemplateColumns: 35ch 1fr 1fr`);
 });
 
 test('supports default align left', () => {
@@ -94,6 +94,42 @@ test('supports align right', () => {
   expect(container).toHaveStyle(`placeItems: flex-end`);
 });
 
+test('supports default alignContainer left', () => {
+  render(
+    <Container data-testid="container">
+      <Text>sdf</Text>
+    </Container>
+  );
+  const container = screen.getByTestId(/container/);
+  expect(container).toHaveStyle(`gridTemplateColumns: 45ch 1fr 1fr`);
+  // eslint-disable-next-line testing-library/no-node-access
+  expect(container.firstChild).toHaveStyle(`gridColumn: 1`);
+});
+
+test('supports alignContainer center', () => {
+  render(
+    <Container alignContainer="center" data-testid="container">
+      <Text>sdf</Text>
+    </Container>
+  );
+  const container = screen.getByTestId(/container/);
+  expect(container).toHaveStyle(`gridTemplateColumns: 1fr 45ch 1fr`);
+  // eslint-disable-next-line testing-library/no-node-access
+  expect(container.firstChild).toHaveStyle(`gridColumn: 2`);
+});
+
+test('supports alignContainer right', () => {
+  render(
+    <Container alignContainer="right" data-testid="container">
+      <Text>sdf</Text>
+    </Container>
+  );
+  const container = screen.getByTestId(/container/);
+  expect(container).toHaveStyle(`gridTemplateColumns: 1fr 1fr 45ch`);
+  // eslint-disable-next-line testing-library/no-node-access
+  expect(container.firstChild).toHaveStyle(`gridColumn: 3`);
+});
+
 test('renders correct HTML element', () => {
   render(
     <Container data-testid="container">