Kaynağa Gözat

Improves layout, code panel, tweaks draw

main
Steve Ruiz 4 yıl önce
ebeveyn
işleme
475d04e3d0

+ 11
- 14
components/canvas/canvas.tsx Dosyayı Görüntüle

@@ -11,7 +11,7 @@ import Bounds from './bounds/bounding-box'
11 11
 import BoundsBg from './bounds/bounds-bg'
12 12
 import Selected from './selected'
13 13
 import Handles from './bounds/handles'
14
-import { isMobile } from 'utils/utils'
14
+import { isMobile, throttle } from 'utils/utils'
15 15
 
16 16
 export default function Canvas() {
17 17
   const rCanvas = useRef<SVGSVGElement>(null)
@@ -34,25 +34,13 @@ export default function Canvas() {
34 34
     } else {
35 35
       if (isMobile()) {
36 36
         state.send('TOUCHED_CANVAS')
37
-        // state.send('POINTED_CANVAS', inputs.touchStart(e, 'canvas'))
38
-        // e.preventDefault()
39
-        // e.stopPropagation()
40 37
       }
41 38
     }
42 39
   }, [])
43 40
 
44
-  // const handleTouchMove = useCallback((e: React.TouchEvent) => {
45
-  //   if (!inputs.canAccept(e.touches[0].identifier)) return
46
-  //   if (inputs.canAccept(e.touches[0].identifier)) {
47
-  //     state.send('MOVED_POINTER', inputs.touchMove(e))
48
-  //   }
49
-  // }, [])
50
-
51 41
   const handlePointerMove = useCallback((e: React.PointerEvent) => {
52 42
     if (!inputs.canAccept(e.pointerId)) return
53
-    if (inputs.canAccept(e.pointerId)) {
54
-      state.send('MOVED_POINTER', inputs.pointerMove(e))
55
-    }
43
+    throttledPointerMove(inputs.pointerMove(e))
56 44
   }, [])
57 45
 
