Repository: marigold-ui/marigold
Pull request #2094 (2022-05-20 23:42:04)

fix(deps): update dependency @types/node to v16.11.36
[![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped) | [`16.11.33` -> `16.11.36`](https://renovatebot.com/diffs/npm/@types%2fnode/16.11.33/16.11.36) | [![age](https://badges.renovateapi.com/packages/npm/@types%2fnode/16.11.36/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@types%2fnode/16.11.36/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@types%2fnode/16.11.36/compatibility-slim/16.11.33)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@types%2fnode/16.11.36/confidence-slim/16.11.33)](https://docs.renovatebot.com/merge-confidence/) |

---

### Configuration

📅 **Schedule**: "before 3am on Saturday" in timezone Europe/Berlin.

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click this checkbox.

---

This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/marigold-ui/marigold).

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

Latest commit: 0b24bf889eafebf172e19e16d50cd3aca569568b

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/renovate/node-16.x?filename=.changeset/gentle-avocados-collect.md&value=---%0A%0A---%0A%0Afix(deps)%3A%20update%20dependency%20%40types%2Fnode%20to%20v16.11.36%0A)



Patch:
diff --git a/.changeset/cuddly-bikes-reflect.md b/.changeset/cuddly-bikes-reflect.md
new file mode 100644
index 000000000..3b447e60f
--- /dev/null
+++ b/.changeset/cuddly-bikes-reflect.md
@@ -0,0 +1,7 @@
+---
+"@marigold/docs": major
+"@marigold/components": major
+"@marigold/tokens": major
+---
+
+feat: <Stack> can align on x and y axis
diff --git a/.changeset/curly-flowers-impress.md b/.changeset/curly-flowers-impress.md
new file mode 100644
index 000000000..2f41ba930
--- /dev/null
+++ b/.changeset/curly-flowers-impress.md
@@ -0,0 +1,8 @@
+---
+"@marigold/components": major
+"@marigold/theme-b2b": major
+"@marigold/theme-core": major
+"@marigold/theme-unicorn": major
+---
+
+refa: separate selection/regular cell + use <Checkbox>
diff --git a/.changeset/seven-toes-bake.md b/.changeset/seven-toes-bake.md
new file mode 100644
index 000000000..17b7c419f
--- /dev/null
+++ b/.changeset/seven-toes-bake.md
@@ -0,0 +1,6 @@
+---
+"@marigold/docs": major
+"@marigold/components": major
+---
+
+feat: <Inline> can align on x and y axis
diff --git a/.changeset/thin-pens-warn.md b/.changeset/thin-pens-warn.md
new file mode 100644
index 000000000..702d641b1
--- /dev/null
+++ b/.changeset/thin-pens-warn.md
@@ -0,0 +1,6 @@
+---
+"@marigold/components": major
+"@marigold/system": major
+---
+
+refa: Remove "variant" prop from <Box>, use `useComponentStyles` instead
diff --git a/config/jest/package.json b/config/jest/package.json
index 8875783e8..43e391cb3 100644
--- a/config/jest/package.json
+++ b/config/jest/package.json
@@ -22,7 +22,7 @@
   },
   "dependencies": {
     "@babel/core": "7.17.12",
-    "@swc/core": "1.2.186",
+    "@swc/core": "1.2.189",
     "@swc/jest": "0.2.21",
     "@types/jest": "27.4.1",
     "babel-jest": "28.1.0",
diff --git a/docs/content/components/inline.mdx b/docs/content/components/inline.mdx
index ddfd4202d..520a27c93 100644
--- a/docs/content/components/inline.mdx
+++ b/docs/content/components/inline.mdx
@@ -22,7 +22,8 @@ import { Inline } from '@marigold/components';
 | Property | Type                           | Default  |
 | :------- | :----------------------------- | :------- |
 | `space`  | `ResponsiveStyleValue<string>` | `none`   |
-| `align`  | `center, top, bottom`          | `center` |
+| `alignY` | `top, center, bottom`          | `center` |
+| `alignX` | `left, center, right`          | `left`   |
 
 ## Examples
 
diff --git a/docs/content/components/stack.mdx b/docs/content/components/stack.mdx
index 482a84e4f..f580e81ca 100644
--- a/docs/content/components/stack.mdx
+++ b/docs/content/components/stack.mdx
@@ -22,10 +22,12 @@ import { Stack } from '@marigold/components';
 
 ## Props
 
-| Property | Type                           | Default |
-| :------- | :----------------------------- | :------ |
-| `space`  | `ResponsiveStyleValue<string>` | `none`  |
-| `align`  | `left, right, center`          | `left`  |
+| Property  | Type                           | Default |
+| :-------- | :----------------------------- | :------ |
+| `space`   | `ResponsiveStyleValue<string>` | `none`  |
+| `alignX`  | `left, right, center`          | `left`  |
+| `alignY`  | `top, bottom, center`          | `left`  |
+| `stretch` | `boolean`                      | `false` |
 
 ## Examples
 
@@ -70,18 +72,30 @@ import { Stack } from '@marigold/components';
 </Stack>
 ```
 
-### Alignment
+### Horizontal Alignment
 
 ```tsx
 <>
   <Stack space="medium">
     <Text>Left</Text>
   </Stack>
-  <Stack space="medium" align="center">
+  <Stack space="medium" alignX="center">
     <Text>Center</Text>
   </Stack>
-  <Stack space="medium" align="right">
+  <Stack space="medium" alignX="right">
     <Text>Right</Text>
   </Stack>
 </>
 ```
+
+### Vertical Alignment
+
+```tsx
+<Box css={{ height: 200, bg: '#f1f3f5', p: 8 }}>
+  <Stack space="medium" stretch alignY="bottom">
+    <Text>Lirum</Text>
+    <Text>Larum</Text>
+    <Text>Löffelstiel!</Text>
+  </Stack>
+</Box>
+```
diff --git a/docs/content/components/table.mdx b/docs/content/components/table.mdx
index d9d4ceecf..45bd4e5a7 100644
--- a/docs/content/components/table.mdx
+++ b/docs/content/components/table.mdx
@@ -115,25 +115,25 @@ import { Table } from '@marigold/components';
     <Table.Column>Year of birth</Table.Column>
   </Table.Header>
   <Table.Body>
-    <Table.Row key={1}>
+    <Table.Row>
       <Table.Cell>Potter</Table.Cell>
       <Table.Cell>Harry</Table.Cell>
       <Table.Cell>Gryffindor</Table.Cell>
       <Table.Cell>1980</Table.Cell>
     </Table.Row>
-    <Table.Row key={2}>
+    <Table.Row>
       <Table.Cell>Malfoy</Table.Cell>
       <Table.Cell>Draco</Table.Cell>
       <Table.Cell>Slytherin</Table.Cell>
       <Table.Cell>1980</Table.Cell>
     </Table.Row>
-    <Table.Row key={3}>
+    <Table.Row>
       <Table.Cell>Diggory</Table.Cell>
       <Table.Cell>Cedric</Table.Cell>
       <Table.Cell>Hufflepuff</Table.Cell>
       <Table.Cell>1977</Table.Cell>
     </Table.Row>
-    <Table.Row key={4}>
+    <Table.Row>
       <Table.Cell>Lovegood</Table.Cell>
       <Table.Cell>Luna</Table.Cell>
       <Table.Cell>Ravenclaw</Table.Cell>
@@ -207,3 +207,91 @@ import { Table } from '@marigold/components';
   );
 };
 ```
+
+### Disabled Rows
+
+```tsx
+<Table
+  aria-label="Table with multiple selection"
+  selectionMode="multiple"
+  disabledKeys={['Malfoy']}
+>
+  <Table.Header>
+    <Table.Column>Name</Table.Column>
+    <Table.Column>Firstname</Table.Column>
+    <Table.Column>House</Table.Column>
+    <Table.Column>Year of birth</Table.Column>
+  </Table.Header>
+  <Table.Body>
+    <Table.Row key="Potter">
+      <Table.Cell>Potter</Table.Cell>
+      <Table.Cell>Harry</Table.Cell>
+      <Table.Cell>Gryffindor</Table.Cell>
+      <Table.Cell>1980</Table.Cell>
+    </Table.Row>
+    <Table.Row key="Malfoy">
+      <Table.Cell>Malfoy</Table.Cell>
+      <Table.Cell>Draco</Table.Cell>
+      <Table.Cell>Slytherin</Table.Cell>
+      <Table.Cell>1980</Table.Cell>
+    </Table.Row>
+    <Table.Row key="Diggory">
+      <Table.Cell>Diggory</Table.Cell>
+      <Table.Cell>Cedric</Table.Cell>
+      <Table.Cell>Hufflepuff</Table.Cell>
+      <Table.Cell>1977</Table.Cell>
+    </Table.Row>
+    <Table.Row key="Lovegood">
+      <Table.Cell>Lovegood</Table.Cell>
+      <Table.Cell>Luna</Table.Cell>
+      <Table.Cell>Ravenclaw</Table.Cell>
+      <Table.Cell>1981</Table.Cell>
+    </Table.Row>
+  </Table.Body>
+</Table>
+```
+
+### Nested Columns
+
+Columns can be nested, which will result in more than one header row to be created. Note the usage of `isRowHeader` in the example below. By default, only the first column is included in the accessibility name for each row.
+
+```tsx
+<Table aria-label="Example table for nested columns">
+  <Table.Header>
+    <Table.Column title="Name">
+      <Table.Column isRowHeader>First Name</Table.Column>
+      <Table.Column isRowHeader>Last Name</Table.Column>
+    </Table.Column>
+    <Table.Column title="Information">
+      <Table.Column>Age</Table.Column>
+      <Table.Column>Birthday</Table.Column>
+    </Table.Column>
+  </Table.Header>
+  <Table.Body>
+    <Table.Row>
+      <Table.Cell>Sam</Table.Cell>
+      <Table.Cell>Smith</Table.Cell>
+      <Table.Cell>36</Table.Cell>
+      <Table.Cell>May 3</Table.Cell>
+    </Table.Row>
+    <Table.Row>
+      <Table.Cell>Julia</Table.Cell>
+      <Table.Cell>Jones</Table.Cell>
+      <Table.Cell>24</Table.Cell>
+      <Table.Cell>February 10</Table.Cell>
+    </Table.Row>
+    <Table.Row>
+      <Table.Cell>Peter</Table.Cell>
+      <Table.Cell>Parker</Table.Cell>
+      <Table.Cell>28</Table.Cell>
+      <Table.Cell>September 7</Table.Cell>
+    </Table.Row>
+    <Table.Row>
+      <Table.Cell>Bruce</Table.Cell>
+      <Table.Cell>Wayne</Table.Cell>
+      <Table.Cell>32</Table.Cell>
+      <Table.Cell>December 18</Table.Cell>
+    </Table.Row>
+  </Table.Body>
+</Table>
+```
diff --git a/docs/src/components/Navigation/Navigation.tsx b/docs/src/components/Navigation/Navigation.tsx
index 05fff997e..48d985cc1 100644
--- a/docs/src/components/Navigation/Navigation.tsx
+++ b/docs/src/components/Navigation/Navigation.tsx
@@ -1,12 +1,21 @@
 import React from 'react';
-import { Box } from '@marigold/components';
+import { Box, CSSObject, useComponentStyles } from '@marigold/system';
 
 import { Link } from '../Link';
 import { NavigationItem, NavigationTree, useNavigation } from './useNavigation';
 
+interface NavigationItemProps extends NavigationItem {
+  css: CSSObject;
+}
+
 interface NavigationSectionProps {
-  name: string;
   children: NavigationTree;
+  name: string;
+  css: {
+    header: CSSObject;
+    list: CSSObject;
+    item: CSSObject;
+  };
 }
 
 // Helper
@@ -20,8 +29,8 @@ const dirToText = (dir: string) =>
 
 // Components
 // ---------------
-const NavigationItemComponent = ({ title, slug }: NavigationItem) => (
-  <Box variant="navigation.item">
+const NavigationItemComponent = ({ title, slug, css }: NavigationItemProps) => (
+  <Box css={css}>
     <Link
       to={slug.startsWith('/') || slug.startsWith('http') ? slug : `/${slug}`}
     >
@@ -30,20 +39,24 @@ const NavigationItemComponent = ({ title, slug }: NavigationItem) => (
   </Box>
 );
 
-const NavigationSection = ({ name, children }: NavigationSectionProps) => {
+const NavigationSection = ({ name, children, css }: NavigationSectionProps) => {
   return (
     <div>
       {Boolean(name.length) && (
-        <Box as="h2" variant="navigation.header">
+        <Box as="h2" css={css.header}>
           {dirToText(name)}
         </Box>
       )}
-      <Box as="ul" variant="navigation.list">
+      <Box as="ul" css={css.list}>
         {children.map(child =>
           'title' in child ? (
-            <NavigationItemComponent key={child.slug} {...child} />
+            <NavigationItemComponent
+              css={css.item}
+              key={child.slug}
+              {...child}
+            />
           ) : (
-            <NavigationSection key={child.name} {...child} />
+            <NavigationSection css={css} key={child.name} {...child} />
           )
         )}
       </Box>
@@ -53,15 +66,17 @@ const NavigationSection = ({ name, children }: NavigationSectionProps) => {
 
 export const Navigation: React.FC = () => {
   const tree = useNavigation();
+  const styles = useComponentStyles(
+    'Navigation',
+    {},
+    { parts: ['container', 'header', 'list', 'item'] }
+  );
 
   return (
-    <Box
-      as="nav"
-      variant="navigation.wrapper"
-      aria-labelledby="primary-navigation"
-    >
-      <NavigationSection name="" children={tree} />
+    <Box as="nav" css={styles.container} aria-labelledby="primary-navigation">
+      <NavigationSection css={styles} name="" children={tree} />
       <NavigationSection
+        css={styles}
         name="Useful Links"
         children={[
           {
diff --git a/docs/src/pages/index.tsx b/docs/src/pages/index.tsx
index c77019639..92b222e15 100644
--- a/docs/src/pages/index.tsx
+++ b/docs/src/pages/index.tsx
@@ -15,7 +15,7 @@ export default function LandingPage() {
         my: '-xsmall',
       }}
     >
-      <Stack space="xxlarge" align="center">
+      <Stack space="xxlarge" alignX="center">
         <Logo size="large" />
         <Inline space="xxlarge">
           <Link variant="outline" to="/introduction/00-getting-started">
diff --git a/docs/src/theme/component.ts b/docs/src/theme/components/Navigation.style.ts
similarity index 50%
rename from docs/src/theme/component.ts
rename to docs/src/theme/components/Navigation.style.ts
index 44c31cde9..8dbcf1089 100644
--- a/docs/src/theme/component.ts
+++ b/docs/src/theme/components/Navigation.style.ts
@@ -1,8 +1,5 @@
-export const component = {
-  navigation: {
-    wrapper: {
-      fontFamily: 'body',
-    },
+export const Navigation = {
+  base: {
     list: {
       p: 'none',
     },
@@ -20,15 +17,4 @@ export const component = {
       pb: 'small',
     },
   },
-  tooltip: {
-    __default: {
-      p: 'xsmall',
-      color: 'gray90',
-      fontSize: 14,
-      border: '1px solid',
-      borderColor: 'blue70',
-      borderRadius: 'large',
-      bg: 'blue10',
-    },
-  },
 } as const;
diff --git a/docs/src/theme/components/Tooltip.style.ts b/docs/src/theme/components/Tooltip.style.ts
new file mode 100644
index 000000000..920bc45ec
--- /dev/null
+++ b/docs/src/theme/components/Tooltip.style.ts
@@ -0,0 +1,66 @@
+import { Theme } from '@marigold/components';
+
+const arrowSize = 6;
+
+export const Tooltip: Theme['components']['Tooltip'] = {
+  base: {
+    container: {
+      color: 'purple10',
+      fontSize: 'xxsmall',
+
+      borderRadius: 'huge',
+      bg: 'blue70',
+
+      p: 'xsmall',
+
+      '&[data-placement="top"]': {
+        mb: arrowSize,
+      },
+
+      '&[data-placement="right"]': {
+        ml: arrowSize,
+      },
+
+      '&[data-placement="bottom"]': {
+        mt: arrowSize,
+      },
+
+      '&[data-placement="left"]': {
+        mr: arrowSize,
+      },
+    },
+
+    arrow: {
+      borderWidth: arrowSize,
+      borderTopColor: 'blue70',
+
+      '[data-placement="right"] &, [data-placement="left"] &': {
+        top: '50%',
+        mt: `-${arrowSize}px`,
+      },
+
+      '[data-placement="top"] &, [data-placement="bottom"] &': {
+        ml: `-${arrowSize}px`,
+      },
+
+      '[data-placement="top"] & ': {
+        top: '100%',
+      },
+
+      '[data-placement="right"] &': {
+        right: '100%',
+        transform: 'rotate(90deg)',
+      },
+
+      '[data-placement="bottom"] & ': {
+        bottom: '100%',
+        transform: 'rotate(180deg)',
+      },
+
+      '[data-placement="left"] &': {
+        left: '100%',
+        transform: 'rotate(270deg)',
+      },
+    },
+  },
+};
diff --git a/docs/src/theme/components/index.ts b/docs/src/theme/components/index.ts
index 4e3292dbb..029765547 100644
--- a/docs/src/theme/components/index.ts
+++ b/docs/src/theme/components/index.ts
@@ -4,5 +4,6 @@ export * from './Divider.style';
 export * from './Headline.style';
 export * from './Link.style';
 export * from './ListBox.style';
+export * from './Navigation.style';
 export * from './Text.style';
 export * from './Select.style';
diff --git a/docs/src/theme/index.ts b/docs/src/theme/index.ts
index d6e8d7019..03db10068 100644
--- a/docs/src/theme/index.ts
+++ b/docs/src/theme/index.ts
@@ -1,10 +1,7 @@
 import { Theme } from '@marigold/components';
 
-// NEW STYLES!
 import * as components from './components';
-
 import { colors } from './colors';
-import { component } from './component';
 
 export const theme: Theme = {
   space: {
@@ -76,7 +73,5 @@ export const theme: Theme = {
     xlarge: 2.5,
     xxlarge: 3,
   },
-  ...component,
-
   components,
 } as const;
diff --git a/package.json b/package.json
index ea70e01df..c0fb796e8 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
     "@testing-library/react": "12.1.5",
     "@testing-library/react-hooks": "7.0.2",
     "@testing-library/user-event": "13.5.0",
-    "@types/node": "16.11.33",
+    "@types/node": "16.11.36",
     "all-contributors-cli": "6.20.0",
     "async-retry": "1.3.3",
     "dotenv": "16.0.0",
diff --git a/packages/components/src/Divider/Divider.tsx b/packages/components/src/Divider/Divider.tsx
index bd4f1885b..6859ec81e 100755
--- a/packages/components/src/Divider/Divider.tsx
+++ b/packages/components/src/Divider/Divider.tsx
@@ -1,8 +1,7 @@
 import React from 'react';
 import { SeparatorProps, useSeparator } from '@react-aria/separator';
 
-import { Box } from '../Box';
-import { ThemeExtension, useComponentStyles } from '@marigold/system';
+import { Box, ThemeExtension, useComponentStyles } from '@marigold/system';
 
 // Theme Extension
 // ---------------
diff --git a/packages/components/src/Inline/Inline.stories.tsx b/packages/components/src/Inline/Inline.stories.tsx
index 52022a45b..ee7ea93ee 100644
--- a/packages/components/src/Inline/Inline.stories.tsx
+++ b/packages/components/src/Inline/Inline.stories.tsx
@@ -1,8 +1,9 @@
-import React from 'react';
+import React, { ReactNode } from 'react';
 import type { Meta, ComponentStory } from '@storybook/react';
-import { Text } from '../Text';
+import { Box } from '@marigold/system';
+import { shadow } from '@marigold/tokens';
+
 import { Inline } from './Inline';
-import { Check } from '@marigold/icons';
 
 export default {
   title: 'Components/Inline',
@@ -22,18 +23,50 @@ export default {
         'xxlarge',
       ],
       description: 'Responsive Style Value',
-      table: {
-        defaultValue: {
-          summary: 'none',
-        },
+    },
+    alignX: {
+      control: {
+        type: 'select',
+      },
+      options: ['left', 'center', 'right'],
+      description: 'Horizontal Alignment',
+    },
+    alignY: {
+      control: {
+        type: 'select',
       },
+      options: ['top', 'center', 'bottom'],
+      description: 'Vertical Alignment',
     },
   },
 } as Meta;
 
+const Block = ({ children }: { children: ReactNode }) => (
+  <Box
+    css={{
+      border: '1px solid #364fc7',
+      borderRadius: 16,
+      bg: '#4263eb',
+      color: '#edf2ff',
+      px: 32,
+      py: 12,
+      boxShadow: shadow['medium-1'],
+    }}
+  >
+    {children}
+  </Box>
+);
+
 export const Basic: ComponentStory<typeof Inline> = args => (
   <Inline {...args}>
-    <Check />
-    <Text>Check</Text>
+    <Block>Lirum</Block>
+    <Block>
+      Larum
+      <br />
+      Larum
+      <br />
+      Larum
+    </Block>
+    <Block>Löffelstiel!</Block>
   </Inline>
 );
diff --git a/packages/components/src/Inline/Inline.tsx b/packages/components/src/Inline/Inline.tsx
index 5361fe064..3017d7241 100755
--- a/packages/components/src/Inline/Inline.tsx
+++ b/packages/components/src/Inline/Inline.tsx
@@ -1,29 +1,46 @@
-import React from 'react';
+import React, { ReactNode } from 'react';
 import { ResponsiveStyleValue } from '@marigold/system';
 
 import { Box } from '../Box';
 
-export interface InlineProps {
-  space?: ResponsiveStyleValue<string>;
-  align?: 'top' | 'center' | 'bottom';
-}
+const ALIGNMENT_X = {
+  left: 'flex-start',
+  center: 'center',
+  right: 'flex-end',
+};
 
-const ALIGNMENT = {
+const ALIGNMENT_Y = {
   top: 'flex-start',
   center: 'center',
   bottom: 'flex-end',
 };
 
-export const Inline: React.FC<InlineProps> = ({
+// Props
+// ---------------
+export interface InlineProps {
+  children?: ReactNode;
+  space?: ResponsiveStyleValue<string>;
+  alignX?: keyof typeof ALIGNMENT_X;
+  alignY?: keyof typeof ALIGNMENT_Y;
+}
+
+// Component
+// ---------------
+export const Inline = ({
   space = 'none',
-  align = 'center',
+  alignX = 'left',
+  alignY = 'center',
   children,
   ...props
-}) => (
+}: InlineProps) => (
   <Box
-    __baseCSS={{ gap: space, flexWrap: 'wrap' }}
-    display="inline-flex"
-    alignItems={ALIGNMENT[align]}
+    css={{
+      display: 'flex',
+      flexWrap: 'wrap',
+      gap: space,
+      alignItems: ALIGNMENT_Y[alignY],
+      justifyContent: ALIGNMENT_X[alignX],
+    }}
     {...props}
   >
     {children}
diff --git a/packages/components/src/Stack/Stack.stories.tsx b/packages/components/src/Stack/Stack.stories.tsx
index 1080d1cdb..3d399ac8e 100644
--- a/packages/components/src/Stack/Stack.stories.tsx
+++ b/packages/components/src/Stack/Stack.stories.tsx
@@ -1,9 +1,11 @@
-import React from 'react';
+import React, { ReactNode } from 'react';
 import type { Meta, ComponentStory } from '@storybook/react';
+import { Box } from '@marigold/system';
+import { shadow } from '@marigold/tokens';
 
 import { Headline } from '../Headline';
-import { Stack } from './Stack';
 import { Text } from '../Text';
+import { Stack } from './Stack';
 
 export default {
   title: 'Components/Stack',
@@ -23,23 +25,27 @@ export default {
         'xxlarge',
       ],
       description: 'Responsive Style Value',
-      table: {
-        defaultValue: {
-          summary: 'none',
-        },
+    },
+    alignX: {
+      control: {
+        type: 'select',
       },
+      options: ['left', 'center', 'right'],
+      description: 'Vertical Alignment',
     },
-    align: {
+    alignY: {
       control: {
         type: 'select',
       },
-      options: ['left', 'right', 'center'],
-      description: 'HTML element style',
-      table: {
-        defaultValue: {
-          summary: 'left',
-        },
+      options: ['top', 'center', 'bottom'],
+      description: 'Vertical Alignment',
+    },
+    stretch: {
+      control: {
+        type: 'boolean',
       },
+      description:
+        'Stretch to fill space (useful if you want to change y alignment)',
     },
   },
 } as Meta;
@@ -111,3 +117,29 @@ export const List: ComponentStory<typeof Stack> = args => (
     </Stack>
   </Stack>
 );
+
+const Block = ({ children }: { children: ReactNode }) => (
+  <Box
+    css={{
+      border: '1px solid #364fc7',
+      borderRadius: 16,
+      bg: '#4263eb',
+      color: '#edf2ff',
+      px: 32,
+      py: 12,
+      boxShadow: shadow['medium-1'],
+    }}
+  >
+    {children}
+  </Box>
+);
+
+export const Stretch: ComponentStory<typeof Stack> = args => (
+  <Box css={{ height: 300 }}>
+    <Stack {...args}>
+      <Block>Lirum</Block>
+      <Block>Larum</Block>
+      <Block>Löffelstiel!</Block>
+    </Stack>
+  </Box>
+);
diff --git a/packages/components/src/Stack/Stack.tsx b/packages/components/src/Stack/Stack.tsx
index b72534101..8266dc9e0 100755
--- a/packages/components/src/Stack/Stack.tsx
+++ b/packages/components/src/Stack/Stack.tsx
@@ -2,33 +2,50 @@ import React, { ReactNode } from 'react';
 import { ResponsiveStyleValue } from '@marigold/system';
 
 import { Box } from '../Box';
+const ALIGNMENT_X = {
+  left: 'flex-start',
+  center: 'center',
+  right: 'flex-end',
+};
 
+const ALIGNMENT_Y = {
+  top: 'flex-start',
+  center: 'center',
+  bottom: 'flex-end',
+};
+
+// Props
+// ---------------
 export interface StackProps {
   as?: 'div' | 'ul' | 'ol';
-  space?: ResponsiveStyleValue<string>;
-  align?: 'left' | 'right' | 'center';
   children?: ReactNode;
+  space?: ResponsiveStyleValue<string>;
+  alignX?: keyof typeof ALIGNMENT_X;
+  alignY?: keyof typeof ALIGNMENT_Y;
+  stretch?: boolean;
 }
 
-const ALIGNMENT = {
-  left: 'flex-start',
-  center: 'center',
-  right: 'flex-end',
-};
-
+// Component
+// ---------------
 export const Stack = ({
-  space = 'none',
-  align = 'left',
   children,
+  space = 'none',
+  alignX = 'left',
+  alignY = 'top',
+  stretch = false,
   ...props
 }: StackProps) => (
   <Box
+    css={{
+      display: 'flex',
+      flexDirection: 'column',
+      p: 0,
+      gap: space,
+      alignItems: ALIGNMENT_X[alignX],
+      justifyContent: ALIGNMENT_Y[alignY],
+      blockSize: stretch ? '100%' : 'auto',
+    }}
     {...props}
-    display="flex"
-    flexDirection="column"
-    alignItems={ALIGNMENT[align]}
-    p="0"
-    css={{ gap: space }}
   >
     {children}
   </Box>
diff --git a/packages/components/src/Table/Context.tsx b/packages/components/src/Table/Context.tsx
new file mode 100644
index 000000000..ae30f539d
--- /dev/null
+++ b/packages/components/src/Table/Context.tsx
@@ -0,0 +1,11 @@
+import { createContext, useContext } from 'react';
+import { TableState } from '@react-stately/table';
+import { ComponentStyleParts } from '@marigold/system';
+
+export interface TableContextProps {
+  state: TableState<object>;
+  styles: ComponentStyleParts<['table', 'header', 'row', 'cell']>;
+}
+
+export const TableContext = createContext<TableContextProps>({} as any);
+export const useTableContext = () => useContext(TableContext);
diff --git a/packages/components/src/Table/Table.stories.tsx b/packages/components/src/Table/Table.stories.tsx
index 890a9305a..f9d43c786 100644
--- a/packages/components/src/Table/Table.stories.tsx
+++ b/packages/components/src/Table/Table.stories.tsx
@@ -14,6 +14,14 @@ export default {
       description: 'selection mode',
       defaultValue: 'none',
     },
+    focusMode: {
+      control: {
+        type: 'select',
+      },
+      options: ['row', 'cell'],
+      description: 'Focus Mode with Keyboard',
+      defaultValue: 'row',
+    },
   },
 } as Meta;
 
@@ -116,3 +124,45 @@ export const ControlledTable: ComponentStory<typeof Table> = args => {
     </Stack>
   );
 };
+
+// https://react-spectrum.adobe.com/react-aria/useTable.html#nested-columns
+export const NestedColumns: ComponentStory<typeof Table> = () => (
+  <Table aria-label="Example table for nested columns">
+    <Table.Header>
+      <Table.Column title="Name">
+        <Table.Column isRowHeader>First Name</Table.Column>
+        <Table.Column isRowHeader>Last Name</Table.Column>
+      </Table.Column>
+      <Table.Column title="Information">
+        <Table.Column>Age</Table.Column>
+        <Table.Column>Birthday</Table.Column>
+      </Table.Column>
+    </Table.Header>
+    <Table.Body>
+      <Table.Row>
+        <Table.Cell>Sam</Table.Cell>
+        <Table.Cell>Smith</Table.Cell>
+        <Table.Cell>36</Table.Cell>
+        <Table.Cell>May 3</Table.Cell>
+      </Table.Row>
+      <Table.Row>
+        <Table.Cell>Julia</Table.Cell>
+        <Table.Cell>Jones</Table.Cell>
+        <Table.Cell>24</Table.Cell>
+        <Table.Cell>February 10</Table.Cell>
+      </Table.Row>
+      <Table.Row>
+        <Table.Cell>Peter</Table.Cell>
+        <Table.Cell>Parker</Table.Cell>
+        <Table.Cell>28</Table.Cell>
+        <Table.Cell>September 7</Table.Cell>
+      </Table.Row>
+      <Table.Row>
+        <Table.Cell>Bruce</Table.Cell>
+        <Table.Cell>Wayne</Table.Cell>
+        <Table.Cell>32</Table.Cell>
+        <Table.Cell>December 18</Table.Cell>
+      </Table.Row>
+    </Table.Body>
+  </Table>
+);
diff --git a/packages/components/src/Table/Table.tsx b/packages/components/src/Table/Table.tsx
index 37129df2e..9867a5189 100755
--- a/packages/components/src/Table/Table.tsx
+++ b/packages/components/src/Table/Table.tsx
@@ -4,21 +4,27 @@ import {
   Cell,
   Column,
   Row,
-  TableBody,
-  TableHeader,
+  TableBody as Body,
+  TableHeader as Header,
   TableStateProps,
   useTableState,
 } from '@react-stately/table';
 
-import { ThemeExtensionsWithParts, useComponentStyles } from '@marigold/system';
-
-import { Box } from '../Box';
+import {
+  Box,
+  ThemeExtensionsWithParts,
+  useComponentStyles,
+} from '@marigold/system';
 
+import { TableContext } from './Context';
+import { TableBody } from './TableBody';
 import { TableCell } from './TableCell';
+import { TableCheckboxCell } from './TableCheckboxCell';
 import { TableColumnHeader } from './TableColumnHeader';
+import { TableHeader } from './TableHeader';
 import { TableHeaderRow } from './TableHeaderRow';
 import { TableRow } from './TableRow';
-import { TableRowGroup } from './TableRowGroup';
+import { TableSelectAllCell } from './TableSelectAllCell';
 
 // Theme Extension
 // ---------------
@@ -31,8 +37,11 @@ export interface TableThemeExtension
 // Props
 // ---------------
 export interface TableProps
-  extends Pick<AriaTableProps<object>, 'onRowAction' | 'onCellAction'>,
-    TableStateProps<object> {
+  extends Pick<
+      AriaTableProps<object>,
+      'focusMode' | 'onRowAction' | 'onCellAction'
+    >,
+    Omit<TableStateProps<object>, 'showSelectionCheckboxes'> {
   variant?: string;
   size?: string;
 }
@@ -40,16 +49,15 @@ export interface TableProps
 // Table Component
 // ---------------
 export const Table: Table = ({ variant, size, ...props }: TableProps) => {
-  // Setup table state and mode
-  const showSelectionCheckboxes =
-    props.selectionMode === 'multiple' && props.selectionBehavior !== 'replace';
+  const tableRef = useRef(null);
   const state = useTableState({
     ...props,
-    showSelectionCheckboxes,
+    showSelectionCheckboxes:
+      props.selectionMode === 'multiple' &&
+      // TODO: It this necessary?
+      props.selectionBehavior !== 'replace',
   });
-
-  const ref = useRef(null);
-  const { gridProps } = useTable(props, state, ref);
+  const { gridProps } = useTable(props, state, tableRef);
 
   const styles = useComponentStyles(
     'Table',
@@ -57,58 +65,58 @@ export const Table: Table = ({ variant, size, ...props }: TableProps) => {
     { parts: ['table', 'header', 'row', 'cell'] }
   );
 
+  const { collection } = state;
+
   return (
-    <Box as="table" ref={ref} __baseCSS={styles.table} {...gridProps}>
-      <TableRowGroup as="thead">
-        {state.collection.headerRows.map(headerRow => (
-          <TableHeaderRow key={headerRow.key} item={headerRow} state={state}>
-            {[...headerRow.childNodes].map(column => (
-              <TableColumnHeader
-                key={column.key}
-                item={column}
-                state={state}
-                isSelectionColumn={column.props.isSelectionCell}
-                css={styles.header}
-              />
-            ))}
-          </TableHeaderRow>
-        ))}
-      </TableRowGroup>
-      <TableRowGroup as="tbody">
-        {[...state.collection.body.childNodes].map(row => (
-          <TableRow css={styles.row} key={row.key} item={row} state={state}>
-            {[...row.childNodes].map(cell => (
-              <TableCell
-                key={cell.key}
-                item={cell}
-                state={state}
-                isSelectionCell={cell.props.isSelectionCell}
-                css={styles.cell}
-              />
-            ))}
-          </TableRow>
-        ))}
-      </TableRowGroup>
-    </Box>
+    <TableContext.Provider value={{ state, styles }}>
+      <Box as="table" ref={tableRef} css={styles.table} {...gridProps}>
+        <TableHeader>
+          {collection.headerRows.map(headerRow => (
+            <TableHeaderRow key={headerRow.key} item={headerRow}>
+              {[...headerRow.childNodes].map(column =>
+                column.props?.isSelectionCell ? (
+                  <TableSelectAllCell key={column.key} column={column} />
+                ) : (
+                  <TableColumnHeader key={column.key} column={column} />
+                )
+              )}
+            </TableHeaderRow>
+          ))}
+        </TableHeader>
+        <TableBody>
+          {[...collection.body.childNodes].map(row => (
+            <TableRow key={row.key} row={row}>
+              {[...row.childNodes].map(cell =>
+                cell.props?.isSelectionCell ? (
+                  <TableCheckboxCell key={cell.key} cell={cell} />
+                ) : (
+                  <TableCell key={cell.key} cell={cell} />
+                )
+              )}
+            </TableRow>
+          ))}
+        </TableBody>
+      </Box>
+    </TableContext.Provider>
   );
 };
 
 // Export collection components to conveniently have access to them.
-Table.Body = TableBody;
+Table.Body = Body;
 Table.Cell = Cell;
 Table.Column = Column;
-Table.Header = TableHeader;
+Table.Header = Header;
 Table.Row = Row;
 
 /**
  * Necessary since TypeScript can not infer the
- * types of the @react-stately components correctly.
+ * types of the @react-stately components.
  */
 interface Table {
   (props: TableProps): JSX.Element;
-  Body: typeof TableBody;
+  Body: typeof Body;
   Cell: typeof Cell;
   Column: typeof Column;
-  Header: typeof TableHeader;
+  Header: typeof Header;
   Row: typeof Row;
 }
diff --git a/packages/components/src/Table/TableBody.tsx b/packages/components/src/Table/TableBody.tsx
new file mode 100644
index 000000000..2dc28f08b
--- /dev/null
+++ b/packages/components/src/Table/TableBody.tsx
@@ -0,0 +1,11 @@
+import React, { ReactNode } from 'react';
+import { useTableRowGroup } from '@react-aria/table';
+
+export interface TableBodyProps {
+  children: ReactNode;
+}
+
+export const TableBody = ({ children }: TableBodyProps) => {
+  const { rowGroupProps } = useTableRowGroup();
+  return <tbody {...rowGroupProps}>{children}</tbody>;
+};
diff --git a/packages/components/src/Table/TableCell.tsx b/packages/components/src/Table/TableCell.tsx
index 4f995f139..6ec8b038c 100644
--- a/packages/components/src/Table/TableCell.tsx
+++ b/packages/components/src/Table/TableCell.tsx
@@ -1,65 +1,41 @@
 import React, { useRef } from 'react';
-import { useCheckbox } from '@react-aria/checkbox';
+import { useTableCell } from '@react-aria/table';
 import { useFocusRing } from '@react-aria/focus';
-import { useTableCell, useTableSelectionCheckbox } from '@react-aria/table';
 import { mergeProps } from '@react-aria/utils';
-import { TableState } from '@react-stately/table';
-import { useToggleState } from '@react-stately/toggle';
-import { Node } from '@react-types/shared';
+import { GridNode } from '@react-types/grid';
 
-import { CSSObject, useStateProps } from '@marigold/system';
+import { Box, useStateProps } from '@marigold/system';
 
-import { Box } from '../Box';
+import { useTableContext } from './Context';
 
-// Props
-// ----------------------------
 export interface TableCellProps {
-  item: Node<object>;
-  state: TableState<object>;
-  /**
-   * Wheter it is a cell with a checkbox or a regular data cell
-   */
-  isSelectionCell?: boolean;
-  css?: CSSObject;
+  cell: GridNode<object>;
 }
 
-// TableCell Component
-// ----------------------------
-export const TableCell = ({
-  item: cell,
-  state,
-  isSelectionCell,
-  css,
-}: TableCellProps) => {
-  const cellRef = useRef(null);
-  const { gridCellProps } = useTableCell({ node: cell }, state, cellRef);
-
-  const { checkboxProps } = useTableSelectionCheckbox(
-    { key: cell.parentKey! },
-    state
-  );
-  const inputRef = useRef(null);
-  const { inputProps } = useCheckbox(
-    checkboxProps,
-    useToggleState(checkboxProps),
-    inputRef
+export const TableCell = ({ cell }: TableCellProps) => {
+  const ref = useRef(null);
+  const { state, styles } = useTableContext();
+  const disabled = state.disabledKeys.has(cell.parentKey!);
+  const { gridCellProps } = useTableCell(
+    {
+      node: cell,
+    },
+    state,
+    ref
   );
 
   const { focusProps, isFocusVisible } = useFocusRing();
-  const stateProps = useStateProps({ focus: isFocusVisible });
+  const stateProps = useStateProps({ disabled, focusVisible: isFocusVisible });
 
   return (
     <Box
       as="td"
-      ref={cellRef}
-      __baseCSS={{
-        textAlign: isSelectionCell ? 'center' : 'left',
-      }}
-      css={css}
+      ref={ref}
+      css={styles.cell}
       {...mergeProps(gridCellProps, focusProps)}
       {...stateProps}
     >
-      {isSelectionCell ? <input {...inputProps} /> : <>{cell.rendered}</>}
+      {cell.rendered}
     </Box>
   );
 };
diff --git a/packages/components/src/Table/TableCheckboxCell.tsx b/packages/components/src/Table/TableCheckboxCell.tsx
new file mode 100644
index 000000000..7b100f53b
--- /dev/null
+++ b/packages/components/src/Table/TableCheckboxCell.tsx
@@ -0,0 +1,52 @@
+import React, { useRef } from 'react';
+import { useTableCell, useTableSelectionCheckbox } from '@react-aria/table';
+import { useFocusRing } from '@react-aria/focus';
+import { mergeProps } from '@react-aria/utils';
+import { GridNode } from '@react-types/grid';
+
+import { Box, useStateProps } from '@marigold/system';
+
+import { Checkbox } from '../Checkbox';
+import { useTableContext } from './Context';
+import { mapCheckboxProps } from './utils';
+
+export interface TableCheckboxCellProps {
+  cell: GridNode<object>;
+}
+
+export const TableCheckboxCell = ({ cell }: TableCheckboxCellProps) => {
+  const ref = useRef(null);
+  const { state, styles } = useTableContext();
+  const disabled = state.disabledKeys.has(cell.parentKey!);
+  const { gridCellProps } = useTableCell(
+    {
+      node: cell,
+    },
+    state,
+    ref
+  );
+
+  const { checkboxProps } = mapCheckboxProps(
+    useTableSelectionCheckbox({ key: cell.parentKey! }, state)
+  );
+
+  const { focusProps, isFocusVisible } = useFocusRing();
+  const stateProps = useStateProps({ disabled, focusVisible: isFocusVisible });
+
+  return (
+    <Box
+      as="td"
+      ref={ref}
+      __baseCSS={{
+        textAlign: 'center',
+        verticalAlign: 'middle',
+        lineHeight: 1,
+      }}
+      css={styles.cell}
+      {...mergeProps(gridCellProps, focusProps)}
+      {...stateProps}
+    >
+      <Checkbox {...checkboxProps} />
+    </Box>
+  );
+};
diff --git a/packages/components/src/Table/TableColumnHeader.tsx b/packages/components/src/Table/TableColumnHeader.tsx
index cb3adfbda..75d834d53 100644
--- a/packages/components/src/Table/TableColumnHeader.tsx
+++ b/packages/components/src/Table/TableColumnHeader.tsx
@@ -1,70 +1,47 @@
-import React, { ReactNode, useRef } from 'react';
-import { useCheckbox } from '@react-aria/checkbox';
+import React, { useRef } from 'react';
+
 import { useFocusRing } from '@react-aria/focus';
-import {
-  useTableSelectAllCheckbox,
-  useTableColumnHeader,
-} from '@react-aria/table';
+import { useHover } from '@react-aria/interactions';
+import { useTableColumnHeader } from '@react-aria/table';
 import { mergeProps } from '@react-aria/utils';
-import { TableState } from '@react-stately/table';
-import { useToggleState } from '@react-stately/toggle';
-import { Node } from '@react-types/shared';
+import { GridNode } from '@react-types/grid';
 
-import { CSSObject, useStateProps } from '@marigold/system';
+import { Box, useStateProps } from '@marigold/system';
 
-import { Box } from '../Box';
-import { Text } from '../Text';
+import { useTableContext } from './Context';
 
-// Props
-// ----------------------------
-export interface TableColumnHeaderProps {
-  chilren?: ReactNode;
-  item: Node<object>;
-  state: TableState<object>;
-  isSelectionColumn?: boolean;
-  css?: CSSObject;
+interface TableColumnHeaderProps {
+  column: GridNode<object>;
 }
 
-// TableColumnHeader Component
-// ----------------------------
-export const TableColumnHeader = ({
-  item: column,
-  state,
-  isSelectionColumn,
-  css,
-}: TableColumnHeaderProps) => {
+export const TableColumnHeader = ({ column }: TableColumnHeaderProps) => {
   const ref = useRef(null);
+  const { state, styles } = useTableContext();
   const { columnHeaderProps } = useTableColumnHeader(
-    { node: column },
+    {
+      node: column,
+    },
     state,
     ref
   );
 
-  const { checkboxProps } = useTableSelectAllCheckbox(state);
-  const inputRef = useRef(null);
-  const { inputProps } = useCheckbox(
-    checkboxProps,
-    useToggleState(checkboxProps),
-    inputRef
-  );
-
+  const { hoverProps, isHovered } = useHover({});
   const { focusProps, isFocusVisible } = useFocusRing();
-  const stateProps = useStateProps({ focus: isFocusVisible });
+  const stateProps = useStateProps({
+    hover: isHovered,
+    focusVisible: isFocusVisible,
+  });
 
   return (
     <Box
       as="th"
+      colSpan={column.colspan}
       ref={ref}
-      __baseCSS={{ textAlign: isSelectionColumn ? 'center' : 'left' }}
-      css={css}
-      {...mergeProps(columnHeaderProps, focusProps)}
+      css={styles.header}
+      {...mergeProps(columnHeaderProps, hoverProps, focusProps)}
       {...stateProps}
     >
-      {isSelectionColumn ? (
-        <input {...inputProps} ref={inputRef} />
-      ) : (
-        <Text size="xxsmall">{column.rendered}</Text>
-      )}
+      {column.rendered}
     </Box>
   );
 };
diff --git a/packages/components/src/Table/TableHeader.tsx b/packages/components/src/Table/TableHeader.tsx
new file mode 100644
index 000000000..20a408446
--- /dev/null
+++ b/packages/components/src/Table/TableHeader.tsx
@@ -0,0 +1,11 @@
+import React, { ReactNode } from 'react';
+import { useTableRowGroup } from '@react-aria/table';
+
+export interface TableHeaderProps {
+  children: ReactNode;
+}
+
+export const TableHeader = ({ children }: TableHeaderProps) => {
+  const { rowGroupProps } = useTableRowGroup();
+  return <thead {...rowGroupProps}>{children}</thead>;
+};
diff --git a/packages/components/src/Table/TableHeaderRow.tsx b/packages/components/src/Table/TableHeaderRow.tsx
index cf147bf28..ce67f5c6c 100644
--- a/packages/components/src/Table/TableHeaderRow.tsx
+++ b/packages/components/src/Table/TableHeaderRow.tsx
@@ -1,23 +1,21 @@
 import React, { ReactNode, useRef } from 'react';
 import { useTableHeaderRow } from '@react-aria/table';
-import { TableState } from '@react-stately/table';
-import { Node } from '@react-types/shared';
+import { GridNode } from '@react-types/grid';
+
+import { useTableContext } from './Context';
 
 // Props
-// ----------------------------
+// ---------------
 export interface TableHeaderRowProps {
-  item: Node<object>;
-  state: TableState<object>;
-  children?: ReactNode;
+  children: ReactNode;
+  item: GridNode<object>;
 }
 
-// TableHeaderRow Component
-// ----------------------------
-export const TableHeaderRow = ({
-  item,
-  state,
-  children,
-}: TableHeaderRowProps) => {
+// Component
+// ---------------
+export const TableHeaderRow = ({ item, children }: TableHeaderRowProps) => {
+  const { state } = useTableContext();
+
   const ref = useRef(null);
   const { rowProps } = useTableHeaderRow({ node: item }, state, ref);
 
diff --git a/packages/components/src/Table/TableRow.tsx b/packages/components/src/Table/TableRow.tsx
index bbc8e750c..c081e61b0 100644
--- a/packages/components/src/Table/TableRow.tsx
+++ b/packages/components/src/Table/TableRow.tsx
@@ -1,47 +1,55 @@
 import React, { ReactNode, useRef } from 'react';
 import { useFocusRing } from '@react-aria/focus';
+import { useHover } from '@react-aria/interactions';
 import { useTableRow } from '@react-aria/table';
 import { mergeProps } from '@react-aria/utils';
-import { TableState } from '@react-stately/table';
-import { Node } from '@react-types/shared';
+import { GridNode } from '@react-types/grid';
 
-import { CSSObject, useStateProps } from '@marigold/system';
+import { Box, useStateProps } from '@marigold/system';
 
-import { Box } from '../Box';
+import { useTableContext } from './Context';
 
 // Props
-// ----------------------------
+// ---------------
 export interface TableRowProps {
   children?: ReactNode;
-  item: Node<object>;
-  state: TableState<object>;
-  css?: CSSObject;
+  row: GridNode<object>;
 }
 
-// TableRow Component
-// ----------------------------
-export const TableRow = ({ item, state, children, css }: TableRowProps) => {
+// Component
+// ---------------
+export const TableRow = ({ children, row }: TableRowProps) => {
   const ref = useRef(null);
-  const isSelected = state.selectionManager.isSelected(item.key);
-  const { rowProps } = useTableRow(
+  const { state, styles } = useTableContext();
+  const { rowProps, isPressed } = useTableRow(
     {
-      node: item,
+      node: row,
     },
     state,
     ref
   );
-  const { focusProps, isFocusVisible } = useFocusRing();
+
+  const disabled = state.disabledKeys.has(row.key);
+  const selected = state.selectionManager.isSelected(row.key);
+
+  // Rows are focused if any cell inside it is focused
+  const { focusProps, isFocusVisible } = useFocusRing({ within: true });
+  const { hoverProps, isHovered } = useHover({ isDisabled: disabled });
+
   const stateProps = useStateProps({
-    focus: isFocusVisible,
-    checked: isSelected,
+    disabled,
+    selected,
+    hover: isHovered,
+    focusVisible: isFocusVisible,
+    active: isPressed,
   });
 
   return (
     <Box
       as="tr"
       ref={ref}
-      css={css}
-      {...mergeProps(rowProps, focusProps)}
+      css={styles.row}
+      {...mergeProps(rowProps, focusProps, hoverProps)}
       {...stateProps}
     >
       {children}
diff --git a/packages/components/src/Table/TableRowGroup.tsx b/packages/components/src/Table/TableRowGroup.tsx
deleted file mode 100644
index f3643c4bf..000000000
--- a/packages/components/src/Table/TableRowGroup.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import React, { ReactNode } from 'react';
-import { useTableRowGroup } from '@react-aria/table';
-
-// Props
-// ----------------------------
-export interface TableRowGroupProps {
-  children?: ReactNode;
-  as: 'thead' | 'tbody' | 'tfoot';
-}
-
-// TableRowGroup Component
-// ----------------------------
-export const TableRowGroup = ({
-  as: Element,
-  children,
-}: TableRowGroupProps) => {
-  const { rowGroupProps } = useTableRowGroup();
-  return <Element {...rowGroupProps}>{children}</Element>;
-};
diff --git a/packages/components/src/Table/TableSelectAllCell.tsx b/packages/components/src/Table/TableSelectAllCell.tsx
new file mode 100644
index 000000000..3d394f8d4
--- /dev/null
+++ b/packages/components/src/Table/TableSelectAllCell.tsx
@@ -0,0 +1,62 @@
+import React, { useRef } from 'react';
+
+import { useFocusRing } from '@react-aria/focus';
+import { useHover } from '@react-aria/interactions';
+import {
+  useTableColumnHeader,
+  useTableSelectAllCheckbox,
+} from '@react-aria/table';
+import { mergeProps } from '@react-aria/utils';
+import { GridNode } from '@react-types/grid';
+
+import { Box, useStateProps } from '@marigold/system';
+
+import { Checkbox } from '../Checkbox';
+import { useTableContext } from './Context';
+import { mapCheckboxProps } from './utils';
+
+// Props
+// ---------------
+export interface TableSelectAllCell {
+  column: GridNode<object>;
+}
+
+// Component
+// ---------------
+export const TableSelectAllCell = ({ column }: TableSelectAllCell) => {
+  const ref = useRef(null);
+  const { state, styles } = useTableContext();
+  const { columnHeaderProps } = useTableColumnHeader(
+    {
+      node: column,
+    },
+    state,
+    ref
+  );
+
+  const { checkboxProps } = mapCheckboxProps(useTableSelectAllCheckbox(state));
+
+  const { hoverProps, isHovered } = useHover({});
+  const { focusProps, isFocusVisible } = useFocusRing();
+  const stateProps = useStateProps({
+    hover: isHovered,
+    focusVisible: isFocusVisible,
+  });
+
+  return (
+    <Box
+      as="th"
+      ref={ref}
+      __baseCSS={{
+        textAlign: 'center',
+        verticalAlign: 'middle',
+        lineHeight: 1,
+      }}
+      css={styles.header}
+      {...mergeProps(columnHeaderProps, hoverProps, focusProps)}
+      {...stateProps}
+    >
+      <Checkbox {...checkboxProps} />
+    </Box>
+  );
+};
diff --git a/packages/components/src/Table/utils.ts b/packages/components/src/Table/utils.ts
new file mode 100644
index 000000000..6a45959aa
--- /dev/null
+++ b/packages/components/src/Table/utils.ts
@@ -0,0 +1,28 @@
+import { AriaCheckboxProps } from '@react-types/checkbox';
+
+export interface MapCheckboxProps {
+  checkboxProps: AriaCheckboxProps;
+}
+
+/**
+ * Map `react-aria` props to ours (no "is"-prefix)
+ */
+export const mapCheckboxProps = ({
+  checkboxProps: {
+    isIndeterminate,
+    isSelected,
+    isDisabled,
+    defaultSelected,
+    ...rest
+  },
+}: MapCheckboxProps) => {
+  const checkboxProps = {
+    disabled: isDisabled,
+    checked: isSelected,
+    defaultChecked: defaultSelected,
+    indeterminate: isIndeterminate,
+    ...rest,
+  } as const;
+
+  return { checkboxProps };
+};
diff --git a/packages/components/src/Tiles/Tiles.stories.tsx b/packages/components/src/Tiles/Tiles.stories.tsx
index 9f49595d4..0e0d73239 100644
--- a/packages/components/src/Tiles/Tiles.stories.tsx
+++ b/packages/components/src/Tiles/Tiles.stories.tsx
@@ -58,7 +58,7 @@ export const Boxes: ComponentStory<typeof Tiles> = args => (
 export const Stacks: ComponentStory<typeof Tiles> = args => (
   <Tiles {...args}>
     <Box border="1px solid #fa8005" bg="orange10" p="small">
-      <Stack space="medium" align="center">
+      <Stack space="medium" alignX="center">
         <Image
           src="https://www.pokewiki.de/images/6/63/Sugimori_004.png"
           alt="glumanda"
@@ -74,7 +74,7 @@ export const Stacks: ComponentStory<typeof Tiles> = args => (
       </Stack>
     </Box>
     <Box border="1px solid #fa8005" bg="orange10" p="small">
-      <Stack space="medium" align="center">
+      <Stack space="medium" alignX="center">
         <Image
           src="https://www.pokewiki.de/images/7/7a/Sugimori_005.png"
           alt="glutexo"
@@ -91,7 +91,7 @@ export const Stacks: ComponentStory<typeof Tiles> = args => (
       </Stack>
     </Box>
     <Box border="1px solid #fa8005" bg="orange10" p="small">
-      <Stack space="medium" align="center">
+      <Stack space="medium" alignX="center">
         <Image
           src="https://www.pokewiki.de/images/9/96/Sugimori_006.png"
           alt="glurak"
diff --git a/packages/system/src/components/Box/Box.tsx b/packages/system/src/components/Box/Box.tsx
index ccd1606a7..da29a3228 100644
--- a/packages/system/src/components/Box/Box.tsx
+++ b/packages/system/src/components/Box/Box.tsx
@@ -9,8 +9,7 @@ import {
 } from '@marigold/types';
 
 import { getNormalizedStyles } from '../../normalize';
-import { CSSObject } from '../../types/system';
-import { ensureArrayVariant } from '../../variant';
+import { CSSObject } from '../../types';
 import { transformPseudos } from './utils';
 
 export interface StyleProps
@@ -58,10 +57,9 @@ export interface StyleProps
 
 export interface BoxOwnProps extends StyleProps {
   css?: CSSObject;
-  variant?: string | string[];
   /**
    * Use to set base styles for the component
-   * @internal Used to set default styles for Marigold components
+   * @internal
    */
   __baseCSS?: CSSObject;
 }
@@ -71,20 +69,16 @@ export interface BoxProps extends PolymorphicPropsWithRef<BoxOwnProps, 'div'> {}
 interface CreateStyleProps {
   as?: BoxProps['as'];
   __baseCSS?: BoxOwnProps['__baseCSS'];
-  variant?: BoxOwnProps['variant'];
   css?: BoxOwnProps['css'];
   styles?: StyleProps;
 }
 
 const createThemedStyle =
-  ({ as, __baseCSS, variant, styles, css }: CreateStyleProps) =>
+  ({ as, __baseCSS, styles, css }: CreateStyleProps) =>
   (theme: Theme) => {
     const themedStyles = merge.all([
       getNormalizedStyles(as),
       transformStyleObject(__baseCSS)(theme),
-      ...ensureArrayVariant(variant).map(v =>
-        transformStyleObject({ variant: v })(theme)
-      ),
       transformStyleObject(styles)(theme),
       transformStyleObject(css)(theme),
     ]) as CSSObject;
@@ -98,8 +92,7 @@ export const Box: PolymorphicComponentWithRef<BoxOwnProps, 'div'> = forwardRef(
       as = 'div',
       children,
       __baseCSS,
-      variant,
-      css = {},
+      css,
       display,
       height,
       width,
@@ -149,7 +142,6 @@ export const Box: PolymorphicComponentWithRef<BoxOwnProps, 'div'> = forwardRef(
         css: createThemedStyle({
           as,
           __baseCSS,
-          variant,
           css,
           styles: {
             display,
diff --git a/packages/system/src/index.ts b/packages/system/src/index.ts
index 612314ba6..711d26589 100644
--- a/packages/system/src/index.ts
+++ b/packages/system/src/index.ts
@@ -3,4 +3,3 @@ export * from './hooks';
 export * from './types';
 
 export * from './normalize';
-export * from './variant';
diff --git a/packages/system/src/variant.ts b/packages/system/src/variant.ts
deleted file mode 100644
index f694c5d0e..000000000
--- a/packages/system/src/variant.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-const isNil = (value: any): value is null | undefined =>
-  value === null || value === undefined;
-
-/**
- * Ensures that the `val` is an array. Will return an empty array if `val` is falsy.
- */
-export const ensureArray = <T>(val?: T | T[]) =>
-  isNil(val) ? [] : Array.isArray(val) ? val : [val];
-
-/**
- * Removes trailing dot from variant, if necessary. This is necessary to support
- * `__default` styles. See https://github.com/system-ui/theme-ui/pull/951
- */
-export const ensureVariantDefault = (val: string) => val.replace(/\.$/, '');
-
-/**
- * Ensures that the `variant` is an array and supports the `__default` key.
- */
-export const ensureArrayVariant = <T extends string>(variant?: T | T[]) =>
-  ensureArray(variant).map(ensureVariantDefault);
-
-export interface State {
-  checked?: boolean;
-  focus?: boolean;
-  hover?: boolean;
-  disabled?: boolean;
-  error?: boolean;
-}
-
-/**
- * Appends given `state` to a `variant`.
- */
-export const appendVariantState = (variant: string, state: keyof State) => {
-  return `${ensureVariantDefault(variant)}.:${state}`;
-};
-
-/**
- * Create a variant array from a `variant` and `state` containing
- * passed states, if they are truthy.
- */
-export const conditional = (
-  variant: string,
-  { disabled = false, ...states }: State
-) => {
-  const entries = [...Object.entries(states), ['disabled', disabled]] as [
-    keyof State,
-    boolean
-  ][];
-  const stateVariants = entries
-    .filter(([, val]) => Boolean(val))
-    .map(([key]) => appendVariantState(variant, key));
-
-  return [variant, ...stateVariants];
-};
diff --git a/packages/tokens/src/shadow.stories.tsx b/packages/tokens/src/shadow.stories.tsx
index c3a6c545f..627632b19 100644
--- a/packages/tokens/src/shadow.stories.tsx
+++ b/packages/tokens/src/shadow.stories.tsx
@@ -23,7 +23,7 @@ export const Shadows = () => {
   const shadow = Token.shadow;
   return (
     <Box bg={Token.color.gray['30']} p={40}>
-      <Stack space="32px" align="center">
+      <Stack space="32px" alignX="center">
         {Object.values(shadow).map(value => (
           <Shadow key={value} value={value} />
         ))}
diff --git a/packages/tokens/src/typography.stories.tsx b/packages/tokens/src/typography.stories.tsx
index 6fea00fc9..855ef0207 100644
--- a/packages/tokens/src/typography.stories.tsx
+++ b/packages/tokens/src/typography.stories.tsx
@@ -9,7 +9,7 @@ export default {
 } as Meta;
 
 export const Fonts = () => (
-  <Stack space="32px" align="center">
+  <Stack space="32px" alignX="center">
     {Object.values(Token.typography.font).map(value => (
       <Box key={value} css={{ fontFamily: value }}>
         A wizard's job is to vex chumps quickly in fog.
@@ -19,7 +19,7 @@ export const Fonts = () => (
 );
 
 export const LineHeights = () => (
-  <Stack space="32px" align="center">
+  <Stack space="32px" alignX="center">
     {Object.values(Token.typography.lineHeight).map(value => (
       <Box
         key={value}
@@ -41,7 +41,7 @@ export const LineHeights = () => (
 );
 
 export const LetterSpacing = () => (
-  <Stack space="32px" align="center">
+  <Stack space="32px" alignX="center">
     {Object.values(Token.typography.letterSpacing).map(value => (
       <Box
         key={value}
@@ -57,7 +57,7 @@ export const LetterSpacing = () => (
 );
 
 export const FontSizes = () => (
-  <Stack space="32px" align="center">
+  <Stack space="32px" alignX="center">
     {Object.values(Token.typography.size.fixed).map(value => (
       <Box
         key={value}
@@ -73,7 +73,7 @@ export const FontSizes = () => (
 );
 
 export const FluidFontSizes = () => (
-  <Stack space="32px" align="center">
+  <Stack space="32px" alignX="center">
     {Object.values(Token.typography.size.fluid).map(value => (
       <Box
         key={value}
@@ -89,7 +89,7 @@ export const FluidFontSizes = () => (
 );
 
 export const FontWeights = () => (
-  <Stack space="32px" align="center">
+  <Stack space="32px" alignX="center">
     {Object.values(Token.typography.weight).map(value => (
       <Box
         key={value}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3e19322f9..191392c80 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -17,7 +17,7 @@ importers:
       '@testing-library/react': 12.1.5
       '@testing-library/react-hooks': 7.0.2
       '@testing-library/user-event': 13.5.0
-      '@types/node': 16.11.33
+      '@types/node': 16.11.36
       all-contributors-cli: 6.20.0
       async-retry: 1.3.3
       dotenv: 16.0.0
@@ -47,13 +47,13 @@ importers:
       '@testing-library/react': 12.1.5_sfoxds7t5ydpegc3knd667wn6m
       '@testing-library/react-hooks': 7.0.2_sfoxds7t5ydpegc3knd667wn6m
       '@testing-library/user-event': 13.5.0_tlwynutqiyp5mns3woioasuxnq
-      '@types/node': 16.11.33
+      '@types/node': 16.11.36
       all-contributors-cli: 6.20.0
       async-retry: 1.3.3
       dotenv: 16.0.0
       eslint: 8.12.0
       husky: 8.0.1
-      jest: 28.1.0_@types+node@16.11.33
+      jest: 28.1.0_@types+node@16.11.36
       jest-environment-jsdom: 28.1.0
       prettier: 2.6.2
       pretty-quick: 3.1.3_prettier@2.6.2
@@ -110,7 +110,7 @@ importers:
   config/jest:
     specifiers:
       '@babel/core': 7.17.12
-      '@swc/core': 1.2.186
+      '@swc/core': 1.2.189
       '@swc/jest': 0.2.21
       '@types/jest': 27.4.1
       babel-jest: 28.1.0
@@ -124,8 +124,8 @@ importers:
       typescript: 4.6.4
     dependencies:
       '@babel/core': 7.17.12
-      '@swc/core': 1.2.186
-      '@swc/jest': 0.2.21_@swc+core@1.2.186
+      '@swc/core': 1.2.189
+      '@swc/jest': 0.2.21_@swc+core@1.2.189
       '@types/jest': 27.4.1
       babel-jest: 28.1.0_@babel+core@7.17.12
       find-up: 5.0.0
@@ -6538,7 +6538,7 @@ packages:
       '@storybook/store': 6.5.0_sfoxds7t5ydpegc3knd667wn6m
       '@storybook/theming': 6.5.0_sfoxds7t5ydpegc3knd667wn6m
       '@storybook/ui': 6.5.0_sfoxds7t5ydpegc3knd667wn6m
-      '@types/node': 16.11.33
+      '@types/node': 16.11.36
       '@types/webpack': 4.41.32
       autoprefixer: 9.8.8
       babel-loader: 8.2.5_tlrwjfnbl7llelxqoonrmw2kde
@@ -6859,7 +6859,7 @@ packages:
       '@babel/register': 7.17.7_@babel+core@7.17.12
       '@storybook/node-logger': 6.5.0
       '@storybook/semver': 7.3.2
-      '@types/node': 16.11.33
+      '@types/node': 16.11.36
       '@types/pretty-hrtime': 1.0.1
       babel-loader: 8.2.5_tlrwjfnbl7llelxqoonrmw2kde
       babel-plugin-macros: 3.1.0
@@ -6930,7 +6930,7 @@ packages:
       '@babel/register': 7.17.7_@babel+core@7.17.12
       '@storybook/node-logger': 6.5.0
       '@storybook/semver': 7.3.2
-      '@types/node': 16.11.33
+      '@types/node': 16.11.36
       '@types/pretty-hrtime': 1.0.1
       babel-loader: 8.2.5_tlrwjfnbl7llelxqoonrmw2kde
       babel-plugin-macros: 3.1.0
@@ -7013,7 +7013,7 @@ packages:
       '@storybook/semver': 7.3.2
       '@storybook/store': 6.5.0_sfoxds7t5ydpegc3knd667wn6m
       '@storybook/telemetry': 6.5.0_4uwuwa3tsio6lextjybsu5dmay
-      '@types/node': 16.11.33
+      '@types/node': 16.11.36
       '@types/node-fetch': 2.6.1
       '@types/pretty-hrtime': 1.0.1
       '@types/webpack': 4.41.32
@@ -7214,7 +7214,7 @@ packages:
       '@storybook/node-logger': 6.5.0
       '@storybook/theming': 6.5.0_sfoxds7t5ydpegc3knd667wn6m
       '@storybook/ui': 6.5.0_sfoxds7t5ydpegc3knd667wn6m
-      '@types/node': 16.11.33
+      '@types/node': 16.11.36
       '@types/webpack': 4.41.32
       babel-loader: 8.2.5_tlrwjfnbl7llelxqoonrmw2kde
       case-sensitive-paths-webpack-plugin: 2.4.0
@@ -7376,7 +7376,7 @@ packages:
       '@storybook/semver': 7.3.2
       '@storybook/store': 6.5.0_sfoxds7t5ydpegc3knd667wn6m
       '@types/estree': 0.0.51
-      '@types/node': 16.11.33
+      '@types/node': 16.11.36
       '@types/webpack-env': 1.16.4
       acorn: 7.4.1
       acorn-jsx: 5.3.2_acorn@7.4.1
@@ -7633,8 +7633,8 @@ packages:
       resolve-from: 5.0.0
     dev: false
 
-  /@swc/core-android-arm-eabi/1.2.186:
-    resolution: {integrity: sha512-y+xiLOlkksP69mCQTbSJi/TvELJ+VAVCS/A8xBynnbZXyst4byaEDz0b6PpSTeFU0QufyygzlIARBBxi48RAQg==}
+  /@swc/core-android-arm-eabi/1.2.189:
+    resolution: {integrity: sha512-0kN3Le6QzFFz+Lc6a/tf/RkJXubWwWaHxF4c0bVm4AKIFf4nRlUCEqEkjdVaZvL92rpBMHaEEBuIIz3T8DqTTQ==}
     engines: {node: '>=10'}
     cpu: [arm]
     os: [android]
@@ -7642,8 +7642,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-android-arm64/1.2.186:
-    resolution: {integrity: sha512-W7FZDXfs2b8UIsdBlyRbG8Me2L5k77nitd38LmPFzj9G67DQWhVyoCoHMx38kbsRE82GVO2LmZ28Ehrl7TQw5w==}
+  /@swc/core-android-arm64/1.2.189:
+    resolution: {integrity: sha512-smsb+YkDw2OKwg66Z63E/G4NlFApDbsiOPmZXFZbtZbNBD9v+wnk6WVA//XR1bdUI9VbzNKlMPKJxQTE685QDw==}
     engines: {node: '>=10'}
     cpu: [arm64]
     os: [android]
@@ -7651,8 +7651,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-darwin-arm64/1.2.186:
-    resolution: {integrity: sha512-v0aKuzZEV8zqyxrFohVzKjbbOWllgUd0Mgs8Fbft/K7Brp4QzBXvSjhOwsnNE4AlwzRLdINQfQz/RO6Ygp9H4Q==}
+  /@swc/core-darwin-arm64/1.2.189:
+    resolution: {integrity: sha512-OGjZRkTulKirJMLYbW9etb59lA9ueDXVwYRVD9SrNh8tRMTf0Nq+SUT/C3LVhBBGC4KSdWOzBAYbDTTdsnY++Q==}
     engines: {node: '>=10'}
     cpu: [arm64]
     os: [darwin]
@@ -7660,8 +7660,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-darwin-x64/1.2.186:
-    resolution: {integrity: sha512-qhwFRvjFxkgiPqpg8ifo9bN6ONlPdn0xWPnkph2rpJhByMkNW2LEIApEPgS0ePhI9gq4Wksp5oxCviH1v36gQA==}
+  /@swc/core-darwin-x64/1.2.189:
+    resolution: {integrity: sha512-BEcxnBHx51514Voe2dn/y1y5H9VNyw7Zpp9+mPekZqx5o/onPD5wZ1ZfAsPrA4UlvM3v16u6ITE/cLawJ/GdAQ==}
     engines: {node: '>=10'}
     cpu: [x64]
     os: [darwin]
@@ -7669,8 +7669,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-freebsd-x64/1.2.186:
-    resolution: {integrity: sha512-HhL4HqqShE3lCB7NWXRVjjiEN4t05usHrCBtHEADsZDAGglJRMjT9ZLGLVxGOxEziWCIR+kOV2jcMv0Bf4Bbaw==}
+  /@swc/core-freebsd-x64/1.2.189:
+    resolution: {integrity: sha512-B6g2NWeh2iw6WPOaM19Uj3VE4se6alT265kWibLUshjcofRfnYT1lNhhkrF1D0EVnpC8I96I/xXNQo4Am9z4zQ==}
     engines: {node: '>=10'}
     cpu: [x64]
     os: [freebsd]
@@ -7678,8 +7678,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-linux-arm-gnueabihf/1.2.186:
-    resolution: {integrity: sha512-ouAREnVdbUnZA0y4wYdAZZKIvqJ1uer9hOCbafgGyrmR9i8Lhswz2fPUGOUc+rxjqsP1z7uN5CpMcAH4KvyNUQ==}
+  /@swc/core-linux-arm-gnueabihf/1.2.189:
+    resolution: {integrity: sha512-6WhPG9pyN5AahQTVQk8MoN1I9Z/Ytfqizuie1wV7mW8FMNmMkiJvBekKtE6ftxu80Hqa34r86WfEwmJKm5MqYw==}
     engines: {node: '>=10'}
     cpu: [arm]
     os: [linux]
@@ -7687,8 +7687,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-linux-arm64-gnu/1.2.186:
-    resolution: {integrity: sha512-b8GbZ2FVlQrDWyqC/KW9zScAvvUx6StLDvGAPWxD2GvFHjE0iPnvLHGvuVuhje0pFFqSwZnQ5/KZ6VyrKowPJw==}
+  /@swc/core-linux-arm64-gnu/1.2.189:
+    resolution: {integrity: sha512-frJTGnxsDe7h2d7BtnBivOdOJTtabkQIIZmHd4JHqafcoekI6teyveIax17axLyimvWl278yTo3hf7ePagD/eg==}
     engines: {node: '>=10'}
     cpu: [arm64]
     os: [linux]
@@ -7696,8 +7696,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-linux-arm64-musl/1.2.186:
-    resolution: {integrity: sha512-vWvfQiC7K2oMxuKbAWTgVVoTs7SpHb8GyecAzQbQWNIyOycLMihCXhgj99cz0GaSeEs/0SEd+FSoU+uldUysjA==}
+  /@swc/core-linux-arm64-musl/1.2.189:
+    resolution: {integrity: sha512-27K38LoZpME5lojDJIUNo7zdTDwAKLm0BMQ7HXWcYOyiDAekhSidI+SrBWxCfLzfuClhFu6/VE3E7j32VFJsiA==}
     engines: {node: '>=10'}
     cpu: [arm64]
     os: [linux]
@@ -7705,8 +7705,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-linux-x64-gnu/1.2.186:
-    resolution: {integrity: sha512-lGBOQd9GZsk6JQd1teZPIirir4vpcGPFlEKaoWMHTVgb4wyU0I6sW2edoHMWu+mUugs12/JpHWh7sw+ubgZzHA==}
+  /@swc/core-linux-x64-gnu/1.2.189:
+    resolution: {integrity: sha512-Ha5oJKOyQm9w7+e+WdRm4ypijzEmglWZGtgBR6vV6ViqqHcTBAU4nG87ex7y7AS9p+Cbc6EOSR9X1qIB8KxtbA==}
     engines: {node: '>=10'}
     cpu: [x64]
     os: [linux]
@@ -7714,8 +7714,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-linux-x64-musl/1.2.186:
-    resolution: {integrity: sha512-H6pFxBpg3R+g0DDXzs39c9A7+O/ai1Zwliwo7jwOfLu4ef/cq2xrKa0AJ22lawtU9A+4gwRCX78phf2ezjC2jw==}
+  /@swc/core-linux-x64-musl/1.2.189:
+    resolution: {integrity: sha512-/p5yXa9HEzpVEuE4ivkW1IvwyYu6fT+L2OvVEs5oXIba80F0Wjy7InWqaa83gwrdMH+bXV6loG8LzZUZu/lpjA==}
     engines: {node: '>=10'}
     cpu: [x64]
     os: [linux]
@@ -7723,8 +7723,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-win32-arm64-msvc/1.2.186:
-    resolution: {integrity: sha512-B178S3J5L9Z21IBVMNCarvM6kQrxHQVtT8V7vhUgldPJ5Nc2ty7ELYvrSdtiARqKP5PacKMur+nb8XIyhoJfIw==}
+  /@swc/core-win32-arm64-msvc/1.2.189:
+    resolution: {integrity: sha512-o/1ueM6/sifNjYnO6NMEXB895spVfJs5oQIPxQG9vJ/4zWLw8YmAx+u1xJY+XGyK6gnroHt7yPiS87qWdbeF6w==}
     engines: {node: '>=10'}
     cpu: [arm64]
     os: [win32]
@@ -7732,8 +7732,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-win32-ia32-msvc/1.2.186:
-    resolution: {integrity: sha512-0VqhXRn+MVth9hdwRR/X0unT9hdUOa5Y8FRUgMm3ft/72bFSAz3E8UNYMWMtVbjuViNYJgAOPML+VE9UqN80JQ==}
+  /@swc/core-win32-ia32-msvc/1.2.189:
+    resolution: {integrity: sha512-YDwRkzykaf+dw5Z7u189cC/Tttkn2NVV84hrGL3LbVuh7wT5PaDhZs4Yz4unZQSlPV12olmZWgNr/i27h5wlpg==}
     engines: {node: '>=10'}
     cpu: [ia32]
     os: [win32]
@@ -7741,8 +7741,8 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core-win32-x64-msvc/1.2.186:
-    resolution: {integrity: sha512-T+sNpLbtg5Q1zrDIOwzRDVCKQHb4eQx8MlIk9tF74amlBLt1GKBdgRn17YAA6GrNHRw7QHaDIeCEdc5OuUztvg==}
+  /@swc/core-win32-x64-msvc/1.2.189:
+    resolution: {integrity: sha512-Nge8Z/ZkAp5p5No50yBDpBG7+ZYaVWGSuwtPj6OJe7orzvDCEm9GgcVE6J9GEjbclSWlCH8B8lUe17GaKRZHbg==}
     engines: {node: '>=10'}
     cpu: [x64]
     os: [win32]
@@ -7750,38 +7750,38 @@ packages:
     dev: false
     optional: true
 
-  /@swc/core/1.2.186:
-    resolution: {integrity: sha512-n+I0z+gIsk+rkO2/UYGLcnyI2bq0YcHFtnMynRtZ8v541luGszFLBrayd3ljnmt4mFzSPY+2gTSQgK5HNuYk5g==}
+  /@swc/core/1.2.189:
+    resolution: {integrity: sha512-S5cKX4ECMSfW78DLFgnlilJZgjrFRYwPslrrwpLl3gpwh+Qo72/Mhn71u7G/5xXW+T/xW5GwPccHfCk+k72uUg==}
     engines: {node: '>=10'}
     hasBin: true
     optionalDependencies:
-      '@swc/core-android-arm-eabi': 1.2.186
-      '@swc/core-android-arm64': 1.2.186
-      '@swc/core-darwin-arm64': 1.2.186
-      '@swc/core-darwin-x64': 1.2.186
-      '@swc/core-freebsd-x64': 1.2.186
-      '@swc/core-linux-arm-gnueabihf': 1.2.186
-      '@swc/core-linux-arm64-gnu': 1.2.186
-      '@swc/core-linux-arm64-musl': 1.2.186
-      '@swc/core-linux-x64-gnu': 1.2.186
-      '@swc/core-linux-x64-musl': 1.2.186
-      '@swc/core-win32-arm64-msvc': 1.2.186
-      '@swc/core-win32-ia32-msvc': 1.2.186
-      '@swc/core-win32-x64-msvc': 1.2.186
+      '@swc/core-android-arm-eabi': 1.2.189
+      '@swc/core-android-arm64': 1.2.189
+      '@swc/core-darwin-arm64': 1.2.189
+      '@swc/core-darwin-x64': 1.2.189
+      '@swc/core-freebsd-x64': 1.2.189
+      '@swc/core-linux-arm-gnueabihf': 1.2.189
+      '@swc/core-linux-arm64-gnu': 1.2.189
+      '@swc/core-linux-arm64-musl': 1.2.189
+      '@swc/core-linux-x64-gnu': 1.2.189
+      '@swc/core-linux-x64-musl': 1.2.189
+      '@swc/core-win32-arm64-msvc': 1.2.189
+      '@swc/core-win32-ia32-msvc': 1.2.189
+      '@swc/core-win32-x64-msvc': 1.2.189
     dev: false
 
   /@swc/helpers/0.3.10:
     resolution: {integrity: sha512-ZCioFJz6NcLAA4zQqN6BORE/SFu2tBdwRU3JXQgLBu6JETvFElAOpaP0HYjWpbnCHFEJ5o6c4wWT8QeLbRoe2w==}
     dev: false
 
-  /@swc/jest/0.2.21_@swc+core@1.2.186:
+  /@swc/jest/0.2.21_@swc+core@1.2.189:
     resolution: {integrity: sha512-/+NcExiZbxXANNhNPnIdFuGq62CeumulLS1bngwqIXd8H7d96LFUfrYzdt8tlTwLMel8tFtQ5aRjzVkyOTyPDw==}
     engines: {npm: '>= 7.0.0'}
     peerDependencies:
       '@swc/core': '*'
     dependencies:
       '@jest/create-cache-key-function': 27.5.1
-      '@swc/core': 1.2.186
+      '@swc/core': 1.2.189
     dev: false
 
   /@szmarczak/http-timer/1.1.2:
@@ -8157,8 +8157,8 @@ packages:
     resolution: {integrity: sha512-+9axpWx2b2JCVovr7Ilgt96uc6C1zBKOQMpGtRbWT9IoR/8ue32GGMfGA4woP8QyP2gBs6GQWEVM3tCybGCxDA==}
     dev: false
 
-  /@types/node/16.11.33:
-    resolution: {integrity: sha512-0PJ0vg+JyU0MIan58IOIFRtSvsb7Ri+7Wltx2qAg94eMOrpg4+uuP3aUHCpxXc1i0jCXiC+zIamSZh3l9AbcQA==}
+  /@types/node/16.11.36:
+    resolution: {integrity: sha512-FR5QJe+TaoZ2GsMHkjuwoNabr+UrJNRr2HNOo+r/7vhcuntM6Ee/pRPOnRhhL2XE9OOvX9VLEq+BcXl3VjNoWA==}
     dev: false
 
   /@types/node/16.9.1:
@@ -16639,7 +16639,7 @@ packages:
       - ts-node
     dev: true
 
-  /jest-cli/28.1.0_@types+node@16.11.33:
+  /jest-cli/28.1.0_@types+node@16.11.36:
     resolution: {integrity: sha512-fDJRt6WPRriHrBsvvgb93OxgajHHsJbk4jZxiPqmZbMDRcHskfJBBfTyjFko0jjfprP544hOktdSi9HVgl4VUQ==}
     engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
     hasBin: true
@@ -16656,7 +16656,7 @@ packages:
       exit: 0.1.2
       graceful-fs: 4.2.10
       import-local: 3.1.0
-      jest-config: 28.1.0_@types+node@16.11.33
+      jest-config: 28.1.0_@types+node@16.11.36
       jest-util: 28.1.0
       jest-validate: 28.1.0
       prompts: 2.4.2
@@ -16705,7 +16705,7 @@ packages:
       - supports-color
     dev: true
 
-  /jest-config/28.1.0_@types+node@16.11.33:
+  /jest-config/28.1.0_@types+node@16.11.36:
     resolution: {integrity: sha512-aOV80E9LeWrmflp7hfZNn/zGA4QKv/xsn2w8QCBP0t0+YqObuCWTSgNbHJ0j9YsTuCO08ZR/wsvlxqqHX20iUA==}
     engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
     peerDependencies:
@@ -16720,7 +16720,7 @@ packages:
       '@babel/core': 7.17.12
       '@jest/test-sequencer': 28.1.0
       '@jest/types': 28.1.0
-      '@types/node': 16.11.33
+      '@types/node': 16.11.36
       babel-jest: 28.1.0_@babel+core@7.17.12
       chalk: 4.1.2
       ci-info: 3.3.0
@@ -17243,7 +17243,7 @@ packages:
       - ts-node
     dev: true
 
-  /jest/28.1.0_@types+node@16.11.33:
+  /jest/28.1.0_@types+node@16.11.36:
     resolution: {integrity: sha512-TZR+tHxopPhzw3c3560IJXZWLNHgpcz1Zh0w5A65vynLGNcg/5pZ+VildAd7+XGOu6jd58XMY/HNn0IkZIXVXg==}
     engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0}
     hasBin: true
@@ -17255,7 +17255,7 @@ packages:
     dependencies:
       '@jest/core': 28.1.0
       import-local: 3.1.0
-      jest-cli: 28.1.0_@types+node@16.11.33
+      jest-cli: 28.1.0_@types+node@16.11.36
     transitivePeerDependencies:
       - '@types/node'
       - supports-color
diff --git a/themes/theme-b2b/src/components/Checkbox.style.ts b/themes/theme-b2b/src/components/Checkbox.style.ts
index 4ca90f125..640f9936c 100644
--- a/themes/theme-b2b/src/components/Checkbox.style.ts
+++ b/themes/theme-b2b/src/components/Checkbox.style.ts
@@ -29,6 +29,12 @@ export const Checkbox: Theme['components']['Checkbox'] = {
         bg: 'primary',
       },
 
+      '&:indeterminate': {
+        color: 'white',
+        borderColor: 'orange80',
+        bg: 'primary',
+      },
+
       '&:disabled': {
         bg: 'gray30',
         borderColor: 'gray40',
diff --git a/themes/theme-b2b/src/components/Table.style.ts b/themes/theme-b2b/src/components/Table.style.ts
index 0123cb2da..02b4f1e70 100644
--- a/themes/theme-b2b/src/components/Table.style.ts
+++ b/themes/theme-b2b/src/components/Table.style.ts
@@ -5,10 +5,11 @@ export const Table: Theme['components']['Table'] = {
     table: { borderCollapse: 'collapse', fontSize: 'xxsmall' },
     header: {
       py: 'xxsmall',
-      px: 'xsmall',
+      px: 'small',
       cursor: 'default',
       color: 'gray00',
       bg: 'gray50',
+      textAlign: 'left',
 
       '&:nth-of-type(even)': { bg: 'gray60' },
 
@@ -20,12 +21,16 @@ export const Table: Theme['components']['Table'] = {
       '&:checked': {
         bg: 'orange10',
       },
-      '&:focus': {
+      '&:hover': {
+        bg: 'gray30',
+      },
+      '&:focus-visible': {
         outlineColor: 'orange60',
       },
     },
     cell: {
-      p: 'xsmall',
+      py: 'xxsmall',
+      px: 'small',
       cursor: 'default',
       borderBottom: '1px solid',
       borderColor: 'gray50',
diff --git a/themes/theme-core/src/components/Checkbox.style.ts b/themes/theme-core/src/components/Checkbox.style.ts
index 09eb27e84..177f42406 100644
--- a/themes/theme-core/src/components/Checkbox.style.ts
+++ b/themes/theme-core/src/components/Checkbox.style.ts
@@ -28,6 +28,12 @@ export const Checkbox: Theme['components']['Checkbox'] = {
         bg: 'blue60',
       },
 
+      '&:indeterminate': {
+        color: 'white',
+        borderColor: 'blue70',
+        bg: 'blue60',
+      },
+
       '&:disabled': {
         bg: 'gray30',
         borderColor: 'gray40',
diff --git a/themes/theme-core/src/components/Table.style.ts b/themes/theme-core/src/components/Table.style.ts
index 8e59bce1f..690e6a749 100644
--- a/themes/theme-core/src/components/Table.style.ts
+++ b/themes/theme-core/src/components/Table.style.ts
@@ -17,7 +17,10 @@ export const Table: Theme['components']['Table'] = {
       '&:checked': {
         bg: 'orange10',
       },
-      '&:focus': {
+      '&:hover': {
+        bg: 'gray20',
+      },
+      '&:focus-visible': {
         outlineColor: 'orange60',
       },
     },
diff --git a/themes/theme-unicorn/src/components/Checkbox.style.ts b/themes/theme-unicorn/src/components/Checkbox.style.ts
index 10c110d92..f84c638a0 100644
--- a/themes/theme-unicorn/src/components/Checkbox.style.ts
+++ b/themes/theme-unicorn/src/components/Checkbox.style.ts
@@ -29,6 +29,12 @@ export const Checkbox: Theme['components']['Checkbox'] = {
         bg: 'primary',
       },
 
+      '&:indeterminate': {
+        color: 'white',
+        borderColor: 'purple80',
+        bg: 'primary',
+      },
+
       '&:disabled': {
         bg: 'gray30',
         borderColor: 'gray40',
diff --git a/themes/theme-unicorn/src/components/Table.style.ts b/themes/theme-unicorn/src/components/Table.style.ts
index caa517758..fbc844938 100644
--- a/themes/theme-unicorn/src/components/Table.style.ts
+++ b/themes/theme-unicorn/src/components/Table.style.ts
@@ -17,7 +17,10 @@ export const Table: Theme['components']['Table'] = {
       '&:checked': {
         bg: 'purple10',
       },
-      '&:focus': {
+      '&:hover': {
+        bg: 'gray30',
+      },
+      '&:focus-visible': {
         outlineColor: 'purple60',
       },
     },


Test patch:
diff --git a/packages/components/src/Stack/Stack.test.tsx b/packages/components/src/Stack/Stack.test.tsx
index 13733a613..d7bb8f347 100644
--- a/packages/components/src/Stack/Stack.test.tsx
+++ b/packages/components/src/Stack/Stack.test.tsx
@@ -43,7 +43,7 @@ test('accepts and uses spacing from theme', () => {
   expect(first).toHaveStyle(`gap: 2px`);
 });
 
-test('aligns children left by default', () => {
+test('align children left by default', () => {
   render(
     <Stack data-testid="stack">
       <Text>first</Text>
@@ -53,9 +53,9 @@ test('aligns children left by default', () => {
   expect(stack).toHaveStyle(`align-items: flex-start`);
 });
 
-test('allows to aligns children to the center', () => {
+test('allows to align children to the center', () => {
   render(
-    <Stack align="center" data-testid="stack">
+    <Stack alignX="center" data-testid="stack">
       <Text>first</Text>
     </Stack>
   );
@@ -63,9 +63,9 @@ test('allows to aligns children to the center', () => {
   expect(stack).toHaveStyle(`align-items: center`);
 });
 
-test('allows to aligns children to the right', () => {
+test('allows to align children to the right', () => {
   render(
-    <Stack align="right" data-testid="stack">
+    <Stack alignX="right" data-testid="stack">
       <Text>first</Text>
     </Stack>
   );
@@ -73,6 +73,56 @@ test('allows to aligns children to the right', () => {
   expect(stack).toHaveStyle(`align-items: flex-end`);
 });
 
+test('children to the top by default', () => {
+  render(
+    <Stack data-testid="stack">
+      <Text>first</Text>
+    </Stack>
+  );
+  const stack = screen.getByTestId('stack');
+  expect(stack).toHaveStyle(`justify-content: flex-start`);
+});
+
+test('allows to align children to the vertical center', () => {
+  render(
+    <Stack alignY="center" data-testid="stack">
+      <Text>first</Text>
+    </Stack>
+  );
+  const stack = screen.getByTestId('stack');
+  expect(stack).toHaveStyle(`justify-content: center`);
+});
+
+test('allows to align children to the bottom', () => {
+  render(
+    <Stack alignY="bottom" data-testid="stack">
+      <Text>first</Text>
+    </Stack>
+  );
+  const stack = screen.getByTestId('stack');
+  expect(stack).toHaveStyle(`justify-content: flex-end`);
+});
+
+test('behaves as inline be default', () => {
+  render(
+    <Stack data-testid="stack">
+      <Text>first</Text>
+    </Stack>
+  );
+  const stack = screen.getByTestId('stack');
+  expect(stack).toHaveStyle(`blockSize: auto`);
+});
+
+test('allows to fill space', () => {
+  render(
+    <Stack stretch data-testid="stack">
+      <Text>first</Text>
+    </Stack>
+  );
+  const stack = screen.getByTestId('stack');
+  expect(stack).toHaveStyle(`blockSize: 100%`);
+});
+
 test('supports nesting', () => {
   render(
     <ThemeProvider theme={theme}>
diff --git a/packages/components/src/Table/Table.test.tsx b/packages/components/src/Table/Table.test.tsx
index a9cbf6ccd..0c622f308 100644
--- a/packages/components/src/Table/Table.test.tsx
+++ b/packages/components/src/Table/Table.test.tsx
@@ -1,9 +1,8 @@
-/* eslint-disable testing-library/prefer-presence-queries */
 import React from 'react';
 import { fireEvent, render, screen } from '@testing-library/react';
 import { ThemeProvider } from '@marigold/system';
 
-import { Table } from '@marigold/components';
+import { Table } from './Table';
 
 // Setup
 // ---------------
@@ -66,15 +65,15 @@ test('renders contens correctly', () => {
   );
 
   // Renders Header
-  expect(screen.queryByText('Name')).toBeInTheDocument();
-  expect(screen.queryByText('Firstname')).toBeInTheDocument();
+  expect(screen.getByText('Name')).toBeInTheDocument();
+  expect(screen.getByText('Firstname')).toBeInTheDocument();
 
   // Renders Content
-  expect(screen.queryByText('Potter')).toBeInTheDocument();
-  expect(screen.queryByText('Harry')).toBeInTheDocument();
+  expect(screen.getByText('Potter')).toBeInTheDocument();
+  expect(screen.getByText('Harry')).toBeInTheDocument();
 
-  expect(screen.queryByText('Malfoy')).toBeInTheDocument();
-  expect(screen.queryByText('Draco')).toBeInTheDocument();
+  expect(screen.getByText('Malfoy')).toBeInTheDocument();
+  expect(screen.getByText('Draco')).toBeInTheDocument();
 });
 
 test('supports theme with parts', () => {
@@ -148,13 +147,6 @@ test('supports selectionMode multiple', () => {
       </Table>
     </ThemeProvider>
   );
-  // Are the Checkboxes rendered?
-  const tableHeaderCheckbox = screen.getAllByRole(/columnheader/)[0];
-  // eslint-disable-next-line testing-library/no-node-access
-  expect(tableHeaderCheckbox.firstChild instanceof HTMLInputElement).toBe(true);
-  const tableRowCheckbox = screen.getAllByRole(/gridcell/)[0];
-  // eslint-disable-next-line testing-library/no-node-access
-  expect(tableRowCheckbox.firstChild instanceof HTMLInputElement).toBe(true);
 
   // select two rows
   const tableRows = screen.getAllByRole('row');
@@ -167,3 +159,36 @@ test('supports selectionMode multiple', () => {
   fireEvent.click(tableRows[1]);
   expect(tableRows[1]).toHaveAttribute('aria-selected', 'false');
 });
+
+test('supports colspans', () => {
+  render(
+    <ThemeProvider theme={theme}>
+      <Table aria-label="Example table for nested columns">
+        <Table.Header>
+          <Table.Column title="Name">
+            <Table.Column isRowHeader>First Name</Table.Column>
+            <Table.Column isRowHeader>Last Name</Table.Column>
+          </Table.Column>
+          <Table.Column title="Information">
+            <Table.Column>Age</Table.Column>
+            <Table.Column>Birthday</Table.Column>
+          </Table.Column>
+        </Table.Header>
+        <Table.Body>
+          <Table.Row>
+            <Table.Cell>Sam</Table.Cell>
+            <Table.Cell>Smith</Table.Cell>
+            <Table.Cell>36</Table.Cell>
+            <Table.Cell>May 3</Table.Cell>
+          </Table.Row>
+        </Table.Body>
+      </Table>
+    </ThemeProvider>
+  );
+
+  const nameHeader = screen.getByText('Name');
+  expect(nameHeader).toHaveAttribute('colspan', '2');
+
+  const informationHeader = screen.getByText('Information');
+  expect(informationHeader).toHaveAttribute('colspan', '2');
+});
diff --git a/packages/system/src/components/Box/Box.test.tsx b/packages/system/src/components/Box/Box.test.tsx
index c41e44421..a32801bc0 100644
--- a/packages/system/src/components/Box/Box.test.tsx
+++ b/packages/system/src/components/Box/Box.test.tsx
@@ -159,47 +159,6 @@ test('default styling overrides normalization', () => {
   expect(element).toHaveStyle(`margin: ${theme.space.medium}px`);
 });
 
-test('variants are applied correctly', () => {
-  render(
-    <ThemeProvider theme={theme}>
-      <Box variant="text.body">Test</Box>
-    </ThemeProvider>
-  );
-  const element = screen.getByText('Test');
-
-  expect(element).toHaveStyle(`font-size: ${theme.fontSizes.body}px`);
-  expect(element).toHaveStyle(`color: ${theme.colors.primary}`);
-});
-
-test('accept an array of variants', () => {
-  render(
-    <ThemeProvider theme={theme}>
-      <Box as="p" variant={['text.headline1', 'text.whitespace']}>
-        Test
-      </Box>
-    </ThemeProvider>
-  );
-  const element = screen.getByText('Test');
-
-  expect(element).toHaveStyle(`font-size: ${theme.fontSizes.large}px`);
-  expect(element).toHaveStyle(`color: ${theme.colors.secondary}`);
-  expect(element).toHaveStyle(`padding: ${theme.space.medium}px`);
-});
-
-test('variants override normalization and default styles', () => {
-  render(
-    <ThemeProvider theme={theme}>
-      <Box __baseCSS={{ p: 'small' }} variant="variant.spacing">
-        Test
-      </Box>
-    </ThemeProvider>
-  );
-  const element = screen.getByText('Test');
-
-  expect(element).toHaveStyle(`margin: ${theme.space.large}px`);
-  expect(element).toHaveStyle(`padding: ${theme.space.large}px`);
-});
-
 test.each([
   [{ display: 'flex' }, 'display: flex'],
   [{ height: 'small' }, 'height: 8px'],
@@ -254,16 +213,10 @@ test.each([
   });
 });
 
-test('style props override normalization, defaults and variants', () => {
+test('style props override normalization and defaults', () => {
   render(
     <ThemeProvider theme={theme}>
-      <Box
-        __baseCSS={{ p: 'small' }}
-        variant="text.body"
-        bg="blue"
-        m="medium"
-        p="large"
-      >
+      <Box __baseCSS={{ p: 'small' }} bg="blue" m="medium" p="large">
         Test
       </Box>
     </ThemeProvider>
@@ -287,12 +240,11 @@ test('apply custom styling via css prop', () => {
   expect(element).toHaveStyle(`color: ${theme.colors.secondary}`);
 });
 
-test('custom styling overrides normalization, defaults, variants and style props', () => {
+test('custom styling overrides normalization, defaults and style props', () => {
   render(
     <ThemeProvider theme={theme}>
       <Box
         __baseCSS={{ p: 'small' }}
-        variant="text.body"
         bg="black"
         css={{ fontSize: 'large', m: 'small', p: 'large', bg: 'blue' }}
       >
@@ -306,8 +258,6 @@ test('custom styling overrides normalization, defaults, variants and style props
   expect(element).toHaveStyle(`padding: ${theme.space.large}px`); // overrides default
   expect(element).toHaveStyle(`font-size: ${theme.fontSizes.large}px`); // overrides variant
   expect(element).toHaveStyle(`background: ${theme.colors.blue}`); // overrides style prop
-
-  expect(element).not.toHaveStyle(`color: ${theme.colors.primary}px`); // variant part that is not overriden
 });
 
 test('transforms states selectors', async () => {
diff --git a/packages/system/src/variant.test.ts b/packages/system/src/variant.test.ts
deleted file mode 100644
index e88db94f4..000000000
--- a/packages/system/src/variant.test.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import {
-  appendVariantState,
-  conditional,
-  ensureArray,
-  ensureArrayVariant,
-  ensureVariantDefault,
-} from './variant';
-
-test('ensure array', () => {
-  expect(ensureArray('foo')).toEqual(['foo']);
-  expect(ensureArray(['foo'])).toEqual(['foo']);
-  expect(ensureArray(['foo', 'bar'])).toEqual(['foo', 'bar']);
-  expect(ensureArray(null)).toEqual([]);
-  expect(ensureArray(undefined)).toEqual([]);
-});
-
-test('ensure variant default', () => {
-  expect(ensureVariantDefault('foo.')).toEqual('foo');
-  expect(ensureVariantDefault('foo')).toEqual('foo');
-});
-
-test('ensure array of variants', () => {
-  expect(ensureArrayVariant('foo')).toEqual(['foo']);
-  expect(ensureArrayVariant(['foo'])).toEqual(['foo']);
-  expect(ensureArrayVariant(['foo', 'bar'])).toEqual(['foo', 'bar']);
-  expect(ensureArrayVariant(undefined)).toEqual([]);
-});
-
-test('append variant state', () => {
-  expect(appendVariantState('foo', 'checked')).toEqual('foo.:checked');
-  expect(appendVariantState('foo', 'focus')).toEqual('foo.:focus');
-  expect(appendVariantState('foo', 'disabled')).toEqual('foo.:disabled');
-});
-
-test('conditional variants', () => {
-  expect(
-    conditional('foo', {
-      checked: true,
-    })
-  ).toMatchInlineSnapshot(`
-    [
-      "foo",
-      "foo.:checked",
-    ]
-  `);
-
-  expect(
-    conditional('foo', {
-      checked: true,
-      focus: true,
-      disabled: true,
-    })
-  ).toMatchInlineSnapshot(`
-    [
-      "foo",
-      "foo.:checked",
-      "foo.:focus",
-      "foo.:disabled",
-    ]
-  `);
-
-  expect(
-    conditional('foo', {
-      checked: true,
-      focus: false,
-      disabled: true,
-    })
-  ).toMatchInlineSnapshot(`
-    [
-      "foo",
-      "foo.:checked",
-      "foo.:disabled",
-    ]
-  `);
-});
-
-test('disabled is always last state variant', () => {
-  const one = conditional('foo', {
-    disabled: true,
-    checked: true,
-    focus: true,
-  });
-
-  expect(one[one.length - 1]).toMatchInlineSnapshot(`"foo.:disabled"`);
-
-  const two = conditional('foo', {
-    checked: true,
-    disabled: true,
-    focus: true,
-  });
-
-  expect(two[two.length - 1]).toMatchInlineSnapshot(`"foo.:disabled"`);
-});