or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration-theming.mddisplay-components.mdfeedback-components.mdform-components.mdgesture-components.mdindex.mdlayout-components.mdnavigation-components.mdpicker-components.md
tile.json

feedback-components.mddocs/

Feedback Components

User feedback components including modals, toasts, loading indicators, and progress displays for communicating system state and user actions.

import { ActionSheet, Popover, Toast, Modal, Dialog, Loading, ProgressBar } from "antd-mobile";

Capabilities

ActionSheet

Action sheet component for presenting a set of options to users in a modal bottom sheet.

/**
 * ActionSheet component for presenting choices in a modal bottom sheet
 * @param props - ActionSheet configuration
 * @returns React ActionSheet element
 */
function ActionSheet(props: ActionSheetProps): JSX.Element;

/**
 * Imperative API for showing ActionSheet
 * @param props - ActionSheet configuration without visibility controls
 * @returns Handler with close method
 */
function showActionSheet(props: Omit<ActionSheetProps, 'visible' | 'destroyOnClose' | 'forceRender'>): ActionSheetShowHandler;

interface ActionSheetProps {
  /** Whether the action sheet is visible */
  visible?: boolean;
  /** Array of action items */
  actions: Action[];
  /** Extra content at the top of the action sheet */
  extra?: React.ReactNode;
  /** Cancel button text */
  cancelText?: React.ReactNode;
  /** Callback when an action is selected */
  onAction?: (action: Action, index: number) => void;
  /** Callback when the action sheet is closed */
  onClose?: () => void;
  /** Callback when mask is clicked */
  onMaskClick?: () => void;
  /** Whether to close when an action is selected */
  closeOnAction?: boolean;
  /** Whether to close when mask is clicked */
  closeOnMaskClick?: boolean;
  /** Whether to add safe area padding */
  safeArea?: boolean;
  /** Custom popup className */
  popupClassName?: string;
  /** Custom styles for different parts */
  styles?: Partial<Record<'body' | 'mask', React.CSSProperties>>;
} & NativeProps;

interface Action {
  /** Unique key for the action */
  key: string | number;
  /** Action text */
  text: React.ReactNode;
  /** Whether the action is disabled */
  disabled?: boolean;
  /** Action description */
  description?: React.ReactNode;
  /** Whether to show in danger style */
  danger?: boolean;
  /** Whether to show in bold style */
  bold?: boolean;
  /** Click handler for the action */
  onClick?: () => void;
}

interface ActionSheetShowHandler {
  /** Close the action sheet */
  close(): void;
}

Usage Examples:

import { ActionSheet, showActionSheet, Button } from "antd-mobile";

// Declarative usage
function ActionSheetExample() {
  const [visible, setVisible] = useState(false);

  const actions = [
    { key: 'copy', text: 'Copy' },
    { key: 'save', text: 'Save to Photos' },
    { key: 'delete', text: 'Delete', danger: true },
  ];

  return (
    <>
      <Button onClick={() => setVisible(true)}>Show ActionSheet</Button>
      <ActionSheet
        visible={visible}
        actions={actions}
        cancelText="Cancel"
        onClose={() => setVisible(false)}
        onAction={(action) => console.log(action.text)}
      />
    </>
  );
}

// Imperative usage
function showOptions() {
  showActionSheet({
    actions: [
      { key: 'edit', text: 'Edit', onClick: () => console.log('Edit') },
      { key: 'share', text: 'Share', onClick: () => console.log('Share') },
      { key: 'delete', text: 'Delete', danger: true, onClick: () => console.log('Delete') },
    ],
    cancelText: 'Cancel',
  });
}

Popover

Popover component for showing contextual content in a floating overlay.

/**
 * Popover component for contextual overlays
 * @param props - Popover configuration
 * @returns React popover element
 */
function Popover(props: PopoverProps): JSX.Element;

