toggle.tsx 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import {Children, useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import {IconAdd, IconSubtract} from 'sentry/icons';
  4. type Props = {
  5. children: React.ReactNode;
  6. highUp: boolean;
  7. wrapClassName: string;
  8. };
  9. function Toggle({highUp, wrapClassName, children}: Props) {
  10. const [isExpanded, setIsExpanded] = useState(false);
  11. if (Children.count(children) === 0) {
  12. return null;
  13. }
  14. const wrappedChildren = <span className={wrapClassName}>{children}</span>;
  15. if (highUp) {
  16. return wrappedChildren;
  17. }
  18. return (
  19. <span>
  20. <IconWrapper
  21. isExpanded={isExpanded}
  22. onClick={evt => {
  23. setIsExpanded(!isExpanded);
  24. evt.preventDefault();
  25. }}
  26. >
  27. {isExpanded ? (
  28. <IconSubtract size="9px" color="white" />
  29. ) : (
  30. <IconAdd size="9px" color="white" />
  31. )}
  32. </IconWrapper>
  33. {isExpanded && wrappedChildren}
  34. </span>
  35. );
  36. }
  37. export default Toggle;
  38. const IconWrapper = styled('div')<{isExpanded: boolean}>`
  39. border-radius: 2px;
  40. display: inline-flex;
  41. align-items: center;
  42. justify-content: center;
  43. cursor: pointer;
  44. ${p =>
  45. p.isExpanded
  46. ? `
  47. background: ${p.theme.gray300};
  48. border: 1px solid ${p.theme.gray300};
  49. &:hover {
  50. background: ${p.theme.gray400};
  51. }
  52. `
  53. : `
  54. background: ${p.theme.blue300};
  55. border: 1px solid ${p.theme.blue300};
  56. &:hover {
  57. background: ${p.theme.blue200};
  58. }
  59. `}
  60. `;