github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/packages/pyroscope-flamegraph/src/FlameGraph/FlameGraphComponent/DiffLegendPaletteDropdown.tsx (about)

     1  import React from 'react';
     2  import cx from 'classnames';
     3  import useResizeObserver from '@react-hook/resize-observer';
     4  import {
     5    ColorBlindPalette,
     6    DefaultPalette,
     7    FlamegraphPalette,
     8  } from './colorPalette';
     9  import DiffLegend from './DiffLegend';
    10  import CheckIcon from './CheckIcon';
    11  // Until we migrate ui to its own package this should do it
    12  // eslint-disable-next-line
    13  import Dropdown, { MenuItem, MenuButton } from '@webapp/ui/Dropdown';
    14  // eslint-disable-next-line
    15  import dropdownStyles from '@webapp/ui/Dropdown.module.scss';
    16  
    17  import styles from './DiffLegendPaletteDropdown.module.css';
    18  
    19  const paletteList = [DefaultPalette, ColorBlindPalette];
    20  
    21  interface DiffLegendPaletteDropdownProps {
    22    palette: FlamegraphPalette;
    23    onChange: (p: FlamegraphPalette) => void;
    24  }
    25  
    26  export const DiffLegendPaletteDropdown = (
    27    props: DiffLegendPaletteDropdownProps
    28  ) => {
    29    const { palette = DefaultPalette, onChange } = props;
    30    const legendRef = React.useRef<HTMLDivElement>(null);
    31    const showMode = useSizeMode(legendRef);
    32  
    33    return (
    34      <>
    35        <div className={styles.row} role="heading" aria-level={2}>
    36          <p style={{ color: palette.goodColor.rgb().string() }}>(-) Removed</p>
    37          <p style={{ color: palette.badColor.rgb().string() }}>Added (+)</p>
    38        </div>
    39  
    40        <div ref={legendRef} className={styles.dropdownWrapper}>
    41          <Dropdown
    42            label="Select a palette"
    43            align="end"
    44            menuButton={
    45              <MenuButton
    46                className={cx(
    47                  // eslint-disable-next-line
    48                  dropdownStyles.dropdownMenuButton,
    49                  styles.diffPaletteDropdown
    50                )}
    51              >
    52                <DiffLegend palette={palette} showMode={showMode} />
    53              </MenuButton>
    54            }
    55            onItemClick={(e) => onChange(e.value)}
    56          >
    57            {paletteList.map((p) => (
    58              <MenuItem key={p.name} value={p}>
    59                <div>
    60                  <label>{p.name}</label>
    61                  <div className={styles.dropdownItem}>
    62                    <DiffLegend palette={p} showMode={showMode} />
    63  
    64                    {p === palette ? <CheckIcon /> : null}
    65                  </div>
    66                </div>
    67              </MenuItem>
    68            ))}
    69          </Dropdown>
    70        </div>
    71      </>
    72    );
    73  };
    74  
    75  /**
    76   * TODO: unify this and toolbar's
    77   * Custom hook that returns the size ('large' | 'small')
    78   * that should be displayed
    79   * based on the toolbar width
    80   */
    81  // arbitrary value
    82  // as a simple heuristic, try to run the comparison view
    83  // and see when the buttons start to overlap
    84  const WIDTH_THRESHOLD = 13 * 37;
    85  const useSizeMode = (target: React.RefObject<HTMLDivElement>) => {
    86    const [size, setSize] = React.useState<'large' | 'small'>('large');
    87  
    88    const calcMode = (width: number) => {
    89      if (width < WIDTH_THRESHOLD) {
    90        return 'small';
    91      }
    92      return 'large';
    93    };
    94  
    95    React.useLayoutEffect(() => {
    96      if (target.current) {
    97        const { width } = target.current.getBoundingClientRect();
    98  
    99        setSize(calcMode(width));
   100      }
   101    }, [target.current]);
   102  
   103    useResizeObserver(target, (entry: ResizeObserverEntry) => {
   104      setSize(calcMode(entry.contentRect.width));
   105    });
   106  
   107    return size;
   108  };
   109  
   110  export default DiffLegendPaletteDropdown;