interface PopoverProps {
  /** Whether popover is visible by default */
  defaultVisible?: boolean;
  /** Whether popover is visible (controlled) */
  visible?: boolean;
  /** Callback when visibility changes */
  onVisibleChange?: (visible: boolean) => void;
  /** Portal container for popover */
  getContainer?: () => HTMLElement;
  /** Whether to destroy content when hidden */
  destroyOnHide?: boolean;
  /** Target element to attach popover to */
  children: React.ReactElement;
  /** Popover appearance mode */
  mode?: 'light' | 'dark';
  /** Trigger method */
  trigger?: 'click';
  /** Popover placement relative to target */
  placement?: 'top' | 'bottom' | 'left' | 'right' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';
  /** Events to stop propagation */
  stopPropagation?: ('click' | 'touchstart')[];
  /** Popover content */
  content: React.ReactNode;
} & NativeProps;

interface PopoverRef {
  /** Show the popover */
  show(): void;
  /** Hide the popover */
  hide(): void;
  /** Current visibility state */
  visible: boolean;
}

Usage Examples:

import { Popover, Button } from "antd-mobile";

function PopoverExample() {
  return (
    <Popover
      content="This is a popover"
      placement="top"
      mode="light"
    >
      <Button>Show Popover</Button>
    </Popover>
  );
}

// With custom content
function PopoverWithMenu() {
  return (
    <Popover
      content={
        <div>
          <div>Edit</div>
          <div>Delete</div>
          <div>Share</div>
        </div>
      }
      placement="bottomRight"
    >
      <Button>Actions</Button>
    </Popover>
  );
}

Toast

Toast notification with imperative API for displaying temporary messages.

/**
 * Toast notification component (typically used via imperative API)
 * @param props - Toast configuration
 * @returns React toast element
 */
function Toast(props: ToastProps): JSX.Element;

interface ToastProps {
  /** Whether toast is visible */
  visible?: boolean;
  /** Toast content */
  content?: React.ReactNode;
  /** Display duration in milliseconds */
  duration?: number;
  /** Toast position */
  position?: 'top' | 'bottom' | 'center';
  /** Whether to show background mask */
  mask?: boolean;
  /** Whether mask is clickable */
  maskClickable?: boolean;
  /** Toast icon */
  icon?: 'success' | 'fail' | 'loading' | React.ReactNode;
  /** Custom toast style */
  getContainer?: HTMLElement | (() => HTMLElement) | null;
  /** After close callback */
  afterClose?: () => void;
} & NativeProps;

// Toast imperative API
declare namespace Toast {
  /**
   * Show toast notification
   * @param content - Toast content or configuration
   * @returns Toast handler for manual control
   */
  function show(content: string | ToastShowProps): ToastHandler;
  
  /**
   * Clear all toast notifications
   */
  function clear(): void;
  
  /**
   * Configure default toast options
   * @param config - Default configuration options
   */
  function config(config: Pick<ToastShowProps, 'duration' | 'position' | 'maskClickable'>): void;
}

interface ToastShowProps {
  /** Toast content */
  content: React.ReactNode;
  /** Display duration in milliseconds */
  duration?: number;
  /** Toast position */
  position?: 'top' | 'bottom' | 'center';
  /** Whether to show background mask */
  mask?: boolean;
  /** Whether mask is clickable */
  maskClickable?: boolean;
  /** Toast icon */
  icon?: 'success' | 'fail' | 'loading' | React.ReactNode;
  /** After close callback */
  afterClose?: () => void;
}

interface ToastHandler {
  /** Close this toast */
  close(): void;
}

Usage Examples:

import { Toast, Button } from "antd-mobile";
// For TypeScript: Handler type needs to be imported separately
import type { ToastHandler } from "antd-mobile/es/components/toast";

