From c767a0949e23e90279943abd4bb26e7de6460201 Mon Sep 17 00:00:00 2001 From: sarahgm <38324334+sarahgm@users.noreply.github.com> Date: Wed, 26 Jul 2023 08:26:34 +0200 Subject: [PATCH] docs: add Hook docs pages (#3215) --- docs/app/_components/Navigation.tsx | 24 +++++++ docs/app/hooks/[...slug]/page.tsx | 59 +++++++++++++++++ docs/content/hooks/.eslintrc.js | 8 +++ .../hooks/useAsyncListData/async.demo.tsx | 66 +++++++++++++++++++ .../useAsyncListData/useAsyncListData.mdx | 29 ++++++++ docs/content/hooks/useTheme/useTheme.demo.tsx | 24 +++++++ docs/content/hooks/useTheme/useTheme.mdx | 30 +++++++++ docs/contentlayer.config.ts | 26 +++++++- docs/scripts/build-registry.mjs | 1 + 9 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 docs/app/hooks/[...slug]/page.tsx create mode 100644 docs/content/hooks/.eslintrc.js create mode 100644 docs/content/hooks/useAsyncListData/async.demo.tsx create mode 100644 docs/content/hooks/useAsyncListData/useAsyncListData.mdx create mode 100644 docs/content/hooks/useTheme/useTheme.demo.tsx create mode 100644 docs/content/hooks/useTheme/useTheme.mdx diff --git a/docs/app/_components/Navigation.tsx b/docs/app/_components/Navigation.tsx index e8140fa690..20327ceb20 100644 --- a/docs/app/_components/Navigation.tsx +++ b/docs/app/_components/Navigation.tsx @@ -6,6 +6,7 @@ import { allContentPages, ComponentPage, allComponentPages, + allHookPages, } from 'contentlayer/generated'; import { siteConfig } from '@/lib/config'; @@ -17,6 +18,24 @@ export interface RenderProps { onClick?: () => void; current: string; } +export const renderHookPages = ({ onClick, current }: RenderProps) => { + const pages = [...allHookPages]; + + return pages.map(({ title, slug }) => ( +
+
+ + {title} + +
+
+ )); +}; export const renderContentPages = ({ onClick, current }: RenderProps) => { const pages = [...allContentPages].sort( @@ -88,6 +107,11 @@ export const Navigation = ({ onClick }: NavigationProps) => {
Components
{renderComponentPages({ onClick, current: pathname })} + +
+
Hooks
+ {renderHookPages({ onClick, current: pathname })} +
); }; diff --git a/docs/app/hooks/[...slug]/page.tsx b/docs/app/hooks/[...slug]/page.tsx new file mode 100644 index 0000000000..1fa75adfb2 --- /dev/null +++ b/docs/app/hooks/[...slug]/page.tsx @@ -0,0 +1,59 @@ +import { notFound } from 'next/navigation'; +import { Metadata } from 'next'; +import { allHookPages } from 'contentlayer/generated'; + +import { Headline } from '@/ui'; +import { Mdx } from '@/ui/mdx'; + +interface HookPageProps { + params: { + slug: string[]; + }; +} + +async function getPageFromParams(params: HookPageProps['params']) { + const slug = params?.slug?.join('/'); + const page = allHookPages.find(page => page.slugAsParams === slug); + + if (!page) { + return null; + } + + return page; +} + +export async function generateMetadata({ + params, +}: HookPageProps): Promise { + const page = await getPageFromParams(params); + + if (!page) { + return {}; + } + + return { + title: page.title, + }; +} + +export async function generateStaticParams(): Promise< + HookPageProps['params'][] +> { + return allHookPages.map(page => ({ + slug: page.slugAsParams.split('/'), + })); +} + +export default async function ContentPage({ params }: HookPageProps) { + const page = await getPageFromParams(params); + if (!page) { + notFound(); + } + + return ( +
+ {page.title} + +
+ ); +} diff --git a/docs/content/hooks/.eslintrc.js b/docs/content/hooks/.eslintrc.js new file mode 100644 index 0000000000..ed0d67d029 --- /dev/null +++ b/docs/content/hooks/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + rules: { + /** + * We use default exports for demos. + */ + 'import/no-anonymous-default-export': 'off', + }, +}; diff --git a/docs/content/hooks/useAsyncListData/async.demo.tsx b/docs/content/hooks/useAsyncListData/async.demo.tsx new file mode 100644 index 0000000000..6fd5c02035 --- /dev/null +++ b/docs/content/hooks/useAsyncListData/async.demo.tsx @@ -0,0 +1,66 @@ +import { Table, useAsyncList } from '@marigold/components'; + +export interface asyncData { + name: string; + height: string; + mass: string; + birth_year: string; +} + +export default () => { + let list = useAsyncList({ + async load({ signal }) { + let res = await fetch(`https://swapi.py4e.com/api/people/?search`, { + signal, + }); + let json = await res.json(); + return { + items: json.results, + }; + }, + async sort({ items, sortDescriptor }) { + return { + items: items.sort((a, b) => { + let first = a[sortDescriptor.column as keyof asyncData]; + let second = b[sortDescriptor.column as keyof asyncData]; + let cmp = + (parseInt(first) || first) < (parseInt(second) || second) ? -1 : 1; + if (sortDescriptor.direction === 'descending') { + cmp *= -1; + } + return cmp; + }), + }; + }, + }); + + return ( + + + + Name + + + Height + + + Mass + + + Birth Year + + + + {item => ( + + {columnKey => {(item as any)[columnKey]}} + + )} + +
+ ); +}; diff --git a/docs/content/hooks/useAsyncListData/useAsyncListData.mdx b/docs/content/hooks/useAsyncListData/useAsyncListData.mdx new file mode 100644 index 0000000000..9fda26b17b --- /dev/null +++ b/docs/content/hooks/useAsyncListData/useAsyncListData.mdx @@ -0,0 +1,29 @@ +--- +title: useAsyncListData +caption: Hook that returns async data +--- + +We use the `useAsyncListData` hook from [`react-spectrum stately package`](https://github.com/adobe/react-spectrum/tree/main/packages/%40react-stately). It extends the `useListData` which is also from `react-spectrum`. + +It supports async loading, pagination, sorting and filtering. +It also manages loading and error states, supports abortable requests and works with any data fetchig library or the built-in browser fetch API. + +More information can be found in the [react-spectrum documentation](https://react-spectrum.adobe.com/react-stately/useAsyncList.html). + +## Usage + +### Import + +To import the hook you just have to use this code below. + +```tsx +import { useAsyncListData, useListData } from '@marigold/components'; +``` + +## Examples + +### Async Table + +This is an example from the [``](/components/table/) component. The data will be loaded asynchronously. + + diff --git a/docs/content/hooks/useTheme/useTheme.demo.tsx b/docs/content/hooks/useTheme/useTheme.demo.tsx new file mode 100644 index 0000000000..1c56c8a028 --- /dev/null +++ b/docs/content/hooks/useTheme/useTheme.demo.tsx @@ -0,0 +1,24 @@ +import { List } from '@marigold/components'; +import { ThemeProvider, useTheme } from '@marigold/system'; + +export default () => { + const theme = useTheme(); + + return ( + +
+ {Object.entries(theme).map(([key, value]) => ( + + {key} + {Object.keys(value).map(item => ( + + {item} +
+
+ ))} +
+ ))} +
+
+ ); +}; diff --git a/docs/content/hooks/useTheme/useTheme.mdx b/docs/content/hooks/useTheme/useTheme.mdx new file mode 100644 index 0000000000..cb75c2925f --- /dev/null +++ b/docs/content/hooks/useTheme/useTheme.mdx @@ -0,0 +1,30 @@ +--- +title: useTheme +caption: Hook that applies a theme +--- + +The `useTheme` is a hook that gets you the current theme and all of its attributes and properties. + +The `useTheme` hook returns the current `theme`, if there isn't a theme it uses the `defaultTheme` + +```tsx +const theme = useTheme(); +``` + +## Usage + +### Import + +To import the hook you just have to use this code below. + +```tsx +import { useTheme } from '@marigold/system'; +``` + +## Examples + +### Get all the Theme Properties + +Here is an example which shows you the chosen theme from the theme switcher on the top of the page. With the `useTheme` hook you can get the particular values for the available properties. + + diff --git a/docs/contentlayer.config.ts b/docs/contentlayer.config.ts index 37b919948a..1c6786cf69 100644 --- a/docs/contentlayer.config.ts +++ b/docs/contentlayer.config.ts @@ -80,6 +80,30 @@ export const ComponentPage = defineDocumentType(() => ({ }, })); +export const HookPage = defineDocumentType(() => ({ + name: 'HookPage', + filePathPattern: 'hooks/**/*.mdx', + contentType: 'mdx', + fields: { + ...commonFields, + }, + 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 + resolve: doc => doc._raw.sourceFileName.split('.')[0], + }, + }, +})); + // Config // --------------- const contentDirPath = './content'; @@ -166,5 +190,5 @@ export default makeSource({ ], ], }, - documentTypes: [ContentPage, ComponentPage], + documentTypes: [ContentPage, ComponentPage, HookPage], }); diff --git a/docs/scripts/build-registry.mjs b/docs/scripts/build-registry.mjs index 65561e2a03..23965f6708 100644 --- a/docs/scripts/build-registry.mjs +++ b/docs/scripts/build-registry.mjs @@ -17,6 +17,7 @@ import dynamic from 'next/dynamic'; export const registry = {`; for (const item of demoPath) { + console.log(item); const name = basename(item, '.demo.tsx'); index += ` '${name}': {