collapsible.tsx 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import {Children, Fragment, useState} from 'react';
  2. import Button from 'sentry/components/button';
  3. import {t, tn} from 'sentry/locale';
  4. type CollapseButtonRenderProps = {
  5. onCollapse: () => void;
  6. };
  7. type ExpandButtonRenderProps = {
  8. numberOfHiddenItems: number;
  9. onExpand: () => void;
  10. };
  11. type Props = {
  12. collapseButton?: (props: CollapseButtonRenderProps) => React.ReactNode;
  13. expandButton?: (props: ExpandButtonRenderProps) => React.ReactNode;
  14. maxVisibleItems?: number;
  15. };
  16. /**
  17. * This component is used to show first X items and collapse the rest
  18. */
  19. const Collapsible: React.FC<Props> = ({
  20. collapseButton,
  21. expandButton,
  22. maxVisibleItems = 5,
  23. children,
  24. }) => {
  25. const [isCollapsed, setCollapsed] = useState(true);
  26. const handleCollapseToggle = () => setCollapsed(!isCollapsed);
  27. const items = Children.toArray(children);
  28. const canCollapse = items.length > maxVisibleItems;
  29. if (!canCollapse) {
  30. return <Fragment>{children}</Fragment>;
  31. }
  32. const visibleItems = isCollapsed ? items.slice(0, maxVisibleItems) : items;
  33. const numberOfHiddenItems = items.length - visibleItems.length;
  34. const showDefault =
  35. (numberOfHiddenItems > 0 && !expandButton) ||
  36. (numberOfHiddenItems === 0 && !collapseButton);
  37. return (
  38. <Fragment>
  39. {visibleItems}
  40. {showDefault && (
  41. <Button priority="link" onClick={handleCollapseToggle}>
  42. {isCollapsed
  43. ? tn('Show %s hidden item', 'Show %s hidden items', numberOfHiddenItems)
  44. : t('Collapse')}
  45. </Button>
  46. )}
  47. {numberOfHiddenItems > 0 &&
  48. expandButton?.({onExpand: handleCollapseToggle, numberOfHiddenItems})}
  49. {numberOfHiddenItems === 0 && collapseButton?.({onCollapse: handleCollapseToggle})}
  50. </Fragment>
  51. );
  52. };
  53. export default Collapsible;