function ToastExample() {
  const showToast = () => {
    Toast.show('Hello World!');
  };

  const showSuccessToast = () => {
    Toast.show({
      content: 'Operation completed successfully',
      icon: 'success',
      duration: 3000,
      position: 'top'
    });
  };

  const showLoadingToast = () => {
    const handler = Toast.show({
      content: 'Processing...',
      icon: 'loading',
      duration: 0  // Don't auto-close
    });
    
    // Close after async operation
    setTimeout(() => {
      handler.close();
      Toast.show({
        content: 'Done!',
        icon: 'success'
      });
    }, 2000);
  };

  const configureToast = () => {
    Toast.config({
      duration: 3000,
      position: 'center',
      maskClickable: true
    });
  };

  return (
    <div>
      <Button onClick={showToast}>Show Toast</Button>
      <Button onClick={showSuccessToast}>Success Toast</Button>
      <Button onClick={showLoadingToast}>Loading Toast</Button>
      <Button onClick={configureToast}>Configure Defaults</Button>
    </div>
  );
}

Modal

Modal dialog with imperative API for confirmations and custom content.

/**
 * Modal dialog component
 * @param props - Modal configuration
 * @returns React modal element
 */
function Modal(props: ModalProps): JSX.Element;

interface ModalProps {
  /** Whether modal is visible */
  visible?: boolean;
  /** Modal title */
  title?: React.ReactNode;
  /** Modal content */
  content?: React.ReactNode;
  /** Close handler */
  onClose?: () => void;
  /** Action buttons */
  actions?: (ModalActionButton | ModalActionButton[])[];
  /** Close on action */
  closeOnAction?: boolean;
  /** Close on mask click */
  closeOnMaskClick?: boolean;
  /** Modal width */
  width?: string | number;
  /** Modal height */
  height?: string | number;
  /** Body style */
  bodyStyle?: React.CSSProperties;
  /** Image configuration */
  image?: string;
  /** Header content */
  header?: React.ReactNode;
  /** Whether to show close button */
  showCloseButton?: boolean;
  /** Stop body scroll */
  stopBodyScroll?: boolean;
  /** Get container */
  getContainer?: HTMLElement | (() => HTMLElement) | null;
  /** After close callback */
  afterClose?: () => void;
  /** Modal content */
  children?: React.ReactNode;
} & NativeProps;

interface ModalActionButton {
  /** Button key */
  key: string | number;
  /** Button text */
  text: React.ReactNode;
  /** Button color */
  color?: 'primary' | 'weak' | 'danger';
  /** Button style */
  bold?: boolean;
  /** Disabled state */
  disabled?: boolean;
  /** Click handler */
  onClick?: () => void | Promise<void>;
}

// Modal imperative API
declare namespace Modal {
  /**
   * Show modal dialog
   * @param props - Modal configuration
   * @returns Modal handler for manual control
   */
  function show(props: ModalShowProps): ModalHandler;
  
  /**
   * Show alert modal
   * @param props - Alert configuration
   * @returns Promise that resolves when alert is closed
   */
  function alert(props: ModalAlertProps): Promise<void>;
  
  /**
   * Show confirm modal
   * @param props - Confirm configuration
   * @returns Promise that resolves with user's choice (true for confirm, false for cancel)
   */
  function confirm(props: ModalConfirmProps): Promise<boolean>;
  
  /**
   * Clear all modals
   */
  function clear(): void;
}

interface ModalShowProps extends Omit<ModalProps, 'visible'> {}

interface ModalAlertProps {
  /** Alert title */
  title?: React.ReactNode;
  /** Alert content */
  content?: React.ReactNode;
  /** Confirm button text */
  confirmText?: string;
  /** Confirm handler */
  onConfirm?: () => void | Promise<void>;
  /** Image */
  image?: string;
}

interface ModalConfirmProps {
  /** Confirm title */
  title?: React.ReactNode;
  /** Confirm content */
  content?: React.ReactNode;
  /** Confirm button text */
  confirmText?: string;
  /** Cancel button text */
  cancelText?: string;
  /** Confirm handler */
  onConfirm?: () => void | Promise<void>;
  /** Cancel handler */
  onCancel?: () => void | Promise<void>;
  /** Image */
  image?: string;
}