58 46
   const handlePointerUp = useCallback((e: React.PointerEvent) => {
@@ -94,8 +82,17 @@ const MainSVG = styled('svg', {
94 82
   touchAction: 'none',
95 83
   zIndex: 100,
96 84
   backgroundColor: '$canvas',
85
+  pointerEvents: 'all',
97 86
 
98 87
   '& *': {
99 88
     userSelect: 'none',
100 89
   },
101 90
 })
91
+
92
+// const throttledPointerMove = throttle((payload: any) => {
93
+//   state.send('MOVED_POINTER', payload)
94
+// }, 16)
95
+
96
+const throttledPointerMove = (payload: any) => {
97
+  state.send('MOVED_POINTER', payload)
98
+}

+ 5
- 0
components/code-panel/code-editor.tsx Dosyayı Görüntüle

@@ -208,6 +208,11 @@ const EditorContainer = styled('div', {
208 208
   pointerEvents: 'all',
209 209
   userSelect: 'all',
210 210
 
211
+  '& > *': {
212
+    userSelect: 'all',
213
+    pointerEvents: 'all',
214
+  },
215
+
211 216
   '.editorLineError': {
212 217
     backgroundColor: '$lineError',
213 218
   },

+ 12
- 1
components/code-panel/code-panel.tsx Dosyayı Görüntüle

@@ -115,11 +115,18 @@ export default function CodePanel() {
115 115
   const { error } = local.data
116 116
 
117 117
   return (
118
-    <Panel.Root data-bp-desktop ref={rContainer} isOpen={isOpen}>
118
+    <Panel.Root
119
+      bp={{ '@initial': 'mobile', '@sm': 'small' }}
120
+      data-bp-desktop
121
+      ref={rContainer}
122
+      isOpen={isOpen}
123
+      variant="code"
124
+    >
119 125
       {isOpen ? (
120 126
         <Panel.Layout>
121 127
           <Panel.Header side="left">
122 128
             <IconButton
129
+              bp={{ '@initial': 'mobile', '@sm': 'small' }}
123 130
               size="small"
124 131
               onClick={() => state.send('TOGGLED_CODE_PANEL_OPEN')}
125 132
             >
@@ -129,6 +136,7 @@ export default function CodePanel() {
129 136
             <ButtonsGroup>
130 137
               <FontSizeButtons>
131 138
                 <IconButton
139
+                  bp={{ '@initial': 'mobile', '@sm': 'small' }}
132 140
                   size="small"
133 141
                   disabled={!local.isIn('editingCode')}
134 142
                   onClick={() => state.send('INCREASED_CODE_FONT_SIZE')}
@@ -144,12 +152,14 @@ export default function CodePanel() {
144 152
                 </IconButton>
145 153
               </FontSizeButtons>
146 154
               <IconButton
155
+                bp={{ '@initial': 'mobile', '@sm': 'small' }}
147 156
                 size="small"
148 157
                 onClick={() => local.send('TOGGLED_DOCS')}
149 158
               >
150 159
                 <Info />
151 160
               </IconButton>
152 161
               <IconButton
162
+                bp={{ '@initial': 'mobile', '@sm': 'small' }}
153 163
                 size="small"
154 164
                 disabled={!local.isIn('editingCode')}
155 165
                 onClick={() => local.send('SAVED_CODE')}
@@ -179,6 +189,7 @@ export default function CodePanel() {
179 189
         </Panel.Layout>
180 190
       ) : (
181 191
         <IconButton
192
+          bp={{ '@initial': 'mobile', '@sm': 'small' }}
182 193
           size="small"
183 194
           onClick={() => state.send('TOGGLED_CODE_PANEL_OPEN')}
184 195
         >

+ 2
- 0
components/controls-panel/controls-panel.tsx Dosyayı Görüntüle

@@ -22,6 +22,7 @@ export default function ControlPanel() {
22 22
         <Panel.Layout>
23 23
           <Panel.Header>
24 24
             <IconButton
25
+              bp={{ '@initial': 'mobile', '@sm': 'small' }}
25 26
               size="small"
26 27
               onClick={() => state.send('CLOSED_CODE_PANEL')}
27 28
             >
@@ -37,6 +38,7 @@ export default function ControlPanel() {
37 38
         </Panel.Layout>
38 39
       ) : (
39 40
         <IconButton
41
+          bp={{ '@initial': 'mobile', '@sm': 'small' }}
40 42
           size="small"
41 43
           onClick={() => state.send('OPENED_CODE_PANEL')}
42 44
         >

+ 19
- 35
components/editor.tsx Dosyayı Görüntüle

@@ -20,21 +20,26 @@ export default function Editor() {
20 20
 
21 21
   return (
22 22
     <Layout>
23
-      <Canvas />
23
+      <CodePanel />
24 24
       <PagePanel />
25
-      <LeftPanels>
25
+      <Spacer />
26
+      <StylePanel />
27
+      <Canvas />
28
+
29
+      {/* <LeftPanels>
26 30
         <CodePanel />
27 31
         {hasControls && <ControlsPanel />}
28
-      </LeftPanels>
29
-      <RightPanels>
30
-        <StylePanel />
31
-      </RightPanels>
32
+      </LeftPanels> */}
32 33
       <ToolsPanel />
33 34
       <StatusBar />
34 35
     </Layout>
35 36
   )
36 37
 }
37 38
 
39
+const Spacer = styled('div', {
40
+  flexGrow: 2,
41
+})
42
+
38 43
 const Layout = styled('main', {
39 44
   position: 'fixed',
40 45
   top: 0,
@@ -43,34 +48,13 @@ const Layout = styled('main', {
43 48
   right: 0,
44 49
   height: '100%',
45 50
   width: '100%',
46
-  display: 'grid',
47
-  gridTemplateRows: '1fr auto 144px',
48
-  gridTemplateColumns: 'minmax(0, 720px) 1fr auto',
49
-  gridTemplateAreas: `
50
-    "leftPanels main rightPanels"
51
-    "tools tools tools"
52
-    "statusbar statusbar statusbar"
53
-  `,
54
-})
55
-
56
-const LeftPanels = styled('div', {
57
-  display: 'grid',
58
-  gridArea: 'leftPanels',
59
-  gridTemplateRows: '1fr auto',
60
-  padding: 8,
61
-  gap: 8,
62
-  zIndex: 250,
63
-  pointerEvents: 'none',
64
-})
65
-
66
-const RightPanels = styled('div', {
67
-  gridArea: 'rightPanels',
68
-  padding: 8,
69
-  display: 'grid',
70
-  gridTemplateRows: 'auto',
71
-  height: 'fit-content',
72
-  justifyContent: 'flex-end',
73
-  gap: 8,
74
-  zIndex: 300,
51
+  padding: '8px 8px 0 8px',
52
+  zIndex: 200,
53
+  display: 'flex',
54
+  alignItems: 'flex-start',
55
+  justifyContent: 'flex-start',
75 56
   pointerEvents: 'none',
57
+  '& > *': {
58
+    PointerEvent: 'all',
59
+  },
76 60
 })

+ 100
- 99
components/page-panel/page-panel.tsx Dosyayı Görüntüle

@@ -29,89 +29,89 @@ export default function PagePanel() {
29 29
   )
30 30
 
31 31
   return (
32
-    <OuterContainer>
33
-      <DropdownMenu.Root
34
-        open={isOpen}
35
-        onOpenChange={(isOpen) => {
36
-          if (rIsOpen.current !== isOpen) {
37
-            setIsOpen(isOpen)
38
-          }
39
-        }}
40
-      >
41
-        <PanelRoot>
42
-          <DropdownMenu.Trigger as={RowButton}>
43
-            <span>{documentPages[currentPageId].name}</span>
44
-            <IconWrapper size="small">
45
-              <ChevronDownIcon />
46
-            </IconWrapper>
47
-          </DropdownMenu.Trigger>
48
-          <DropdownMenu.Content sideOffset={8}>
49
-            <PanelRoot>
50
-              <DropdownMenu.RadioGroup
51
-                as={Content}
52
-                value={currentPageId}
53
-                onValueChange={(id) => {
54
-                  setIsOpen(false)
55
-                  state.send('CHANGED_CURRENT_PAGE', { id })
56
-                }}
57
-              >
58
-                {sorted.map(({ id, name }) => (
59
-                  <ContextMenu.Root key={id}>
60
-                    <ContextMenu.Trigger>
61
-                      <StyledRadioItem key={id} value={id}>
62
-                        <span>{name}</span>
63
-                        <DropdownMenu.ItemIndicator
64
-                          as={IconWrapper}
65
-                          size="small"
66
-                        >
67
-                          <CheckIcon />
68
-                        </DropdownMenu.ItemIndicator>
69
-                      </StyledRadioItem>
70
-                    </ContextMenu.Trigger>
71
-                    <StyledContextMenuContent>
72
-                      <ContextMenu.Group>
73
-                        <StyledContextMenuItem
74
-                          onSelect={() => state.send('RENAMED_PAGE', { id })}
75
-                        >
76
-                          Rename
77
-                        </StyledContextMenuItem>
78
-                        <StyledContextMenuItem
79
-                          onSelect={() => {
80
-                            setIsOpen(false)
81
-                            state.send('DELETED_PAGE', { id })
82
-                          }}
83
-                        >
84
-                          Delete
85
-                        </StyledContextMenuItem>
86
-                      </ContextMenu.Group>
87
-                    </StyledContextMenuContent>
88
-                  </ContextMenu.Root>
89
-                ))}
90
-              </DropdownMenu.RadioGroup>
91
-              <DropdownMenu.Separator />
92
-              <RowButton
93
-                onClick={() => {
94
-                  setIsOpen(false)
95
-                  state.send('CREATED_PAGE')
96
-                }}
97
-              >
98
-                <span>Create Page</span>
99
-                <IconWrapper size="small">
100
-                  <PlusIcon />
101
-                </IconWrapper>
102
-              </RowButton>
103
-            </PanelRoot>
104
-          </DropdownMenu.Content>
105
-        </PanelRoot>
106
-      </DropdownMenu.Root>
107
-    </OuterContainer>
32
+    <DropdownMenu.Root
33
+      open={isOpen}
34
+      onOpenChange={(isOpen) => {
35
+        if (rIsOpen.current !== isOpen) {
36
+          setIsOpen(isOpen)
37
+        }
38
+      }}
39
+    >
40
+      <PanelRoot>
41
+        <DropdownMenu.Trigger
42
+          as={RowButton}
43
+          bp={{ '@initial': 'mobile', '@sm': 'small' }}
44
+          css={{ paddingRight: 12 }}
45
+        >
46
+          <span>{documentPages[currentPageId].name}</span>
47
+        </DropdownMenu.Trigger>
48
+        <DropdownMenu.Content sideOffset={8}>
49
+          <PanelRoot>
50
+            <DropdownMenu.RadioGroup
51
+              as={Content}
52
+              value={currentPageId}
53
+              onValueChange={(id) => {
54
+                setIsOpen(false)
55
+                state.send('CHANGED_CURRENT_PAGE', { id })
56
+              }}
57
+            >
58
+              {sorted.map(({ id, name }) => (
59
+                <ContextMenu.Root key={id}>
60
+                  <ContextMenu.Trigger>
61
+                    <StyledRadioItem
62
+                      key={id}
63
+                      value={id}
64
+                      bp={{ '@initial': 'mobile', '@sm': 'small' }}
65
+                    >
66
+                      <span>{name}</span>
67
+                      <DropdownMenu.ItemIndicator as={IconWrapper} size="small">
68
+                        <CheckIcon />
69
+                      </DropdownMenu.ItemIndicator>
70
+                    </StyledRadioItem>
71
+                  </ContextMenu.Trigger>
72
+                  <StyledContextMenuContent>
73
+                    <ContextMenu.Group>
74
+                      <StyledContextMenuItem
75
+                        onSelect={() => state.send('RENAMED_PAGE', { id })}
76
+                      >
77
+                        Rename
78
+                      </StyledContextMenuItem>
79
+                      <StyledContextMenuItem
80
+                        onSelect={() => {
81
+                          setIsOpen(false)
82
+                          state.send('DELETED_PAGE', { id })
83
+                        }}
84
+                      >
85
+                        Delete
86
+                      </StyledContextMenuItem>
87
+                    </ContextMenu.Group>
88
+                  </StyledContextMenuContent>
89
+                </ContextMenu.Root>
90
+              ))}
91
+            </DropdownMenu.RadioGroup>
92
+            <DropdownMenu.Separator />
93
+            <RowButton
94
+              bp={{ '@initial': 'mobile', '@sm': 'small' }}
95
+              onClick={() => {
96
+                setIsOpen(false)
97
+                state.send('CREATED_PAGE')
98
+              }}
99
+            >
100
+              <span>Create Page</span>
101
+              <IconWrapper size="small">
102
+                <PlusIcon />
103
+              </IconWrapper>
104
+            </RowButton>
105
+          </PanelRoot>
106
+        </DropdownMenu.Content>
107
+      </PanelRoot>
108
+    </DropdownMenu.Root>
108 109
   )
109 110
 }
110 111
 
111 112
 const PanelRoot = styled('div', {
112
-  minWidth: 1,
113
-  width: 184,
114
-  maxWidth: 184,
113
+  marginLeft: 8,
114
+  zIndex: 200,
115 115
   overflow: 'hidden',
116 116
   position: 'relative',
117 117
   display: 'flex',
@@ -128,11 +128,12 @@ const PanelRoot = styled('div', {
128 128
 
129 129
 const Content = styled(Panel.Content, {
130 130
   width: '100%',
131
+  minWidth: 128,
131 132
 })
132 133
 
133 134
 const StyledRadioItem = styled(DropdownMenu.RadioItem, {
134 135
   height: 32,
135
-  width: '100%',
136
+  width: 'auto',
136 137
   display: 'flex',
137 138
   alignItems: 'center',
138 139
   justifyContent: 'space-between',
@@ -143,26 +144,21 @@ const StyledRadioItem = styled(DropdownMenu.RadioItem, {
143 144
   fontFamily: '$ui',
144 145
   backgroundColor: 'transparent',
145 146
   outline: 'none',
146
-  '&:hover': {
147
-    backgroundColor: '$hover',
148
-  },
149
-  '&:focus-within': {
150
-    backgroundColor: '$hover',
147
+  variants: {
148
+    bp: {
149
+      mobile: {},
150
+      small: {
151
+        '&:hover': {
152
+          backgroundColor: '$hover',
153
+        },
154
+        '&:focus-within': {
155
+          backgroundColor: '$hover',
156
+        },
157
+      },
158
+    },
151 159
   },
152 160
 })
153 161
 
154
-const OuterContainer = styled('div', {
155
-  position: 'fixed',
156
-  top: 8,
157
-  left: 0,
158
-  display: 'flex',
159
-  alignItems: 'center',
160
-  justifyContent: 'center',
161
-  width: '100%',
162
-  zIndex: 200,
163
-  height: 44,
164
-})
165
-
166 162
 const StyledContextMenuContent = styled(ContextMenu.Content, {
167 163
   padding: '2px',
168 164
   borderRadius: '4px',
@@ -184,8 +180,13 @@ const StyledContextMenuItem = styled(ContextMenu.Item, {
184 180
   fontFamily: '$ui',
185 181
   backgroundColor: 'transparent',
186 182
   outline: 'none',
187
-  '&:hover': {
188
-    backgroundColor: '$hover',
183
+  bp: {
184
+    mobile: {},
185
+    small: {
186
+      '&:hover:not(:disabled)': {
187
+        backgroundColor: '$hover',
188
+      },
189
+    },
189 190
   },
190 191
 })
191 192
 

+ 36
- 0
components/panel.tsx Dosyayı Görüntüle

@@ -12,6 +12,13 @@ export const Root = styled('div', {
12 12
   boxShadow: '0px 2px 4px rgba(0,0,0,.2)',
13 13
 
14 14
   variants: {
15
+    bp: {
16
+      mobile: {},
17
+      small: {},
18
+    },
19
+    variant: {
20
+      code: {},
21
+    },
15 22
     isOpen: {
16 23
       true: {},
17 24
       false: {
@@ -21,6 +28,35 @@ export const Root = styled('div', {
21 28
       },
22 29
     },
23 30
   },
31
+  compoundVariants: [
32
+    {
33
+      isOpen: true,
34
+      variant: 'code',
35
+      css: {
36
+        position: 'absolute',
37
+        top: 8,
38
+        left: 8,
39
+        right: 8,
40
+        bottom: 48,
41
+        maxWidth: 720,
42
+        zIndex: 1000,
43
+      },
44
+    },
45
+    {
46
+      isOpen: true,
47
+      variant: 'code',
48
+      bp: 'small',
49
+      css: {
50
+        position: 'absolute',
51
+        top: 8,
52
+        left: 8,
53
+        right: 8,
54
+        bottom: 128,
55
+        maxWidth: 720,
56
+        zIndex: 1000,
57
+      },
58
+    },
59
+  ],
24 60
 })
25 61
 
26 62
 export const Layout = styled('div', {

+ 16
- 8
components/shared.tsx Dosyayı Görüntüle

@@ -23,15 +23,19 @@ export const IconButton = styled('button', {
23 23
     gridColumn: 1,
24 24
   },
25 25
 
26
-  '&:hover:not(:disabled)': {
27
-    backgroundColor: '$hover',
28
-  },
29
-
30 26
   '&:disabled': {
31 27
     opacity: '0.5',
32 28
   },
33 29
 
34 30
   variants: {
31
+    bp: {
32
+      mobile: {},
33
+      small: {
34
+        '&:hover:not(:disabled)': {
35
+          backgroundColor: '$hover',
36
+        },
37
+      },
38
+    },
35 39
     size: {
36 40
       small: {
37 41
         '& svg': {
@@ -80,10 +84,6 @@ export const RowButton = styled('button', {
80 84
   padding: '4px 6px 4px 12px',
81 85
   borderRadius: 4,
82 86
 
83
-  '&:hover': {
84
-    backgroundColor: '$hover',
85
-  },
86
-
87 87
   '& label': {
88 88
     fontWeight: '$1',
89 89
     margin: 0,
@@ -98,6 +98,14 @@ export const RowButton = styled('button', {
98 98
   },
99 99
 
100 100
   variants: {
101
+    bp: {
102
+      mobile: {},
103
+      small: {
104
+        '&:hover:not(:disabled)': {
105
+          backgroundColor: '$hover',
106
+        },
107
+      },
108
+    },
101 109
     size: {
102 110
       icon: {
103 111
         padding: '4px ',

+ 1
- 1
components/status-bar.tsx Dosyayı Görüntüle

@@ -32,6 +32,7 @@ const StatusBarContainer = styled('div', {
32 32
   bottom: 0,
33 33
   left: 0,
34 34
   width: '100%',
35
+  zIndex: 300,
35 36
   height: 40,
36 37
   userSelect: 'none',
37 38
   borderTop: '1px solid black',
@@ -43,7 +44,6 @@ const StatusBarContainer = styled('div', {
43 44
   gap: 8,
44 45
   fontSize: '$0',
45 46
   padding: '0 16px',
46
-  zIndex: 200,
47 47
 
48 48
   variants: {
49 49
     size: {

+ 30
- 4
components/style-panel/align-distribute.tsx Dosyayı Görüntüle

@@ -64,20 +64,32 @@ export default function AlignDistribute({
64 64
 }) {
65 65
   return (
66 66
     <Container>
67
-      <IconButton size="small" disabled={!hasTwoOrMore} onClick={alignLeft}>
67
+      <IconButton
68
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
69
+        size="small"
70
+        disabled={!hasTwoOrMore}
71
+        onClick={alignLeft}
72
+      >
68 73
         <AlignLeftIcon />
69 74
       </IconButton>
70 75
       <IconButton
76
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
71 77
         size="small"
72 78
         disabled={!hasTwoOrMore}
73 79
         onClick={alignCenterHorizontal}
74 80
       >
75 81
         <AlignCenterHorizontallyIcon />
76 82
       </IconButton>
77
-      <IconButton size="small" disabled={!hasTwoOrMore} onClick={alignRight}>
83
+      <IconButton
84
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
85
+        size="small"
86
+        disabled={!hasTwoOrMore}
87
+        onClick={alignRight}
88
+      >
78 89
         <AlignRightIcon />
79 90
       </IconButton>
80 91
       <IconButton
92
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
81 93
         size="small"
82 94
         disabled={!hasTwoOrMore}
83 95
         onClick={stretchHorizontally}
@@ -85,26 +97,39 @@ export default function AlignDistribute({
85 97
         <StretchHorizontallyIcon />
86 98
       </IconButton>
87 99
       <IconButton
100
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
88 101
         size="small"
89 102
         disabled={!hasThreeOrMore}
90 103
         onClick={distributeHorizontally}
91 104
       >
92 105
         <SpaceEvenlyHorizontallyIcon />
93 106
       </IconButton>
94
-      <IconButton size="small" disabled={!hasTwoOrMore} onClick={alignTop}>
107
+      <IconButton
108
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
109
+        size="small"
110
+        disabled={!hasTwoOrMore}
111
+        onClick={alignTop}
112
+      >
95 113
         <AlignTopIcon />
96 114
       </IconButton>
97 115
       <IconButton
116
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
98 117
         size="small"
99 118
         disabled={!hasTwoOrMore}
100 119
         onClick={alignCenterVertical}
101 120
       >
102 121
         <AlignCenterVerticallyIcon />
103 122
       </IconButton>
104
-      <IconButton size="small" disabled={!hasTwoOrMore} onClick={alignBottom}>
123
+      <IconButton
124
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
125
+        size="small"
126
+        disabled={!hasTwoOrMore}
127
+        onClick={alignBottom}
128
+      >
105 129
         <AlignBottomIcon />
106 130
       </IconButton>
107 131
       <IconButton
132
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
108 133
         size="small"
109 134
         disabled={!hasTwoOrMore}
110 135
         onClick={stretchVertically}
@@ -112,6 +137,7 @@ export default function AlignDistribute({
112 137
         <StretchVerticallyIcon />
113 138
       </IconButton>
114 139
       <IconButton
140
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
115 141
         size="small"
116 142
         disabled={!hasThreeOrMore}
117 143
         onClick={distributeVertically}

+ 1
- 1
components/style-panel/color-content.tsx Dosyayı Görüntüle

@@ -12,7 +12,7 @@ export default function ColorContent({
12 12
   onChange: (color: ColorStyle) => void
13 13
 }) {
14 14
   return (
15
-    <DropdownContent sideOffset={0} side="bottom">
15
+    <DropdownContent sideOffset={8} side="bottom">
16 16
       {Object.keys(strokes).map((color: ColorStyle) => (
17 17
         <DropdownMenu.DropdownMenuItem
18 18
           as={IconButton}

+ 4
- 1
components/style-panel/color-picker.tsx Dosyayı Görüntüle

@@ -13,7 +13,10 @@ interface Props {
13 13
 export default function ColorPicker({ color, onChange }: Props) {
14 14
   return (
15 15
     <DropdownMenu.Root>
16
-      <DropdownMenu.Trigger as={RowButton}>
16
+      <DropdownMenu.Trigger
17
+        as={RowButton}
18
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
19
+      >
17 20
         <label htmlFor="color">Color</label>
18 21
         <IconWrapper>
19 22
           <Square fill={strokes[color]} />

+ 1
- 0
components/style-panel/is-filled-picker.tsx Dosyayı Görüntüle

@@ -13,6 +13,7 @@ export default function IsFilledPicker({ isFilled, onChange }: Props) {
13 13
   return (
14 14
     <Checkbox.Root
15 15
       as={RowButton}
16
+      bp={{ '@initial': 'mobile', '@sm': 'small' }}
16 17
       checked={isFilled}
17 18
       onCheckedChange={(e: React.ChangeEvent<HTMLInputElement>) =>
18 19
         onChange(e.currentTarget.checked)

+ 4
- 1
components/style-panel/quick-color-select.tsx Dosyayı Görüntüle

@@ -11,7 +11,10 @@ export default function QuickColorSelect() {
11 11
 
12 12
   return (
13 13
     <DropdownMenu.Root>
14
-      <DropdownMenu.Trigger as={IconButton}>
14
+      <DropdownMenu.Trigger
15
+        as={IconButton}
16
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
17
+      >
15 18
         <Tooltip label="Color">
16 19
           <Square fill={strokes[color]} stroke={strokes[color]} />
17 20
         </Tooltip>

+ 5
- 2
components/style-panel/quick-dash-select.tsx Dosyayı Görüntüle

@@ -22,10 +22,13 @@ export default function QuickdashSelect() {
22 22
 
23 23
   return (
24 24
     <DropdownMenu.Root>
25
-      <DropdownMenu.Trigger as={IconButton}>
25
+      <DropdownMenu.Trigger
26
+        as={IconButton}
27
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
28
+      >
26 29
         <Tooltip label="Dash">{dashes[dash]}</Tooltip>
27 30
       </DropdownMenu.Trigger>
28
-      <DropdownContent direction="vertical">
31
+      <DropdownContent sideOffset={8} direction="vertical">
29 32
         <DashItem isActive={dash === DashStyle.Solid} dash={DashStyle.Solid} />
30 33
         <DashItem
31 34
           isActive={dash === DashStyle.Dashed}

+ 5
- 2
components/style-panel/quick-size-select.tsx Dosyayı Görüntüle

@@ -17,12 +17,15 @@ export default function QuickSizeSelect() {
17 17
 
18 18
   return (
19 19
     <DropdownMenu.Root>
20
-      <DropdownMenu.Trigger as={IconButton}>
20
+      <DropdownMenu.Trigger
21
+        as={IconButton}
22
+        bp={{ '@initial': 'mobile', '@sm': 'small' }}
23
+      >
21 24
         <Tooltip label="Size">
22 25
           <Circle size={sizes[size]} stroke="none" fill="currentColor" />
23 26
         </Tooltip>
24 27
       </DropdownMenu.Trigger>
25
-      <DropdownContent direction="vertical">
28
+      <DropdownContent sideOffset={8} direction="vertical">
26 29
         <SizeItem isActive={size === SizeStyle.Small} size={SizeStyle.Small} />
27 30
         <SizeItem
28 31
           isActive={size === SizeStyle.Medium}

+ 11
- 0
components/style-panel/style-panel.tsx Dosyayı Görüntüle

@@ -44,6 +44,7 @@ export default function StylePanel() {
44 44
           <QuickSizeSelect />
45 45
           <QuickdashSelect />
46 46
           <IconButton
47
+            bp={{ '@initial': 'mobile', '@sm': 'small' }}
47 48
             title="Style"
48 49
             size="small"
49 50
             onClick={() => state.send('TOGGLED_STYLE_PANEL_OPEN')}
@@ -92,6 +93,7 @@ function SelectedShapeStyles() {
92 93
       <Panel.Header side="right">
93 94
         <h3>Style</h3>
94 95
         <IconButton
96
+          bp={{ '@initial': 'mobile', '@sm': 'small' }}
95 97
           size="small"
96 98
           onClick={() => state.send('TOGGLED_STYLE_PANEL_OPEN')}
97 99
         >
@@ -117,6 +119,7 @@ function SelectedShapeStyles() {
117 119
         </Row>
118 120
         <ButtonsRow>
119 121
           <IconButton
122
+            bp={{ '@initial': 'mobile', '@sm': 'small' }}
120 123
             disabled={!hasSelection}
121 124
             size="small"
122 125
             onClick={() => state.send('DUPLICATED')}
@@ -137,6 +140,7 @@ function SelectedShapeStyles() {
137 140
           </IconButton>
138 141
 
139 142
           <IconButton
143
+            bp={{ '@initial': 'mobile', '@sm': 'small' }}
140 144
             disabled={!hasSelection}
141 145
             size="small"
142 146
             onClick={() => state.send('TOGGLED_SHAPE_HIDE')}
@@ -147,6 +151,7 @@ function SelectedShapeStyles() {
147 151
           </IconButton>
148 152
 
149 153
           <IconButton
154
+            bp={{ '@initial': 'mobile', '@sm': 'small' }}
150 155
             disabled={!hasSelection}
151 156
             size="small"
152 157
             onClick={() => state.send('TOGGLED_SHAPE_LOCK')}
@@ -157,6 +162,7 @@ function SelectedShapeStyles() {
157 162
           </IconButton>
158 163
 
159 164
           <IconButton
165
+            bp={{ '@initial': 'mobile', '@sm': 'small' }}
160 166
             disabled={!hasSelection}
161 167
             size="small"
162 168
             onClick={() => state.send('TOGGLED_SHAPE_ASPECT_LOCK')}
@@ -168,6 +174,7 @@ function SelectedShapeStyles() {
168 174
         </ButtonsRow>
169 175
         <ButtonsRow>
170 176
           <IconButton
177
+            bp={{ '@initial': 'mobile', '@sm': 'small' }}
171 178
             disabled={!hasSelection}
172 179
             size="small"
173 180
             onClick={() => state.send('MOVED', { type: MoveType.ToBack })}
@@ -178,6 +185,7 @@ function SelectedShapeStyles() {
178 185
           </IconButton>
179 186
 
180 187
           <IconButton
188
+            bp={{ '@initial': 'mobile', '@sm': 'small' }}
181 189
             disabled={!hasSelection}
182 190
             size="small"
183 191
             onClick={() => state.send('MOVED', { type: MoveType.Backward })}
@@ -188,6 +196,7 @@ function SelectedShapeStyles() {
188 196
           </IconButton>
189 197
 
190 198
           <IconButton
199
+            bp={{ '@initial': 'mobile', '@sm': 'small' }}
191 200
             disabled={!hasSelection}
192 201
             size="small"
193 202
             onClick={() => state.send('MOVED', { type: MoveType.Forward })}
@@ -198,6 +207,7 @@ function SelectedShapeStyles() {
198 207
           </IconButton>
199 208
 
200 209
           <IconButton
210
+            bp={{ '@initial': 'mobile', '@sm': 'small' }}
201 211
             disabled={!hasSelection}
202 212
             size="small"
203 213
             onClick={() => state.send('MOVED', { type: MoveType.ToFront })}
@@ -208,6 +218,7 @@ function SelectedShapeStyles() {
208 218
           </IconButton>
209 219
 
210 220
           <IconButton
221
+            bp={{ '@initial': 'mobile', '@sm': 'small' }}
211 222
             disabled={!hasSelection}
212 223
             size="small"
213 224
             onClick={() => state.send('DELETED')}

+ 20
- 0
components/tools-panel/tools-panel.tsx Dosyayı Görüntüle

@@ -10,6 +10,7 @@ import {
10 10
   Pencil2Icon,
11 11
   SewingPinIcon,
12 12
   SquareIcon,
13
+  TextIcon,
13 14
 } from '@radix-ui/react-icons'
14 15
 import { IconButton } from 'components/shared'
15 16
 import React from 'react'
@@ -27,6 +28,7 @@ const selectDrawTool = () => state.send('SELECTED_DRAW_TOOL')
27 28
 const selectEllipseTool = () => state.send('SELECTED_ELLIPSE_TOOL')
28 29
 const selectLineTool = () => state.send('SELECTED_LINE_TOOL')
29 30
 const selectPolylineTool = () => state.send('SELECTED_POLYLINE_TOOL')
31
+const selectTextTool = () => state.send('SELECTED_TEXT_TOOL')
30 32
 const selectRayTool = () => state.send('SELECTED_RAY_TOOL')
31 33
 const selectRectangleTool = () => state.send('SELECTED_RECTANGLE_TOOL')
32 34
 const selectSelectTool = () => state.send('SELECTED_SELECT_TOOL')
@@ -47,6 +49,7 @@ export default function ToolsPanel() {
47 49
           <Tooltip label="Select">
48 50
             <IconButton
49 51
               name="select"
52
+              bp={{ '@initial': 'mobile', '@sm': 'small' }}
50 53
               size={{ '@initial': 'small', '@sm': 'small', '@md': 'large' }}
51 54
               onClick={selectSelectTool}
52 55
               isActive={activeTool === 'select'}
@@ -59,6 +62,7 @@ export default function ToolsPanel() {
59 62
           <Tooltip label="Draw">
60 63
             <IconButton
61 64
               name={ShapeType.Draw}
65
+              bp={{ '@initial': 'mobile', '@sm': 'small' }}
62 66
               size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
63 67
               onClick={selectDrawTool}
64 68
               isActive={activeTool === ShapeType.Draw}
@@ -69,6 +73,7 @@ export default function ToolsPanel() {
69 73
           <Tooltip label="Rectangle">
70 74
             <IconButton
71 75
               name={ShapeType.Rectangle}
76
+              bp={{ '@initial': 'mobile', '@sm': 'small' }}
72 77
               size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
73 78
               onClick={selectRectangleTool}
74 79
               isActive={activeTool === ShapeType.Rectangle}
@@ -79,6 +84,7 @@ export default function ToolsPanel() {
79 84
           <Tooltip label="Ellipse">
80 85
             <IconButton
81 86
               name={ShapeType.Circle}
87
+              bp={{ '@initial': 'mobile', '@sm': 'small' }}
82 88
               size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
83 89
               onClick={selectEllipseTool}
84 90
               isActive={activeTool === ShapeType.Ellipse}
@@ -89,6 +95,7 @@ export default function ToolsPanel() {
89 95
           <Tooltip label="Arrow">
90 96
             <IconButton
91 97
               name={ShapeType.Arrow}
98
+              bp={{ '@initial': 'mobile', '@sm': 'small' }}
92 99
               size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
93 100
               onClick={selectArrowTool}
94 101
               isActive={activeTool === ShapeType.Arrow}
@@ -96,6 +103,17 @@ export default function ToolsPanel() {
96 103
               <ArrowTopRightIcon />
97 104
             </IconButton>
98 105
           </Tooltip>
106
+          <Tooltip label="Text">
107
+            <IconButton
108
+              name={ShapeType.Arrow}
109
+              bp={{ '@initial': 'mobile', '@sm': 'small' }}
110
+              size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
111
+              onClick={selectTextTool}
112
+              isActive={activeTool === ShapeType.Text}
113
+            >
114
+              <TextIcon />
115
+            </IconButton>
116
+          </Tooltip>
99 117
           {/* <IconButton
100 118
             name={ShapeType.Circle}
101 119
             size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
@@ -132,6 +150,7 @@ export default function ToolsPanel() {
132 150
         <Container>
133 151
           <Tooltip label="Lock Tool">
134 152
             <IconButton
153
+              bp={{ '@initial': 'mobile', '@sm': 'small' }}
135 154
               size={{ '@initial': 'small', '@sm': 'small', '@md': 'large' }}
136 155
               onClick={selectToolLock}
137 156
             >
@@ -141,6 +160,7 @@ export default function ToolsPanel() {
141 160
           {isPenLocked && (
142 161
             <Tooltip label="Unlock Pen">
143 162
               <IconButton
163
+                bp={{ '@initial': 'mobile', '@sm': 'small' }}
144 164
                 size={{ '@initial': 'small', '@sm': 'small', '@md': 'large' }}
145 165
                 onClick={selectToolLock}
146 166
               >

+ 4
- 4
lib/shape-utils/draw.tsx Dosyayı Görüntüle

@@ -164,10 +164,10 @@ function renderPath(shape: DrawShape, style: ShapeStyles) {
164 164
     shape.points,
165 165
     getSvgPathFromStroke(
166 166
       getStroke(shape.points, {
167
-        size: +styles.strokeWidth * 2,
168
-        thinning: 0.9,
169
-        end: { taper: 100 },
170
-        start: { taper: 40 },
167
+        size: 1 + +styles.strokeWidth * 2,
168
+        thinning: 0.83,
169
+        end: { taper: +styles.strokeWidth * 16 },
170
+        start: { taper: +styles.strokeWidth * 16 },
171 171
       })
172 172
     )
173 173
   )

+ 3
- 3
pages/_app.tsx Dosyayı Görüntüle

@@ -1,6 +1,6 @@
1
-import { AppProps } from "next/app"
2
-import { globalStyles } from "styles"
3
-import "styles/globals.css"
1
+import { AppProps } from 'next/app'
2
+import { globalStyles } from 'styles'
3
+import 'styles/globals.css'
4 4
 
5 5
 function MyApp({ Component, pageProps }: AppProps) {
6 6
   globalStyles()

+ 2
- 2
pages/_document.tsx Dosyayı Görüntüle

@@ -1,5 +1,5 @@
1
-import NextDocument, { Html, Head, Main, NextScript } from "next/document"
2
-import { dark, getCssString } from "styles"
1
+import NextDocument, { Html, Head, Main, NextScript } from 'next/document'
2
+import { dark, getCssString } from 'styles'
3 3
 
4 4
 class MyDocument extends NextDocument {
5 5
   static async getInitialProps(ctx) {

+ 8
- 4
pages/index.tsx Dosyayı Görüntüle

@@ -1,11 +1,15 @@
1 1
 // import Editor from "components/editor"
2
-import dynamic from "next/dynamic"
3
-const Editor = dynamic(() => import("components/editor"), { ssr: false })
2
+import Head from 'next/head'
3
+import dynamic from 'next/dynamic'
4
+const Editor = dynamic(() => import('components/editor'), { ssr: false })
4 5
 
5 6
 export default function Home() {
6 7
   return (
7
-    <div>
8
+    <>
9
+      <Head>
10
+        <title>tldraw</title>
11
+      </Head>
8 12
       <Editor />
9
-    </div>
13
+    </>
10 14
   )
11 15
 }

+ 8
- 0
types.ts Dosyayı Görüntüle

@@ -65,6 +65,7 @@ export enum ShapeType {
65 65
   Rectangle = 'rectangle',
66 66
   Draw = 'draw',
67 67
   Arrow = 'arrow',
68
+  Text = 'text',
68 69
 }
69 70
 
70 71
 // Consider:
@@ -183,6 +184,11 @@ export interface ArrowShape extends BaseShape {
183 184
   }
184 185
 }
185 186
 
187
+export interface TextShape extends BaseShape {
188
+  type: ShapeType.Text
189
+  text: string
190
+}
191
+
186 192
 export type MutableShape =
187 193
   | DotShape
188 194
   | CircleShape
@@ -193,6 +199,7 @@ export type MutableShape =
193 199
   | DrawShape
194 200
   | RectangleShape
195 201
   | ArrowShape
202
+  | TextShape
196 203
 
197 204
 export type Shape = Readonly<MutableShape>
198 205
 
@@ -206,6 +213,7 @@ export interface Shapes {
206 213
   [ShapeType.Draw]: Readonly<DrawShape>
207 214
   [ShapeType.Rectangle]: Readonly<RectangleShape>
208 215
   [ShapeType.Arrow]: Readonly<ArrowShape>
216
+  [ShapeType.Text]: Readonly<TextShape>
209 217
 }
210 218
 
211 219
 export type ShapeByType<T extends ShapeType> = Shapes[T]

Loading…
İptal
Kaydet