Ringtone app
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.
 
 
 

126 lines
2.3 KiB

  1. import styled from 'styled-components';
  2. import {ChangeEventHandler, FC, ReactChild} from 'react';
  3. const Base = styled('div')({
  4. height: '3rem',
  5. borderRadius: '0.25rem',
  6. overflow: 'hidden',
  7. position: 'relative',
  8. '::after': {
  9. content: "''",
  10. borderWidth: 1,
  11. borderStyle: 'solid',
  12. borderColor: 'inherit',
  13. position: 'absolute',
  14. top: 0,
  15. left: 0,
  16. width: '100%',
  17. height: '100%',
  18. borderRadius: 'inherit',
  19. boxSizing: 'border-box',
  20. pointerEvents: 'none',
  21. opacity: 0.5,
  22. },
  23. })
  24. const ClickArea = styled('label')({
  25. display: 'block',
  26. width: '100%',
  27. height: '100%',
  28. margin: 0,
  29. padding: '0 1rem',
  30. boxSizing: 'border-box',
  31. font: 'inherit',
  32. border: 0,
  33. backgroundColor: 'transparent',
  34. color: 'inherit',
  35. outline: 0,
  36. textTransform: 'uppercase',
  37. fontWeight: 'bolder',
  38. position: 'relative',
  39. borderRadius: 'inherit',
  40. })
  41. const Input = styled('input')({
  42. position: 'absolute',
  43. left: -999999,
  44. })
  45. const ButtonWrapper = styled('span')({
  46. display: 'grid',
  47. placeContent: 'center',
  48. borderRadius: 'inherit',
  49. position: 'absolute',
  50. top: 0,
  51. left: 0,
  52. width: '100%',
  53. height: '100%',
  54. lineHeight: 0,
  55. cursor: 'pointer',
  56. [`${Input}:disabled + &`]: {
  57. cursor: 'not-allowed',
  58. },
  59. [`${Input}:checked + &`]: {
  60. backgroundColor: 'Highlight !important',
  61. },
  62. })
  63. const VARIANTS = {
  64. default: {
  65. backgroundColor: 'var(--color-bg, white)',
  66. borderColor: 'var(--color-fg, black)',
  67. color: 'var(--color-fg, black)',
  68. },
  69. primary: {
  70. backgroundColor: 'var(--color-fg, black)',
  71. borderColor: 'var(--color-fg, black)',
  72. color: 'var(--color-bg, white)',
  73. },
  74. }
  75. type Props = {
  76. children?: ReactChild,
  77. className?: string,
  78. type?: 'checkbox' | 'radio',
  79. block?: boolean,
  80. variant?: keyof typeof VARIANTS,
  81. name?: string,
  82. value?: string,
  83. defaultChecked?: boolean,
  84. onChange?: ChangeEventHandler<HTMLInputElement>,
  85. disabled?: boolean,
  86. }
  87. const ToggleButton: FC<Props> = ({
  88. children,
  89. className,
  90. type = 'checkbox',
  91. block,
  92. variant = 'default',
  93. ...etcProps
  94. }) => {
  95. return (
  96. <Base
  97. className={className}
  98. style={{
  99. display: block ? 'block' : 'inline-block',
  100. width: block ? '100%' : undefined,
  101. }}
  102. >
  103. <ClickArea>
  104. <Input
  105. {...etcProps}
  106. type={type}
  107. />
  108. <ButtonWrapper
  109. style={VARIANTS[variant]}
  110. >
  111. {children}
  112. </ButtonWrapper>
  113. </ClickArea>
  114. </Base>
  115. )
  116. }
  117. export default ToggleButton