You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Switch.tsx 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import React, { useCallback } from 'react';
  2. import { makeStyles } from 'tss-react/mui';
  3. import { isMobileBrowser } from '../../../environment/utils';
  4. import { ISwitchProps } from '../types';
  5. interface IProps extends ISwitchProps {
  6. className?: string;
  7. /**
  8. * Id of the toggle.
  9. */
  10. id?: string;
  11. }
  12. const useStyles = makeStyles()(theme => {
  13. return {
  14. container: {
  15. position: 'relative',
  16. backgroundColor: theme.palette.ui05,
  17. borderRadius: '12px',
  18. width: '40px',
  19. height: '24px',
  20. border: 0,
  21. outline: 0,
  22. cursor: 'pointer',
  23. transition: '.3s',
  24. display: 'inline-block',
  25. '&.disabled': {
  26. backgroundColor: theme.palette.ui05,
  27. cursor: 'default',
  28. '& .toggle': {
  29. backgroundColor: theme.palette.ui03
  30. }
  31. },
  32. '&.is-mobile': {
  33. height: '32px',
  34. width: '50px',
  35. borderRadius: '32px'
  36. }
  37. },
  38. containerOn: {
  39. backgroundColor: theme.palette.action01
  40. },
  41. toggle: {
  42. width: '16px',
  43. height: '16px',
  44. position: 'absolute',
  45. zIndex: 5,
  46. top: '4px',
  47. left: '4px',
  48. backgroundColor: theme.palette.ui10,
  49. borderRadius: '100%',
  50. transition: '.3s',
  51. '&.is-mobile': {
  52. width: '24px',
  53. height: '24px'
  54. }
  55. },
  56. toggleOn: {
  57. left: '20px',
  58. '&.is-mobile': {
  59. left: '22px'
  60. }
  61. },
  62. checkbox: {
  63. position: 'absolute',
  64. zIndex: 10,
  65. cursor: 'pointer',
  66. left: 0,
  67. right: 0,
  68. top: 0,
  69. bottom: 0,
  70. width: '100%',
  71. height: '100%',
  72. opacity: 0,
  73. '&.focus-visible + .toggle-checkbox-ring': {
  74. outline: 0,
  75. boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`
  76. }
  77. },
  78. checkboxRing: {
  79. position: 'absolute',
  80. pointerEvents: 'none',
  81. zIndex: 6,
  82. left: 0,
  83. right: 0,
  84. top: 0,
  85. bottom: 0,
  86. width: '100%',
  87. height: '100%',
  88. borderRadius: '12px',
  89. '&.is-mobile': {
  90. borderRadius: '32px'
  91. }
  92. }
  93. };
  94. });
  95. const Switch = ({ className, id, checked, disabled, onChange }: IProps) => {
  96. const { classes: styles, cx } = useStyles();
  97. const isMobile = isMobileBrowser();
  98. const change = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
  99. onChange(e.target.checked);
  100. }, []);
  101. return (
  102. <span
  103. className = { cx('toggle-container', styles.container, checked && styles.containerOn,
  104. isMobile && 'is-mobile', disabled && 'disabled', className) }>
  105. <input
  106. type = 'checkbox'
  107. { ...(id ? { id } : {}) }
  108. checked = { checked }
  109. className = { styles.checkbox }
  110. disabled = { disabled }
  111. onChange = { change } />
  112. <div className = { cx('toggle-checkbox-ring', styles.checkboxRing, isMobile && 'is-mobile') } />
  113. <div className = { cx('toggle', styles.toggle, checked && styles.toggleOn, isMobile && 'is-mobile') } />
  114. </span>
  115. );
  116. };
  117. export default Switch;