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.

tools-panel.tsx 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import {
  2. ArrowTopRightIcon,
  3. CircleIcon,
  4. CursorArrowIcon,
  5. LockClosedIcon,
  6. LockOpen1Icon,
  7. Pencil1Icon,
  8. Pencil2Icon,
  9. SquareIcon,
  10. TextIcon,
  11. } from '@radix-ui/react-icons'
  12. import { IconButton } from 'components/shared'
  13. import React from 'react'
  14. import state, { useSelector } from 'state'
  15. import styled from 'styles'
  16. import { ShapeType } from 'types'
  17. import UndoRedo from './undo-redo'
  18. import Zoom from './zoom'
  19. import Tooltip from '../tooltip'
  20. const selectArrowTool = () => state.send('SELECTED_ARROW_TOOL')
  21. const selectDrawTool = () => state.send('SELECTED_DRAW_TOOL')
  22. const selectEllipseTool = () => state.send('SELECTED_ELLIPSE_TOOL')
  23. const selectTextTool = () => state.send('SELECTED_TEXT_TOOL')
  24. const selectRectangleTool = () => state.send('SELECTED_RECTANGLE_TOOL')
  25. const selectSelectTool = () => state.send('SELECTED_SELECT_TOOL')
  26. const selectToolLock = () => state.send('TOGGLED_TOOL_LOCK')
  27. export default function ToolsPanel(): JSX.Element {
  28. const activeTool = useSelector((s) => s.data.activeTool)
  29. const isToolLocked = useSelector((s) => s.data.settings.isToolLocked)
  30. const isPenLocked = useSelector((s) => s.data.settings.isPenLocked)
  31. return (
  32. <OuterContainer>
  33. <Zoom />
  34. <Flex size={{ '@sm': 'small' }}>
  35. <Container>
  36. <Tooltip label="Select">
  37. <IconButton
  38. name="select"
  39. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  40. size={{ '@initial': 'small', '@sm': 'small', '@md': 'medium' }}
  41. onClick={selectSelectTool}
  42. isActive={activeTool === 'select'}
  43. >
  44. <CursorArrowIcon />
  45. </IconButton>
  46. </Tooltip>
  47. </Container>
  48. <Container>
  49. <Tooltip label="Draw">
  50. <IconButton
  51. name={ShapeType.Draw}
  52. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  53. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  54. onClick={selectDrawTool}
  55. isActive={activeTool === ShapeType.Draw}
  56. >
  57. <Pencil1Icon />
  58. </IconButton>
  59. </Tooltip>
  60. <Tooltip label="Rectangle">
  61. <IconButton
  62. name={ShapeType.Rectangle}
  63. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  64. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  65. onClick={selectRectangleTool}
  66. isActive={activeTool === ShapeType.Rectangle}
  67. >
  68. <SquareIcon />
  69. </IconButton>
  70. </Tooltip>
  71. <Tooltip label="Ellipse">
  72. <IconButton
  73. name={ShapeType.Ellipse}
  74. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  75. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  76. onClick={selectEllipseTool}
  77. isActive={activeTool === ShapeType.Ellipse}
  78. >
  79. <CircleIcon />
  80. </IconButton>
  81. </Tooltip>
  82. <Tooltip label="Arrow">
  83. <IconButton
  84. name={ShapeType.Arrow}
  85. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  86. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  87. onClick={selectArrowTool}
  88. isActive={activeTool === ShapeType.Arrow}
  89. >
  90. <ArrowTopRightIcon />
  91. </IconButton>
  92. </Tooltip>
  93. <Tooltip label="Text">
  94. <IconButton
  95. name={ShapeType.Text}
  96. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  97. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  98. onClick={selectTextTool}
  99. isActive={activeTool === ShapeType.Text}
  100. >
  101. <TextIcon />
  102. </IconButton>
  103. </Tooltip>
  104. </Container>
  105. <Container>
  106. <Tooltip label="Lock Tool">
  107. <IconButton
  108. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  109. size={{ '@initial': 'small', '@sm': 'small', '@md': 'medium' }}
  110. onClick={selectToolLock}
  111. >
  112. {isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
  113. </IconButton>
  114. </Tooltip>
  115. {isPenLocked && (
  116. <Tooltip label="Unlock Pen">
  117. <IconButton
  118. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  119. size={{ '@initial': 'small', '@sm': 'small', '@md': 'medium' }}
  120. onClick={selectToolLock}
  121. >
  122. <Pencil2Icon />
  123. </IconButton>
  124. </Tooltip>
  125. )}
  126. </Container>
  127. </Flex>
  128. <UndoRedo />
  129. </OuterContainer>
  130. )
  131. }
  132. const OuterContainer = styled('div', {
  133. position: 'fixed',
  134. bottom: 44,
  135. left: 0,
  136. right: 0,
  137. padding: '0 8px 12px 8px',
  138. width: '100%',
  139. display: 'flex',
  140. alignItems: 'flex-end',
  141. justifyContent: 'center',
  142. flexWrap: 'wrap',
  143. gap: 16,
  144. zIndex: 200,
  145. })
  146. const Flex = styled('div', {
  147. display: 'flex',
  148. width: '100%',
  149. padding: '0 4px',
  150. justifyContent: 'space-between',
  151. alignItems: 'flex-end',
  152. variants: {
  153. size: {
  154. small: {
  155. width: 'auto',
  156. padding: '0',
  157. justifyContent: 'center',
  158. '& > *:nth-child(n+2)': {
  159. marginLeft: 16,
  160. },
  161. },
  162. },
  163. },
  164. })
  165. const Container = styled('div', {
  166. position: 'relative',
  167. backgroundColor: '$panel',
  168. borderRadius: '4px',
  169. overflow: 'hidden',
  170. border: '1px solid $panel',
  171. pointerEvents: 'all',
  172. userSelect: 'none',
  173. height: '100%',
  174. display: 'flex',
  175. padding: 4,
  176. boxShadow: '0px 2px 4px rgba(0,0,0,.12)',
  177. '& svg': {
  178. strokeWidth: 0,
  179. },
  180. })