vitess.io/vitess@v0.16.2/web/vtadmin/src/components/dialog/Dialog.tsx (about)

     1  import { Fragment, useRef } from 'react';
     2  import { Dialog as HUDialog, Transition } from '@headlessui/react';
     3  import { Icon, Icons } from '../Icon';
     4  
     5  interface DialogProps {
     6      icon?: Icons;
     7      isOpen: boolean;
     8      title?: string;
     9      description?: string;
    10      content?: React.ReactElement;
    11      onCancel?: () => void;
    12      onConfirm?: Function;
    13      onClose?: () => void;
    14      loading?: boolean;
    15      loadingText?: string;
    16      confirmText?: string;
    17      cancelText?: string;
    18      footer?: React.ReactElement;
    19      hideFooter?: boolean;
    20      children?: React.ReactElement;
    21      hideConfirm?: boolean;
    22      hideCancel?: boolean;
    23      className?: string;
    24  }
    25  
    26  /**
    27   * Dialog is a controlled component, and its open state is controlled by the isOpen property.
    28   * User should pass in a function to set isOpen to the onClose property.
    29   */
    30  const Dialog: React.FC<DialogProps> = ({
    31      icon,
    32      title,
    33      description,
    34      children,
    35      isOpen,
    36      loading,
    37      loadingText,
    38      confirmText,
    39      cancelText,
    40      footer,
    41      hideFooter,
    42      hideCancel,
    43      hideConfirm,
    44      onCancel,
    45      onConfirm,
    46      onClose,
    47      className,
    48  }) => {
    49      const cancelButtonRef = useRef(null);
    50  
    51      return (
    52          <Transition.Root show={isOpen} as={Fragment}>
    53              <HUDialog
    54                  as="div"
    55                  className="fixed z-10 inset-0 overflow-y-auto"
    56                  initialFocus={cancelButtonRef}
    57                  onClose={(_) => {
    58                      onClose?.();
    59                  }}
    60              >
    61                  <div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
    62                      <Transition.Child
    63                          as={Fragment}
    64                          enter="ease-out duration-300"
    65                          enterFrom="opacity-0"
    66                          enterTo="opacity-100"
    67                          leave="ease-in duration-200"
    68                          leaveFrom="opacity-100"
    69                          leaveTo="opacity-0"
    70                      >
    71                          <HUDialog.Overlay className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
    72                      </Transition.Child>
    73  
    74                      {/* This element is to trick the browser into centering the modal contents. */}
    75                      <span className="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">
    76                          &#8203;
    77                      </span>
    78                      <Transition.Child
    79                          as={Fragment}
    80                          enter="ease-out duration-300"
    81                          enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
    82                          enterTo="opacity-100 translate-y-0 sm:scale-100"
    83                          leave="ease-in duration-200"
    84                          leaveFrom="opacity-100 translate-y-0 sm:scale-100"
    85                          leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
    86                      >
    87                          <div
    88                              className={`inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-2xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full ${className}`}
    89                          >
    90                              <div className="bg-white px-4 py-5 sm:py-8 sm:px-6 w-full">
    91                                  <div className="sm:flex sm:items-start">
    92                                      {icon && (
    93                                          <div className="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
    94                                              <Icon icon={icon} />
    95                                          </div>
    96                                      )}
    97                                      <div className="text-center sm:mt-0 sm:text-left w-full">
    98                                          {title && (
    99                                              <HUDialog.Title
   100                                                  as="h2"
   101                                                  className="text-xl leading-6 font-medium text-primary"
   102                                              >
   103                                                  {title}
   104                                              </HUDialog.Title>
   105                                          )}
   106                                          {description && (
   107                                              <div className="mt-2">
   108                                                  <p className="text-sm text-secondary">{description}</p>
   109                                              </div>
   110                                          )}
   111                                          {Boolean(children) && children}
   112                                      </div>
   113                                  </div>
   114                              </div>
   115                              {!footer && !hideFooter && (
   116                                  <div className="px-4 py-3 flex gap-2 sm:px-6 sm:flex-row-reverse">
   117                                      {!hideConfirm && (
   118                                          <button
   119                                              disabled={loading}
   120                                              type="button"
   121                                              className="btn"
   122                                              onClick={() => {
   123                                                  onConfirm?.();
   124                                              }}
   125                                          >
   126                                              {loading ? loadingText : confirmText || 'Confirm'}
   127                                          </button>
   128                                      )}
   129                                      {!hideCancel && (
   130                                          <button
   131                                              type="button"
   132                                              className="btn btn-secondary"
   133                                              onClick={() => {
   134                                                  onCancel?.();
   135                                                  onClose?.();
   136                                              }}
   137                                              ref={cancelButtonRef}
   138                                          >
   139                                              {cancelText || 'Cancel'}
   140                                          </button>
   141                                      )}
   142                                  </div>
   143                              )}
   144                              {Boolean(footer) && footer}
   145                          </div>
   146                      </Transition.Child>
   147                  </div>
   148              </HUDialog>
   149          </Transition.Root>
   150      );
   151  };
   152  
   153  export default Dialog;