or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

ai-advanced.mddata-display.mdform-components.mdindex.mdinput-selection.mdlayout-navigation.mdloading-progress.mdmodal-overlay.mdtheming-customization.mdtiles-layout.md
tile.json

modal-overlay.mddocs/

Modal & Overlay Components

Modal systems, tooltips, popovers, and overlay components for interactive content, contextual information, and user confirmations.

Capabilities

Modal Components

Full-featured modal system with various sizes, types, and interaction patterns.

/**
 * Basic modal component
 */
interface ModalProps {
  /** Modal is open */
  open: boolean;
  /** Close request handler */
  onRequestClose?: (event: React.MouseEvent | React.KeyboardEvent) => void;
  /** Modal heading text */
  modalHeading?: string;
  /** Modal label text */
  modalLabel?: string;
  /** Primary button text */
  primaryButtonText?: string;
  /** Secondary button text */
  secondaryButtonText?: string;
  /** Primary button click handler */
  onRequestSubmit?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  /** Secondary button click handler */
  onSecondarySubmit?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  /** Modal size */
  size?: "xs" | "sm" | "md" | "lg";
  /** Danger modal variant */
  danger?: boolean;
  /** Alert modal variant */
  alert?: boolean;
  /** Passive modal (no buttons) */
  passiveModal?: boolean;
  /** Modal content */
  children?: React.ReactNode;
  /** CSS class name */
  className?: string;
  /** Icon description for close button */
  iconDescription?: string;
  /** Primary button disabled */
  primaryButtonDisabled?: boolean;
  /** Secondary button disabled */
  secondaryButtonDisabled?: boolean;
  /** Prevent focus trap */
  preventCloseOnClickOutside?: boolean;
  /** Loading state */
  primaryButtonLoading?: boolean;
  /** Focus trap */
  focusTrap?: boolean;
  /** Container element selector */
  selectorsFloatingMenus?: string[];
}

/**
 * Modal wrapper for consistent behavior
 */
interface ModalWrapperProps {
  /** Modal trigger button text */
  buttonTriggerText?: string;
  /** Button trigger className */
  buttonTriggerClassName?: string;
  /** Modal is open */
  status?: "closed" | "open";
  /** Handle open event */
  handleOpen?: () => void;
  /** Modal children */
  children?: React.ReactNode;
  /** Trigger button kind */
  triggerButtonKind?: "primary" | "secondary" | "danger" | "ghost" | "tertiary";
  /** Trigger button icon */
  triggerButtonIconDescription?: string;
  /** Disable trigger button */
  disabled?: boolean;
  /** Handle submit */
  handleSubmit?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  /** Submit button text */
  primaryButtonText?: string;
  /** Handle secondary */
  handleSecondarySubmit?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  /** Secondary button text */
  secondaryButtonText?: string;
  /** Modal heading */
  modalHeading?: string;
  /** Modal label */
  modalLabel?: string;
  /** Modal size */
  size?: "xs" | "sm" | "md" | "lg";
  /** Danger modal */
  danger?: boolean;
  /** Alert modal */
  alert?: boolean;
  /** Passive modal */
  passiveModal?: boolean;
}

/**
 * Composed modal for custom layouts
 */
interface ComposedModalProps {
  /** Modal is open */
  open: boolean;
  /** Close handler */
  onClose?: () => void;
  /** Modal size */
  size?: "xs" | "sm" | "md" | "lg";
  /** Danger variant */
  danger?: boolean;
  /** Prevent close on outside click */
  preventCloseOnClickOutside?: boolean;
  /** Modal children */
  children: React.ReactNode;
  /** CSS class name */
  className?: string;
  /** Container selector */
  selectorsFloatingMenus?: string[];
}

/**
 * Modal header component
 */
interface ModalHeaderProps {
  /** Header content */
  children?: React.ReactNode;
  /** Button icon description */
  buttonOnClose?: () => void;
  /** CSS class name */
  className?: string;
  /** Close icon description */
  closeIconDescription?: string;
  /** Icon description */
  iconDescription?: string;
  /** Modal label */
  label?: string;
  /** Modal title */
  title?: string;
}

/**
 * Modal body component
 */
interface ModalBodyProps {
  /** Body content */
  children?: React.ReactNode;
  /** CSS class name */
  className?: string;
  /** Aria label */
  "aria-label"?: string;
  /** Has form */
  hasForm?: boolean;
  /** Has scrolling content */
  hasScrollingContent?: boolean;
}

/**
 * Modal footer component
 */
