radio.tsx 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. import {css, Theme} from '@emotion/react';
  2. import styled from '@emotion/styled';
  3. import {growIn} from 'sentry/styles/animations';
  4. interface CheckedProps extends React.InputHTMLAttributes<HTMLInputElement> {
  5. disabled?: boolean;
  6. radioSize?: 'small';
  7. }
  8. const checkedCss = (p: CheckedProps, theme: Theme) => css`
  9. display: block;
  10. width: ${p.radioSize === 'small' ? '0.5rem' : '0.875rem'};
  11. height: ${p.radioSize === 'small' ? '0.5rem' : '0.875rem'};
  12. border-radius: 50%;
  13. background-color: ${theme.active};
  14. animation: 0.2s ${growIn} ease;
  15. opacity: ${p.disabled ? 0.4 : null};
  16. `;
  17. const Radio = styled('input')<CheckedProps>`
  18. display: flex;
  19. padding: 0;
  20. width: ${p => (p.radioSize === 'small' ? '1rem' : '1.5rem')};
  21. height: ${p => (p.radioSize === 'small' ? '1rem' : '1.5rem')};
  22. position: relative;
  23. border-radius: 50%;
  24. align-items: center;
  25. justify-content: center;
  26. border: 1px solid ${p => p.theme.border};
  27. box-shadow: inset ${p => p.theme.dropShadowMedium};
  28. background: none;
  29. appearance: none;
  30. transition: border 0.1s, box-shadow 0.1s;
  31. /* TODO(bootstrap): Our bootstrap CSS adds this, we can remove when we remove that */
  32. margin: 0 !important;
  33. &:focus,
  34. &.focus-visible {
  35. outline: none;
  36. border-color: ${p => p.theme.focusBorder};
  37. box-shadow: ${p => p.theme.focusBorder} 0 0 0 1px;
  38. }
  39. &:checked:after {
  40. content: '';
  41. ${p => checkedCss(p, p.theme)}
  42. }
  43. `;
  44. Radio.defaultProps = {
  45. type: 'radio',
  46. };
  47. export default Radio;