瀏覽代碼

Feat: Use tooltips instead of titles on whiteboard buttons (#7643)

 Move select and pan to main toolbar
 Create tooltip component
 Add tooltip support to button, toggle, toggle groups, select and color input
 Style shortcuts on primary tools
Konstantinos 2 年之前
父節點
當前提交
109b491042
共有 28 個文件被更改,包括 239 次插入128 次删除
  1. 1 8
      e2e-tests/whiteboards.spec.ts
  2. 1 0
      tldraw/apps/tldraw-logseq/package.json
  3. 4 11
      tldraw/apps/tldraw-logseq/src/components/ActionBar/ActionBar.tsx
  4. 10 2
      tldraw/apps/tldraw-logseq/src/components/Button/Button.tsx
  5. 10 13
      tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx
  6. 19 19
      tldraw/apps/tldraw-logseq/src/components/ContextMenu/ContextMenu.tsx
  7. 12 10
      tldraw/apps/tldraw-logseq/src/components/GeometryTools/GeometryTools.tsx
  8. 13 12
      tldraw/apps/tldraw-logseq/src/components/PrimaryTools/PrimaryTools.tsx
  9. 18 4
      tldraw/apps/tldraw-logseq/src/components/ToolButton/ToolButton.tsx
  10. 31 0
      tldraw/apps/tldraw-logseq/src/components/Tooltip/Tooltip.tsx
  11. 1 0
      tldraw/apps/tldraw-logseq/src/components/Tooltip/index.ts
  12. 12 1
      tldraw/apps/tldraw-logseq/src/components/inputs/ColorInput.tsx
  13. 13 9
      tldraw/apps/tldraw-logseq/src/components/inputs/SelectInput.tsx
  14. 10 7
      tldraw/apps/tldraw-logseq/src/components/inputs/ShapeLinksInput.tsx
  15. 13 8
      tldraw/apps/tldraw-logseq/src/components/inputs/ToggleGroupInput.tsx
  16. 11 7
      tldraw/apps/tldraw-logseq/src/components/inputs/ToggleInput.tsx
  17. 1 1
      tldraw/apps/tldraw-logseq/src/lib/tools/BoxTool.tsx
  18. 1 1
      tldraw/apps/tldraw-logseq/src/lib/tools/EraseTool.tsx
  19. 1 1
      tldraw/apps/tldraw-logseq/src/lib/tools/HighlighterTool.tsx
  20. 1 1
      tldraw/apps/tldraw-logseq/src/lib/tools/LineTool.tsx
  21. 1 1
      tldraw/apps/tldraw-logseq/src/lib/tools/LogseqPortalTool/LogseqPortalTool.tsx
  22. 1 1
      tldraw/apps/tldraw-logseq/src/lib/tools/PencilTool.tsx
  23. 1 1
      tldraw/apps/tldraw-logseq/src/lib/tools/TextTool.tsx
  24. 31 7
      tldraw/apps/tldraw-logseq/src/styles.css
  25. 1 1
      tldraw/demo/src/App.jsx
  26. 1 1
      tldraw/packages/core/src/lib/tools/TLMoveTool/TLMoveTool.ts
  27. 1 1
      tldraw/packages/core/src/lib/tools/TLSelectTool/TLSelectTool.tsx
  28. 19 0
      tldraw/yarn.lock

+ 1 - 8
e2e-tests/whiteboards.spec.ts

@@ -80,18 +80,11 @@ test('set whiteboard title', async ({ page }) => {
   )
 })
 
