mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
UI: Support CalloutContainer, CalloutTitle and CalloutDescription components
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'fumadocs-ui': patch
|
||||
---
|
||||
|
||||
Support `CalloutContainer`, `CalloutTitle` and `CalloutDescription` components.
|
||||
|
||||
They're now MDX components included by default.
|
||||
@@ -1,62 +1,105 @@
|
||||
import { CircleCheck, CircleX, Info, TriangleAlert } from 'lucide-react';
|
||||
import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';
|
||||
import type { ComponentProps, ReactNode } from 'react';
|
||||
import { cn } from '@/utils/cn';
|
||||
|
||||
type CalloutProps = Omit<
|
||||
HTMLAttributes<HTMLDivElement>,
|
||||
'title' | 'type' | 'icon'
|
||||
> & {
|
||||
title?: ReactNode;
|
||||
export type CalloutType = 'info' | 'warn' | 'error' | 'success' | 'warning';
|
||||
|
||||
const iconClass = 'size-5 -me-0.5 fill-(--callout-color) text-fd-card';
|
||||
|
||||
export function Callout({
|
||||
children,
|
||||
title,
|
||||
...props
|
||||
}: { title?: ReactNode } & Omit<CalloutContainerProps, 'title'>) {
|
||||
return (
|
||||
<CalloutContainer {...props}>
|
||||
{title && <CalloutTitle>{title}</CalloutTitle>}
|
||||
<CalloutDescription>{children}</CalloutDescription>
|
||||
</CalloutContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export interface CalloutContainerProps extends ComponentProps<'div'> {
|
||||
/**
|
||||
* @defaultValue info
|
||||
*/
|
||||
type?: 'info' | 'warn' | 'error' | 'success' | 'warning';
|
||||
type?: CalloutType;
|
||||
|
||||
/**
|
||||
* Force an icon
|
||||
*/
|
||||
icon?: ReactNode;
|
||||
};
|
||||
}
|
||||
|
||||
const iconClass = 'size-5 -me-0.5 fill-(--callout-color) text-fd-card';
|
||||
function resolveAlias(type: CalloutType) {
|
||||
if (type === 'warn') return 'warning';
|
||||
if ((type as unknown) === 'tip') return 'info';
|
||||
return type;
|
||||
}
|
||||
|
||||
export const Callout = forwardRef<HTMLDivElement, CalloutProps>(
|
||||
({ className, children, title, type = 'info', icon, ...props }, ref) => {
|
||||
if (type === 'warn') type = 'warning';
|
||||
if ((type as unknown) === 'tip') type = 'info';
|
||||
export function CalloutContainer({
|
||||
type: inputType = 'info',
|
||||
icon,
|
||||
children,
|
||||
className,
|
||||
style,
|
||||
...props
|
||||
}: CalloutContainerProps) {
|
||||
const type = resolveAlias(inputType);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex gap-2 my-4 rounded-xl border bg-fd-card p-3 ps-1 text-sm text-fd-card-foreground shadow-md',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
style={
|
||||
{
|
||||
'--callout-color': `var(--color-fd-${type}, var(--color-fd-muted))`,
|
||||
...props.style,
|
||||
} as object
|
||||
}
|
||||
>
|
||||
<div role="none" className="w-0.5 bg-(--callout-color)/50 rounded-sm" />
|
||||
{icon ??
|
||||
{
|
||||
info: <Info className={iconClass} />,
|
||||
warning: <TriangleAlert className={iconClass} />,
|
||||
error: <CircleX className={iconClass} />,
|
||||
success: <CircleCheck className={iconClass} />,
|
||||
}[type]}
|
||||
<div className="flex flex-col gap-2 min-w-0 flex-1">
|
||||
{title && <p className="font-medium !my-0">{title}</p>}
|
||||
<div className="text-fd-muted-foreground prose-no-margin empty:hidden">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex gap-2 my-4 rounded-xl border bg-fd-card p-3 ps-1 text-sm text-fd-card-foreground shadow-md',
|
||||
className,
|
||||
)}
|
||||
style={
|
||||
{
|
||||
'--callout-color': `var(--color-fd-${type}, var(--color-fd-muted))`,
|
||||
...style,
|
||||
} as object
|
||||
}
|
||||
{...props}
|
||||
>
|
||||
<div role="none" className="w-0.5 bg-(--callout-color)/50 rounded-sm" />
|
||||
{icon ??
|
||||
{
|
||||
info: <Info className={iconClass} />,
|
||||
warning: <TriangleAlert className={iconClass} />,
|
||||
error: <CircleX className={iconClass} />,
|
||||
success: <CircleCheck className={iconClass} />,
|
||||
}[type]}
|
||||
<div className="flex flex-col gap-2 min-w-0 flex-1">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Callout.displayName = 'Callout';
|
||||
export function CalloutTitle({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<'p'>) {
|
||||
return (
|
||||
<p className={cn('font-medium my-0!', className)} {...props}>
|
||||
{children}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
export function CalloutDescription({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: ComponentProps<'p'>) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'text-fd-muted-foreground prose-no-margin empty:hidden',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ export function Card({ icon, title, description, ...props }: CardProps) {
|
||||
) : null}
|
||||
<h3 className="not-prose mb-1 text-sm font-medium">{title}</h3>
|
||||
{description ? (
|
||||
<p className="!my-0 text-sm text-fd-muted-foreground">{description}</p>
|
||||
<p className="my-0! text-sm text-fd-muted-foreground">{description}</p>
|
||||
) : null}
|
||||
<div className="text-sm text-fd-muted-foreground prose-no-margin empty:hidden">
|
||||
{props.children}
|
||||
|
||||
@@ -8,7 +8,12 @@ import type {
|
||||
} from 'react';
|
||||
import { Image as FrameworkImage } from 'fumadocs-core/framework';
|
||||
import { Card, Cards } from '@/components/card';
|
||||
import { Callout } from '@/components/callout';
|
||||
import {
|
||||
Callout,
|
||||
CalloutContainer,
|
||||
CalloutDescription,
|
||||
CalloutTitle,
|
||||
} from '@/components/callout';
|
||||
import { Heading } from '@/components/heading';
|
||||
import { cn } from '@/utils/cn';
|
||||
import {
|
||||
@@ -77,6 +82,9 @@ const defaultMdxComponents = {
|
||||
),
|
||||
table: Table,
|
||||
Callout,
|
||||
CalloutContainer,
|
||||
CalloutTitle,
|
||||
CalloutDescription,
|
||||
};
|
||||
|
||||
export const createRelativeLink: typeof import('./mdx.server').createRelativeLink =
|
||||
|
||||
Reference in New Issue
Block a user