fieldWrapper.tsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import {css} from '@emotion/react';
  2. import styled from '@emotion/styled';
  3. import space from 'sentry/styles/space';
  4. /**
  5. * Using Parameters<typeof FieldWrapper> in the Field component somehow
  6. * causes an infinite recursive depth so exporting the props is best workaround
  7. */
  8. export interface FieldWrapperProps {
  9. /**
  10. * When false adds padding to the right of the element to ensure visual
  11. * consistency with other fields that aren't using flexible control states.
  12. */
  13. hasControlState?: boolean;
  14. /**
  15. * Is "highlighted", i.e. after a search
  16. */
  17. highlighted?: boolean;
  18. /**
  19. * Display the field control container in "inline" fashion. The label and
  20. * description will be aligned to the left, while the control itself will be
  21. * aligned to the right.
  22. */
  23. inline?: boolean;
  24. /**
  25. * When stacking forms the bottom border is hidden and padding is adjusted
  26. * for form elements to be stacked on each other.
  27. */
  28. stacked?: boolean;
  29. }
  30. const inlineStyle = (p: FieldWrapperProps) =>
  31. p.inline
  32. ? css`
  33. align-items: center;
  34. `
  35. : css`
  36. flex-direction: column;
  37. align-items: stretch;
  38. `;
  39. const getPadding = (p: FieldWrapperProps) =>
  40. p.stacked && !p.inline
  41. ? css`
  42. padding: 0 ${p.hasControlState ? 0 : space(2)} ${space(2)} 0;
  43. `
  44. : css`
  45. padding: ${space(2)} ${p.hasControlState ? 0 : space(2)} ${space(2)} ${space(2)};
  46. `;
  47. const FieldWrapper = styled('div')<FieldWrapperProps>`
  48. ${getPadding}
  49. ${inlineStyle}
  50. display: flex;
  51. transition: background 0.15s;
  52. ${p =>
  53. !p.stacked &&
  54. css`
  55. border-bottom: 1px solid ${p.theme.innerBorder};
  56. `}
  57. ${p =>
  58. p.highlighted &&
  59. css`
  60. position: relative;
  61. &:after {
  62. content: '';
  63. display: block;
  64. position: absolute;
  65. top: -1px;
  66. left: -1px;
  67. right: -1px;
  68. bottom: -1px;
  69. border: 1px solid ${p.theme.purple300};
  70. pointer-events: none;
  71. }
  72. `}
  73. /* Better padding with form inside of a modal */
  74. ${p =>
  75. !p.hasControlState &&
  76. css`
  77. [role='document'] & {
  78. padding-right: 0;
  79. }
  80. `}
  81. &:last-child {
  82. border-bottom: none;
  83. ${p => (p.stacked ? 'padding-bottom: 0' : '')};
  84. }
  85. `;
  86. export default FieldWrapper;