-test('select rectangle tool', async ({ page }) => {
-  await page.keyboard.press('7')
-  await expect(
-    page.locator('.tl-geometry-tools-pane-anchor [title*="Rectangle"]')
-  ).toHaveAttribute('data-selected', 'true')
-})
-
 test('draw a rectangle', async ({ page }) => {
   const canvas = await page.waitForSelector('.logseq-tldraw')
   const bounds = (await canvas.boundingBox())!
 
-  await page.keyboard.press('7')
+  await page.keyboard.press('r')
 
   await page.mouse.move(bounds.x + 5, bounds.y + 5)
   await page.mouse.down()

+ 1 - 0
tldraw/apps/tldraw-logseq/package.json

@@ -19,6 +19,7 @@
     "@radix-ui/react-switch": "^1.0.1",
     "@radix-ui/react-toggle": "^1.0.1",
     "@radix-ui/react-toggle-group": "^1.0.1",
+    "@radix-ui/react-tooltip": "^1.0.2",
     "@tldraw/core": "2.0.0-alpha.1",
     "@tldraw/react": "2.0.0-alpha.1",
     "@tldraw/vec": "2.0.0-alpha.1",

+ 4 - 11
tldraw/apps/tldraw-logseq/src/components/ActionBar/ActionBar.tsx

@@ -31,26 +31,19 @@ export const ActionBar = observer(function ActionBar(): JSX.Element {
   return (
     <div className="tl-action-bar">
       <div className="tl-toolbar tl-history-bar">
-        <ToolButton title="Select" id="select" icon="select-cursor" />
-        <ToolButton
-          title="Move"
-          id="move"
-          icon={app.isIn('move.panning') ? 'hand-grab' : 'hand-stop'}
-        />
-        <Separator.Root className="tl-toolbar-separator" orientation="vertical" />
-        <Button title="Undo" onClick={undo}>
+        <Button tooltip="Undo" onClick={undo}>
           <TablerIcon name="arrow-back-up" />
         </Button>
-        <Button title="Redo" onClick={redo}>
+        <Button tooltip="Redo" onClick={redo}>
           <TablerIcon name="arrow-forward-up" />
         </Button>
       </div>
 
       <div className="tl-toolbar tl-zoom-bar">
-        <Button title="Zoom in" onClick={zoomIn} id="tl-zoom-in">
+        <Button tooltip="Zoom in" onClick={zoomIn} id="tl-zoom-in">
           <TablerIcon name="plus" />
         </Button>
-        <Button title="Zoom out" onClick={zoomOut} id="tl-zoom-out">
+        <Button tooltip="Zoom out" onClick={zoomOut} id="tl-zoom-out">
           <TablerIcon name="minus" />
         </Button>
         <Separator.Root className="tl-toolbar-separator" orientation="vertical" />

+ 10 - 2
tldraw/apps/tldraw-logseq/src/components/Button/Button.tsx

@@ -1,7 +1,15 @@
+import { Tooltip } from '../Tooltip'
+import type { Side } from '@radix-ui/react-popper'
 export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
   children: React.ReactNode
+  tooltip?: React.ReactNode
+  tooltipSide?: Side
 }
 
-export function Button({ className, ...rest }: ButtonProps) {
-  return <button className={'tl-button ' + (className ?? '')} {...rest} />
+export function Button({ className, tooltip, tooltipSide, ...rest }: ButtonProps) {
+  return (
+    <Tooltip content={tooltip} side={tooltipSide}>
+      <button className={'tl-button ' + (className ?? '')} {...rest} />
+    </Tooltip>
+  )
 }

+ 10 - 13
tldraw/apps/tldraw-logseq/src/components/ContextBar/contextBarActionFactory.tsx

@@ -15,7 +15,6 @@ import type {
   TextShape,
   YouTubeShape,
 } from '../../lib'
-import { LogseqContext } from '../../lib/logseq-context'
 import { Button } from '../Button'
 import { TablerIcon } from '../icons'
 import { ColorInput } from '../inputs/ColorInput'
@@ -96,7 +95,7 @@ const EditAction = observer(() => {
   return (
     <Button
       type="button"
-      title="Edit"
+      tooltip="Edit"
       onClick={() => {
         app.api.editShape(shape)
         if (shape.props.type === 'logseq-portal') {
@@ -161,10 +160,12 @@ const LogseqPortalViewModeAction = observer(() => {
     {
       value: '1',
       icon: 'object-compact',
+      tooltip: 'Collapse',
     },
     {
       value: '0',
       icon: 'object-expanded',
+      tooltip: 'Expand',
     },
   ]
   return (
@@ -214,7 +215,7 @@ const ScaleLevelAction = observer(() => {
   ]
   return (
     <SelectInput
-      title="Scale Level"
+      tooltip="Scale Level"
       options={sizeOptions}
       value={scaleLevel}
       onValueChange={v => {
@@ -242,7 +243,7 @@ const IFrameSourceAction = observer(() => {
 
   return (
     <span className="flex gap-3">
-      <Button title="Reload" type="button" onClick={handleReload}>
+      <Button tooltip="Reload" type="button" onClick={handleReload}>
         <TablerIcon name="refresh" />
       </Button>
       <TextInput
@@ -251,7 +252,7 @@ const IFrameSourceAction = observer(() => {
         value={`${shape.props.url}`}
         onChange={handleChange}
       />
-      <Button title="Open website url" type="button" onClick={() => window.open(shape.props.url)}>
+      <Button tooltip="Open website url" type="button" onClick={() => window.open(shape.props.url)}>
         <TablerIcon name="external-link" />
       </Button>
     </span>
@@ -275,7 +276,7 @@ const YoutubeLinkAction = observer(() => {
         onChange={handleChange}
       />
       <Button
-        title="Open YouTube Link"
+        tooltip="Open YouTube Link"
         type="button"
         onClick={() => window.logseq?.api?.open_external_link?.(shape.props.url)}
       >
@@ -299,12 +300,7 @@ const NoFillAction = observer(() => {
   const noFill = shapes.every(s => s.props.noFill)
 
   return (
-    <ToggleInput
-      title="Fill Toggle"
-      className="tl-button"
-      pressed={noFill}
-      onPressedChange={handleChange}
-    >
+    <ToggleInput title="Fill" className="tl-button" pressed={noFill} onPressedChange={handleChange}>
       <TablerIcon name={noFill ? 'droplet-off' : 'droplet'} />
     </ToggleInput>
   )
@@ -334,7 +330,6 @@ const SwatchAction = observer(() => {
   const color = shapes[0].props.noFill ? shapes[0].props.stroke : shapes[0].props.fill
   return (
     <ColorInput
-      title="Color Picker"
       popoverSide="top"
       color={color}
       opacity={shapes[0].props.opacity}
@@ -354,10 +349,12 @@ const StrokeTypeAction = observer(() => {
     {
       value: 'line',
       icon: 'circle',
+      tooltip: 'Solid',
     },
     {
       value: 'dashed',
       icon: 'circle-dashed',
+      tooltip: 'Dashed',
     },
   ]
 

+ 19 - 19
tldraw/apps/tldraw-logseq/src/components/ContextMenu/ContextMenu.tsx

@@ -58,26 +58,26 @@ export const ContextMenu = observer(function ContextMenu({
               <ReactContextMenu.Item>
                 <div className="tl-menu-button-row pb-0">
                   <Button
-                    title="Align left"
+                    tooltip="Align left"
                     onClick={() => runAndTransition(() => app.align(AlignType.Left))}
                   >
                     <TablerIcon name="layout-align-left" />
                   </Button>
                   <Button
-                    title="Align center horizontally"
+                    tooltip="Align center horizontally"
                     onClick={() => runAndTransition(() => app.align(AlignType.CenterHorizontal))}
                   >
                     <TablerIcon name="layout-align-center" />
                   </Button>
                   <Button
-                    title="Align right"
+                    tooltip="Align right"
                     onClick={() => runAndTransition(() => app.align(AlignType.Right))}
                   >
                     <TablerIcon name="layout-align-right" />
                   </Button>
                   <Separator.Root className="tl-toolbar-separator" orientation="vertical" />
                   <Button
-                    title="Distribute horizontally"
+                    tooltip="Distribute horizontally"
                     onClick={() =>
                       runAndTransition(() => app.distribute(DistributeType.Horizontal))
                     }
@@ -87,26 +87,26 @@ export const ContextMenu = observer(function ContextMenu({
                 </div>
                 <div className="tl-menu-button-row pt-0">
                   <Button
-                    title="Align top"
+                    tooltip="Align top"
                     onClick={() => runAndTransition(() => app.align(AlignType.Top))}
                   >
                     <TablerIcon name="layout-align-top" />
                   </Button>
                   <Button
-                    title="Align center vertically"
+                    tooltip="Align center vertically"
                     onClick={() => runAndTransition(() => app.align(AlignType.CenterVertical))}
                   >
                     <TablerIcon name="layout-align-middle" />
                   </Button>
                   <Button
-                    title="Align bottom"
+                    tooltip="Align bottom"
                     onClick={() => runAndTransition(() => app.align(AlignType.Bottom))}
                   >
                     <TablerIcon name="layout-align-bottom" />
                   </Button>
                   <Separator.Root className="tl-toolbar-separator" orientation="vertical" />
                   <Button
-                    title="Distribute vertically"
+                    tooltip="Distribute vertically"
                     onClick={() => runAndTransition(() => app.distribute(DistributeType.Vertical))}
                   >
                     <TablerIcon name="layout-distribute-horizontal" />
@@ -165,17 +165,17 @@ export const ContextMenu = observer(function ContextMenu({
             </div>
           </ReactContextMenu.Item>
           {app.selectedShapes?.size === 1 && (
-          <ReactContextMenu.Item
-            className="tl-menu-item"
-            onClick={() => runAndTransition(() => app.paste(undefined, true))}
-          >
-            Paste as link
-            <div className="tl-menu-right-slot">
-              <span className="keyboard-shortcut">
-                <code>{MOD_KEY}</code> <code>⇧</code> <code>V</code>
-              </span>
-            </div>
-          </ReactContextMenu.Item>
+            <ReactContextMenu.Item
+              className="tl-menu-item"
+              onClick={() => runAndTransition(() => app.paste(undefined, true))}
+            >
+              Paste as link
+              <div className="tl-menu-right-slot">
+                <span className="keyboard-shortcut">
+                  <code>{MOD_KEY}</code> <code>⇧</code> <code>V</code>
+                </span>
+              </div>
+            </ReactContextMenu.Item>
           )}
           <ReactContextMenu.Separator className="menu-separator" />
           <ReactContextMenu.Item

+ 12 - 10
tldraw/apps/tldraw-logseq/src/components/GeometryTools/GeometryTools.tsx

@@ -10,17 +10,17 @@ export const GeometryTools = observer(function GeometryTools() {
     {
       id: 'box',
       icon: 'square',
-      title: 'Rectangle',
+      tooltip: 'Rectangle',
     },
     {
       id: 'ellipse',
       icon: 'circle',
-      title: 'Circle',
+      tooltip: 'Circle',
     },
     {
       id: 'polygon',
       icon: 'triangle',
-      title: 'Triangle',
+      tooltip: 'Triangle',
     },
   ]
 
@@ -37,13 +37,15 @@ export const GeometryTools = observer(function GeometryTools() {
 
   return (
     <Popover.Root>
-      <Popover.Trigger className="tl-geometry-tools-pane-anchor">
-        <ToolButton {...geometries.find(geo => geo.id === activeGeomId)!} />
-        <TablerIcon
-          data-selected={geometries.some(geo => geo.id === app.selectedTool.id)}
-          className="tl-popover-indicator"
-          name="chevron-down-left"
-        />
+      <Popover.Trigger asChild>
+        <div className="tl-geometry-tools-pane-anchor">
+          <ToolButton {...geometries.find(geo => geo.id === activeGeomId)!} />
+          <TablerIcon
+            data-selected={geometries.some(geo => geo.id === app.selectedTool.id)}
+            className="tl-popover-indicator"
+            name="chevron-down-left"
+          />
+        </div>
       </Popover.Trigger>
 
       <Popover.Content className="tl-popover-content" side="left" sideOffset={15}>

+ 13 - 12
tldraw/apps/tldraw-logseq/src/components/PrimaryTools/PrimaryTools.tsx

@@ -16,25 +16,26 @@ export const PrimaryTools = observer(function PrimaryTools() {
   return (
     <div className="tl-primary-tools">
       <div className="tl-toolbar tl-tools-floating-panel">
-        <ToolButton title="Add block or page" id="logseq-portal" icon="circle-plus" />
+        <ToolButton tooltip="Select" id="select" icon="select-cursor" />
+        <ToolButton
+          tooltip="Move"
+          id="move"
+          icon={app.isIn('move.panning') ? 'hand-grab' : 'hand-stop'}
+        />
         <Separator.Root className="tl-toolbar-separator" orientation="horizontal" />
-        <ToolButton title="Draw" id="pencil" icon="ballpen" />
-        <ToolButton title="Highlight" id="highlighter" icon="highlight" />
-        <ToolButton title="Eraser" id="erase" icon="eraser" />
-        <ToolButton title="Connector" id="line" icon="connector" />
-        <ToolButton title="Text" id="text" icon="text" />
+        <ToolButton tooltip="Add block or page" id="logseq-portal" icon="circle-plus" />
+        <ToolButton tooltip="Draw" id="pencil" icon="ballpen" />
+        <ToolButton tooltip="Highlight" id="highlighter" icon="highlight" />
+        <ToolButton tooltip="Eraser" id="erase" icon="eraser" />
+        <ToolButton tooltip="Connector" id="line" icon="connector" />
+        <ToolButton tooltip="Text" id="text" icon="text" />
         <GeometryTools />
         <Separator.Root
           className="tl-toolbar-separator"
           orientation="horizontal"
           style={{ margin: '0 -4px' }}
         />
-        <ColorInput
-          title="Color Picker"
-          popoverSide="left"
-          color={app.settings.color}
-          setColor={handleSetColor}
-        />
+        <ColorInput popoverSide="left" color={app.settings.color} setColor={handleSetColor} />
       </div>
     </div>
   )

+ 18 - 4
tldraw/apps/tldraw-logseq/src/components/ToolButton/ToolButton.tsx

@@ -8,9 +8,10 @@ import { TablerIcon } from '../icons'
 export interface ToolButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
   id: string
   icon: string | React.ReactNode
+  tooltip: string
 }
 
-export const ToolButton = observer(({ id, icon, title, ...props }: ToolButtonProps) => {
+export const ToolButton = observer(({ id, icon, tooltip, ...props }: ToolButtonProps) => {
   const app = useApp()
 
   const handleToolClick = React.useCallback(
@@ -24,13 +25,26 @@ export const ToolButton = observer(({ id, icon, title, ...props }: ToolButtonPro
   // Tool must exist
   const Tool = [...app.Tools, TLSelectTool, TLMoveTool]?.find(T => T.id === id)
 
-  const shortcut = ((Tool as any)['shortcut'] as string[])?.join(', ').toUpperCase()
+  const shortcuts = (Tool as any)['shortcut']
+
+  const tooltipContent = shortcuts ? (
+    <>
+      {tooltip}
+      <span className="ml-2 keyboard-shortcut">
+        {shortcuts
+          .map((shortcut: string, idx: number) => <code key={idx}>{shortcut.toUpperCase()}</code>)
+          .reduce((prev: React.ReactNode, curr: React.ReactNode) => [prev, ' | ', curr])}
+      </span>
+    </>
+  ) : (
+    { tooltip }
+  )
 
-  const titleWithShortcut = shortcut ? `${title} - ${shortcut}` : title
   return (
     <Button
       {...props}
-      title={titleWithShortcut}
+      tooltipSide="left"
+      tooltip={tooltipContent}
       data-tool={id}
       data-selected={id === app.selectedTool.id}
       onClick={handleToolClick}

+ 31 - 0
tldraw/apps/tldraw-logseq/src/components/Tooltip/Tooltip.tsx

@@ -0,0 +1,31 @@
+import * as ReactTooltip from '@radix-ui/react-tooltip'
+import type { Side } from '@radix-ui/react-popper'
+export interface TooltipProps extends ReactTooltip.TooltipContentProps {
+  children: React.ReactNode
+  side?: Side
+  sideOffset?: number
+  content?: React.ReactNode
+}
+
+export function Tooltip({ side, content, sideOffset = 10, ...rest }: TooltipProps) {
+  return content ? (
+    <ReactTooltip.Provider delayDuration={300}>
+      <ReactTooltip.Root>
+        <ReactTooltip.Trigger asChild>{rest.children}</ReactTooltip.Trigger>
+        <ReactTooltip.Portal>
+          <ReactTooltip.Content
+            className="tl-tooltip-content"
+            sideOffset={sideOffset}
+            side={side}
+            {...rest}
+          >
+            {content}
+            <ReactTooltip.Arrow className="tl-tooltip-arrow" />
+          </ReactTooltip.Content>
+        </ReactTooltip.Portal>
+      </ReactTooltip.Root>
+    </ReactTooltip.Provider>
+  ) : (
+    <>{rest.children}</>
+  )
+}

+ 1 - 0
tldraw/apps/tldraw-logseq/src/components/Tooltip/index.ts

@@ -0,0 +1 @@
+export * from './Tooltip'

+ 12 - 1
tldraw/apps/tldraw-logseq/src/components/inputs/ColorInput.tsx

@@ -3,6 +3,7 @@ import * as Slider from '@radix-ui/react-slider'
 import { Color } from '@tldraw/core'
 import { TablerIcon } from '../icons'
 import { PopoverButton } from '../PopoverButton'
+import { Tooltip } from '../Tooltip'
 
 interface ColorInputProps extends React.HTMLAttributes<HTMLButtonElement> {
   color?: string
@@ -33,7 +34,17 @@ export function ColorInput({
   }
 
   return (
-    <PopoverButton {...rest} border arrow side={popoverSide} label={renderColor(color)}>
+    <PopoverButton
+      {...rest}
+      border
+      arrow
+      side={popoverSide}
+      label={
+        <Tooltip content={'Color'} side={popoverSide} sideOffset={14}>
+          {renderColor(color)}
+        </Tooltip>
+      }
+    >
       <div className="p-1">
         <div className={'tl-color-palette'}>
           {Object.values(Color).map(value => (

+ 13 - 9
tldraw/apps/tldraw-logseq/src/components/inputs/SelectInput.tsx

@@ -1,6 +1,7 @@
 import * as React from 'react'
 import * as Select from '@radix-ui/react-select'
 import { TablerIcon } from '../icons'
+import { Tooltip } from '../Tooltip'
 
 export interface SelectOption {
   value: string
@@ -10,10 +11,11 @@ export interface SelectOption {
 interface SelectInputProps extends React.HTMLAttributes<HTMLElement> {
   options: SelectOption[]
   value: string
+  tooltip?: React.ReactNode
   onValueChange: (value: string) => void
 }
 
-export function SelectInput({ options, value, onValueChange, ...rest }: SelectInputProps) {
+export function SelectInput({ options, tooltip, value, onValueChange, ...rest }: SelectInputProps) {
   const [isOpen, setIsOpen] = React.useState(false)
   return (
     <div {...rest} className="tl-select-input">
@@ -23,14 +25,16 @@ export function SelectInput({ options, value, onValueChange, ...rest }: SelectIn
         value={value}
         onValueChange={onValueChange}
       >
-        <Select.Trigger className="tl-select-input-trigger">
-          <div className="tl-select-input-trigger-value">
-            <Select.Value />
-          </div>
-          <Select.Icon style={{ lineHeight: 1 }}>
-            <TablerIcon name={isOpen ? 'chevron-up' : 'chevron-down'} />
-          </Select.Icon>
-        </Select.Trigger>
+        <Tooltip content={tooltip}>
+          <Select.Trigger className="tl-select-input-trigger">
+            <div className="tl-select-input-trigger-value">
+              <Select.Value />
+            </div>
+            <Select.Icon style={{ lineHeight: 1 }}>
+              <TablerIcon name={isOpen ? 'chevron-up' : 'chevron-down'} />
+            </Select.Icon>
+          </Select.Trigger>
+        </Tooltip>
 
         <Select.Portal className="tl-select-input-portal">
           <Select.Content className="tl-select-input-content">

+ 10 - 7
tldraw/apps/tldraw-logseq/src/components/inputs/ShapeLinksInput.tsx

@@ -6,6 +6,7 @@ import { observer } from 'mobx-react-lite'
 import { LogseqContext } from '../../lib/logseq-context'
 import { BlockLink } from '../BlockLink'
 import { Button } from '../Button'
+import { Tooltip } from '../Tooltip'
 import { TablerIcon } from '../icons'
 import { PopoverButton } from '../PopoverButton'
 import { LogseqQuickSearch } from '../QuickSearch'
@@ -38,11 +39,11 @@ function ShapeLinkItem({
         <BlockLink id={id} showReferenceContent={showContent} />
       </div>
       <div className="flex-1" />
-      <Button title="Open Page" type="button" onClick={() => handlers?.redirectToPage(id)}>
+      <Button tooltip="Open Page" type="button" onClick={() => handlers?.redirectToPage(id)}>
         <TablerIcon name="open-as-page" />
       </Button>
       <Button
-        title="Open Page in Right Sidebar"
+        tooltip="Open Page in Right Sidebar"
         type="button"
         onClick={() => handlers?.sidebarAddBlock(id, type === 'B' ? 'block' : 'page')}
       >
@@ -51,7 +52,7 @@ function ShapeLinkItem({
       {onRemove && (
         <Button
           className="tl-shape-links-panel-item-remove-button"
-          title="Remove link"
+          tooltip="Remove link"
           type="button"
           onClick={onRemove}
         >
@@ -89,10 +90,12 @@ export const ShapeLinksInput = observer(function ShapeLinksInput({
       align="start"
       alignOffset={-6}
       label={
-        <div className="flex gap-1 relative items-center justify-center px-1">
-          <TablerIcon name={noOfLinks > 0 ? 'link' : 'add-link'} />
-          {noOfLinks > 0 && <div className="tl-shape-links-count">{noOfLinks}</div>}
-        </div>
+        <Tooltip content={'Link'} sideOffset={14}>
+          <div className="flex gap-1 relative items-center justify-center px-1">
+            <TablerIcon name={noOfLinks > 0 ? 'link' : 'add-link'} />
+            {noOfLinks > 0 && <div className="tl-shape-links-count">{noOfLinks}</div>}
+          </div>
+        </Tooltip>
       }
     >
       <div className="color-level rounded-lg" data-show-reference-panel={showReferencePanel}>

+ 13 - 8
tldraw/apps/tldraw-logseq/src/components/inputs/ToggleGroupInput.tsx

@@ -1,9 +1,11 @@
 import * as ToggleGroup from '@radix-ui/react-toggle-group'
 import { TablerIcon } from '../icons'
+import { Tooltip } from '../Tooltip'
 
 export interface ToggleGroupInputOption {
   value: string
   icon: string
+  tooltip?: string
 }
 
 interface ToggleGroupInputProps extends React.HTMLAttributes<HTMLElement> {
@@ -28,14 +30,17 @@ export function ToggleGroupInput({ options, value, onValueChange }: ToggleGroupI
     >
       {options.map(option => {
         return (
-          <ToggleGroup.Item
-            className="tl-toggle-group-input-button"
-            key={option.value}
-            value={option.value}
-            disabled={option.value === value}
-          >
-            <TablerIcon name={option.icon} />
-          </ToggleGroup.Item>
+          <Tooltip content={option.tooltip} key={option.value}>
+            <div className='inline-block'>
+              <ToggleGroup.Item
+                className="tl-toggle-group-input-button"
+                value={option.value}
+                disabled={option.value === value}
+              >
+                <TablerIcon name={option.icon} />
+              </ToggleGroup.Item>
+            </div>
+          </Tooltip>
         )
       })}
     </ToggleGroup.Root>

+ 11 - 7
tldraw/apps/tldraw-logseq/src/components/inputs/ToggleInput.tsx

@@ -1,3 +1,4 @@
+import { Tooltip } from '../Tooltip'
 import * as Toggle from '@radix-ui/react-toggle'
 
 interface ToggleInputProps extends React.HTMLAttributes<HTMLElement> {
@@ -11,15 +12,18 @@ export function ToggleInput({
   pressed,
   onPressedChange,
   className,
+  title,
   ...rest
 }: ToggleInputProps) {
   return (
-    <Toggle.Root
-      {...rest}
-      data-toggle={toggle}
-      className={'tl-toggle-input' + (className ? ' ' + className : '')}
-      pressed={pressed}
-      onPressedChange={onPressedChange}
-    ></Toggle.Root>
+    <Tooltip content={title}>
+      <Toggle.Root
+        {...rest}
+        data-toggle={toggle}
+        className={'tl-toggle-input' + (className ? ' ' + className : '')}
+        pressed={pressed}
+        onPressedChange={onPressedChange}
+      ></Toggle.Root>
+    </Tooltip>
   )
 }

+ 1 - 1
tldraw/apps/tldraw-logseq/src/lib/tools/BoxTool.tsx

@@ -4,6 +4,6 @@ import { BoxShape, type Shape } from '../shapes'
 
 export class BoxTool extends TLBoxTool<BoxShape, Shape, TLReactEventMap> {
   static id = 'box'
-  static shortcut = ['7', 'r']
+  static shortcut = ['9', 'r']
   Shape = BoxShape
 }

+ 1 - 1
tldraw/apps/tldraw-logseq/src/lib/tools/EraseTool.tsx

@@ -4,5 +4,5 @@ import type { Shape } from '../shapes'
 
 export class NuEraseTool extends TLEraseTool<Shape, TLReactEventMap> {
   static id = 'erase'
-  static shortcut = ['4', 'e']
+  static shortcut = ['6', 'e']
 }

+ 1 - 1
tldraw/apps/tldraw-logseq/src/lib/tools/HighlighterTool.tsx

@@ -4,7 +4,7 @@ import { HighlighterShape, type Shape } from '../shapes'
 
 export class HighlighterTool extends TLDrawTool<HighlighterShape, Shape, TLReactEventMap> {
   static id = 'highlighter'
-  static shortcut = ['3', 'h']
+  static shortcut = ['5', 'h']
   Shape = HighlighterShape
   simplify = true
   simplifyTolerance = 0.618

+ 1 - 1
tldraw/apps/tldraw-logseq/src/lib/tools/LineTool.tsx

@@ -5,6 +5,6 @@ import { LineShape, type Shape } from '../shapes'
 // @ts-expect-error maybe later
 export class LineTool extends TLLineTool<LineShape, Shape, TLReactEventMap> {
   static id = 'line'
-  static shortcut = ['5', 'c']
+  static shortcut = ['7', 'c']
   Shape = LineShape
 }

+ 1 - 1
tldraw/apps/tldraw-logseq/src/lib/tools/LogseqPortalTool/LogseqPortalTool.tsx

@@ -9,7 +9,7 @@ export class LogseqPortalTool extends TLTool<
   TLApp<Shape, TLReactEventMap>
 > {
   static id = 'logseq-portal'
-  static shortcut = ['1']
+  static shortcut = ['3']
   static states = [IdleState, CreatingState]
   static initial = 'idle'
 

+ 1 - 1
tldraw/apps/tldraw-logseq/src/lib/tools/PencilTool.tsx

@@ -4,7 +4,7 @@ import { PencilShape, type Shape } from '../shapes'
 
 export class PencilTool extends TLDrawTool<PencilShape, Shape, TLReactEventMap> {
   static id = 'pencil'
-  static shortcut = ['2', 'd']
+  static shortcut = ['4', 'd']
   Shape = PencilShape
   simplify = false
 }

+ 1 - 1
tldraw/apps/tldraw-logseq/src/lib/tools/TextTool.tsx

@@ -4,6 +4,6 @@ import { TextShape, type Shape } from '../shapes'
 
 export class TextTool extends TLTextTool<TextShape, Shape, TLReactEventMap> {
   static id = 'text'
-  static shortcut = ['6', 't']
+  static shortcut = ['8', 't']
   Shape = TextShape
 }

+ 31 - 7
tldraw/apps/tldraw-logseq/src/styles.css

@@ -808,13 +808,6 @@ button.tl-select-input-trigger {
   @apply p-0 rounded-none;
 }
 
-.logseq-img-icon {
-  width: 20px;
-  height: 20px;
-  border-radius: 4px;
-  box-shadow: 0 8px 12px 0 #85c8c81a, 0 4px 32px 0 #85c8c880;
-}
-
 .tl-target-not-found {
   @apply flex h-full w-full items-center justify-center;
 }
@@ -1162,3 +1155,34 @@ button.tl-shape-links-panel-item-remove-button {
     @apply inline;
   }
 }
+
+.tl-tooltip-content {
+  border-radius: 4px;
+  padding: 10px 15px;
+  font-size: 15px;
+  line-height: 1;
+  color: var(--ls-secondary-text-color);
+  background-color: var(--ls-secondary-background-color);
+  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
+  user-select: none;
+  animation-duration: 700ms;
+  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
+  will-change: transform, opacity;
+
+  &[data-state='delayed-open'] {
+    animation-name: fadeIn;
+  }
+}
+
+.tl-tooltip-arrow {
+  fill: var(--ls-secondary-background-color);
+}
+
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}

+ 1 - 1
tldraw/demo/src/App.jsx

@@ -213,7 +213,7 @@ export default function App() {
   }, [])
 
   return (
-    <div className={`h-screen w-screen`} id="main-content-container">
+    <div className={`h-screen w-screen z-0 relative`}>
       <ThemeSwitcher />
       <PreviewButton model={model} />
       <TldrawApp

+ 1 - 1
tldraw/packages/core/src/lib/tools/TLMoveTool/TLMoveTool.ts

@@ -10,7 +10,7 @@ export class TLMoveTool<
   R extends TLApp<S, K> = TLApp<S, K>
 > extends TLTool<S, K, R> {
   static id = 'move'
-  static shortcut = ['m', '9']
+  static shortcut = ['2', 'm']
 
   static states = [IdleState, IdleHoldState, PanningState, PinchingState]
 

+ 1 - 1
tldraw/packages/core/src/lib/tools/TLSelectTool/TLSelectTool.tsx

@@ -33,7 +33,7 @@ export class TLSelectTool<
 
   static initial = 'idle'
 
-  static shortcut = ['s', '8']
+  static shortcut = ['1', 's']
 
   static states = [
     IdleState,

+ 19 - 0
tldraw/yarn.lock

@@ -872,6 +872,25 @@
     "@radix-ui/react-primitive" "1.0.1"
     "@radix-ui/react-use-controllable-state" "1.0.0"
 
+"@radix-ui/react-tooltip@^1.0.2":
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.0.2.tgz#8e10b075767f785bf013146fdc954ac6885efda3"
+  integrity sha512-11gUlok2rv5mu+KBtxniOKKNKjqC/uTbgFHWoQdbF46vMV+zjDaBvCtVDK9+MTddlpmlisGPGvvojX7Qm0yr+g==
+  dependencies:
+    "@babel/runtime" "^7.13.10"
+    "@radix-ui/primitive" "1.0.0"
+    "@radix-ui/react-compose-refs" "1.0.0"
+    "@radix-ui/react-context" "1.0.0"
+    "@radix-ui/react-dismissable-layer" "1.0.2"
+    "@radix-ui/react-id" "1.0.0"
+    "@radix-ui/react-popper" "1.0.1"
+    "@radix-ui/react-portal" "1.0.1"
+    "@radix-ui/react-presence" "1.0.0"
+    "@radix-ui/react-primitive" "1.0.1"
+    "@radix-ui/react-slot" "1.0.1"
+    "@radix-ui/react-use-controllable-state" "1.0.0"
+    "@radix-ui/react-visually-hidden" "1.0.1"
+
 "@radix-ui/[email protected]":
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.0.tgz#9e7b8b6b4946fe3cbe8f748c82a2cce54e7b6a90"