checkboxField.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import styled from '@emotion/styled';
  2. import Checkbox from 'sentry/components/checkbox';
  3. import space from 'sentry/styles/space';
  4. import FieldDescription from '../field/fieldDescription';
  5. import FieldHelp from '../field/fieldHelp';
  6. import FieldLabel from '../field/fieldLabel';
  7. import FieldRequiredBadge from '../field/fieldRequiredBadge';
  8. import FormField from '../formField';
  9. type FormFieldProps = Omit<
  10. React.ComponentProps<typeof FormField>,
  11. 'children' | 'help' | 'disabled' | 'required'
  12. >;
  13. type Props = {
  14. /**
  15. * The input name
  16. */
  17. name: string;
  18. /**
  19. * Is the field disabled?
  20. */
  21. disabled?: boolean;
  22. /**
  23. * Help or description of the field
  24. */
  25. help?: React.ReactNode | React.ReactElement | ((props: Props) => React.ReactNode);
  26. /**
  27. * User visible field label
  28. */
  29. label?: React.ReactNode;
  30. /**
  31. * Is the field required?
  32. */
  33. required?: boolean;
  34. } & FormFieldProps;
  35. function CheckboxField(props: Props) {
  36. const {name, disabled, stacked, required, label, help} = props;
  37. const helpElement = typeof help === 'function' ? help(props) : help;
  38. const ariaLabel = typeof label === 'string' ? label : undefined;
  39. return (
  40. <FormField name={name} inline={false} stacked={stacked}>
  41. {({onChange, value, id}) => {
  42. function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
  43. const newValue = e.target.checked;
  44. onChange?.(newValue, e);
  45. }
  46. return (
  47. <FieldLayout>
  48. <ControlWrapper>
  49. <Checkbox
  50. id={id}
  51. name={name}
  52. disabled={disabled}
  53. checked={value === true}
  54. onChange={handleChange}
  55. />
  56. </ControlWrapper>
  57. <FieldDescription htmlFor={id} aria-label={ariaLabel}>
  58. {label && (
  59. <FieldLabel disabled={disabled}>
  60. <span>
  61. {label}
  62. {required && <FieldRequiredBadge />}
  63. </span>
  64. </FieldLabel>
  65. )}
  66. {helpElement && (
  67. <FieldHelp stacked={stacked} inline>
  68. {helpElement}
  69. </FieldHelp>
  70. )}
  71. </FieldDescription>
  72. </FieldLayout>
  73. );
  74. }}
  75. </FormField>
  76. );
  77. }
  78. const ControlWrapper = styled('span')`
  79. align-self: flex-start;
  80. display: flex;
  81. margin-right: ${space(1)};
  82. & input {
  83. margin: 0;
  84. }
  85. `;
  86. const FieldLayout = styled('div')`
  87. display: flex;
  88. flex-direction: row;
  89. `;
  90. export default CheckboxField;