interface ModalFooterProps {
  /** Footer content */
  children?: React.ReactNode;
  /** CSS class name */
  className?: string;
  /** Primary button text */
  primaryButtonText?: string;
  /** Primary button disabled */
  primaryButtonDisabled?: boolean;
  /** Primary click handler */
  onRequestSubmit?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  /** Secondary button text */
  secondaryButtonText?: string;
  /** Secondary button disabled */
  secondaryButtonDisabled?: boolean;
  /** Secondary click handler */
  onRequestClose?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  /** Danger variant */
  danger?: boolean;
  /** Close text */
  closeText?: string;
  /** Submit text */
  submitText?: string;
}

Usage Examples:

import { 
  Modal, 
  ModalWrapper, 
  ComposedModal, 
  ModalHeader, 
  ModalBody, 
  ModalFooter 
} from "@carbon/react";

// Basic modal
<Modal
  open={isModalOpen}
  onRequestClose={() => setIsModalOpen(false)}
  modalHeading="Delete item"
  modalLabel="Confirmation"
  primaryButtonText="Delete"
  secondaryButtonText="Cancel"
  danger
  onRequestSubmit={handleDelete}
>
  <p>Are you sure you want to delete this item? This action cannot be undone.</p>
</Modal>

// Modal with wrapper (trigger button included)
<ModalWrapper
  buttonTriggerText="Open modal"
  modalHeading="Add new item"
  primaryButtonText="Add"
  secondaryButtonText="Cancel"
  handleSubmit={handleAdd}
>
  <TextInput id="item-name" labelText="Item name" />
  <TextArea id="description" labelText="Description" />
</ModalWrapper>

// Composed modal for custom layout
<ComposedModal open={isOpen} onClose={() => setIsOpen(false)} size="lg">
  <ModalHeader 
    label="Settings"
    title="User Preferences"
    buttonOnClose={() => setIsOpen(false)}
  />
  <ModalBody hasScrollingContent>
    <Tabs>
      <TabList>
        <Tab>General</Tab>
        <Tab>Privacy</Tab>
        <Tab>Notifications</Tab>
      </TabList>
      <TabPanels>
        <TabPanel>General settings content...</TabPanel>
        <TabPanel>Privacy settings content...</TabPanel>
        <TabPanel>Notification settings content...</TabPanel>
      </TabPanels>
    </Tabs>
  </ModalBody>
  <ModalFooter
    primaryButtonText="Save"
    secondaryButtonText="Cancel"
    onRequestSubmit={handleSave}
    onRequestClose={() => setIsOpen(false)}
  />
</ComposedModal>

Tooltip Components

Contextual help and information tooltips with various positioning options.

/**
 * Basic tooltip component
 */
interface TooltipProps {
  /** Tooltip content */
  children: React.ReactNode;
  /** Tooltip text */
  label: string;
  /** Tooltip description */
  description?: string;
  /** Tooltip position */
  align?: 
    | "top" 
    | "top-left" 
    | "top-right" 
    | "bottom" 
    | "bottom-left" 
    | "bottom-right" 
    | "left" 
    | "right";
  /** Show tooltip on focus */
  showIcon?: boolean;
  /** Icon description */
  iconDescription?: string;
  /** Tooltip trigger type */
  triggerClassName?: string;
  /** Tooltip text */
  tooltipText?: string;
  /** Default open */
  defaultOpen?: boolean;
  /** Auto align */
  autoAlign?: boolean;
  /** Close on activation */
  closeOnActivation?: boolean;
  /** Entry/exit delay */
  enterDelayMs?: number;
  /** Exit delay */
  leaveDelayMs?: number;
}

/**
 * Definition tooltip for terms and definitions
 */
interface DefinitionTooltipProps {
  /** Term to define */
  children: React.ReactNode;
  /** Definition text */
  definition: string;
  /** Tooltip position */
  align?: 
    | "top" 
    | "top-left" 
    | "top-right" 
    | "bottom" 
    | "bottom-left" 
    | "bottom-right" 
    | "left" 
    | "right";
  /** Trigger type */
  triggerClassName?: string;
  /** Default open state */
  defaultOpen?: boolean;
  /** Open state (controlled) */
  open?: boolean;
  /** Open change handler */
  onOpenChange?: (open: boolean) => void;
}

Usage Examples:

import { Tooltip, DefinitionTooltip, Button } from "@carbon/react";
import { Information } from "@carbon/react/icons";

// Basic tooltip
<Tooltip label="This button saves your changes" align="top">
  <Button>Save</Button>
</Tooltip>

// Tooltip with description
<Tooltip 
  label="Autosave" 
  description="Your changes are automatically saved every 30 seconds"
  align="bottom"
>
  <Button hasIconOnly iconDescription="Autosave enabled">
    <Information />
  </Button>
</Tooltip>

