radio.tsx 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import * as React from 'react';
  2. import {css} from '@emotion/react';
  3. import styled from '@emotion/styled';
  4. import {growIn} from 'app/styles/animations';
  5. import {Theme} from 'app/utils/theme';
  6. type Props = {radioSize?: 'small'};
  7. type CheckedProps = Props &
  8. Omit<React.HTMLProps<HTMLInputElement>, 'as'> & {theme: Theme};
  9. const checkedCss = (p: CheckedProps) => css`
  10. display: block;
  11. width: ${p.radioSize === 'small' ? '8px' : '1rem'};
  12. height: ${p.radioSize === 'small' ? '8px' : '1rem'};
  13. border-radius: 50%;
  14. background-color: ${p.theme.active};
  15. animation: 0.2s ${growIn} ease;
  16. opacity: ${p.disabled ? 0.4 : null};
  17. `;
  18. const Radio = styled('input')<Props>`
  19. display: flex;
  20. padding: 0;
  21. width: ${p => (p.radioSize === 'small' ? '16px' : '1.5em')};
  22. height: ${p => (p.radioSize === 'small' ? '16px' : '1.5em')};
  23. position: relative;
  24. border-radius: 50%;
  25. align-items: center;
  26. justify-content: center;
  27. border: 1px solid ${p => p.theme.border};
  28. box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.04);
  29. background: none;
  30. appearance: none;
  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 !important;
  36. border: 1px solid ${p => p.theme.border};
  37. box-shadow: rgba(209, 202, 216, 0.5) 0 0 0 3px;
  38. }
  39. &:checked:after {
  40. content: '';
  41. ${p => checkedCss(p)}
  42. }
  43. `;
  44. Radio.defaultProps = {
  45. type: 'radio',
  46. };
  47. export default Radio;