Repository: marigold-ui/marigold
Pull request #3123 (2023-07-12 06:54:38)

docs: Navigation

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

Latest commit: 0d120f3e30fd4ea9d19897f18a7d3e2743f76006

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/main/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/docs-navigation?filename=.changeset/yellow-ants-work.md&value=---%0A%22%40marigold%2Fdocs%22%3A%20patch%0A---%0A%0Adocs%3A%20Navigation%0A)


vercel[bot]: [vc]: #V3pydxLVcBDfFI82i1jT6T5fymJNIHYeUaMQvwVsYjw=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJtYXJpZ29sZCIsInJvb3REaXJlY3RvcnkiOm51bGwsImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9tYXJpZ29sZC9tYXJpZ29sZC84Mm9VWTZ2UXpnNDF0c2syaXhxeUZHa3ZaNGVEIiwibmV4dENvbW1pdFN0YXR1cyI6IlBFTkRJTkcifSx7Im5hbWUiOiJtYXJpZ29sZC1kb2NzIiwicm9vdERpcmVjdG9yeSI6bnVsbCwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL21hcmlnb2xkL21hcmlnb2xkLWRvY3MvQkxhcXZBV3BraWtYdUZhQkdqamRaNEtrdTExOSIsIm5leHRDb21taXRTdGF0dXMiOiJQRU5ESU5HIn1dfQ==
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Updated (UTC) |
| :--- | :----- | :------ | :------ |
| **marigold** | 🔄 Building ([Inspect](https://vercel.com/marigold/marigold/82oUY6vQzg41tsk2ixqyFGkvZ4eD)) |  | Jul 12, 2023 6:54am |
| **marigold-docs** | 🔄 Building ([Inspect](https://vercel.com/marigold/marigold-docs/BLaqvAWpkikXuFaBGjjdZ4Kku119)) |  | Jul 12, 2023 6:54am |



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

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

```diff
@@            Coverage Diff            @@
##              main     #3123   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          110       110           
  Lines         6846      6859   +13     
  Branches       305       305           
=========================================
+ Hits          6846      6859   +13     
```

| [Impacted Files](https://app.codecov.io/gh/marigold-ui/marigold/pull/3123?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui) | Coverage Δ | |
|---|---|---|
| [packages/components/src/Header/Header.tsx](https://app.codecov.io/gh/marigold-ui/marigold/pull/3123?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui#diff-cGFja2FnZXMvY29tcG9uZW50cy9zcmMvSGVhZGVyL0hlYWRlci50c3g=) | `100.00% <100.00%> (ø)` | |
| [packages/system/src/utils.ts](https://app.codecov.io/gh/marigold-ui/marigold/pull/3123?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui#diff-cGFja2FnZXMvc3lzdGVtL3NyYy91dGlscy50cw==) | `100.00% <100.00%> (ø)` | |

sarahgm: @sebald conflicts 

Patch:
diff --git a/config/eslint/index.js b/config/eslint/index.js
index 508237c45..720643213 100644
--- a/config/eslint/index.js
+++ b/config/eslint/index.js
@@ -2,8 +2,8 @@ module.exports = {
   extends: [
     'react-app',
     'react-app/jest',
-    'prettier',
     'plugin:tailwindcss/recommended',
+    'prettier',
   ],
   settings: {
     react: {
diff --git a/docs/app/_components/Logo.tsx b/docs/app/_components/Logo.tsx
new file mode 100644
index 000000000..51729ae24
--- /dev/null
+++ b/docs/app/_components/Logo.tsx
@@ -0,0 +1,14 @@
+import React, { type SVGProps } from 'react';
+
+export const Logo = (props: SVGProps<any>) => (
+  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160" {...props}>
+    <path
+      fill="#46505a"
+      d="M137 1c-4 0-9 2-13 6-14 14-14 43-14 43s29 0 43-14c4-4 6-8 7-12a77 77 0 00-23-23z"
+    />
+    <path
+      fill="#f98422"
+      d="M63 4c-3 3-4 8-4 14 0 20 20 40 20 40s20-20 20-40c0-6-1-11-4-14a80 80 0 00-32 0zm32 154c3-4 4-8 4-14 0-20-20-40-20-40s-21 20-21 40c0 6 2 10 5 14a80 80 0 0032 0zm61-93c-4-3-8-5-14-5-20 0-40 21-40 21s20 20 40 20c6 0 10-1 14-4a80 80 0 000-32zM2 97c4 3 8 4 14 4 20 0 40-20 40-20S36 60 16 60c-6 0-10 2-14 4a80 80 0 000 33zm143 27c-1-4-3-9-7-13-14-14-43-14-43-14s0 29 14 43c4 4 9 6 13 7a80 80 0 0023-23zM13 38c1 4 3 8 7 13 14 14 43 14 43 14s0-29-14-43c-4-4-9-6-13-7a77 77 0 00-23 23zm23 109c4-1 9-3 13-7 14-14 14-43 14-43s-29 0-43 14c-4 4-6 9-7 12a80 80 0 0023 24z"
+    />
+  </svg>
+);
diff --git a/docs/app/_components/MobileNavigation.tsx b/docs/app/_components/MobileNavigation.tsx
new file mode 100644
index 000000000..4875a75dd
--- /dev/null
+++ b/docs/app/_components/MobileNavigation.tsx
@@ -0,0 +1,46 @@
+'use client';
+
+import { Dialog, Button, Header } from '@/ui';
+
+import { Logo } from './Logo';
+import { Navigation } from './Navigation';
+
+// Helpers
+// ---------------
+const MenuIcon = () => (
+  <svg
+    xmlns="http://www.w3.org/2000/svg"
+    width="28"
+    height="28"
+    viewBox="0 0 24 24"
+    fill="none"
+    stroke="currentColor"
+    strokeWidth="2"
+    strokeLinecap="round"
+    strokeLinejoin="round"
+  >
+    <circle cx="12" cy="12" r="10" />
+    <polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76" />
+  </svg>
+);
+
+// Component
+// ---------------
+export const MobileNavigation = () => (
+  <Dialog.Trigger>
+    <Button variant="ghost" className="md:hidden">
+      <MenuIcon />
+    </Button>
+    <Dialog variant="fullpage" closeButton>
+      {({ close }) => (
+        <>
+          <Header className="flex items-center gap-2 pl-4 text-3xl font-bold uppercase tracking-tight text-[#46505a]">
+            <Logo className="h-10 w-10" />
+            Marigold
+          </Header>
+          <Navigation onClick={close} />
+        </>
+      )}
+    </Dialog>
+  </Dialog.Trigger>
+);
diff --git a/docs/app/_components/NavLink.tsx b/docs/app/_components/NavLink.tsx
new file mode 100644
index 000000000..42711ad4a
--- /dev/null
+++ b/docs/app/_components/NavLink.tsx
@@ -0,0 +1,56 @@
+import type { ComponentProps } from 'react';
+import Link from 'next/link';
+import { cn, cva, type VariantProps } from '@marigold/system';
+
+const styles = cva([], {
+  variants: {
+    variant: {
+      default: [
+        'text-secondary-500 -ml-px block border-l border-transparent py-1 pl-4 text-sm',
+      ],
+      main: ['text-secondary-600'],
+    },
+    current: {
+      true: '',
+      false: '',
+    },
+  },
+  compoundVariants: [
+    {
+      variant: 'default',
+      current: true,
+      className: 'border-primary-500 text-primary-500 font-medium',
+    },
+    {
+      variant: 'default',
+      current: false,
+      className: 'hover:border-secondary-600 hover:text-secondary-800',
+    },
+    {
+      variant: 'main',
+      current: true,
+      className: 'text-primary-500 font-medium',
+    },
+    {
+      variant: 'main',
+      current: false,
+      className: 'hover:text-secondary-900',
+    },
+  ],
+  defaultVariants: {
+    variant: 'default',
+  },
+});
+
+export interface NavLinkProps
+  extends VariantProps<typeof styles>,
+    ComponentProps<typeof Link> {}
+
+export const NavLink = ({
+  variant,
+  current,
+  className,
+  ...props
+}: NavLinkProps) => (
+  <Link {...props} className={cn(styles({ variant, current, className }))} />
+);
diff --git a/docs/app/_components/Navigation.tsx b/docs/app/_components/Navigation.tsx
new file mode 100644
index 000000000..824eaed0f
--- /dev/null
+++ b/docs/app/_components/Navigation.tsx
@@ -0,0 +1,93 @@
+'use client';
+
+import { usePathname } from 'next/navigation';
+
+import {
+  allContentPages,
+  ComponentPage,
+  allComponentPages,
+} from 'contentlayer/generated';
+
+import { siteConfig } from '@/lib/config';
+import { NavLink } from './NavLink';
+
+// Render Sections
+// ---------------
+export interface RenderProps {
+  onClick?: () => void;
+  current: string;
+}
+
+export const renderContentPages = ({ onClick, current }: RenderProps) => {
+  const pages = [...allContentPages].sort(
+    (a, b) => (a.order || 1000) - (b.order || 1000)
+  );
+
+  return pages.map(({ title, slug }) => (
+    <NavLink
+      key={slug}
+      variant="main"
+      current={current === slug}
+      href={slug}
+      onClick={onClick}
+    >
+      {title}
+    </NavLink>
+  ));
+};
+
+export const renderComponentPages = ({ onClick, current }: RenderProps) => {
+  const groups = siteConfig.navigation.componentGroups;
+  const pages: { [group in ComponentPage['group']]?: ComponentPage[] } = {};
+
+  allComponentPages.forEach(page => {
+    const group = pages[page.group] || [];
+    return (pages[page.group] = [...group, page]);
+  });
+
+  const list = Object.entries(pages);
+  list.sort(([a], [b]) => groups.indexOf(a) - groups.indexOf(b));
+
+  return list.map(([group, list]) => (
+    <div key={group} className="flex flex-col gap-2">
+      <div className="text-secondary-700 text-sm font-semibold">{group}</div>
+      <div className="border-secondary-300 ml-0.5 flex flex-col gap-2 border-l">
+        {list.map(({ title, slug }) => (
+          <NavLink
+            key={slug}
+            current={current === slug}
+            href={slug}
+            onClick={onClick}
+          >
+            {title}
+          </NavLink>
+        ))}
+      </div>
+    </div>
+  ));
+};
+
+// Props
+// ---------------
+export interface NavigationProps {
+  onClick?: () => void;
+}
+
+// Compponent
+// ---------------
+export const Navigation = ({ onClick }: NavigationProps) => {
+  const pathname = usePathname();
+
+  return (
+    <nav className="flex flex-col gap-8 pl-4 pt-8">
+      <div className="flex flex-col gap-4">
+        {renderContentPages({ onClick, current: pathname })}
+      </div>
+
+      <div className="flex flex-col gap-4">
+        <div className="font-semibold">Components</div>
+        {renderComponentPages({ onClick, current: pathname })}
+      </div>
+    </nav>
+  );
+};
diff --git a/docs/app/_components/SiteHeader.tsx b/docs/app/_components/SiteHeader.tsx
new file mode 100644
index 000000000..64958157b
--- /dev/null
+++ b/docs/app/_components/SiteHeader.tsx
@@ -0,0 +1,11 @@
+import { MobileNavigation } from './MobileNavigation';
+import { SiteNavigation } from './SiteNavigation';
+
+export const SiteHeader = () => (
+  <header className="border-secondary-300 sticky top-0 z-10 w-full border-b bg-white">
+    <div className="container flex h-14 items-center">
+      <MobileNavigation />
+      <SiteNavigation />
+    </div>
+  </header>
+);
diff --git a/docs/app/_components/SiteNavigation.tsx b/docs/app/_components/SiteNavigation.tsx
new file mode 100644
index 000000000..ee8364d8b
--- /dev/null
+++ b/docs/app/_components/SiteNavigation.tsx
@@ -0,0 +1,10 @@
+import { Logo } from './Logo';
+
+export const SiteNavigation = () => (
+  <div className="hidden w-full md:flex">
+    <div className="flex items-center gap-2 text-lg font-bold uppercase tracking-tight text-[#46505a]">
+      <Logo className="h-6 w-6" />
+      Marigold
+    </div>
+  </div>
+);
diff --git a/docs/app/components/components/ThemeSwitch.tsx b/docs/app/components/[...slug]/_components/ThemeSwitch.tsx
similarity index 100%
rename from docs/app/components/components/ThemeSwitch.tsx
rename to docs/app/components/[...slug]/_components/ThemeSwitch.tsx
diff --git a/docs/app/components/components/icons/BlankCanvas.tsx b/docs/app/components/[...slug]/_components/icons/BlankCanvas.tsx
similarity index 100%
rename from docs/app/components/components/icons/BlankCanvas.tsx
rename to docs/app/components/[...slug]/_components/icons/BlankCanvas.tsx
diff --git a/docs/app/components/components/icons/index.ts b/docs/app/components/[...slug]/_components/icons/index.ts
similarity index 100%
rename from docs/app/components/components/icons/index.ts
rename to docs/app/components/[...slug]/_components/icons/index.ts
diff --git a/docs/app/components/components/index.ts b/docs/app/components/[...slug]/_components/index.ts
similarity index 100%
rename from docs/app/components/components/index.ts
rename to docs/app/components/[...slug]/_components/index.ts
diff --git a/docs/app/components/[...slug]/page.tsx b/docs/app/components/[...slug]/page.tsx
index dbdbce66e..9d0e5e04d 100644
--- a/docs/app/components/[...slug]/page.tsx
+++ b/docs/app/components/[...slug]/page.tsx
@@ -3,7 +3,7 @@ import { Metadata } from 'next';
 import { allComponentPages } from 'contentlayer/generated';
 
 import { Mdx } from '@/ui/mdx';
-import { MarigoldThemeSwitch, ThemeMenu } from '../components';
+import { MarigoldThemeSwitch, ThemeMenu } from './_components';
 
 import { b2bTheme, coreTheme } from '@/theme';
 import { SSRProvider } from '@/ui';
diff --git a/docs/app/layout.tsx b/docs/app/layout.tsx
index 824571f9e..d141df32d 100644
--- a/docs/app/layout.tsx
+++ b/docs/app/layout.tsx
@@ -4,26 +4,32 @@ import { MarigoldProvider } from '@/ui';
 import { theme } from '@/theme';
 import { fontSans } from '@/theme/fonts';
 
+import { SiteHeader } from './_components/SiteHeader';
+import { Navigation } from './_components/Navigation';
+
+// Metadata
+// ---------------
 export const metadata = {
   title: 'Marigold Documentation',
   description: "Documentation of Reservix' Design System",
 };
 
-export default function RootLayout({
-  children,
-}: {
-  children: React.ReactNode;
-}) {
+// Layout
+// ---------------
+const Layout = ({ children }: { children: React.ReactNode }) => {
   return (
     <html lang="en">
       <body className={`${fontSans.className} min-h-screen`}>
         <MarigoldProvider theme={theme}>
           <div className="flex min-h-screen flex-col">
-            <header className="sticky top-0 z-40 w-full bg-white">
-              <div className="container">Marigold Docs</div>
-            </header>
-            <div className="flex-1">
-              <div className="container">{children}</div>
+            <SiteHeader />
+            <div className="container flex-1">
+              <aside className="fixed top-14 z-20 -ml-2 hidden w-60 overflow-y-auto md:block">
+                <Navigation />
+              </aside>
+              <div className="md:pl-60">
+                <main className="max-w-3xl">{children}</main>
+              </div>
             </div>
             <footer className="container">Marigold Footer</footer>
           </div>
@@ -31,4 +37,6 @@ export default function RootLayout({
       </body>
     </html>
   );
-}
+};
+
+export default Layout;
diff --git a/docs/content/components/accordion/accordion.mdx b/docs/content/components/accordion/accordion.mdx
index c0b0a3bdb..5fc92f9ee 100644
--- a/docs/content/components/accordion/accordion.mdx
+++ b/docs/content/components/accordion/accordion.mdx
@@ -1,7 +1,7 @@
 ---
 title: Accordion
 caption: Component to show and hide related content from the main page.
-group: Collections
+group: Collection
 ---
 
 An `<Accordion>` is a component that allows you to organizing content into collapsible sections. It consists of a series of vertically stacked items. Accordions are commonly used in website and application designs to present information in a compact and organized way, allowing users to focus on the specific information they are interested in without being overwhelmed by excessive content.
diff --git a/docs/content/components/button/button.mdx b/docs/content/components/button/button.mdx
index 4a45548a5..dca06d3d2 100644
--- a/docs/content/components/button/button.mdx
+++ b/docs/content/components/button/button.mdx
@@ -1,7 +1,7 @@
 ---
 title: Button
 caption: Whenever you need that clicky thing.
-group: form
+group: Form
 ---
 
 The `<Button>` is a common form component, that renders a button element, which allows users to perform an action.
diff --git a/docs/content/components/checkbox/checkbox.mdx b/docs/content/components/checkbox/checkbox.mdx
new file mode 100644
index 000000000..955cecb4b
--- /dev/null
+++ b/docs/content/components/checkbox/checkbox.mdx
@@ -0,0 +1,11 @@
+---
+title: Checkbox
+caption: Component to select one or more options.
+group: Form
+---
+
+The `<Checkbox>` component allows users to select one or more options from a set of options. In order to group multiple checkboxes, use the `<CheckboxGroup>` component.
+
+There are several props for the `<Checkbox>` and the `<CheckboxGroup>`.
+
+You don't have to click on the `<Checkbox>` itself, you can also just click on the label next to the box.
diff --git a/docs/content/components/table/table.mdx b/docs/content/components/table/table.mdx
index d8e6e4004..98d1956a9 100644
--- a/docs/content/components/table/table.mdx
+++ b/docs/content/components/table/table.mdx
@@ -1,7 +1,7 @@
 ---
 title: Table
 caption: Component for building tables.
-group: Collections
+group: Collection
 ---
 
 The `<Table>` component allows to present data in a table format. It enhances the functionality of regular `<table>` elements with the possibility to interact and select the data, as well as, helps with accessibility by providing keyboard navigation.
diff --git a/docs/content/components/text-field/text-field.mdx b/docs/content/components/text-field/text-field.mdx
new file mode 100644
index 000000000..0e4a93985
--- /dev/null
+++ b/docs/content/components/text-field/text-field.mdx
@@ -0,0 +1,11 @@
+---
+title: TextField
+caption: Component for input forms.
+group: Form
+---
+
+The `<TextField>` is a form component which allows user to enter text with a keyboard. It consists of a label, an input field and a help text. The latter also contains error messages.
+
+It has many properties that it brings with it. You can set label for labeling the `<TextField>` itself, a `description` which behaves as help text. It is also possible to add error messages by adding the `error` and `errorMessage` prop. Another often used property is the `required` prop. You can also write all other HTML input properties down.
+
+The `<FieldGroup>` is a component to layout the label and the fieldbase itself. On that you can use `labelWidth` which is a string type to set the width of the label. Because the label is set to the left side in the core theme, it has only an impact on that.
diff --git a/docs/contentlayer.config.ts b/docs/contentlayer.config.ts
index d51327f33..c49214ec9 100644
--- a/docs/contentlayer.config.ts
+++ b/docs/contentlayer.config.ts
@@ -1,7 +1,6 @@
 import {
   defineDocumentType,
   makeSource,
-  type ComputedFields,
   type FieldDefs,
 } from 'contentlayer/source-files';
 
@@ -9,6 +8,8 @@ import remarkGfm from 'remark-gfm';
 import rehypeSlug from 'rehype-slug';
 import rehypeAutolinkHeadings from 'rehype-autolink-headings';
 
+import { siteConfig } from './lib/config';
+
 // Helpers
 // ---------------
 const commonFields: FieldDefs = {
@@ -22,13 +23,6 @@ const commonFields: FieldDefs = {
   },
 };
 
-const computedFields: ComputedFields = {
-  slug: {
-    type: 'string',
-    resolve: doc => `/${doc._raw.flattenedPath}`,
-  },
-};
-
 // Page Types
 // ---------------
 export const ContentPage = defineDocumentType(() => ({
@@ -42,7 +36,10 @@ export const ContentPage = defineDocumentType(() => ({
     },
   },
   computedFields: {
-    ...computedFields,
+    slug: {
+      type: 'string',
+      resolve: doc => doc._raw.flattenedPath.replace('pages', ''),
+    },
     slugAsParams: {
       type: 'string',
       resolve: doc => doc._raw.flattenedPath.split('/').slice(1).join('/'),
@@ -58,20 +55,19 @@ export const ComponentPage = defineDocumentType(() => ({
     ...commonFields,
     group: {
       type: 'enum',
-      options: [
-        'applicaiton',
-        'collection',
-        'content',
-        'form',
-        'layout',
-        'navigation',
-        'overlay',
-      ],
+      options: siteConfig.navigation.componentGroups,
       required: true,
     },
   },
   computedFields: {
-    ...computedFields,
+    slug: {
+      type: 'string',
+      resolve: doc =>
+        `/${doc._raw.flattenedPath.substring(
+          0,
+          doc._raw.flattenedPath.lastIndexOf('/')
+        )}`,
+    },
     slugAsParams: {
       type: 'string',
       // Slugs are matched agains the name of the component or rather the file name
diff --git a/docs/lib/config.ts b/docs/lib/config.ts
new file mode 100644
index 000000000..d7bb010f4
--- /dev/null
+++ b/docs/lib/config.ts
@@ -0,0 +1,13 @@
+export const siteConfig = {
+  navigation: {
+    componentGroups: [
+      'Applicaiton',
+      'Layout',
+      'Navigation',
+      'Form',
+      'Collection',
+      'Overlay',
+      'Content',
+    ],
+  },
+};
diff --git a/docs/next.config.js b/docs/next.config.js
index 5f6e48b72..7c2b165e6 100644
--- a/docs/next.config.js
+++ b/docs/next.config.js
@@ -8,6 +8,9 @@ const nextConfig = {
   typescript: {
     ignoreBuildErrors: true,
   },
+  eslint: {
+    ignoreDuringBuilds: true,
+  },
   transpilePackages: [
     '@marigold/components',
     '@marigold/theme-preset',
diff --git a/docs/public/logo.svg b/docs/public/logo.svg
new file mode 100644
index 000000000..bc9a0ab46
--- /dev/null
+++ b/docs/public/logo.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160"><path fill="#46505a" d="M137 1c-4 0-9 2-13 6-14 14-14 43-14 43s29 0 43-14c4-4 6-8 7-12a77 77 0 0 0-23-23z"/><path fill="#f98422" d="M63 4c-3 3-4 8-4 14 0 20 20 40 20 40s20-20 20-40c0-6-1-11-4-14a80 80 0 0 0-32 0zm32 154c3-4 4-8 4-14 0-20-20-40-20-40s-21 20-21 40c0 6 2 10 5 14a80 80 0 0 0 32 0zm61-93c-4-3-8-5-14-5-20 0-40 21-40 21s20 20 40 20c6 0 10-1 14-4a80 80 0 0 0 0-32zM2 97c4 3 8 4 14 4 20 0 40-20 40-20S36 60 16 60c-6 0-10 2-14 4a80 80 0 0 0 0 33zm143 27c-1-4-3-9-7-13-14-14-43-14-43-14s0 29 14 43c4 4 9 6 13 7a80 80 0 0 0 23-23zM13 38c1 4 3 8 7 13 14 14 43 14 43 14s0-29-14-43c-4-4-9-6-13-7a77 77 0 0 0-23 23zm23 109c4-1 9-3 13-7 14-14 14-43 14-43s-29 0-43 14c-4 4-6 9-7 12a80 80 0 0 0 23 24z"/></svg>
\ No newline at end of file
diff --git a/docs/tailwind.config.ts b/docs/tailwind.config.ts
index 093c0551a..d3abdd93e 100644
--- a/docs/tailwind.config.ts
+++ b/docs/tailwind.config.ts
@@ -9,7 +9,7 @@ const config: Config = {
     './theme/root.ts',
     './theme/*.ts',
     './theme/**/*.ts',
-    './components/**/*.{js,ts,jsx,tsx,mdx}',
+    './ui/**/*.{js,ts,jsx,tsx,mdx}',
     './app/**/*.{js,ts,jsx,tsx,mdx}',
 
     // Marigold components
diff --git a/docs/theme/components/Button.styles.ts b/docs/theme/components/Button.styles.ts
index 1aa69e386..e88037810 100644
--- a/docs/theme/components/Button.styles.ts
+++ b/docs/theme/components/Button.styles.ts
@@ -1,5 +1,13 @@
 import { ThemeComponent, cva } from '@marigold/system';
 
 export const Button: ThemeComponent<'Button'> = cva(
-  'flex gap-2 rounded-sm border border-solid p-2'
+  'flex gap-2 rounded-sm border border-solid p-2',
+  {
+    variants: {
+      variant: {
+        ghost:
+          'text-secondary-700 hover:text-secondary-900 border-transparent p-0',
+      },
+    },
+  }
 );
diff --git a/docs/theme/components/Dialog.styles.ts b/docs/theme/components/Dialog.styles.ts
new file mode 100644
index 000000000..f2b268c91
--- /dev/null
+++ b/docs/theme/components/Dialog.styles.ts
@@ -0,0 +1,18 @@
+import { ThemeComponent, cva } from '@marigold/system';
+
+export const Dialog: ThemeComponent<'Dialog'> = {
+  closeButton: cva('absolute right-2 top-2', {
+    variants: {
+      variant: {
+        fullpage: ['h-6 w-6', 'right-4 top-4'],
+      },
+    },
+  }),
+  container: cva('bg-bg-surface relative rounded-sm px-4 pb-8 pt-4 shadow-sm', {
+    variants: {
+      variant: {
+        fullpage: 'h-screen w-screen pt-10',
+      },
+    },
+  }),
+};
diff --git a/docs/theme/components/Header.styles.ts b/docs/theme/components/Header.styles.ts
new file mode 100644
index 000000000..092933033
--- /dev/null
+++ b/docs/theme/components/Header.styles.ts
@@ -0,0 +1,3 @@
+import { ThemeComponent, cva } from '@marigold/system';
+
+export const Header: ThemeComponent<'Header'> = cva();
diff --git a/docs/theme/components/Headline.styles.tsx b/docs/theme/components/Headline.styles.tsx
new file mode 100644
index 000000000..c32f5f140
--- /dev/null
+++ b/docs/theme/components/Headline.styles.tsx
@@ -0,0 +1,3 @@
+import { ThemeComponent, cva } from '@marigold/system';
+
+export const Headline: ThemeComponent<'Headline'> = cva();
diff --git a/docs/theme/components/Underlay.styles.ts b/docs/theme/components/Underlay.styles.ts
index 5759b9136..7ee1be788 100644
--- a/docs/theme/components/Underlay.styles.ts
+++ b/docs/theme/components/Underlay.styles.ts
@@ -1,5 +1,9 @@
 import { ThemeComponent, cva } from '@marigold/system';
 
-export const Underlay: ThemeComponent<'Underlay'> = cva(
-  'bg-bg-underlay/50 backdrop-blur-sm'
-);
+export const Underlay: ThemeComponent<'Underlay'> = cva('', {
+  variants: {
+    variant: {
+      modal: 'bg-bg-underlay/50 backdrop-blur-sm',
+    },
+  },
+});
diff --git a/docs/theme/components/index.ts b/docs/theme/components/index.ts
index db21b38d6..f2caa44e6 100644
--- a/docs/theme/components/index.ts
+++ b/docs/theme/components/index.ts
@@ -1,5 +1,7 @@
 export * from './Button.styles';
 export * from './Card.styles';
+export * from './Dialog.styles';
+export * from './Header.styles';
 export * from './Headline.styles';
 export * from './Link.styles';
 export * from './Menu.styles';
diff --git a/docs/theme/tokens.ts b/docs/theme/tokens.ts
index 567b318db..6704af331 100644
--- a/docs/theme/tokens.ts
+++ b/docs/theme/tokens.ts
@@ -20,6 +20,7 @@ export const colors = {
   // Brand
   // ---------------
   ...brand,
+  secondary: tw.slate,
 
   // Text
   // ---------------
@@ -42,6 +43,10 @@ export const colors = {
 
     underlay: tw.slate[500],
 
+    surface: {
+      DEFAULT: tw.white,
+    },
+
     // Status
     info: tw.sky[100],
     warning: tw.amber[100],
diff --git a/docs/ui/mdx.tsx b/docs/ui/mdx.tsx
index c2489211d..285b831c2 100644
--- a/docs/ui/mdx.tsx
+++ b/docs/ui/mdx.tsx
@@ -1,8 +1,9 @@
 'use client';
+
 import { HTMLAttributes } from 'react';
 import { useMDXComponent } from 'next-contentlayer/hooks';
 
-import * as DocComponents from '@/app/components/components';
+import * as DocComponents from '@/app/components/[...slug]/_components';
 import { Headline, Message, Link, Text } from './';
 import { IconList } from '@/app/components';
 // Typography
diff --git a/packages/components/src/Header/Header.tsx b/packages/components/src/Header/Header.tsx
index 3a8eb31cf..99b1f2b3b 100644
--- a/packages/components/src/Header/Header.tsx
+++ b/packages/components/src/Header/Header.tsx
@@ -1,5 +1,5 @@
 import React, { ReactNode } from 'react';
-import { useClassNames } from '@marigold/system';
+import { cn, useClassNames } from '@marigold/system';
 import { HtmlProps } from '@marigold/types';
 
 // Props
@@ -12,10 +12,21 @@ export interface HeaderProps extends HtmlProps<'header'> {
 
 // Component
 // ---------------
-export const Header = ({ children, variant, size, ...props }: HeaderProps) => {
-  const classNames = useClassNames({ component: 'Header', variant, size });
+export const Header = ({
+  children,
+  variant,
+  size,
+  className,
+  ...props
+}: HeaderProps) => {
+  const classNames = useClassNames({
+    component: 'Header',
+    variant,
+    size,
+    className,
+  });
   return (
-    <header {...props} className={classNames}>
+    <header {...props} className={cn(classNames)}>
       {children}
     </header>
   );
diff --git a/packages/system/src/utils.ts b/packages/system/src/utils.ts
index 9eb9b3bce..0287ab7bf 100644
--- a/packages/system/src/utils.ts
+++ b/packages/system/src/utils.ts
@@ -7,6 +7,8 @@ import {
   StringToBoolean,
 } from 'class-variance-authority/dist/types';
 
+export type { VariantProps } from 'class-variance-authority';
+
 export type ConfigSchema = Record<string, Record<string, ClassValue>>;
 export type ConfigVariants<T extends ConfigSchema> = {
   [Variant in keyof T]?: StringToBoolean<keyof T[Variant]> | null | undefined;


Test patch:
diff --git a/docs/app/components/components/AppearanceTable.tsx b/docs/app/components/[...slug]/_components/AppearanceTable.tsx
similarity index 100%
rename from docs/app/components/components/AppearanceTable.tsx
rename to docs/app/components/[...slug]/_components/AppearanceTable.tsx
diff --git a/docs/app/components/components/PropsTable.tsx b/docs/app/components/[...slug]/_components/PropsTable.tsx
similarity index 100%
rename from docs/app/components/components/PropsTable.tsx
rename to docs/app/components/[...slug]/_components/PropsTable.tsx
diff --git a/docs/app/components/components/ThemeMenu.tsx b/docs/app/components/[...slug]/_components/ThemeMenu.tsx
similarity index 100%
rename from docs/app/components/components/ThemeMenu.tsx
rename to docs/app/components/[...slug]/_components/ThemeMenu.tsx
diff --git a/docs/app/components/components/ThemeSwitch.test.tsx b/docs/app/components/[...slug]/_components/ThemeSwitch.test.tsx
similarity index 93%
rename from docs/app/components/components/ThemeSwitch.test.tsx
rename to docs/app/components/[...slug]/_components/ThemeSwitch.test.tsx
index b873c583a..93d01da67 100644
--- a/docs/app/components/components/ThemeSwitch.test.tsx
+++ b/docs/app/components/[...slug]/_components/ThemeSwitch.test.tsx
@@ -1,6 +1,6 @@
 import React, { ReactNode } from 'react';
 import { act, renderHook } from '@testing-library/react-hooks';
-import { b2bTheme, coreTheme } from '../../../theme';
+import { b2bTheme, coreTheme } from '../../../../theme';
 import { MarigoldThemeSwitch, useThemeSwitch } from './ThemeSwitch';
 
 const themes = {