index.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import QuestionTooltip from 'sentry/components/questionTooltip';
  2. import ControlState from './controlState';
  3. import FieldControl from './fieldControl';
  4. import FieldDescription from './fieldDescription';
  5. import FieldErrorReason from './fieldErrorReason';
  6. import FieldHelp from './fieldHelp';
  7. import FieldLabel from './fieldLabel';
  8. import FieldQuestion from './fieldQuestion';
  9. import FieldRequiredBadge from './fieldRequiredBadge';
  10. import FieldWrapper from './fieldWrapper';
  11. import {FieldGroupProps} from './types';
  12. /**
  13. * XXX: BC with getsentry
  14. */
  15. export type FieldProps = FieldGroupProps;
  16. /**
  17. * A component to render a Field (i.e. label + help + form "control"),
  18. * generally inside of a Panel.
  19. *
  20. * This is unconnected to any Form state
  21. */
  22. function Field({
  23. className,
  24. disabled = false,
  25. inline = true,
  26. visible = true,
  27. ...rest
  28. }: FieldGroupProps) {
  29. const props = {
  30. inline,
  31. disabled,
  32. visible,
  33. ...rest,
  34. };
  35. const {
  36. alignRight,
  37. children,
  38. controlClassName,
  39. disabledReason,
  40. error,
  41. flexibleControlStateSize,
  42. help,
  43. hideLabel,
  44. highlighted,
  45. id,
  46. isSaved,
  47. isSaving,
  48. label,
  49. labelText,
  50. required,
  51. showHelpInTooltip,
  52. stacked,
  53. style,
  54. } = props;
  55. const isVisible = typeof visible === 'function' ? visible(props) : visible;
  56. const isDisabled = typeof disabled === 'function' ? disabled(props) : disabled;
  57. if (!isVisible) {
  58. return null;
  59. }
  60. const helpElement = typeof help === 'function' ? help(props) : help;
  61. const shouldRenderLabel = !hideLabel && !!label;
  62. const controlProps = {
  63. inline,
  64. alignRight,
  65. disabledReason,
  66. flexibleControlStateSize,
  67. controlState: <ControlState error={!!error} isSaving={isSaving} isSaved={isSaved} />,
  68. errorState: error ? <FieldErrorReason>{error}</FieldErrorReason> : null,
  69. className: controlClassName,
  70. disabled: isDisabled,
  71. help: helpElement,
  72. };
  73. // See comments in prop types
  74. const control =
  75. typeof children === 'function' ? (
  76. children({...props, ...controlProps})
  77. ) : (
  78. <FieldControl {...controlProps}>{children}</FieldControl>
  79. );
  80. // Provide an `aria-label` to the FieldDescription label if our label is a
  81. // string value. This helps with testing and accessability. Without this the
  82. // aria label contains the entire description.
  83. const ariaLabel = labelText ?? (typeof label === 'string' ? label : undefined);
  84. // The help ID is used for the input element to have an `aria-describedby`
  85. const helpId = `${id}_help`;
  86. return (
  87. <FieldWrapper
  88. className={className}
  89. inline={inline}
  90. stacked={stacked}
  91. highlighted={highlighted}
  92. hasControlState={!flexibleControlStateSize}
  93. style={style}
  94. >
  95. {(shouldRenderLabel || helpElement) && (
  96. <FieldDescription inline={inline} htmlFor={id} aria-label={ariaLabel}>
  97. {shouldRenderLabel && (
  98. <FieldLabel disabled={isDisabled}>
  99. <span>
  100. {label}
  101. {required && <FieldRequiredBadge />}
  102. </span>
  103. {helpElement && showHelpInTooltip && (
  104. <FieldQuestion>
  105. <QuestionTooltip position="top" size="sm" title={helpElement} />
  106. </FieldQuestion>
  107. )}
  108. </FieldLabel>
  109. )}
  110. {helpElement && !showHelpInTooltip && (
  111. <FieldHelp id={helpId} stacked={stacked} inline={inline}>
  112. {helpElement}
  113. </FieldHelp>
  114. )}
  115. </FieldDescription>
  116. )}
  117. {control}
  118. </FieldWrapper>
  119. );
  120. }
  121. export default Field;