flex.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import {CSSProperties} from 'react';
  2. import styled from '@emotion/styled';
  3. import type {CssSize} from 'sentry/utils/number/toPixels';
  4. import toPixels from 'sentry/utils/number/toPixels';
  5. interface FlexProps {
  6. align?: CSSProperties['alignItems'];
  7. column?: boolean;
  8. gap?: number | CssSize;
  9. h?: number | CssSize;
  10. justify?: CSSProperties['justifyContent'];
  11. m?: number | CssSize;
  12. maxH?: number | CssSize;
  13. mb?: number | CssSize;
  14. minH?: number | CssSize;
  15. ml?: number | CssSize;
  16. mr?: number | CssSize;
  17. mt?: number | CssSize;
  18. mx?: number | CssSize;
  19. my?: number | CssSize;
  20. p?: number | CssSize;
  21. pb?: number | CssSize;
  22. pl?: number | CssSize;
  23. pr?: number | CssSize;
  24. pt?: number | CssSize;
  25. px?: number | CssSize;
  26. py?: number | CssSize;
  27. w?: number | CssSize;
  28. wrap?: CSSProperties['flexWrap'];
  29. }
  30. // TODO(@eliashussary): move to common folder / bring up in fe-tsc
  31. const FlexContainer = styled('div')<FlexProps>`
  32. /* these can all come from a better base primitive */
  33. display: flex;
  34. height: ${p => toPixels(p.h)};
  35. width: ${p => toPixels(p.w)};
  36. min-height: ${p => toPixels(p.minH)};
  37. max-height: ${p => toPixels(p.maxH)};
  38. /* padding */
  39. padding: ${p => toPixels(p.p)};
  40. padding-left: ${p => toPixels(p.pl || p.px)};
  41. padding-right: ${p => toPixels(p.pr || p.px)};
  42. padding-top: ${p => toPixels(p.pt || p.py)};
  43. padding-bottom: ${p => toPixels(p.pb || p.py)};
  44. /* margin */
  45. margin: ${p => toPixels(p.m)};
  46. margin-left: ${p => toPixels(p.ml || p.mx)};
  47. margin-right: ${p => toPixels(p.mr || p.mx)};
  48. margin-top: ${p => toPixels(p.mt || p.my)};
  49. margin-bottom: ${p => toPixels(p.mb || p.my)};
  50. /* flex specific */
  51. flex-direction: ${p => (p.column ? 'column' : 'row')};
  52. justify-content: ${p => p.justify};
  53. align-items: ${p => p.align};
  54. gap: ${p => toPixels(p.gap)};
  55. flex-wrap: ${p => p.wrap};
  56. `;
  57. interface FlexItemProps {
  58. basis?: CSSProperties['flexBasis'];
  59. grow?: CSSProperties['flexGrow'];
  60. shrink?: CSSProperties['flexShrink'];
  61. }
  62. const FlexItem = styled('div')<FlexItemProps>`
  63. flex-grow: ${p => p.grow ?? 0};
  64. flex-shrink: ${p => p.shrink ?? 1};
  65. flex-basis: ${p => p.basis ?? 'auto'};
  66. overflow: hidden;
  67. `;
  68. export const Flex = Object.assign(FlexContainer, {
  69. ...FlexContainer,
  70. Container: FlexContainer,
  71. Item: FlexItem,
  72. });