// Definition tooltip
<p>
  Our product uses{" "}
  <DefinitionTooltip
    definition="Machine learning algorithms that can understand and generate human-like text"
    align="bottom"
  >
    artificial intelligence
  </DefinitionTooltip>{" "}
  to improve user experience.
</p>

Toggletip Component

Interactive tooltip that remains open until dismissed, perfect for forms and help content.

/**
 * Toggletip component for interactive tooltips
 */
interface ToggletipProps {
  /** Toggletip content */
  children: React.ReactNode;
  /** Default open state */
  defaultOpen?: boolean;
  /** Open state (controlled) */
  open?: boolean;
  /** Open change handler */
  onOpenChange?: (open: boolean) => void;
  /** CSS class name */
  className?: string;
}

/**
 * Toggletip button trigger
 */
interface ToggletipButtonBaseProps extends React.ComponentPropsWithoutRef<"button"> {
  /** Button content */
  children: React.ReactNode;
  /** Button label for accessibility */
  label?: string;
}

/**
 * Toggletip content container
 */
interface ToggletipContentProps {
  /** Content children */
  children: React.ReactNode;
  /** CSS class name */
  className?: string;
}

/**
 * Toggletip actions container
 */
interface ToggleTipActionsProps {
  /** Action children */
  children: React.ReactNode;
  /** CSS class name */
  className?: string;
}

Usage Examples:

import { 
  Toggletip, 
  ToggletipButton, 
  ToggletipContent, 
  ToggletipActions,
  Button,
  Link
} from "@carbon/react";
import { Information } from "@carbon/react/icons";

<Toggletip>
  <ToggletipButton label="Additional information">
    <Information />
  </ToggletipButton>
  <ToggletipContent>
    <p>
      This field accepts email addresses in the standard format.
      For example: user@example.com
    </p>
    <ToggletipActions>
      <Link href="/help/email-format">Learn more</Link>
      <Button size="sm" kind="ghost">Got it</Button>
    </ToggletipActions>
  </ToggletipContent>
</Toggletip>

Popover Component

Advanced positioning component for custom overlay content.

/**
 * Popover positioning component
 */
interface PopoverProps {
  /** Popover is open */
  open?: boolean;
  /** Drop direction */
  dropShadow?: boolean;
  /** High contrast */
  highContrast?: boolean;
  /** Light variant */
  light?: boolean;
  /** Popover children */
  children: React.ReactNode;
  /** CSS class name */
  className?: string;
  /** Relative positioning */
  relative?: boolean;
  /** Caret positioning */
  caret?: boolean;
  /** Alignment */
  align?: 
    | "top" 
    | "top-left" 
    | "top-right" 
    | "bottom" 
    | "bottom-left" 
    | "bottom-right" 
    | "left" 
    | "left-bottom" 
    | "left-top" 
    | "right" 
    | "right-bottom" 
    | "right-top";
  /** Auto align */
  autoAlign?: boolean;
}

/**
 * Popover content container
 */
interface PopoverContentProps {
  /** Content children */
  children: React.ReactNode;
  /** CSS class name */
  className?: string;
}

Usage Examples:

import { Popover, PopoverContent, Button } from "@carbon/react";

<Popover
  open={isPopoverOpen}
  align="bottom-left"
  dropShadow
  onRequestClose={() => setIsPopoverOpen(false)}
>
  <Button onClick={() => setIsPopoverOpen(!isPopoverOpen)}>
    Options
  </Button>
  <PopoverContent>
    <div style={{ padding: '1rem' }}>
      <h4>Quick Actions</h4>
      <ul>
        <li><Link href="#">Edit</Link></li>
        <li><Link href="#">Duplicate</Link></li>
        <li><Link href="#">Delete</Link></li>
      </ul>
    </div>
  </PopoverContent>
</Popover>

Context Menu

Right-click context menu for contextual actions.

/**
 * Context menu hook for creating right-click menus
 */
interface ContextMenuProps {
  /** Menu items */
  children: React.ReactNode;
  /** Menu is open */
  open?: boolean;
  /** Position of menu */
  x?: number;
  y?: number;
  /** Close handler */
  onClose?: () => void;
  /** Size variant */
  size?: "sm" | "md" | "lg";
  /** Target element */
  target?: React.RefObject<HTMLElement>;
}

/**
 * Context menu hook
 */
function useContextMenu(): {
  /** Open context menu */
  open: (event: React.MouseEvent, data?: any) => void;
  /** Close context menu */
  close: () => void;
  /** Menu is open */
  isOpen: boolean;
  /** Menu position */
  position: { x: number; y: number };
  /** Menu data */
  data: any;
}

Usage Examples:

import { useContextMenu, Menu, MenuItem } from "@carbon/react";

