mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
UI: Change code block usages
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
---
|
||||
'fumadocs-ui': major
|
||||
---
|
||||
|
||||
**Move `keepCodeBlockBackground` option to code block component**
|
||||
|
||||
**why:** Easier to customise code block styles.
|
||||
|
||||
**migrate:**
|
||||
|
||||
Enable `keepBackground` on `<CodeBlock />`, and remove deprecated usage.
|
||||
|
||||
```tsx
|
||||
import { Pre, CodeBlock } from 'fumadocs-ui/components/codeblock';
|
||||
|
||||
<MDX
|
||||
components={{
|
||||
pre: ({ ref: _ref, ...props }) => (
|
||||
<CodeBlock keepBackground {...props}>
|
||||
<Pre>{props.children}</Pre>
|
||||
</CodeBlock>
|
||||
),
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
'fumadocs-core': major
|
||||
---
|
||||
|
||||
**Remove deprecated option `defaultLang`**
|
||||
|
||||
**why:** The default language feature has been supported by Shiki Rehype integration, you should use it directly.
|
||||
|
||||
**migrate:** Rename to `defaultLanguage`.
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
'fumadocs-ui': major
|
||||
---
|
||||
|
||||
**Change code block component usage**
|
||||
|
||||
**why:** The previous usage was confusing, some props are passed directly to `pre` while some are not.
|
||||
|
||||
**migrate:**
|
||||
|
||||
Pass all props to `CodeBlock` component.
|
||||
This also includes class names, change your custom styles if necessary.
|
||||
|
||||
```tsx
|
||||
import { Pre, CodeBlock } from 'fumadocs-ui/components/codeblock';
|
||||
|
||||
<MDX
|
||||
components={{
|
||||
// HTML `ref` attribute conflicts with `forwardRef`
|
||||
pre: ({ ref: _ref, ...props }) => (
|
||||
<CodeBlock {...props}>
|
||||
<Pre>{props.children}</Pre>
|
||||
</CodeBlock>
|
||||
),
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
You can ignore this if you didn't customise the default `pre` element.
|
||||
@@ -3,6 +3,8 @@ title: Markdown
|
||||
description: How to write documents
|
||||
---
|
||||
|
||||
import { HomeIcon } from 'lucide-react';
|
||||
|
||||
## Introduction
|
||||
|
||||
Fumadocs provides many useful extensions to MDX, a markup language. Here is a brief introduction to the default MDX syntax of Fumadocs UI.
|
||||
@@ -72,7 +74,9 @@ see [MDX Syntax](https://mdxjs.com/docs/what-is-mdx/#mdx-syntax) to learn more.
|
||||
|
||||
### Cards
|
||||
|
||||
A [`Card`](/docs/ui/mdx/card) component is included by default. Similar to links, but you can display more information (e.g. icons).
|
||||
Useful for adding links, it is included by default.
|
||||
|
||||
Same as normal links, but you can display more information (e.g. icons).
|
||||
|
||||
```mdx
|
||||
<Cards>
|
||||
@@ -92,32 +96,74 @@ A [`Card`](/docs/ui/mdx/card) component is included by default. Similar to links
|
||||
/>
|
||||
</Cards>
|
||||
|
||||
#### Icon
|
||||
|
||||
You can specify an icon to cards.
|
||||
|
||||
```mdx
|
||||
import { HomeIcon } from 'lucide-react';
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
icon={<HomeIcon />}
|
||||
href="/"
|
||||
title="Home"
|
||||
description="Go back to home"
|
||||
/>
|
||||
</Cards>
|
||||
```
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
icon={<HomeIcon />}
|
||||
href="/"
|
||||
title="Home"
|
||||
description="Go back to home"
|
||||
/>
|
||||
</Cards>
|
||||
|
||||
### Callouts
|
||||
|
||||
Useful for adding tips/warnings, it is included by default.
|
||||
|
||||
```mdx
|
||||
<Callout title="Title" type="info">
|
||||
Hello World
|
||||
</Callout>
|
||||
<Callout title="Title" type="warn">
|
||||
Hello World
|
||||
</Callout>
|
||||
<Callout>Hello World</Callout>
|
||||
```
|
||||
|
||||
<Callout>Hello World</Callout>
|
||||
|
||||
#### Title
|
||||
|
||||
Specify a callout title.
|
||||
|
||||
```mdx
|
||||
<Callout title="Title">Hello World</Callout>
|
||||
```
|
||||
|
||||
<Callout title="Title">Hello World</Callout>
|
||||
|
||||
#### Types
|
||||
|
||||
You can specify the type of callout.
|
||||
|
||||
- `info` (default)
|
||||
- `warn`
|
||||
- `error`
|
||||
|
||||
```mdx
|
||||
<Callout title="Title" type="error">
|
||||
Hello World
|
||||
</Callout>
|
||||
```
|
||||
|
||||
<Callout title="Title" type="info">
|
||||
Hello World
|
||||
</Callout>
|
||||
<Callout title="Title" type="warn">
|
||||
Hello World
|
||||
</Callout>
|
||||
<Callout title="Title" type="error">
|
||||
Hello World
|
||||
</Callout>
|
||||
|
||||
### Customisation
|
||||
|
||||
See [all MDX components and available options](/docs/ui/mdx).
|
||||
|
||||
## Heading Anchors
|
||||
|
||||
An anchor is automatically applied to all headings, it sanitizes invalid characters like spaces. (e.g. `Hello World` to `hello-world`)
|
||||
|
||||
@@ -8,35 +8,17 @@ preview: callout
|
||||
|
||||
Add it to your MDX components.
|
||||
|
||||
```mdx
|
||||
```tsx
|
||||
import { Callout } from 'fumadocs-ui/components/callout';
|
||||
|
||||
<Callout title="Title">Hello World</Callout>
|
||||
<MDX
|
||||
components={{
|
||||
Callout,
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
### Types
|
||||
|
||||
You can specify the type of callout.
|
||||
|
||||
- `info` (default)
|
||||
- `warn`
|
||||
- `error`
|
||||
|
||||
```mdx
|
||||
<Callout title="Title" type="warn">
|
||||
Hello World
|
||||
</Callout>
|
||||
```
|
||||
|
||||
<Callout title="Title" type="warn">
|
||||
Hello World
|
||||
</Callout>
|
||||
|
||||
### Without Title
|
||||
|
||||
You can create a Callout without title.
|
||||
|
||||
<Callout>Hello World</Callout>
|
||||
See [Markdown](/docs/ui/markdown#callouts) for usages.
|
||||
|
||||
### Reference
|
||||
|
||||
|
||||
@@ -10,24 +10,26 @@ import { HomeIcon } from 'lucide-react';
|
||||
|
||||
Add it to your MDX components.
|
||||
|
||||
```mdx
|
||||
```tsx
|
||||
import { Card, Cards } from 'fumadocs-ui/components/card';
|
||||
|
||||
<MDX
|
||||
components={{
|
||||
Card: (props) => <Card {...props} />,
|
||||
Cards: (props) => <Cards {...props} />,
|
||||
Card,
|
||||
Cards,
|
||||
}}
|
||||
/>
|
||||
/>;
|
||||
```
|
||||
|
||||
See [Markdown](/docs/ui/markdown#cards) for usages.
|
||||
|
||||
### Cards
|
||||
|
||||
The container of cards.
|
||||
|
||||
### Card
|
||||
|
||||
Based on `<Link />`.
|
||||
Based on Next.js `<Link />`.
|
||||
|
||||
```json doc-gen:typescript
|
||||
{
|
||||
@@ -36,28 +38,6 @@ Based on `<Link />`.
|
||||
}
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
Pass the href, title and description.
|
||||
|
||||
```mdx
|
||||
<Cards>
|
||||
<Card
|
||||
href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
|
||||
title="Fetching, Caching, and Revalidating"
|
||||
description="Learn more about caching in Next.js"
|
||||
/>
|
||||
</Cards>
|
||||
```
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
href="https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating"
|
||||
title="Fetching, Caching, and Revalidating"
|
||||
description="Learn more about caching in Next.js"
|
||||
/>
|
||||
</Cards>
|
||||
|
||||
### With Icons
|
||||
|
||||
```mdx
|
||||
|
||||
@@ -34,27 +34,46 @@ Display code blocks, added by default.
|
||||
|
||||
Wrap the pre element in `<CodeBlock />`, which acts as the wrapper of code block.
|
||||
|
||||
```mdx
|
||||
```tsx
|
||||
import { Pre, CodeBlock } from 'fumadocs-ui/components/codeblock';
|
||||
|
||||
<MDX
|
||||
components={{
|
||||
pre: ({ ref: _ref, title, ...props }) => (
|
||||
<CodeBlock title={title}>
|
||||
<Pre {...props} />
|
||||
// HTML `ref` attribute conflicts with `forwardRef`
|
||||
pre: ({ ref: _ref, ...props }) => (
|
||||
<CodeBlock {...props}>
|
||||
<Pre>{props.children}</Pre>
|
||||
</CodeBlock>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
/>;
|
||||
```
|
||||
|
||||
See [Markdown](/docs/ui/markdown#codeblock) for supported features.
|
||||
See [Markdown](/docs/ui/markdown#codeblock) for usages.
|
||||
|
||||
### Keep Background
|
||||
|
||||
Use the background color generated by Shiki (the Rehype Code plugin).
|
||||
|
||||
```tsx
|
||||
import { Pre, CodeBlock } from 'fumadocs-ui/components/codeblock';
|
||||
|
||||
<MDX
|
||||
components={{
|
||||
pre: ({ ref: _ref, ...props }) => (
|
||||
<CodeBlock keepBackground {...props}>
|
||||
<Pre>{props.children}</Pre>
|
||||
</CodeBlock>
|
||||
),
|
||||
}}
|
||||
/>;
|
||||
```
|
||||
|
||||
### Icons
|
||||
|
||||
You can specify a custom icon by passing an `icon` prop to `CodeBlock` component.
|
||||
Specify a custom icon by passing an `icon` prop to `CodeBlock` component.
|
||||
|
||||
By default, the icon will be injected by the custom Shiki transformer automatically.
|
||||
By default, the icon will be injected by the custom Shiki transformer.
|
||||
|
||||
```js title="config.js"
|
||||
console.log('js');
|
||||
|
||||
@@ -6,7 +6,7 @@ index: true
|
||||
|
||||
## Usage
|
||||
|
||||
The default MDX components include Card, Code Blocks and Headings.
|
||||
The default MDX components include Cards, Callouts, Code Blocks and Headings.
|
||||
|
||||
```ts
|
||||
import defaultComponents from 'fumadocs-ui/mdx';
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
} from 'fumadocs-ui/components/codeblock';
|
||||
import { Popup, PopupContent, PopupTrigger } from 'fumadocs-ui/twoslash/popup';
|
||||
import { Wrapper } from '@/components/preview/wrapper';
|
||||
import { cn } from './utils/cn';
|
||||
|
||||
export function useMDXComponents(components: MDXComponents): MDXComponents {
|
||||
return {
|
||||
@@ -19,9 +18,9 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
|
||||
Popup,
|
||||
PopupContent,
|
||||
PopupTrigger,
|
||||
pre: ({ title, className, icon, allowCopy, ...props }: CodeBlockProps) => (
|
||||
<CodeBlock title={title} icon={icon} allowCopy={allowCopy}>
|
||||
<Pre className={cn('max-h-[400px]', className)} {...props} />
|
||||
pre: (props: CodeBlockProps) => (
|
||||
<CodeBlock {...props}>
|
||||
<Pre className="max-h-[400px]">{props.children}</Pre>
|
||||
</CodeBlock>
|
||||
),
|
||||
Tabs,
|
||||
|
||||
@@ -72,14 +72,6 @@ export type RehypeCodeOptions = RehypeShikiOptions & {
|
||||
*/
|
||||
filterMetaString?: (metaString: string) => string;
|
||||
|
||||
/**
|
||||
* Default language
|
||||
*
|
||||
* @defaultValue plaintext
|
||||
* @deprecated Use `defaultLanguage` instead
|
||||
*/
|
||||
defaultLang?: string;
|
||||
|
||||
/**
|
||||
* Add icon to code blocks
|
||||
*/
|
||||
@@ -141,10 +133,6 @@ export function rehypeCode(
|
||||
codeOptions.transformers = [...codeOptions.transformers, transformerTab()];
|
||||
}
|
||||
|
||||
if (codeOptions.defaultLang) {
|
||||
codeOptions.defaultLanguage = codeOptions.defaultLang;
|
||||
}
|
||||
|
||||
return rehypeShiki.call(this, codeOptions) as Transformer<Root, Root>;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ export const Accordion = forwardRef<
|
||||
className="not-prose flex flex-row items-center font-medium text-fd-foreground"
|
||||
>
|
||||
<AccordionPrimitive.Trigger className="flex flex-1 items-center gap-2 p-4 text-start focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fd-ring">
|
||||
<ChevronRight className="-ms-1 size-4 text-fd-muted-foreground transition-transform duration-200 group-data-[state=open]/accordion:rotate-90" />
|
||||
<ChevronRight className="-ms-1 size-4 shrink-0 text-fd-muted-foreground transition-transform duration-200 group-data-[state=open]/accordion:rotate-90" />
|
||||
{title}
|
||||
</AccordionPrimitive.Trigger>
|
||||
{id ? <CopyButton id={id} /> : null}
|
||||
|
||||
@@ -18,7 +18,7 @@ export function Cards(
|
||||
export type CardProps = {
|
||||
icon?: ReactNode;
|
||||
title: string;
|
||||
description: string;
|
||||
description?: string;
|
||||
} & Omit<LinkProps, 'title'>;
|
||||
|
||||
export function Card({
|
||||
@@ -41,7 +41,9 @@ export function Card({
|
||||
</div>
|
||||
) : null}
|
||||
<h3 className="mb-1 font-medium">{title}</h3>
|
||||
<p className="text-fd-muted-foreground">{description}</p>
|
||||
{description ? (
|
||||
<p className="text-fd-muted-foreground">{description}</p>
|
||||
) : null}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,13 +26,25 @@ export type CodeBlockProps = HTMLAttributes<HTMLElement> & {
|
||||
*/
|
||||
icon?: ReactNode;
|
||||
|
||||
/**
|
||||
* Allow to copy code with copy button
|
||||
*
|
||||
* @defaultValue true
|
||||
*/
|
||||
allowCopy?: boolean;
|
||||
|
||||
/**
|
||||
* Keep original background color generated by Shiki or Rehype Code
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
keepBackground?: boolean;
|
||||
};
|
||||
|
||||
export const Pre = forwardRef<HTMLPreElement, HTMLAttributes<HTMLPreElement>>(
|
||||
({ className, ...props }, ref) => {
|
||||
return (
|
||||
<pre ref={ref} className={cn('nd-codeblock p-4', className)} {...props}>
|
||||
<pre ref={ref} className={cn('p-4', className)} {...props}>
|
||||
{props.children}
|
||||
</pre>
|
||||
);
|
||||
@@ -42,7 +54,17 @@ export const Pre = forwardRef<HTMLPreElement, HTMLAttributes<HTMLPreElement>>(
|
||||
Pre.displayName = 'Pre';
|
||||
|
||||
export const CodeBlock = forwardRef<HTMLElement, CodeBlockProps>(
|
||||
({ title, allowCopy = true, icon, className, ...props }, ref) => {
|
||||
(
|
||||
{
|
||||
title,
|
||||
allowCopy = true,
|
||||
keepBackground = false,
|
||||
icon,
|
||||
className,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const areaRef = useRef<HTMLDivElement>(null);
|
||||
const onCopy = useCallback(() => {
|
||||
const pre = areaRef.current?.getElementsByTagName('pre').item(0);
|
||||
@@ -61,7 +83,8 @@ export const CodeBlock = forwardRef<HTMLElement, CodeBlockProps>(
|
||||
<figure
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'not-prose group relative my-6 overflow-hidden rounded-lg border bg-fd-secondary/50 text-sm',
|
||||
'not-prose group fd-codeblock relative my-6 overflow-hidden rounded-lg border bg-fd-secondary/50 text-sm',
|
||||
keepBackground && 'fd-codeblock-keep-bg',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -2,15 +2,17 @@
|
||||
|
||||
import * as Base from '@/components/codeblock';
|
||||
|
||||
export function Pre({
|
||||
title,
|
||||
allowCopy,
|
||||
icon,
|
||||
...props
|
||||
}: Base.CodeBlockProps): React.ReactElement {
|
||||
/**
|
||||
* You are NOT supposed to use this component directly.
|
||||
*
|
||||
* This should be referenced in the output generated by the Rehype Code plugin.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function Pre(props: Base.CodeBlockProps): React.ReactElement {
|
||||
return (
|
||||
<Base.CodeBlock title={title} allowCopy={allowCopy} icon={icon}>
|
||||
<Base.Pre {...props} />
|
||||
<Base.CodeBlock {...props}>
|
||||
<Base.Pre>{props.children}</Base.Pre>
|
||||
</Base.CodeBlock>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,13 +31,6 @@ interface DocsUIOptions {
|
||||
* Color preset
|
||||
*/
|
||||
preset?: keyof typeof presets | Preset;
|
||||
|
||||
/**
|
||||
* Keep code block background of theme
|
||||
*
|
||||
* @defaultValue false
|
||||
*/
|
||||
keepCodeBlockBackground?: boolean;
|
||||
}
|
||||
|
||||
type Keys =
|
||||
@@ -115,11 +108,7 @@ function createTailwindColors(
|
||||
}
|
||||
|
||||
export const docsUi = plugin.withOptions<DocsUIOptions>(
|
||||
({
|
||||
cssPrefix = '',
|
||||
preset = 'default',
|
||||
keepCodeBlockBackground = false,
|
||||
} = {}) => {
|
||||
({ cssPrefix = '', preset = 'default' } = {}) => {
|
||||
return ({ addBase, addComponents, addUtilities }) => {
|
||||
const { light, dark, css } =
|
||||
typeof preset === 'string' ? presets[preset] : preset;
|
||||
@@ -139,22 +128,22 @@ export const docsUi = plugin.withOptions<DocsUIOptions>(
|
||||
if (css) addBase(css);
|
||||
|
||||
addComponents({
|
||||
'.nd-codeblock span': {
|
||||
'.fd-codeblock pre span': {
|
||||
color: 'var(--shiki-light)',
|
||||
},
|
||||
'.dark .nd-codeblock span': {
|
||||
'.dark .fd-codeblock pre span': {
|
||||
color: 'var(--shiki-dark)',
|
||||
},
|
||||
'.nd-codeblock code': {
|
||||
'.fd-codeblock code': {
|
||||
display: 'grid',
|
||||
'font-size': '13px',
|
||||
},
|
||||
'.nd-codeblock .highlighted': {
|
||||
'.fd-codeblock .highlighted': {
|
||||
margin: '0 -16px',
|
||||
padding: '0 16px',
|
||||
'background-color': `theme('colors.fd-primary.DEFAULT / 10%')`,
|
||||
},
|
||||
'.nd-codeblock .highlighted-word': {
|
||||
'.fd-codeblock .highlighted-word': {
|
||||
padding: '1px 2px',
|
||||
margin: '-1px -3px',
|
||||
border: '1px solid',
|
||||
@@ -162,21 +151,14 @@ export const docsUi = plugin.withOptions<DocsUIOptions>(
|
||||
'background-color': `theme('colors.fd-primary.DEFAULT / 10%')`,
|
||||
'border-radius': '2px',
|
||||
},
|
||||
'.fd-codeblock-keep-bg': {
|
||||
'background-color': 'var(--shiki-light-bg)',
|
||||
},
|
||||
'.dark .fd-codeblock-keep-bg': {
|
||||
'background-color': 'var(--shiki-dark-bg)',
|
||||
},
|
||||
});
|
||||
|
||||
if (keepCodeBlockBackground) {
|
||||
addComponents({
|
||||
'.nd-codeblock': {
|
||||
color: 'var(--shiki-light)',
|
||||
'background-color': 'var(--shiki-light-bg)',
|
||||
},
|
||||
'.dark .nd-codeblock': {
|
||||
color: 'var(--shiki-dark)',
|
||||
'background-color': 'var(--shiki-dark-bg)',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
addUtilities({
|
||||
'.steps': {
|
||||
'counter-reset': 'step',
|
||||
@@ -234,9 +216,6 @@ export const docsUi = plugin.withOptions<DocsUIOptions>(
|
||||
},
|
||||
colors: createTailwindColors(cssPrefix, addGlobalColors),
|
||||
...animations,
|
||||
typography: {
|
||||
DEFAULT: typographyConfig,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
@@ -246,6 +225,13 @@ export function createPreset(options: DocsUIOptions = {}): PresetsConfig {
|
||||
return {
|
||||
darkMode: 'class',
|
||||
plugins: [typography, docsUi(options)],
|
||||
theme: {
|
||||
extend: {
|
||||
typography: {
|
||||
DEFAULT: typographyConfig,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user