+ const headings = extractHeadingsFromJSX(
+ page.content as {
+ props: { children: React.ReactElement[] };
+ },
+ );
+
+ return (
+
+
+
+
+ {page.title}
+
+
+ {description}
+
+
-
+
+ 0}>
+
+
+
+
);
}
diff --git a/apps/web/app/(marketing)/docs/_components/docs-nav-link.tsx b/apps/web/app/(marketing)/docs/_components/docs-nav-link.tsx
new file mode 100644
index 000000000..960ce90b9
--- /dev/null
+++ b/apps/web/app/(marketing)/docs/_components/docs-nav-link.tsx
@@ -0,0 +1,26 @@
+'use client';
+
+import Link from 'next/link';
+import { usePathname } from 'next/navigation';
+
+import { SidebarMenuButton, SidebarMenuItem } from '@kit/ui/shadcn-sidebar';
+import { cn, isRouteActive } from '@kit/ui/utils';
+
+export function DocsNavLink({ label, url }: { label: string; url: string }) {
+ const currentPath = usePathname();
+ const isCurrent = isRouteActive(url, currentPath, true);
+
+ return (
+
+
+
+ {label}
+
+
+
+ );
+}
diff --git a/apps/web/app/(marketing)/docs/_components/docs-navigation.tsx b/apps/web/app/(marketing)/docs/_components/docs-navigation.tsx
index 6fe22b971..1d21e7fb7 100644
--- a/apps/web/app/(marketing)/docs/_components/docs-navigation.tsx
+++ b/apps/web/app/(marketing)/docs/_components/docs-navigation.tsx
@@ -1,192 +1,68 @@
-'use client';
-
-import { useEffect, useMemo, useState } from 'react';
-
-import Link from 'next/link';
-import { usePathname } from 'next/navigation';
-
-import { Menu } from 'lucide-react';
-
import { Cms } from '@kit/cms';
-import { isBrowser } from '@kit/shared/utils';
-import { Button } from '@kit/ui/button';
-import { If } from '@kit/ui/if';
-import { cn, isRouteActive } from '@kit/ui/utils';
+import {
+ Sidebar,
+ SidebarGroup,
+ SidebarGroupContent,
+ SidebarMenu,
+ SidebarMenuSub,
+} from '@kit/ui/shadcn-sidebar';
-function DocsNavLink({
- label,
- url,
- level,
- activePath,
-}: {
- label: string;
- url: string;
- level: number;
- activePath: string;
-}) {
- const isCurrent = isRouteActive(url, activePath, true);
- const isFirstLevel = level === 0;
+import { DocsNavLink } from '~/(marketing)/docs/_components/docs-nav-link';
- return (
-
- );
-}
+import { FloatingDocumentationNavigation } from './floating-docs-navigation';
-function Node({
- node,
- level,
- activePath,
-}: {
- node: Cms.ContentItem;
- level: number;
- activePath: string;
-}) {
+function Node({ node, level }: { node: Cms.ContentItem; level: number }) {
const pathPrefix = `/docs`;
const url = `${pathPrefix}/${node.slug}`;
return (
<>
-
+
{(node.children ?? []).length > 0 && (
-
+
)}
>
);
}
-function Tree({
- pages,
- level,
- activePath,
-}: {
- pages: Cms.ContentItem[];
- level: number;
- activePath: string;
-}) {
+function Tree({ pages, level }: { pages: Cms.ContentItem[]; level: number }) {
+ if (level === 0) {
+ return pages.map((treeNode, index) => (
+
+
+
+
+
+
+
+ ));
+ }
+
return (
-
0,
- })}
- >
+
{pages.map((treeNode, index) => (
-
+
))}
-
+
);
}
export function DocsNavigation({ pages }: { pages: Cms.ContentItem[] }) {
- const activePath = usePathname();
-
return (
<>
-
+
+
-
+
+
+
>
);
}
-
-function FloatingDocumentationNavigation({
- pages,
- activePath,
-}: React.PropsWithChildren<{
- pages: Cms.ContentItem[];
- activePath: string;
-}>) {
- const body = useMemo(() => {
- return isBrowser() ? document.body : null;
- }, []);
-
- const [isVisible, setIsVisible] = useState(false);
-
- const enableScrolling = (element: HTMLElement) =>
- (element.style.overflowY = '');
-
- const disableScrolling = (element: HTMLElement) =>
- (element.style.overflowY = 'hidden');
-
- // enable/disable body scrolling when the docs are toggled
- useEffect(() => {
- if (!body) {
- return;
- }
-
- if (isVisible) {
- disableScrolling(body);
- } else {
- enableScrolling(body);
- }
- }, [isVisible, body]);
-
- // hide docs when navigating to another page
- useEffect(() => {
- setIsVisible(false);
- }, [activePath]);
-
- const onClick = () => {
- setIsVisible(!isVisible);
- };
-
- return (
- <>
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/apps/web/app/(marketing)/docs/_components/docs-table-of-contents.tsx b/apps/web/app/(marketing)/docs/_components/docs-table-of-contents.tsx
new file mode 100644
index 000000000..e06b4d026
--- /dev/null
+++ b/apps/web/app/(marketing)/docs/_components/docs-table-of-contents.tsx
@@ -0,0 +1,51 @@
+'use client';
+
+import Link from 'next/link';
+
+interface NavItem {
+ text: string;
+ level: number;
+ href: string;
+ children: NavItem[];
+}
+
+export function DocsTableOfContents(props: { data: NavItem[] }) {
+ const navData = props.data;
+
+ return (
+
+
+ {navData.map((item) => (
+ -
+
+ {item.text}
+
+ {item.children && (
+
+ {item.children.map((child) => (
+ -
+
+ {child.text}
+
+
+ ))}
+
+ )}
+
+ ))}
+
+
+ );
+}
diff --git a/apps/web/app/(marketing)/docs/_components/floating-docs-navigation.tsx b/apps/web/app/(marketing)/docs/_components/floating-docs-navigation.tsx
new file mode 100644
index 000000000..840d8947a
--- /dev/null
+++ b/apps/web/app/(marketing)/docs/_components/floating-docs-navigation.tsx
@@ -0,0 +1,73 @@
+'use client';
+
+import { useEffect, useMemo, useState } from 'react';
+
+import { usePathname } from 'next/navigation';
+
+import { Menu } from 'lucide-react';
+
+import { isBrowser } from '@kit/shared/utils';
+import { Button } from '@kit/ui/button';
+import { If } from '@kit/ui/if';
+
+export function FloatingDocumentationNavigation(
+ props: React.PropsWithChildren,
+) {
+ const activePath = usePathname();
+
+ const body = useMemo(() => {
+ return isBrowser() ? document.body : null;
+ }, []);
+
+ const [isVisible, setIsVisible] = useState(false);
+
+ const enableScrolling = (element: HTMLElement) =>
+ (element.style.overflowY = '');
+
+ const disableScrolling = (element: HTMLElement) =>
+ (element.style.overflowY = 'hidden');
+
+ // enable/disable body scrolling when the docs are toggled
+ useEffect(() => {
+ if (!body) {
+ return;
+ }
+
+ if (isVisible) {
+ disableScrolling(body);
+ } else {
+ enableScrolling(body);
+ }
+ }, [isVisible, body]);
+
+ // hide docs when navigating to another page
+ useEffect(() => {
+ setIsVisible(false);
+ }, [activePath]);
+
+ const onClick = () => {
+ setIsVisible(!isVisible);
+ };
+
+ return (
+ <>
+
+
+ {props.children}
+
+
+
+
+ >
+ );
+}
diff --git a/apps/web/app/(marketing)/docs/_lib/utils.ts b/apps/web/app/(marketing)/docs/_lib/utils.ts
new file mode 100644
index 000000000..e714ec047
--- /dev/null
+++ b/apps/web/app/(marketing)/docs/_lib/utils.ts
@@ -0,0 +1,136 @@
+import { Cms } from '@kit/cms';
+
+interface HeadingNode {
+ text: string;
+ level: number;
+ href: string;
+ children: HeadingNode[];
+}
+
+/**
+ * @name buildDocumentationTree
+ * @description Build a tree structure for the documentation pages.
+ * @param pages
+ */
+export function buildDocumentationTree(pages: Cms.ContentItem[]) {
+ const tree: Cms.ContentItem[] = [];
+
+ pages.forEach((page) => {
+ if (page.parentId) {
+ const parent = pages.find((item) => item.slug === page.parentId);
+
+ if (!parent) {
+ return;
+ }
+
+ if (!parent.children) {
+ parent.children = [];
+ }
+
+ parent.children.push(page);
+
+ // sort children by order
+ parent.children.sort((a, b) => a.order - b.order);
+ } else {
+ tree.push(page);
+ }
+ });
+
+ return tree.sort((a, b) => a.order - b.order);
+}
+
+/**
+ * @name extractHeadingsFromJSX
+ * @description Extract headings from JSX. This is used to generate the table of contents for the documentation pages.
+ * @param jsx
+ */
+export function extractHeadingsFromJSX(jsx: {
+ props: { children: React.ReactElement[] };
+}) {
+ const headings: HeadingNode[] = [];
+ let currentH2: HeadingNode | null = null;
+
+ function getTextContent(
+ children: React.ReactElement[] | string | React.ReactElement,
+ ): string {
+ if (typeof children === 'string') {
+ return children;
+ }
+
+ if (Array.isArray(children)) {
+ return children.map((child) => getTextContent(child)).join('');
+ }
+
+ if (
+ (
+ children.props as {
+ children: React.ReactElement;
+ }
+ ).children
+ ) {
+ return getTextContent((children.props as { children: React.ReactElement }).children);
+ }
+
+ return '';
+ }
+
+ jsx.props.children.forEach((node) => {
+ if (!node || typeof node !== 'object' || !('type' in node)) {
+ return;
+ }
+
+ const nodeType = node.type as string;
+
+ const text = getTextContent(
+ (
+ node.props as {
+ children: React.ReactElement[];
+ }
+ ).children,
+ );
+
+ if (nodeType === 'h1') {
+ const slug = generateSlug(text);
+
+ headings.push({
+ text,
+ level: 1,
+ href: `#${slug}`,
+ children: [],
+ });
+ } else if (nodeType === 'h2') {
+ const slug = generateSlug(text);
+
+ currentH2 = {
+ text,
+ level: 2,
+ href: `#${slug}`,
+ children: [],
+ };
+
+ if (headings.length > 0) {
+ headings[headings.length - 1]!.children.push(currentH2);
+ } else {
+ headings.push(currentH2);
+ }
+ } else if (nodeType === 'h3' && currentH2) {
+ const slug = generateSlug(text);
+
+ currentH2.children.push({
+ text,
+ level: 3,
+ href: `#${slug}`,
+ children: [],
+ });
+ }
+ });
+
+ return headings;
+}
+
+function generateSlug(text: string): string {
+ return text
+ .toLowerCase()
+ .replace(/[^a-z0-9]+/g, '-')
+ .replace(/(^-|-$)/g, '');
+}
diff --git a/apps/web/app/(marketing)/docs/layout.tsx b/apps/web/app/(marketing)/docs/layout.tsx
index c4337487d..fee293755 100644
--- a/apps/web/app/(marketing)/docs/layout.tsx
+++ b/apps/web/app/(marketing)/docs/layout.tsx
@@ -1,56 +1,24 @@
-import { Cms } from '@kit/cms';
+import { SidebarProvider } from '@kit/ui/shadcn-sidebar';
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
// local imports
import { DocsNavigation } from './_components/docs-navigation';
import { getDocs } from './_lib/server/docs.loader';
+import { buildDocumentationTree } from './_lib/utils';
async function DocsLayout({ children }: React.PropsWithChildren) {
const { resolvedLanguage } = await createI18nServerInstance();
- const pages = await getDocs(resolvedLanguage);
+ const docs = await getDocs(resolvedLanguage);
+ const tree = buildDocumentationTree(docs);
return (
-
-
+
+
{children}
-
+
);
}
export default DocsLayout;
-
-// we want to place all the children under their parent
-// based on the property parentId
-function buildDocumentationTree(pages: Cms.ContentItem[]) {
- const tree: Cms.ContentItem[] = [];
- const map: Record
= {};
-
- pages.forEach((page) => {
- map[page.id] = page;
- });
-
- pages.forEach((page) => {
- if (page.parentId) {
- const parent = map[page.parentId];
-
- if (!parent) {
- return;
- }
-
- if (!parent.children) {
- parent.children = [];
- }
-
- parent.children.push(page);
-
- // sort children by order
- parent.children.sort((a, b) => a.order - b.order);
- } else {
- tree.push(page);
- }
- });
-
- return tree.sort((a, b) => a.order - b.order);
-}
diff --git a/apps/web/app/(marketing)/docs/loading.tsx b/apps/web/app/(marketing)/docs/loading.tsx
new file mode 100644
index 000000000..902f1f609
--- /dev/null
+++ b/apps/web/app/(marketing)/docs/loading.tsx
@@ -0,0 +1,3 @@
+import { GlobalLoader } from '@kit/ui/global-loader';
+
+export default GlobalLoader;
\ No newline at end of file
diff --git a/apps/web/content/documentation/authentication/configuration.mdoc b/apps/web/content/documentation/authentication/configuration.mdoc
index 08250384c..da7ffdc85 100644
--- a/apps/web/content/documentation/authentication/configuration.mdoc
+++ b/apps/web/content/documentation/authentication/configuration.mdoc
@@ -2,8 +2,7 @@
title: "Configuration"
description: "Learn how authentication works in MakerKit and how to configure it."
publishedAt: 2024-04-11
-order: 0
-parent: "authentication/authentication"
+order: 1
status: "published"
---
diff --git a/apps/web/content/documentation/getting-started/installing-dependencies.mdoc b/apps/web/content/documentation/getting-started/installing-dependencies.mdoc
index 1af89bf83..ceeb75974 100644
--- a/apps/web/content/documentation/getting-started/installing-dependencies.mdoc
+++ b/apps/web/content/documentation/getting-started/installing-dependencies.mdoc
@@ -2,7 +2,6 @@
title: "Installing Dependencies"
description: "Learn how to install dependencies for your project."
publishedAt: 2024-04-11
-parent: "getting-started/getting-started"
order: 0
status: "published"
---
diff --git a/packages/cms/keystatic/src/content-renderer.tsx b/packages/cms/keystatic/src/content-renderer.tsx
index 0fceb95af..e5d80dec4 100644
--- a/packages/cms/keystatic/src/content-renderer.tsx
+++ b/packages/cms/keystatic/src/content-renderer.tsx
@@ -1,3 +1,3 @@
export function KeystaticContentRenderer(props: { content: unknown }) {
- return {props.content as React.ReactNode}
;
+ return props.content as React.ReactNode;
}
diff --git a/packages/cms/keystatic/src/keystatic-client.ts b/packages/cms/keystatic/src/keystatic-client.ts
index 27bb399e3..9ebcefba6 100644
--- a/packages/cms/keystatic/src/keystatic-client.ts
+++ b/packages/cms/keystatic/src/keystatic-client.ts
@@ -1,13 +1,8 @@
-import React from 'react';
-
import { Cms, CmsClient } from '@kit/cms-types';
import { createKeystaticReader } from './create-reader';
-import {
- CustomMarkdocComponents,
- CustomMarkdocTags,
-} from './custom-components';
import { PostEntryProps } from './keystatic.config';
+import { renderMarkdoc } from './markdoc';
export function createKeystaticClient() {
return new KeystaticClient();
@@ -85,12 +80,78 @@ class KeystaticClient implements CmsClient {
return right - left;
});
- const items = await Promise.all(
- filtered.slice(startOffset, endOffset).map(async (item) => {
- const children = docs.filter((item) => item.entry.parent === item.slug);
+ function processItems(items: typeof docs) {
+ const result: typeof docs = [...items];
- return this.mapPost(item, children);
- }),
+ const indexFiles = items.filter((item) => {
+ const parts = item.slug.split('/');
+
+ return (
+ parts.length > 1 &&
+ parts[parts.length - 1] === parts[parts.length - 2]
+ );
+ });
+
+ function findParentIndex(pathParts: string[]): string | null {
+ // Try each level up from the current path until we find an index file
+ for (let i = pathParts.length - 1; i > 0; i--) {
+ const currentPath = pathParts.slice(0, i).join('/');
+
+ const possibleParent = indexFiles.find((indexFile) => {
+ const indexParts = indexFile.slug.split('/');
+ const indexFolderPath = indexParts.slice(0, -1).join('/');
+
+ return indexFolderPath === currentPath;
+ });
+
+ if (possibleParent) {
+ return possibleParent.slug;
+ }
+ }
+ return null;
+ }
+
+ result.forEach((item) => {
+ const pathParts = item.slug.split('/');
+
+ // Skip if this is a root level index file (e.g., "authentication/authentication")
+ if (pathParts.length === 2 && pathParts[0] === pathParts[1]) {
+ item.entry.parent = null;
+ return;
+ }
+
+ // Check if current item is an index file
+ const isIndexFile =
+ pathParts[pathParts.length - 1] === pathParts[pathParts.length - 2];
+
+ if (isIndexFile) {
+ // For index files, find parent in the level above
+ const parentPath = pathParts.slice(0, -2);
+ if (parentPath.length > 0) {
+ item.entry.parent = findParentIndex(
+ parentPath.concat(parentPath[parentPath.length - 1]!),
+ );
+ } else {
+ item.entry.parent = null;
+ }
+ } else {
+ // For regular files, find parent in the current folder
+ item.entry.parent = findParentIndex(pathParts);
+ }
+ });
+
+ return result;
+ }
+
+ const itemsWithParents = processItems(filtered);
+
+ const items = await Promise.all(
+ itemsWithParents
+ .slice(startOffset, endOffset)
+ .sort((a, b) => {
+ return (a.entry.order ?? 0) - (b.entry.order ?? 0);
+ })
+ .map((item) => this.mapPost(item)),
);
return {
@@ -157,25 +218,17 @@ class KeystaticClient implements CmsClient {
slug: string;
},
>(item: Type, children: Type[] = []): Promise {
- const { transform, renderers } = await import('@markdoc/markdoc');
-
const publishedAt = item.entry.publishedAt
? new Date(item.entry.publishedAt)
: new Date();
- const markdoc = await item.entry.content();
-
- const content = transform(markdoc.node, {
- tags: CustomMarkdocTags,
- });
-
- const html = renderers.react(content, React, {
- components: CustomMarkdocComponents,
- });
+ const content = await item.entry.content();
+ const html = await renderMarkdoc(content.node);
return {
id: item.slug,
title: item.entry.title,
+ label: item.entry.label,
url: item.slug,
slug: item.slug,
description: item.entry.description,
@@ -201,7 +254,7 @@ class KeystaticClient implements CmsClient {
parentId: item.entry.parent ?? undefined,
order: item.entry.order ?? 1,
children: await Promise.all(
- children.map(async (child) => this.mapPost(child, [])),
+ children.map((child) => this.mapPost(child, [])),
),
};
}
diff --git a/packages/cms/keystatic/src/keystatic.config.ts b/packages/cms/keystatic/src/keystatic.config.ts
index 4a570c00c..d33437769 100644
--- a/packages/cms/keystatic/src/keystatic.config.ts
+++ b/packages/cms/keystatic/src/keystatic.config.ts
@@ -66,6 +66,7 @@ function getKeystaticCollections(path: string) {
format: { contentField: 'content' },
schema: {
title: fields.slug({ name: { label: 'Title' } }),
+ label: fields.text({ label: 'Label', validation: { isRequired: false } }),
image: fields.image({
label: 'Image',
directory: 'public/site/images',
@@ -101,6 +102,7 @@ function getKeystaticCollections(path: string) {
format: { contentField: 'content' },
schema: {
title: fields.slug({ name: { label: 'Title' } }),
+ label: fields.text({ label: 'Label', validation: { isRequired: false } }),
content: getContentField(),
image: fields.image({
label: 'Image',
diff --git a/packages/cms/keystatic/src/markdoc-nodes.ts b/packages/cms/keystatic/src/markdoc-nodes.ts
new file mode 100644
index 000000000..59a89bc68
--- /dev/null
+++ b/packages/cms/keystatic/src/markdoc-nodes.ts
@@ -0,0 +1,42 @@
+// Or replace this with your own function
+import { Config, Node, RenderableTreeNode, Tag } from '@markdoc/markdoc';
+
+function generateID(
+ children: Array,
+ attributes: Record,
+) {
+ if (attributes.id && typeof attributes.id === 'string') {
+ return attributes.id;
+ }
+
+ return children
+ .filter((child) => typeof child === 'string')
+ .join(' ')
+ .replace(/[?]/g, '')
+ .replace(/\s+/g, '-')
+ .toLowerCase();
+}
+
+const heading = {
+ children: ['inline'],
+ attributes: {
+ id: { type: String },
+ level: { type: Number, required: true, default: 1 },
+ },
+ transform(node: Node, config: Config) {
+ const attributes = node.transformAttributes(config);
+ const children = node.transformChildren(config);
+
+ const id = generateID(children, attributes);
+
+ return new Tag(
+ `h${node.attributes.level}`,
+ { ...attributes, id },
+ children,
+ );
+ },
+};
+
+export const MarkdocNodes = {
+ heading,
+};
diff --git a/packages/cms/keystatic/src/markdoc.tsx b/packages/cms/keystatic/src/markdoc.tsx
new file mode 100644
index 000000000..b4ca159f8
--- /dev/null
+++ b/packages/cms/keystatic/src/markdoc.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+
+import { Node } from '@markdoc/markdoc';
+
+import {
+ CustomMarkdocComponents,
+ CustomMarkdocTags,
+} from './custom-components';
+import { MarkdocNodes } from './markdoc-nodes';
+
+/**
+ * @name renderMarkdoc
+ * @description Renders a Markdoc tree to React
+ */
+export async function renderMarkdoc(node: Node) {
+ const { transform, renderers } = await import('@markdoc/markdoc');
+
+ const content = transform(node, {
+ tags: {
+ ...CustomMarkdocTags,
+ },
+ nodes: {
+ ...MarkdocNodes,
+ },
+ });
+
+ return renderers.react(content, React, {
+ components: CustomMarkdocComponents,
+ });
+}
diff --git a/packages/cms/types/src/cms-client.ts b/packages/cms/types/src/cms-client.ts
index de7fc8f09..bc4a90af9 100644
--- a/packages/cms/types/src/cms-client.ts
+++ b/packages/cms/types/src/cms-client.ts
@@ -3,6 +3,7 @@ export namespace Cms {
export interface ContentItem {
id: string;
title: string;
+ label: string | undefined;
url: string;
description: string | undefined;
content: unknown;
diff --git a/packages/cms/wordpress/src/wp-client.ts b/packages/cms/wordpress/src/wp-client.ts
index 60a7d191e..1b1450884 100644
--- a/packages/cms/wordpress/src/wp-client.ts
+++ b/packages/cms/wordpress/src/wp-client.ts
@@ -139,6 +139,7 @@ class WordpressClient implements CmsClient {
return {
id: item.id.toString(),
title: item.title.rendered,
+ label: item.title.rendered,
content: item.content.rendered,
description: item.excerpt.rendered,
image,
@@ -217,6 +218,7 @@ class WordpressClient implements CmsClient {
description: item.excerpt.rendered,
children: [],
title: item.title.rendered,
+ label: item.title.rendered,
content: item.content.rendered,
slug: item.slug,
publishedAt: item.date,
diff --git a/packages/ui/src/shadcn/sidebar.tsx b/packages/ui/src/shadcn/sidebar.tsx
index cae9431ea..5b8ddde81 100644
--- a/packages/ui/src/shadcn/sidebar.tsx
+++ b/packages/ui/src/shadcn/sidebar.tsx
@@ -209,7 +209,7 @@ const Sidebar = React.forwardRef<
HTMLDivElement,
React.ComponentProps<'div'> & {
side?: 'left' | 'right';
- variant?: 'sidebar' | 'floating' | 'inset';
+ variant?: 'sidebar' | 'floating' | 'inset' | 'ghost';
collapsible?: 'offcanvas' | 'icon' | 'none';
}
>(
@@ -285,7 +285,13 @@ const Sidebar = React.forwardRef<
button]:hidden',
+ {
+ 'bg-background': variant === 'ghost',
+ 'bg-sidebar': variant !== 'ghost',
+ },
+ )}
style={
{
'--sidebar-width': SIDEBAR_WIDTH_MOBILE,
@@ -313,12 +319,15 @@ const Sidebar = React.forwardRef<
{/* This is what handles the sidebar gap on desktop */}
{children}
@@ -862,11 +876,7 @@ export function SidebarNavigation({
const ContentContainer = (props: React.PropsWithChildren) => {
if (item.collapsible) {
- return (
-
- {props.children}
-
- );
+ return
{props.children};
}
return props.children;