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 ( -
-
-        {source}
-      
-
-
- -
- -
-
-
-
+ + +
+ +
+ +
+
+
+
+ + {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