interface ModalHandler {
  /** Close this modal */
  close(): void;
}

Dialog

System dialog with native styling and imperative API.

/**
 * Dialog component with native styling
 * @param props - Dialog configuration
 * @returns React dialog element
 */
function Dialog(props: DialogProps): JSX.Element;

interface DialogProps {
  /** Whether dialog is visible */
  visible?: boolean;
  /** Dialog title */
  title?: React.ReactNode;
  /** Dialog content */
  content?: React.ReactNode;
  /** Close handler */
  onClose?: () => void;
  /** Action buttons */
  actions?: (DialogActionButton | DialogActionButton[])[];
  /** Close on action */
  closeOnAction?: boolean;
  /** Close on mask click */
  closeOnMaskClick?: boolean;
  /** Image configuration */
  image?: string;
  /** Header content */
  header?: React.ReactNode;
  /** Body style */
  bodyStyle?: React.CSSProperties;
  /** Get container */
  getContainer?: HTMLElement | (() => HTMLElement) | null;
  /** After close callback */
  afterClose?: () => void;
  /** Dialog content */
  children?: React.ReactNode;
} & NativeProps;

interface DialogActionButton {
  /** Button key */
  key: string | number;
  /** Button text */
  text: React.ReactNode;
  /** Button color */
  color?: 'primary' | 'weak' | 'danger';
  /** Button style */
  bold?: boolean;
  /** Disabled state */
  disabled?: boolean;
  /** Click handler */
  onClick?: () => void | Promise<void>;
}

// Dialog imperative API
declare namespace Dialog {
  /**
   * Show dialog
   * @param props - Dialog configuration
   * @returns Dialog handler for manual control
   */
  function show(props: DialogShowProps): DialogHandler;
  
  /**
   * Show alert dialog
   * @param props - Alert configuration
   * @returns Promise that resolves when alert is closed
   */
  function alert(props: DialogAlertProps): Promise<void>;
  
  /**
   * Show confirm dialog
   * @param props - Confirm configuration
   * @returns Promise that resolves with user's choice (true for confirm, false for cancel)
   */
  function confirm(props: DialogConfirmProps): Promise<boolean>;
  
  /**
   * Clear all dialogs
   */
  function clear(): void;
}

interface DialogShowProps extends Omit<DialogProps, 'visible'> {}
interface DialogAlertProps extends ModalAlertProps {}
interface DialogConfirmProps extends ModalConfirmProps {}

interface DialogHandler {
  /** Close this dialog */
  close(): void;
}

Loading

Loading spinner indicator component.

/**
 * Loading spinner component
 * @param props - Loading configuration
 * @returns React loading element
 */
function Loading(props: LoadingProps): JSX.Element;

interface LoadingProps {
  /** Loading color */
  color?: 'default' | 'primary' | 'white' | string;
  /** Loading size */
  size?: 'mini' | 'small' | 'middle' | 'large';
} & NativeProps<'--color' | '--size'>;

DotLoading

Dots loading animation component.

/**
 * Dots loading animation component
 * @param props - DotLoading configuration
 * @returns React dot loading element
 */
function DotLoading(props: DotLoadingProps): JSX.Element;

interface DotLoadingProps {
  /** Loading color */
  color?: 'default' | 'primary' | 'white' | string;
  /** Loading size */
  size?: 'mini' | 'small' | 'middle' | 'large';
} & NativeProps<'--color' | '--size' | '--speed'>;

SpinLoading

Spinning loading animation component.

/**
 * Spinning loading animation component
 * @param props - SpinLoading configuration
 * @returns React spin loading element
 */
function SpinLoading(props: SpinLoadingProps): JSX.Element;

