Callout

Un componente para mostrar información importante.

Default Callout
This is a default callout without any specific variant.
Information
This is an info callout used for general information.
Success
This is a success callout. The operation was completed successfully.
1import { Callout } from '@/components/ui/callout';
2
3export function Default() {
4 return (
5 <div className="flex w-full flex-col gap-4">
6 <Callout title="Default Callout">
7 This is a default callout without any specific variant.
8 </Callout>
9
10 <Callout variant="info" title="Information">
11 This is an info callout used for general information.
12 </Callout>
13
14 <Callout variant="warning" title="Warning">
15 This is a warning callout. Be careful interacting with this.
16 </Callout>
17
18 <Callout variant="danger" title="Error">
19 This is a danger callout. Something went wrong.
20 </Callout>
21
22 <Callout variant="success" title="Success">
23 This is a success callout. The operation was completed successfully.
24 </Callout>
25 </div>
26 );
27}

Instalación

Copia y pega el siguiente código en tu proyecto.
import {
Alert01Icon,
Alert02Icon,
CheckmarkCircle01Icon,
InformationCircleIcon,
} from '@hugeicons/core-free-icons';
import { HugeiconsIcon } from '@hugeicons/react';
import { cva, type VariantProps } from 'class-variance-authority';
import React from 'react';
import { cn } from '../lib/cn';
const calloutVariants = cva('flex w-full items-start gap-3 rounded-md border p-4 text-sm', {
variants: {
variant: {
default: 'bg-card/50 text-card-foreground border-border',
info: 'bg-info/10 text-info border-info/20',
warning: 'bg-warning/10 text-warning border-warning/20',
danger: 'bg-destructive/10 text-destructive border-destructive/20',
success: 'bg-success/10 text-success border-success/20',
},
},
defaultVariants: {
variant: 'default',
},
});
interface CalloutProps
extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof calloutVariants> {
icon?: React.ReactNode;
title?: string;
}
const CalloutTitle = ({
className,
ref,
...props
}: React.HTMLAttributes<HTMLDivElement> & { ref?: React.Ref<HTMLDivElement> }) => (
<div
ref={ref}
className={cn('leading-none font-semibold tracking-tight', className)}
{...props}
/>
);
CalloutTitle.displayName = 'CalloutTitle';
const CalloutContent = ({
className,
ref,
...props
}: React.HTMLAttributes<HTMLDivElement> & { ref?: React.Ref<HTMLDivElement> }) => (
<div
ref={ref}
className={cn('text-muted-foreground/90 [&_p]:leading-relaxed', className)}
{...props}
/>
);
CalloutContent.displayName = 'CalloutContent';
const CalloutIcon = ({
className,
ref,
...props
}: React.HTMLAttributes<HTMLDivElement> & { ref?: React.Ref<HTMLDivElement> }) => (
<div
ref={ref}
aria-hidden="true"
className={cn('mt-0.5 shrink-0 text-base select-none', className)}
{...props}
/>
);
CalloutIcon.displayName = 'CalloutIcon';
const CalloutRoot = ({
className,
variant,
icon,
title,
children,
ref,
...props
}: CalloutProps & { ref?: React.Ref<HTMLDivElement> }) => {
const getIcon = () => {
if (icon) return icon;
switch (variant) {
case 'info':
return <HugeiconsIcon icon={InformationCircleIcon} size={18} />;
case 'warning':
return <HugeiconsIcon icon={Alert02Icon} size={18} />;
case 'danger':
return <HugeiconsIcon icon={Alert01Icon} size={18} />;
case 'success':
return <HugeiconsIcon icon={CheckmarkCircle01Icon} size={18} />;
default:
return null;
}
};
const calloutIcon = getIcon();
const role = variant === 'danger' || variant === 'warning' ? 'alert' : 'region';
return (
<div ref={ref} role={role} className={cn(calloutVariants({ variant }), className)} {...props}>
{calloutIcon ? <CalloutIcon>{calloutIcon}</CalloutIcon> : null}
<div className="flex-1 space-y-1">
{title ? <CalloutTitle>{title}</CalloutTitle> : null}
<CalloutContent>{children}</CalloutContent>
</div>
</div>
);
};
CalloutRoot.displayName = 'Callout';
const Callout = Object.assign(CalloutRoot, {
Title: CalloutTitle,
Content: CalloutContent,
Icon: CalloutIcon,
});
export { Callout, calloutVariants };
export type { CalloutProps };
Asegúrate de actualizar las rutas de importación según la estructura de tu proyecto.

Anatomía

import { Callout } from '@/components/ui/callout';
<Callout variant="info" title="Nota">
Este es un callout con información.
</Callout>

Ejemplos

Variantes

El componente Callout viene con diferentes variantes para indicar el tipo de mensaje.
<Callout>Callout por defecto</Callout>
<Callout variant="info">Callout de información</Callout>
<Callout variant="warning">Callout de advertencia</Callout>
<Callout variant="danger">Callout de peligro</Callout>
<Callout variant="success">Callout de éxito</Callout>

Icono Personalizado

Puedes anular el icono por defecto pasando la propiedad icon.
<Callout icon={<MiIconoPersonalizado />}>Callout con icono personalizado</Callout>

Referencia de API

Callout

PropiedadTipoPor defectoDescripción
variant"default" | "info" | "warning" | "danger" | "success""default"El estilo del callout.
iconReact.ReactNodeIcono personalizado para mostrar. Si no se proporciona, se usa un icono por defecto basado en la variante.
titlestringEl título del callout.
classNamestringNombres de clases CSS adicionales.
childrenReact.ReactNodeEl contenido del callout.