flex.tsx 2.3 KB

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