shadimage
mui-treasury
itemai-artifactsource: ok · hit

AI Artifact

A container component for displaying artifacts with header, actions, and content areas

npx shadcn add "https://mui-treasury.com/r/ai-artifact.json"
free

Where it goes

navbar

Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.

Dependencies

Bundle weight · light
iconslucide-react

Files2 · source cached 10/14/2026, 11:29:03 AM

components/ai-artifact/ai-artifact.tsx
'use client';

import { type ComponentProps, memo } from 'react';

import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton';
import Paper from '@mui/material/Paper';
import Tooltip from '@mui/material/Tooltip';
import Typography from '@mui/material/Typography';
import { XIcon } from 'lucide-react';

export type ArtifactProps = ComponentProps<typeof Paper>;

export const Artifact = ({ children, sx, ...props }: ArtifactProps) => (
  <Paper
    elevation={4}
    sx={{
      display: 'flex',
      flexDirection: 'column',
      overflow: 'hidden',
      border: 1,
      borderColor: 'divider',
      ...sx,
    }}
    {...props}
  >
    {children}
  </Paper>
);

export type ArtifactHeaderProps = ComponentProps<typeof Box>;

export const ArtifactHeader = ({
  children,
  sx,
  ...props
}: ArtifactHeaderProps) => (
  <Box
    sx={[
      (theme) => ({
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'space-between',
        borderBottom: 1,
        borderColor: 'divider',
        bgcolor: (theme.vars || theme).palette.action.hover,
        px: 2,
        py: 1.5,
      }),
      ...(Array.isArray(sx) ? sx : [sx]),
    ]}
    {...props}
  >
    {children}
  </Box>
);

export type ArtifactCloseProps = ComponentProps<typeof IconButton>;

export const ArtifactClose = memo(
  ({ children, size = 'small', sx, ...props }: ArtifactCloseProps) => (
    <IconButton
      size={size}
      type="button"
      sx={{
        width: 32,
        height: 32,
        p: 0,
        color: 'text.secondary',
        '&:hover': {
          color: 'text.primary',
        },
        ...sx,
      }}
      aria-label="Close"
      {...props}
    >
      {children ?? <XIcon className="size-4" />}
    </IconButton>
  ),
);

ArtifactClose.displayName = 'ArtifactClose';

export type ArtifactTitleProps = ComponentProps<typeof Typography>;

export const ArtifactTitle = ({ sx, ...props }: ArtifactTitleProps) => (
  <Typography
    variant="body2"
    sx={{
      fontWeight: 500,
      color: 'text.primary',
      ...sx,
    }}
    {...props}
  />
);

export type ArtifactDescriptionProps = ComponentProps<typeof Typography>;

export const ArtifactDescription = ({
  sx,
  ...props
}: ArtifactDescriptionProps) => (
  <Typography
    variant="body2"
    sx={{
      color: 'text.secondary',
      ...sx,
    }}
    {...props}
  />
);

export type ArtifactActionsProps = ComponentProps<typeof Box>;

export const ArtifactActions = ({
  children,
  sx,
  ...props
}: ArtifactActionsProps) => (
  <Box
    sx={{
      display: 'flex',
      alignItems: 'center',
      gap: 0.5,
      ...sx,
    }}
    {...props}
  >
    {children}
  </Box>
);

export type ArtifactActionProps = ComponentProps<typeof IconButton> & {
  tooltip?: string;
  label?: string;
  icon?: React.ComponentType<{ className?: string }>;
};

export const ArtifactAction = ({
  tooltip,
  label,
  icon: Icon,
  children,
  size = 'small',
  sx,
  ...props
}: ArtifactActionProps) => {
  const button = (
    <IconButton
      size={size}
      type="button"
      sx={{
        width: 32,
        height: 32,
        p: 0,
        color: 'text.secondary',
        '&:hover': {
          color: 'text.primary',
        },
        ...sx,
      }}
      aria-label={label || tooltip}
      {...props}
    >
      {Icon ? <Icon className="size-4" /> : children}
    </IconButton>
  );

  if (tooltip) {
    return (
      <Tooltip title={tooltip} arrow>
        {button}
      </Tooltip>
    );
  }

  return button;
};

export type ArtifactContentProps = ComponentProps<typeof Box>;

export const ArtifactContent = ({
  children,
  sx,
  ...props
}: ArtifactContentProps) => (
  <Box
    sx={{
      flex: 1,
      overflow: 'auto',
      p: 2,
      ...sx,
    }}
    {...props}
  >
    {children}
  </Box>
);
components/ai-artifact/index.ts
export * from './ai-artifact';

More from mui-treasury

Browse all components in this library →