diff --git a/docs/app/[...slug]/page.tsx b/docs/app/[...slug]/page.tsx
index 3330f8c628..ee9578c6c4 100644
--- a/docs/app/[...slug]/page.tsx
+++ b/docs/app/[...slug]/page.tsx
@@ -46,7 +46,6 @@ export async function generateStaticParams(): Promise<
export default async function ContentPage({ params }: ContentPageProps) {
const page = await getPageFromParams(params);
-
if (!page) {
notFound();
}
diff --git a/docs/content/components/accordion/accordion-basic.demo.tsx b/docs/content/components/accordion/accordion-basic.demo.tsx
new file mode 100644
index 0000000000..1c4b302b4a
--- /dev/null
+++ b/docs/content/components/accordion/accordion-basic.demo.tsx
@@ -0,0 +1,22 @@
+import { Accordion, Headline, TextField } from '@marigold/components';
+
+export default () => (
+
+
+ {/* just to test scroll */}
+
+ Some Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem
+ voluptatem minima hic ex ullam, asperiores quaerat quas eveniet, magnam
+ quisquam dolores. Beatae eaque eveniet error ipsa veniam vero culpa
+ recusandae?
+
+
+
+
+ two
+
+
+ Some Imformations
+
+
+);
diff --git a/docs/content/components/accordion/accordion.mdx b/docs/content/components/accordion/accordion.mdx
index 5fc92f9ee1..1c8dd6f06a 100644
--- a/docs/content/components/accordion/accordion.mdx
+++ b/docs/content/components/accordion/accordion.mdx
@@ -28,3 +28,5 @@ import { Accordion } from '@marigold/components';
### Props Accordion.Item
## Examples
+
+
diff --git a/docs/contentlayer.config.ts b/docs/contentlayer.config.ts
index 2db77d950a..47590317fc 100644
--- a/docs/contentlayer.config.ts
+++ b/docs/contentlayer.config.ts
@@ -6,9 +6,12 @@ import {
import remarkGfm from 'remark-gfm';
import rehypeSlug from 'rehype-slug';
+import rehypePrettyCode from 'rehype-pretty-code';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
+import { visit } from 'unist-util-visit';
import { rehypeComponentDemo } from './lib/mdx/rehype-component-demo';
+
import { siteConfig } from './lib/config';
// Helpers
@@ -88,6 +91,58 @@ export default makeSource({
rehypePlugins: [
[rehypeComponentDemo, { contentDirPath }],
rehypeSlug,
+ // to inject the source code and other stuff inside `pre` element props
+ () => tree => {
+ visit(tree, node => {
+ if (node?.type === 'element' && node?.tagName === 'pre') {
+ const [codeEl] = node.children;
+ if (codeEl.tagName !== 'code') {
+ return;
+ }
+
+ if (codeEl.data?.meta) {
+ // Extract event from meta and pass it down the tree.
+ const regex = /event="([^"]*)"/;
+ const match = codeEl.data?.meta.match(regex);
+ if (match) {
+ node.__event__ = match ? match[1] : null;
+ codeEl.data.meta = codeEl.data.meta.replace(regex, '');
+ }
+ }
+ node.__rawString__ = codeEl.children?.[0].value;
+ }
+ });
+ },
+ [
+ rehypePrettyCode,
+ {
+ onVisitLine(node: any) {
+ if (node.children.length === 0) {
+ node.children = [{ type: 'text', value: ' ' }];
+ }
+ },
+ onVisitHighlightedLine(node: any) {
+ node.properties.className.push('line--highlighted');
+ },
+ onVisitHighlightedWord(node: any) {
+ node.properties.className = ['word--highlighted'];
+ },
+ },
+ ],
+ () => tree => {
+ visit(tree, node => {
+ if (node?.type === 'element' && node?.tagName === 'div') {
+ if (!('data-rehype-pretty-code-fragment' in node.properties)) {
+ return;
+ }
+ const preElement = node.children.at(-1);
+ if (preElement.tagName !== 'pre') {
+ return;
+ }
+ preElement.properties['__rawString__'] = node.__rawString__;
+ }
+ });
+ },
[
rehypeAutolinkHeadings,
{
diff --git a/docs/package.json b/docs/package.json
index 522d0e1954..a1e4363c04 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -27,9 +27,12 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-use": "17.4.0",
+ "react-use-clipboard": "1.0.9",
"rehype-autolink-headings": "6.1.1",
+ "rehype-pretty-code": "0.10.0",
"rehype-slug": "5.1.0",
"remark-gfm": "3.0.1",
+ "shiki": "0.14.3",
"tailwindcss": "3.3.2",
"zx": "7.2.2"
},
diff --git a/docs/registry/index.tsx b/docs/registry/index.tsx
index 568090e650..d9d01bf3a5 100644
--- a/docs/registry/index.tsx
+++ b/docs/registry/index.tsx
@@ -4,6 +4,20 @@
import dynamic from 'next/dynamic';
export const registry = {
+ 'accordion-basic': {
+ name: 'accordion-basic',
+ demo: dynamic(
+ () => import('@/content/components/accordion/accordion-basic.demo')
+ ),
+ file: 'content/components/accordion/accordion-basic.demo.tsx',
+ },
+ 'basic-accordion': {
+ name: 'basic-accordion',
+ demo: dynamic(
+ () => import('@/content/components/accordion/basic-accordion.demo')
+ ),
+ file: 'content/components/accordion/basic-accordion.demo.tsx',
+ },
rightside: {
name: 'rightside',
demo: dynamic(() => import('@/content/components/aside/rightside.demo')),
@@ -14,13 +28,6 @@ export const registry = {
demo: dynamic(() => import('@/content/components/aside/space.demo')),
file: 'content/components/aside/space.demo.tsx',
},
- 'basic-accordion': {
- name: 'basic-accordion',
- demo: dynamic(
- () => import('@/content/components/accordion/basic-accordion.demo')
- ),
- file: 'content/components/accordion/basic-accordion.demo.tsx',
- },
'horizontal-breakout': {
name: 'horizontal-breakout',
demo: dynamic(
diff --git a/docs/theme/components/Tabs.styles.ts b/docs/theme/components/Tabs.styles.ts
new file mode 100644
index 0000000000..ca39bbec31
--- /dev/null
+++ b/docs/theme/components/Tabs.styles.ts
@@ -0,0 +1,9 @@
+import { ThemeComponent, cva } from '@marigold/system';
+
+export const Tabs: ThemeComponent<'Tabs'> = {
+ tabs: cva('mb-4 border-b'),
+ tab: cva([
+ 'text-text-primary-muted aria-selected:text-text-primary px-2 py-1 font-medium',
+ 'aria-selected:border-border -m-px border-b-2 border-transparent',
+ ]),
+};
diff --git a/docs/theme/components/index.ts b/docs/theme/components/index.ts
index f2caa44e66..e6bb1a0116 100644
--- a/docs/theme/components/index.ts
+++ b/docs/theme/components/index.ts
@@ -6,6 +6,7 @@ export * from './Headline.styles';
export * from './Link.styles';
export * from './Menu.styles';
export * from './Message.styles';
+export * from './Tabs.styles';
export * from './Table.styles';
export * from './Text.styles';
export * from './Underlay.styles';
diff --git a/docs/theme/tokens.ts b/docs/theme/tokens.ts
index 644d1311d6..4d7917c1d9 100644
--- a/docs/theme/tokens.ts
+++ b/docs/theme/tokens.ts
@@ -27,6 +27,7 @@ export const colors = {
text: {
primary: {
DEFAULT: tw.slate[950],
+ muted: tw.slate[500],
},
// State
@@ -54,5 +55,7 @@ export const colors = {
// Border
// ---------------
- border: {},
+ border: {
+ DEFAULT: tw.slate[900],
+ },
};
diff --git a/docs/ui/ComponentDemo.tsx b/docs/ui/ComponentDemo.tsx
index 23a907de01..49efd75716 100644
--- a/docs/ui/ComponentDemo.tsx
+++ b/docs/ui/ComponentDemo.tsx
@@ -1,9 +1,8 @@
import { ReactNode } from 'react';
+import { MarigoldProvider, Tabs } from './marigold';
import { type Theme } from '@marigold/system';
-import { registry } from '../registry';
-import { MarigoldProvider } from './marigold';
-
+import { registry } from '@/registry';
import { useThemeSwitch } from '@/app/_components/ThemeSwitch';
export interface ComponentDemoProps {
name: keyof typeof registry;
@@ -11,27 +10,27 @@ export interface ComponentDemoProps {
children?: ReactNode;
}
-export const ComponentDemo = ({
- name,
- source,
- children,
-}: ComponentDemoProps) => {
+export const ComponentDemo = ({ name, children }: ComponentDemoProps) => {
const Demo = registry[name].demo;
const { current, themes } = useThemeSwitch();
return (
-
+
+
+
+
+
+ {children}
+
+
);
};
diff --git a/docs/ui/CopyButton.tsx b/docs/ui/CopyButton.tsx
new file mode 100644
index 0000000000..548860439e
--- /dev/null
+++ b/docs/ui/CopyButton.tsx
@@ -0,0 +1,42 @@
+import React from 'react';
+import { Button } from '@marigold/components';
+import useClipboard from 'react-use-clipboard';
+
+interface CopyProps {
+ codeString: string;
+}
+
+export const CopyButton = ({ codeString }: CopyProps) => {
+ const [isCopied, setCopied] = useClipboard(codeString, {
+ successDuration: 1000,
+ });
+ return (
+
+ );
+};
diff --git a/docs/ui/mdx.tsx b/docs/ui/mdx.tsx
index 5e79311cb2..779c30f857 100644
--- a/docs/ui/mdx.tsx
+++ b/docs/ui/mdx.tsx
@@ -3,10 +3,12 @@
import { HTMLAttributes } from 'react';
import { useMDXComponent } from 'next-contentlayer/hooks';
-import * as DocComponents from '@/app/components/[...slug]/_components';
import { IconList } from '@/app/components';
-import { ComponentDemo } from './ComponentDemo';
+
import { Headline, Message, Link, Text } from './';
+import { ComponentDemo } from './ComponentDemo';
+import { CopyButton } from './CopyButton';
+import * as DocComponents from '@/app/components/[...slug]/_components';
// Typography
// ---------------
@@ -35,14 +37,30 @@ const typography = {
),
code: (props: HTMLAttributes) => (
-
+
),
hr: ({ ...props }: HTMLAttributes) => (
),
+ // `__rawString__` is source code to be copied
+ pre: ({
+ __rawString__,
+ ...props
+ }: HTMLAttributes & { __rawString__: string }) => {
+ return (
+
+
+
+
+
+ {props.children}
+
+
+ );
+ },
};
// MDX Components
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e7cf823405..7faca57dc8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,9 +1,5 @@
lockfileVersion: '6.0'
-settings:
- autoInstallPeers: true
- excludeLinksFromLockfile: false
-
importers:
.:
dependencies:
@@ -142,7 +138,7 @@ importers:
version: 8.0.3(@babel/plugin-syntax-flow@7.16.7)(@babel/plugin-transform-react-jsx@7.17.3)(eslint@8.44.0)
eslint-plugin-import:
specifier: 2.27.5
- version: 2.27.5(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)
+ version: 2.27.5(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.44.0)
eslint-plugin-jest:
specifier: 27.2.1
version: 27.2.1(@typescript-eslint/eslint-plugin@5.61.0)(eslint@8.44.0)(jest@29.5.0)(typescript@5.0.4)
@@ -386,15 +382,24 @@ importers:
react-use:
specifier: 17.4.0
version: 17.4.0(react-dom@18.2.0)(react@18.2.0)
+ react-use-clipboard:
+ specifier: 1.0.9
+ version: 1.0.9(react-dom@18.2.0)(react@18.2.0)
rehype-autolink-headings:
specifier: 6.1.1
version: 6.1.1
+ rehype-pretty-code:
+ specifier: 0.10.0
+ version: 0.10.0(shiki@0.14.3)
rehype-slug:
specifier: 5.1.0
version: 5.1.0
remark-gfm:
specifier: 3.0.1
version: 3.0.1
+ shiki:
+ specifier: 0.14.3
+ version: 0.14.3
tailwindcss:
specifier: 3.3.2
version: 3.3.2(ts-node@10.9.1)
@@ -9552,6 +9557,13 @@ packages:
engines: { node: '>=12' }
dev: false
+ /ansi-sequence-parser@1.1.0:
+ resolution:
+ {
+ integrity: sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==,
+ }
+ dev: false
+
/ansi-styles@3.2.1:
resolution:
{
@@ -12885,7 +12897,7 @@ packages:
confusing-browser-globals: 1.0.11
eslint: 8.44.0
eslint-plugin-flowtype: 8.0.3(@babel/plugin-syntax-flow@7.16.7)(@babel/plugin-transform-react-jsx@7.17.3)(eslint@8.44.0)
- eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.61.0)(eslint@8.44.0)
+ eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.44.0)
eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.61.0)(eslint@8.44.0)(jest@29.5.0)(typescript@5.0.4)
eslint-plugin-jsx-a11y: 6.7.1(eslint@8.44.0)
eslint-plugin-react: 7.32.2(eslint@8.44.0)
@@ -13028,42 +13040,6 @@ packages:
- supports-color
dev: false
- /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.61.0)(eslint@8.44.0):
- resolution:
- {
- integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==,
- }
- engines: { node: '>=4' }
- peerDependencies:
- '@typescript-eslint/parser': '*'
- eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
- peerDependenciesMeta:
- '@typescript-eslint/parser':
- optional: true
- dependencies:
- '@typescript-eslint/parser': 5.61.0(eslint@8.44.0)(typescript@5.0.4)
- array-includes: 3.1.6
- array.prototype.flat: 1.3.1
- array.prototype.flatmap: 1.3.1
- debug: 3.2.7
- doctrine: 2.1.0
- eslint: 8.44.0
- eslint-import-resolver-node: 0.3.7
- eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.61.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.44.0)
- has: 1.0.3
- is-core-module: 2.12.1
- is-glob: 4.0.3
- minimatch: 3.1.2
- object.values: 1.1.6
- resolve: 1.22.2
- semver: 6.3.0
- tsconfig-paths: 3.14.2
- transitivePeerDependencies:
- - eslint-import-resolver-typescript
- - eslint-import-resolver-webpack
- - supports-color
- dev: false
-
/eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.61.0)(eslint@8.44.0)(jest@29.5.0)(typescript@5.0.4):
resolution:
{
@@ -14848,6 +14824,18 @@ packages:
readable-stream: 3.6.2
safe-buffer: 5.2.1
+ /hash-obj@4.0.0:
+ resolution:
+ {
+ integrity: sha512-FwO1BUVWkyHasWDW4S8o0ssQXjvyghLV2rfVhnN36b2bbcj45eGiuzdn9XOvOpjV3TKQD7Gm2BWNXdE9V4KKYg==,
+ }
+ engines: { node: '>=12' }
+ dependencies:
+ is-obj: 3.0.0
+ sort-keys: 5.0.0
+ type-fest: 1.4.0
+ dev: false
+
/hash-wasm@4.9.0:
resolution:
{
@@ -15780,6 +15768,14 @@ packages:
}
engines: { node: '>=0.12.0' }
+ /is-obj@3.0.0:
+ resolution:
+ {
+ integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==,
+ }
+ engines: { node: '>=12' }
+ dev: false
+
/is-path-cwd@2.2.0:
resolution:
{
@@ -19424,6 +19420,13 @@ packages:
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
+ /parse-numeric-range@1.3.0:
+ resolution:
+ {
+ integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==,
+ }
+ dev: false
+
/parse5@6.0.1:
resolution:
{
@@ -21048,6 +21051,20 @@ packages:
tslib: 2.6.0
dev: false
+ /react-use-clipboard@1.0.9(react-dom@18.2.0)(react@18.2.0):
+ resolution:
+ {
+ integrity: sha512-OcMzc14usXhqQnAkvzmhCXAbW5WBT2LSgscVh2vKHXZfg72jFsSOsEearqdeC/nUj8YxEfLnziqe7AE7YkWFwA==,
+ }
+ peerDependencies:
+ react: ^16.8.0 || ^17 || ^18
+ react-dom: ^16.8.0 || ^17 || ^18
+ dependencies:
+ copy-to-clipboard: 3.3.3
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/react-use@17.4.0(react-dom@18.2.0)(react@18.2.0):
resolution:
{
@@ -21312,6 +21329,21 @@ packages:
unist-util-visit: 4.1.2
dev: false
+ /rehype-pretty-code@0.10.0(shiki@0.14.3):
+ resolution:
+ {
+ integrity: sha512-qCD071Y+vUxEy9yyrATPk2+W9q7qCbzZgtc9suZhu75bmRQvOlBhJt4d3WvqSMTamkKoFkvqtCjyAk+ggH+aXQ==,
+ }
+ engines: { node: '>=16' }
+ peerDependencies:
+ shiki: 0.x
+ dependencies:
+ '@types/hast': 2.3.4
+ hash-obj: 4.0.0
+ parse-numeric-range: 1.3.0
+ shiki: 0.14.3
+ dev: false
+
/rehype-slug@5.1.0:
resolution:
{
@@ -22057,6 +22089,18 @@ packages:
rechoir: 0.6.2
dev: true
+ /shiki@0.14.3:
+ resolution:
+ {
+ integrity: sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==,
+ }
+ dependencies:
+ ansi-sequence-parser: 1.1.0
+ jsonc-parser: 3.2.0
+ vscode-oniguruma: 1.7.0
+ vscode-textmate: 8.0.0
+ dev: false
+
/side-channel@1.0.4:
resolution:
{
@@ -22166,6 +22210,16 @@ packages:
transitivePeerDependencies:
- supports-color
+ /sort-keys@5.0.0:
+ resolution:
+ {
+ integrity: sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==,
+ }
+ engines: { node: '>=12' }
+ dependencies:
+ is-plain-obj: 4.1.0
+ dev: false
+
/source-list-map@2.0.1:
resolution:
{
@@ -23537,6 +23591,14 @@ packages:
}
engines: { node: '>=8' }
+ /type-fest@1.4.0:
+ resolution:
+ {
+ integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==,
+ }
+ engines: { node: '>=10' }
+ dev: false
+
/type-fest@2.19.0:
resolution:
{
@@ -24211,6 +24273,20 @@ packages:
integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==,
}
+ /vscode-oniguruma@1.7.0:
+ resolution:
+ {
+ integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==,
+ }
+ dev: false
+
+ /vscode-textmate@8.0.0:
+ resolution:
+ {
+ integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==,
+ }
+ dev: false
+
/w3c-xmlserializer@4.0.0:
resolution:
{
@@ -24854,3 +24930,7 @@ packages:
which: 3.0.1
yaml: 2.3.1
dev: false
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false