github.com/grafana/pyroscope@v1.18.0/public/app/ui/Dialog/Dialog.tsx (about)

     1  /* eslint-disable react/jsx-props-no-spreading */
     2  import React, { Ref, ReactNode } from 'react';
     3  import ModalUnstyled from '@mui/base/ModalUnstyled';
     4  import Button from '@pyroscope/ui/Button';
     5  import cx from 'classnames';
     6  import styles from './Dialog.module.css';
     7  
     8  const Backdrop = React.forwardRef<
     9    HTMLDivElement,
    10    { open?: boolean; className: string }
    11  >((props, ref) => {
    12    const { className, ...other } = props;
    13    return (
    14      <div className={`${className} ${styles.backdrop}`} ref={ref} {...other} />
    15    );
    16  });
    17  
    18  Backdrop.displayName = 'Backdrop';
    19  
    20  type DialogHeaderProps = { children: ReactNode; className?: string } & (
    21    | { closeable: true; onClose: () => void }
    22    | { closeable?: false }
    23  );
    24  export const DialogHeader = React.forwardRef(
    25    (props: DialogHeaderProps, ref?: Ref<HTMLInputElement>) => {
    26      const { children, className, closeable } = props;
    27      return (
    28        <div className={cx(styles.header, className)} ref={ref}>
    29          {children}
    30          {closeable ? (
    31            <Button
    32              aria-label="Close"
    33              onClick={() => props.onClose()}
    34              noBox
    35              className={styles.closeButton}
    36            />
    37          ) : null}
    38        </div>
    39      );
    40    }
    41  );
    42  DialogHeader.displayName = 'DialogHeader';
    43  
    44  interface DialogFooterProps {
    45    children: ReactNode;
    46    className?: string;
    47  }
    48  export const DialogFooter = React.forwardRef(
    49    (props: DialogFooterProps, ref?: Ref<HTMLInputElement>) => {
    50      const { children, className } = props;
    51      return (
    52        <div className={cx(styles.footer, className)} ref={ref}>
    53          {children}
    54        </div>
    55      );
    56    }
    57  );
    58  DialogFooter.displayName = 'DialogFooter';
    59  
    60  interface DialogBodyProps {
    61    children: ReactNode;
    62    className?: string;
    63  }
    64  export const DialogBody = React.forwardRef(
    65    (props: DialogBodyProps, ref?: Ref<HTMLInputElement>) => {
    66      const { children, className } = props;
    67      return (
    68        <div className={cx(styles.body, className)} ref={ref}>
    69          {children}
    70        </div>
    71      );
    72    }
    73  );
    74  DialogBody.displayName = 'DialogBody';
    75  
    76  type DialogProps = Exclude<
    77    React.ComponentProps<typeof ModalUnstyled>,
    78    'components'
    79  > & {
    80    className?: string;
    81    /** The header ID */
    82    ['aria-labelledby']: string;
    83  };
    84  export function Dialog(props: DialogProps) {
    85    const { className } = props;
    86    return (
    87      <ModalUnstyled
    88        {...props}
    89        components={{ Backdrop }}
    90        className={cx(styles.modal, className)}
    91      >
    92        <div
    93          aria-modal="true"
    94          aria-labelledby={props['aria-labelledby']}
    95          className={styles.modalContainer}
    96        >
    97          {props.children}
    98        </div>
    99      </ModalUnstyled>
   100    );
   101  }
   102  
   103  export function DialogActions({ children }: { children: React.ReactNode }) {
   104    return <div className={styles.dialogActions}>{children}</div>;
   105  }