roleSelectControl.tsx 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import {components, OptionProps} from 'react-select';
  2. import styled from '@emotion/styled';
  3. import SelectControl, {ControlProps} from 'sentry/components/forms/selectControl';
  4. import space from 'sentry/styles/space';
  5. import {MemberRole} from 'sentry/types';
  6. import theme from 'sentry/utils/theme';
  7. type OptionType = {
  8. label: string;
  9. value: string;
  10. disabled: boolean;
  11. description: string;
  12. };
  13. type Props = Omit<ControlProps<OptionType>, 'onChange' | 'value'> & {
  14. roles: MemberRole[];
  15. disableUnallowed: boolean;
  16. value?: string;
  17. /**
  18. * Narrower type than SelectControl because there is no empty value
  19. */
  20. onChange?: (value: OptionType) => void;
  21. };
  22. function RoleSelectControl({roles, disableUnallowed, ...props}: Props) {
  23. return (
  24. <SelectControl
  25. options={roles?.map(
  26. (r: MemberRole) =>
  27. ({
  28. value: r.id,
  29. label: r.name,
  30. disabled: disableUnallowed && !r.allowed,
  31. description: r.desc,
  32. } as OptionType)
  33. )}
  34. components={{
  35. Option: ({label, data, ...optionProps}: OptionProps<OptionType>) => (
  36. <components.Option label={label} {...(optionProps as any)}>
  37. <RoleItem>
  38. <h1>{label}</h1>
  39. <div>{data.description}</div>
  40. </RoleItem>
  41. </components.Option>
  42. ),
  43. }}
  44. styles={{
  45. control: provided => ({
  46. ...provided,
  47. borderBottomLeftRadius: theme.borderRadius,
  48. borderBottomRightRadius: theme.borderRadius,
  49. }),
  50. menu: provided => ({
  51. ...provided,
  52. borderRadius: theme.borderRadius,
  53. marginTop: space(0.5),
  54. width: '350px',
  55. overflow: 'hidden',
  56. }),
  57. }}
  58. {...props}
  59. />
  60. );
  61. }
  62. const RoleItem = styled('div')`
  63. display: grid;
  64. grid-template-columns: 80px 1fr;
  65. grid-gap: ${space(1)};
  66. h1,
  67. div {
  68. font-size: ${p => p.theme.fontSizeSmall};
  69. line-height: 1.4;
  70. margin: ${space(0.25)} 0;
  71. }
  72. `;
  73. export default RoleSelectControl;