interface SpinLoadingProps {
  /** Loading color */
  color?: 'default' | 'primary' | 'white' | string;
  /** Loading size */
  size?: 'mini' | 'small' | 'middle' | 'large';
} & NativeProps<'--color' | '--size' | '--speed'>;

ProgressBar

Linear progress indicator component.

/**
 * Linear progress bar component
 * @param props - ProgressBar configuration
 * @returns React progress bar element
 */
function ProgressBar(props: ProgressBarProps): JSX.Element;

interface ProgressBarProps {
  /** Progress percentage (0-100) */
  percent?: number;
  /** Progress bar color */
  color?: string;
  /** Track color */
  trackColor?: string;
  /** Show progress text */
  text?: boolean | ((percent: number) => React.ReactNode);
  /** Whether progress is rounded */
  rounded?: boolean;
} & NativeProps<'--fill-color' | '--track-color' | '--track-width' | '--text-width'>;

ProgressCircle

Circular progress indicator component.

/**
 * Circular progress indicator component
 * @param props - ProgressCircle configuration
 * @returns React progress circle element
 */
function ProgressCircle(props: ProgressCircleProps): JSX.Element;

interface ProgressCircleProps {
  /** Progress percentage (0-100) */
  percent?: number;
  /** Circle color */
  color?: string | string[];
  /** Track color */
  trackColor?: string;
  /** Circle size */
  size?: number;
  /** Show progress text */
  text?: boolean | ((percent: number) => React.ReactNode);
  /** Track width */
  trackWidth?: number;
  /** Fill width */
  fillWidth?: number;
  /** Progress circle content */
  children?: React.ReactNode;
} & NativeProps<'--fill-color' | '--track-color' | '--track-width' | '--size'>;

Mask

Background mask overlay component.

/**
 * Background mask overlay component
 * @param props - Mask configuration
 * @returns React mask element
 */
function Mask(props: MaskProps): JSX.Element;

interface MaskProps {
  /** Whether mask is visible */
  visible?: boolean;
  /** Click handler */
  onMaskClick?: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
  /** Mask color */
  color?: 'black' | 'white';  
  /** Mask opacity */
  opacity?: 'default' | 'thin' | 'thick' | number;
  /** Destroy on close */
  destroyOnClose?: boolean;
  /** Force render */
  forceRender?: boolean;
  /** Disable body scroll */
  disableBodyScroll?: boolean;
  /** Stop propagation */
  stopPropagation?: string[];
  /** Get container */
  getContainer?: HTMLElement | (() => HTMLElement) | null;
  /** After show callback */
  afterShow?: () => void;
  /** After close callback */
  afterClose?: () => void;
  /** Mask content */
  children?: React.ReactNode;
} & NativeProps<'--z-index' | '--background'>;

Usage Examples

import { 
  Toast, 
  Modal, 
  Dialog, 
  Button, 
  ProgressBar, 
  Loading 
} from "antd-mobile";

function FeedbackExample() {
  const showModal = () => {
    Modal.show({
      title: 'Confirm Action',
      content: 'Are you sure you want to proceed?',
      actions: [
        {
          key: 'cancel',
          text: 'Cancel',
          color: 'weak'
        },
        {
          key: 'confirm',
          text: 'Confirm',
          color: 'primary',
          onClick: async () => {
            Toast.loading('Processing...');
            await new Promise(resolve => setTimeout(resolve, 2000));
            Toast.success('Completed!');
          }
        }
      ]
    });
  };

  const showDialog = () => {
    Dialog.confirm({
      title: 'Delete Item',
      content: 'This action cannot be undone.',
      onConfirm: () => {
        Toast.success('Deleted successfully');
      }
    });
  };

  return (
    <div>
      <Button onClick={showModal}>Show Modal</Button>
      <Button onClick={showDialog}>Show Dialog</Button>
      
      <ProgressBar percent={65} text />
      <Loading color="primary" size="large" />
    </div>
  );
}