fieldControl.tsx 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import styled from '@emotion/styled';
  2. import QuestionTooltip from 'sentry/components/questionTooltip';
  3. import space from 'sentry/styles/space';
  4. import FieldControlState from './fieldControlState';
  5. import {FieldGroupProps} from './types';
  6. type FieldControlProps = Pick<
  7. FieldGroupProps,
  8. | 'alignRight'
  9. | 'controlState'
  10. | 'disabled'
  11. | 'disabledReason'
  12. | 'errorState'
  13. | 'flexibleControlStateSize'
  14. | 'hideControlState'
  15. | 'inline'
  16. > & {
  17. children: React.ReactNode;
  18. };
  19. const FieldControl = ({
  20. inline,
  21. alignRight,
  22. disabled,
  23. disabledReason,
  24. errorState,
  25. controlState,
  26. children,
  27. hideControlState,
  28. flexibleControlStateSize,
  29. }: FieldControlProps) => (
  30. <FieldControlErrorWrapper inline={inline}>
  31. <FieldControlWrapper>
  32. <FieldControlStyled alignRight={alignRight}>{children}</FieldControlStyled>
  33. {disabled && disabledReason && (
  34. <DisabledIndicator className="disabled-indicator">
  35. <StyledQuestionTooltip title={disabledReason} size="sm" position="top" />
  36. </DisabledIndicator>
  37. )}
  38. {!hideControlState && (
  39. <FieldControlState flexibleControlStateSize={!!flexibleControlStateSize}>
  40. {controlState}
  41. </FieldControlState>
  42. )}
  43. </FieldControlWrapper>
  44. {!hideControlState && errorState}
  45. </FieldControlErrorWrapper>
  46. );
  47. export default FieldControl;
  48. // This wraps Control + ControlError message
  49. // * can NOT be a flex box here because of `position: absolute` on "control error message"
  50. // * can NOT have overflow hidden because "control error message" overflows
  51. const FieldControlErrorWrapper = styled('div')<{inline?: boolean}>`
  52. ${p => (p.inline ? 'width: 50%; padding-left: 10px;' : '')};
  53. position: relative;
  54. `;
  55. const FieldControlStyled = styled('div')<{alignRight?: boolean}>`
  56. display: flex;
  57. flex: 1;
  58. flex-direction: column;
  59. position: relative;
  60. max-width: 100%;
  61. ${p => (p.alignRight ? 'align-items: flex-end;' : '')};
  62. `;
  63. const FieldControlWrapper = styled('div')`
  64. display: flex;
  65. flex-shrink: 0;
  66. `;
  67. const StyledQuestionTooltip = styled(QuestionTooltip)`
  68. display: block;
  69. margin: 0 auto;
  70. `;
  71. const DisabledIndicator = styled('div')`
  72. display: flex;
  73. align-items: center;
  74. margin-left: ${space(1)};
  75. `;