function MyComponent() {
  const contextMenu = useContextMenu();
  
  return (
    <div
      onContextMenu={(e) => {
        e.preventDefault();
        contextMenu.open(e, { itemId: 'item-1' });
      }}
    >
      Right-click me for context menu
      
      {contextMenu.isOpen && (
        <Menu
          open={contextMenu.isOpen}
          x={contextMenu.position.x}
          y={contextMenu.position.y}
          onClose={contextMenu.close}
        >
          <MenuItem onClick={() => console.log('Edit', contextMenu.data)}>
            Edit
          </MenuItem>
          <MenuItem onClick={() => console.log('Delete', contextMenu.data)}>
            Delete
          </MenuItem>
        </Menu>
      )}
    </div>
  );
}

Menu Components

Dropdown menus and menu systems for navigation and actions.

/**
 * Menu container component
 */
interface MenuProps {
  /** Menu items */
  children: React.ReactNode;
  /** Menu is open */
  open?: boolean;
  /** Menu position */
  x?: number;
  y?: number;
  /** Close handler */
  onClose?: () => void;
  /** Menu size */
  size?: "xs" | "sm" | "md" | "lg";
  /** Target element ref */
  target?: React.RefObject<HTMLElement>;
  /** Auto close on selection */
  autoClose?: boolean;
}

/**
 * Menu item component
 */
interface MenuItemProps extends React.ComponentPropsWithoutRef<"button"> {
  /** Menu item content */
  children: React.ReactNode;
  /** Item is disabled */
  disabled?: boolean;
  /** Item kind */
  kind?: "default" | "danger";
  /** Item label */
  label?: string;
  /** Render icon */
  renderIcon?: React.ComponentType<any>;
  /** Shortcut text */
  shortcut?: string;
}

/**
 * Menu button component (button + menu)
 */
interface MenuButtonProps {
  /** Button text */
  children: React.ReactNode;
  /** Menu items */
  menu: React.ReactNode;
  /** Button kind */
  kind?: "primary" | "secondary" | "tertiary" | "ghost";
  /** Button size */
  size?: "sm" | "md" | "lg";
  /** Button disabled */
  disabled?: boolean;
  /** Menu size */
  menuSize?: "xs" | "sm" | "md" | "lg";
  /** Menu alignment */
  menuAlignment?: "top" | "bottom";
  /** Flipped menu position */
  flipped?: boolean;
}

Usage Examples:

import { MenuButton, Menu, MenuItem } from "@carbon/react";
import { Add, Edit, Delete } from "@carbon/react/icons";

// Menu button with dropdown
<MenuButton
  kind="primary"
  menu={
    <Menu>
      <MenuItem renderIcon={Add}>Add item</MenuItem>
      <MenuItem renderIcon={Edit}>Edit item</MenuItem>
      <MenuItem renderIcon={Delete} kind="danger">Delete item</MenuItem>
    </Menu>
  }
>
  Actions
</MenuButton>

// Standalone menu
<Menu open={isMenuOpen} onClose={() => setIsMenuOpen(false)}>
  <MenuItem onClick={() => handleAction('save')}>
    Save
  </MenuItem>
  <MenuItem onClick={() => handleAction('export')}>
    Export
  </MenuItem>
  <MenuItem disabled>
    Print (unavailable)
  </MenuItem>
</Menu>

Notification Components

/**
 * Toast notification (temporary)
 */
interface ToastNotificationProps {
  /** Notification kind */
  kind?: "error" | "info" | "info-square" | "success" | "warning" | "warning-alt";
  /** Notification title */
  title: string;
  /** Notification subtitle */
  subtitle?: string;
  /** Notification caption */
  caption?: string;
  /** Close handler */
  onClose?: () => void;
  /** Close button description */
  closeButtonDescription?: string;
  /** Notification role */
  role?: "alert" | "log" | "status";
  /** Timeout in milliseconds */
  timeout?: number;
  /** Hide close button */
  hideCloseButton?: boolean;
  /** Low contrast */
  lowContrast?: boolean;
}

/**
 * Inline notification (persistent)
 */
interface InlineNotificationProps {
  /** Notification kind */
  kind?: "error" | "info" | "info-square" | "success" | "warning" | "warning-alt";
  /** Notification title */
  title: string;
  /** Notification subtitle */
  subtitle?: string;
  /** Close handler */
  onClose?: () => void;
  /** Close button description */
  closeButtonDescription?: string;
  /** Notification role */
  role?: "alert" | "log" | "status";
  /** Hide close button */
  hideCloseButton?: boolean;
  /** Low contrast */
  lowContrast?: boolean;
  /** Action button */
  actions?: React.ReactNode;
}