tldraw 3.16.0-canary.9e000da8269c → 3.16.0-canary.a962044c3d3b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/dist-cjs/index.d.ts +57 -3
  2. package/dist-cjs/index.js +10 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js +10 -1
  5. package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js.map +2 -2
  6. package/dist-cjs/lib/ui/components/AccessibilityMenu.js +35 -0
  7. package/dist-cjs/lib/ui/components/AccessibilityMenu.js.map +7 -0
  8. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +2 -1
  9. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
  10. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js +3 -2
  11. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js.map +2 -2
  12. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +3 -3
  13. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js.map +2 -2
  14. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +1 -1
  15. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
  16. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +2 -1
  17. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  18. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js +3 -2
  19. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js.map +2 -2
  20. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +2 -2
  21. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js.map +2 -2
  22. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +2 -0
  23. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  24. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +171 -140
  25. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  26. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js +3 -3
  27. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +2 -2
  28. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js +26 -25
  29. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +3 -3
  30. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +6 -5
  31. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +2 -2
  32. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +9 -10
  33. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +2 -2
  34. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +5 -4
  35. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  36. package/dist-cjs/lib/ui/components/menu-items.js +6 -0
  37. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  38. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js +4 -15
  39. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +3 -3
  40. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  41. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  42. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +3 -2
  43. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +3 -3
  44. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +18 -7
  45. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  46. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +267 -0
  47. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +7 -0
  48. package/dist-cjs/lib/ui/components/primitives/layout.js +51 -0
  49. package/dist-cjs/lib/ui/components/primitives/layout.js.map +7 -0
  50. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +0 -1
  51. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  52. package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js +3 -2
  53. package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js.map +2 -2
  54. package/dist-cjs/lib/ui/context/actions.js +15 -0
  55. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  56. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  57. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  58. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +3 -0
  59. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  60. package/dist-cjs/lib/ui/version.js +3 -3
  61. package/dist-cjs/lib/ui/version.js.map +1 -1
  62. package/dist-esm/index.d.mts +57 -3
  63. package/dist-esm/index.mjs +17 -1
  64. package/dist-esm/index.mjs.map +2 -2
  65. package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs +10 -1
  66. package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs.map +2 -2
  67. package/dist-esm/lib/ui/components/AccessibilityMenu.mjs +19 -0
  68. package/dist-esm/lib/ui/components/AccessibilityMenu.mjs.map +7 -0
  69. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +2 -1
  70. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
  71. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs +3 -2
  72. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs.map +2 -2
  73. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +3 -5
  74. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs.map +2 -2
  75. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +1 -1
  76. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
  77. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -1
  78. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  79. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs +3 -2
  80. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs.map +2 -2
  81. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs +2 -2
  82. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs.map +2 -2
  83. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +3 -1
  84. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  85. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +171 -140
  86. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  87. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs +3 -3
  88. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +2 -2
  89. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs +26 -25
  90. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +2 -2
  91. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +6 -5
  92. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
  93. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +9 -10
  94. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +2 -2
  95. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +5 -4
  96. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  97. package/dist-esm/lib/ui/components/menu-items.mjs +6 -0
  98. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  99. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +4 -5
  100. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +2 -2
  101. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +1 -1
  102. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  103. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +3 -2
  104. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
  105. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +18 -7
  106. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  107. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +237 -0
  108. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +7 -0
  109. package/dist-esm/lib/ui/components/primitives/layout.mjs +21 -0
  110. package/dist-esm/lib/ui/components/primitives/layout.mjs.map +7 -0
  111. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +0 -1
  112. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  113. package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs +3 -2
  114. package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs.map +2 -2
  115. package/dist-esm/lib/ui/context/actions.mjs +15 -0
  116. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  117. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  118. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +3 -0
  119. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  120. package/dist-esm/lib/ui/version.mjs +3 -3
  121. package/dist-esm/lib/ui/version.mjs.map +1 -1
  122. package/package.json +3 -3
  123. package/src/index.ts +13 -0
  124. package/src/lib/shapes/shared/usePrefersReducedMotion.tsx +11 -1
  125. package/src/lib/ui/components/AccessibilityMenu.tsx +20 -0
  126. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +2 -1
  127. package/src/lib/ui/components/DefaultMenuPanel.tsx +4 -3
  128. package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +4 -4
  129. package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +1 -1
  130. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +3 -2
  131. package/src/lib/ui/components/SharePanel/PeopleMenuItem.tsx +4 -3
  132. package/src/lib/ui/components/SharePanel/UserPresenceColorPicker.tsx +3 -3
  133. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +3 -1
  134. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +146 -107
  135. package/src/lib/ui/components/StylePanel/DoubleDropdownPicker.tsx +3 -3
  136. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +7 -6
  137. package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +7 -6
  138. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +10 -11
  139. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +14 -11
  140. package/src/lib/ui/components/menu-items.tsx +8 -0
  141. package/src/lib/ui/components/primitives/TldrawUiButtonPicker.tsx +38 -36
  142. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +1 -1
  143. package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +4 -2
  144. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +34 -12
  145. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +313 -0
  146. package/src/lib/ui/components/primitives/layout.tsx +33 -0
  147. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +0 -1
  148. package/src/lib/ui/context/TldrawUiContextProvider.tsx +23 -20
  149. package/src/lib/ui/context/actions.tsx +15 -0
  150. package/src/lib/ui/context/events.tsx +1 -0
  151. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +3 -0
  152. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +3 -0
  153. package/src/lib/ui/version.ts +3 -3
  154. package/src/lib/ui.css +80 -69
  155. package/tldraw.css +82 -69
@@ -35,6 +35,11 @@ import { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiTo
35
35
  import { DoubleDropdownPicker } from './DoubleDropdownPicker'
36
36
  import { DropdownPicker } from './DropdownPicker'
37
37
 
38
+ // Local component for style panel subheadings
39
+ function StylePanelSubheading({ children }: { children: React.ReactNode }) {
40
+ return <h3 className="tlui-style-panel__subheading">{children}</h3>
41
+ }
42
+
38
43
  /** @public */
39
44
  export interface TLUiStylePanelContentProps {
40
45
  styles: ReturnType<typeof useRelevantStyles>
@@ -115,6 +120,7 @@ export function CommonStylePickerSet({ styles, theme }: ThemeStylePickerSetProps
115
120
  const editor = useEditor()
116
121
 
117
122
  const onHistoryMark = useCallback((id: string) => editor.markHistoryStoppingPoint(id), [editor])
123
+ const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
118
124
 
119
125
  const handleValueChange = useStyleChangeCallback()
120
126
 
@@ -129,70 +135,90 @@ export function CommonStylePickerSet({ styles, theme }: ThemeStylePickerSetProps
129
135
  <>
130
136
  <div className="tlui-style-panel__section__common" data-testid="style.panel">
131
137
  {color === undefined ? null : (
132
- <TldrawUiToolbar label={msg('style-panel.color')}>
133
- <TldrawUiButtonPicker
134
- title={msg('style-panel.color')}
135
- uiType="color"
136
- style={DefaultColorStyle}
137
- items={STYLES.color}
138
- value={color}
139
- onValueChange={handleValueChange}
140
- theme={theme}
141
- onHistoryMark={onHistoryMark}
142
- />
143
- </TldrawUiToolbar>
144
- )}
145
- <OpacitySlider />
146
- </div>
147
- {showPickers && (
148
- <div className="tlui-style-panel__section">
149
- {fill === undefined ? null : (
150
- <TldrawUiToolbar label={msg('style-panel.fill')}>
138
+ <>
139
+ {showUiLabels && (
140
+ <StylePanelSubheading>{msg('style-panel.color')}</StylePanelSubheading>
141
+ )}
142
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.color')}>
151
143
  <TldrawUiButtonPicker
152
- title={msg('style-panel.fill')}
153
- uiType="fill"
154
- style={DefaultFillStyle}
155
- items={STYLES.fill}
156
- value={fill}
144
+ title={msg('style-panel.color')}
145
+ uiType="color"
146
+ style={DefaultColorStyle}
147
+ items={STYLES.color}
148
+ value={color}
157
149
  onValueChange={handleValueChange}
158
150
  theme={theme}
159
151
  onHistoryMark={onHistoryMark}
160
152
  />
161
153
  </TldrawUiToolbar>
154
+ </>
155
+ )}
156
+ <OpacitySlider />
157
+ </div>
158
+ {showPickers && (
159
+ <div className="tlui-style-panel__section">
160
+ {fill === undefined ? null : (
161
+ <>
162
+ {showUiLabels && (
163
+ <StylePanelSubheading>{msg('style-panel.fill')}</StylePanelSubheading>
164
+ )}
165
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.fill')}>
166
+ <TldrawUiButtonPicker
167
+ title={msg('style-panel.fill')}
168
+ uiType="fill"
169
+ style={DefaultFillStyle}
170
+ items={STYLES.fill}
171
+ value={fill}
172
+ onValueChange={handleValueChange}
173
+ theme={theme}
174
+ onHistoryMark={onHistoryMark}
175
+ />
176
+ </TldrawUiToolbar>
177
+ </>
162
178
  )}
163
179
  {dash === undefined ? null : (
164
- <TldrawUiToolbar label={msg('style-panel.dash')}>
165
- <TldrawUiButtonPicker
166
- title={msg('style-panel.dash')}
167
- uiType="dash"
168
- style={DefaultDashStyle}
169
- items={STYLES.dash}
170
- value={dash}
171
- onValueChange={handleValueChange}
172
- theme={theme}
173
- onHistoryMark={onHistoryMark}
174
- />
175
- </TldrawUiToolbar>
180
+ <>
181
+ {showUiLabels && (
182
+ <StylePanelSubheading>{msg('style-panel.dash')}</StylePanelSubheading>
183
+ )}
184
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.dash')}>
185
+ <TldrawUiButtonPicker
186
+ title={msg('style-panel.dash')}
187
+ uiType="dash"
188
+ style={DefaultDashStyle}
189
+ items={STYLES.dash}
190
+ value={dash}
191
+ onValueChange={handleValueChange}
192
+ theme={theme}
193
+ onHistoryMark={onHistoryMark}
194
+ />
195
+ </TldrawUiToolbar>
196
+ </>
176
197
  )}
177
198
  {size === undefined ? null : (
178
- <TldrawUiToolbar label={msg('style-panel.size')}>
179
- <TldrawUiButtonPicker
180
- title={msg('style-panel.size')}
181
- uiType="size"
182
- style={DefaultSizeStyle}
183
- items={STYLES.size}
184
- value={size}
185
- onValueChange={(style, value) => {
186
- handleValueChange(style, value)
187
- const selectedShapeIds = editor.getSelectedShapeIds()
188
- if (selectedShapeIds.length > 0) {
189
- kickoutOccludedShapes(editor, selectedShapeIds)
190
- }
191
- }}
192
- theme={theme}
193
- onHistoryMark={onHistoryMark}
194
- />
195
- </TldrawUiToolbar>
199
+ <>
200
+ {showUiLabels && (
201
+ <StylePanelSubheading>{msg('style-panel.size')}</StylePanelSubheading>
202
+ )}
203
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.size')}>
204
+ <TldrawUiButtonPicker
205
+ title={msg('style-panel.size')}
206
+ uiType="size"
207
+ style={DefaultSizeStyle}
208
+ items={STYLES.size}
209
+ value={size}
210
+ onValueChange={(style, value) => {
211
+ handleValueChange(style, value)
212
+ const selectedShapeIds = editor.getSelectedShapeIds()
213
+ if (selectedShapeIds.length > 0) {
214
+ kickoutOccludedShapes(editor, selectedShapeIds)
215
+ }
216
+ }}
217
+ theme={theme}
218
+ onHistoryMark={onHistoryMark}
219
+ />
220
+ </TldrawUiToolbar>
221
+ </>
196
222
  )}
197
223
  </div>
198
224
  )}
@@ -207,6 +233,8 @@ export function TextStylePickerSet({ theme, styles }: ThemeStylePickerSetProps)
207
233
 
208
234
  const editor = useEditor()
209
235
  const onHistoryMark = useCallback((id: string) => editor.markHistoryStoppingPoint(id), [editor])
236
+ const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
237
+ const labelStr = showUiLabels && msg('style-panel.font')
210
238
 
211
239
  const font = styles.get(DefaultFontStyle)
212
240
  const textAlign = styles.get(DefaultTextAlignStyle)
@@ -219,33 +247,37 @@ export function TextStylePickerSet({ theme, styles }: ThemeStylePickerSetProps)
219
247
  return (
220
248
  <div className="tlui-style-panel__section">
221
249
  {font === undefined ? null : (
222
- <TldrawUiToolbar label={msg('style-panel.font')}>
223
- <TldrawUiButtonPicker
224
- title={msg('style-panel.font')}
225
- uiType="font"
226
- style={DefaultFontStyle}
227
- items={STYLES.font}
228
- value={font}
229
- onValueChange={handleValueChange}
230
- theme={theme}
231
- onHistoryMark={onHistoryMark}
232
- />
233
- </TldrawUiToolbar>
250
+ <>
251
+ {labelStr && <StylePanelSubheading>{labelStr}</StylePanelSubheading>}
252
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.font')}>
253
+ <TldrawUiButtonPicker
254
+ title={msg('style-panel.font')}
255
+ uiType="font"
256
+ style={DefaultFontStyle}
257
+ items={STYLES.font}
258
+ value={font}
259
+ onValueChange={handleValueChange}
260
+ theme={theme}
261
+ onHistoryMark={onHistoryMark}
262
+ />
263
+ </TldrawUiToolbar>
264
+ </>
234
265
  )}
235
266
 
236
267
  {textAlign === undefined ? null : (
237
- <TldrawUiToolbar label={msg('style-panel.align')} className="tlui-style-panel__row">
238
- <TldrawUiButtonPicker
239
- title={msg('style-panel.align')}
240
- uiType="align"
241
- style={DefaultTextAlignStyle}
242
- items={STYLES.textAlign}
243
- value={textAlign}
244
- onValueChange={handleValueChange}
245
- theme={theme}
246
- onHistoryMark={onHistoryMark}
247
- />
248
- <div className="tlui-style-panel__row__extra-button">
268
+ <>
269
+ {showUiLabels && <StylePanelSubheading>{msg('style-panel.align')}</StylePanelSubheading>}
270
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.align')}>
271
+ <TldrawUiButtonPicker
272
+ title={msg('style-panel.align')}
273
+ uiType="align"
274
+ style={DefaultTextAlignStyle}
275
+ items={STYLES.textAlign}
276
+ value={textAlign}
277
+ onValueChange={handleValueChange}
278
+ theme={theme}
279
+ onHistoryMark={onHistoryMark}
280
+ />
249
281
  <TldrawUiToolbarButton
250
282
  type="icon"
251
283
  title={msg('style-panel.vertical-align')}
@@ -254,23 +286,26 @@ export function TextStylePickerSet({ theme, styles }: ThemeStylePickerSetProps)
254
286
  >
255
287
  <TldrawUiButtonIcon icon="vertical-align-middle" />
256
288
  </TldrawUiToolbarButton>
257
- </div>
258
- </TldrawUiToolbar>
289
+ </TldrawUiToolbar>
290
+ </>
259
291
  )}
260
292
 
261
293
  {labelAlign === undefined ? null : (
262
- <TldrawUiToolbar label={msg('style-panel.label-align')} className="tlui-style-panel__row">
263
- <TldrawUiButtonPicker
264
- title={msg('style-panel.label-align')}
265
- uiType="align"
266
- style={DefaultHorizontalAlignStyle}
267
- items={STYLES.horizontalAlign}
268
- value={labelAlign}
269
- onValueChange={handleValueChange}
270
- theme={theme}
271
- onHistoryMark={onHistoryMark}
272
- />
273
- <div className="tlui-style-panel__row__extra-button">
294
+ <>
295
+ {showUiLabels && (
296
+ <StylePanelSubheading>{msg('style-panel.label-align')}</StylePanelSubheading>
297
+ )}
298
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.label-align')}>
299
+ <TldrawUiButtonPicker
300
+ title={msg('style-panel.label-align')}
301
+ uiType="align"
302
+ style={DefaultHorizontalAlignStyle}
303
+ items={STYLES.horizontalAlign}
304
+ value={labelAlign}
305
+ onValueChange={handleValueChange}
306
+ theme={theme}
307
+ onHistoryMark={onHistoryMark}
308
+ />
274
309
  {verticalLabelAlign === undefined ? (
275
310
  <TldrawUiToolbarButton
276
311
  type="icon"
@@ -292,8 +327,8 @@ export function TextStylePickerSet({ theme, styles }: ThemeStylePickerSetProps)
292
327
  onValueChange={handleValueChange}
293
328
  />
294
329
  )}
295
- </div>
296
- </TldrawUiToolbar>
330
+ </TldrawUiToolbar>
331
+ </>
297
332
  )}
298
333
  </div>
299
334
  )
@@ -309,7 +344,7 @@ export function GeoStylePickerSet({ styles }: StylePickerSetProps) {
309
344
  }
310
345
 
311
346
  return (
312
- <TldrawUiToolbar label={msg('style-panel.geo')}>
347
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.geo')}>
313
348
  <DropdownPicker
314
349
  id="geo"
315
350
  type="menu"
@@ -335,7 +370,7 @@ export function SplineStylePickerSet({ styles }: StylePickerSetProps) {
335
370
  }
336
371
 
337
372
  return (
338
- <TldrawUiToolbar label={msg('style-panel.spline')}>
373
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.spline')}>
339
374
  <DropdownPicker
340
375
  id="spline"
341
376
  type="menu"
@@ -361,7 +396,7 @@ export function ArrowStylePickerSet({ styles }: StylePickerSetProps) {
361
396
  }
362
397
 
363
398
  return (
364
- <TldrawUiToolbar label={msg('style-panel.arrow-kind')}>
399
+ <TldrawUiToolbar orientation="horizontal" label={msg('style-panel.arrow-kind')}>
365
400
  <DropdownPicker
366
401
  id="arrow-kind"
367
402
  type="menu"
@@ -410,6 +445,7 @@ export function OpacitySlider() {
410
445
  const editor = useEditor()
411
446
 
412
447
  const onHistoryMark = useCallback((id: string) => editor.markHistoryStoppingPoint(id), [editor])
448
+ const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
413
449
 
414
450
  const opacity = useValue('opacity', () => editor.getSharedOpacity(), [editor])
415
451
  const trackEvent = useUiEvents()
@@ -443,15 +479,18 @@ export function OpacitySlider() {
443
479
  )
444
480
 
445
481
  return (
446
- <TldrawUiSlider
447
- data-testid="style.opacity"
448
- value={opacityIndex >= 0 ? opacityIndex : tldrawSupportedOpacities.length - 1}
449
- label={opacity.type === 'mixed' ? 'style-panel.mixed' : `opacity-style.${opacity.value}`}
450
- onValueChange={handleOpacityValueChange}
451
- steps={tldrawSupportedOpacities.length - 1}
452
- title={msg('style-panel.opacity')}
453
- onHistoryMark={onHistoryMark}
454
- ariaValueModifier={25}
455
- />
482
+ <>
483
+ {showUiLabels && <StylePanelSubheading>{msg('style-panel.opacity')}</StylePanelSubheading>}
484
+ <TldrawUiSlider
485
+ data-testid="style.opacity"
486
+ value={opacityIndex >= 0 ? opacityIndex : tldrawSupportedOpacities.length - 1}
487
+ label={opacity.type === 'mixed' ? 'style-panel.mixed' : `opacity-style.${opacity.value}`}
488
+ onValueChange={handleOpacityValueChange}
489
+ steps={tldrawSupportedOpacities.length - 1}
490
+ title={msg('style-panel.opacity')}
491
+ onHistoryMark={onHistoryMark}
492
+ ariaValueModifier={25}
493
+ />
494
+ </>
456
495
  )
457
496
  }
@@ -68,7 +68,7 @@ function DoubleDropdownPickerInner<T extends string>({
68
68
  <div title={msg(label)} className="tlui-style-panel__double-select-picker-label">
69
69
  {msg(label)}
70
70
  </div>
71
- <TldrawUiToolbar label={msg(label)} className="tlui-buttons__horizontal">
71
+ <TldrawUiToolbar orientation="horizontal" label={msg(label)}>
72
72
  <TldrawUiPopover id={idA} open={isOpenA} onOpenChange={setIsOpenA}>
73
73
  <TldrawUiPopoverTrigger>
74
74
  <TldrawUiToolbarButton
@@ -86,7 +86,7 @@ function DoubleDropdownPickerInner<T extends string>({
86
86
  </TldrawUiToolbarButton>
87
87
  </TldrawUiPopoverTrigger>
88
88
  <TldrawUiPopoverContent side="left" align="center" sideOffset={80} alignOffset={0}>
89
- <TldrawUiToolbar label={msg(labelA)} className="tlui-buttons__grid">
89
+ <TldrawUiToolbar orientation="grid" label={msg(labelA)}>
90
90
  <TldrawUiMenuContextProvider type="icons" sourceId="style-panel">
91
91
  {itemsA.map((item) => {
92
92
  return (
@@ -126,7 +126,7 @@ function DoubleDropdownPickerInner<T extends string>({
126
126
  </TldrawUiToolbarButton>
127
127
  </TldrawUiPopoverTrigger>
128
128
  <TldrawUiPopoverContent side="left" align="center" sideOffset={116} alignOffset={0}>
129
- <TldrawUiToolbar label={msg(labelB)} className="tlui-buttons__grid">
129
+ <TldrawUiToolbar orientation="grid" label={msg(labelB)}>
130
130
  <TldrawUiMenuContextProvider type="icons" sourceId="style-panel">
131
131
  {itemsB.map((item) => {
132
132
  return (
@@ -1,5 +1,4 @@
1
1
  import { SharedStyle, StyleProp, tlmenus, useEditor } from '@tldraw/editor'
2
- import classNames from 'classnames'
3
2
  import * as React from 'react'
4
3
  import { StyleValuesForUi } from '../../../styles'
5
4
  import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
@@ -57,7 +56,12 @@ function DropdownPickerInner<T extends string>({
57
56
 
58
57
  const popoverId = `style panel ${id}`
59
58
  return (
60
- <TldrawUiPopover id={popoverId} open={isOpen} onOpenChange={setIsOpen}>
59
+ <TldrawUiPopover
60
+ id={popoverId}
61
+ open={isOpen}
62
+ onOpenChange={setIsOpen}
63
+ className="tlui-style-panel__dropdown-picker"
64
+ >
61
65
  <TldrawUiPopoverTrigger>
62
66
  <TldrawUiToolbarButton
63
67
  type={type}
@@ -70,10 +74,7 @@ function DropdownPickerInner<T extends string>({
70
74
  </TldrawUiToolbarButton>
71
75
  </TldrawUiPopoverTrigger>
72
76
  <TldrawUiPopoverContent side="left" align="center">
73
- <TldrawUiToolbar
74
- label={labelStr}
75
- className={classNames('tlui-buttons__grid', `tlui-buttons__${stylePanelType}`)}
76
- >
77
+ <TldrawUiToolbar orientation="grid" label={labelStr}>
77
78
  <TldrawUiMenuContextProvider type="icons" sourceId="style-panel">
78
79
  {items.map((item) => {
79
80
  return (
@@ -44,14 +44,15 @@ export const DefaultToolbar = memo(function DefaultToolbar({ children }: Default
44
44
  : breakpoint < PORTRAIT_BREAKPOINT.TABLET
45
45
 
46
46
  return (
47
- <div ref={ref} className="tlui-toolbar">
48
- <div className="tlui-toolbar__inner">
49
- <div className="tlui-toolbar__left">
47
+ <div ref={ref} className="tlui-main-toolbar">
48
+ <div className="tlui-main-toolbar__inner">
49
+ <div className="tlui-main-toolbar__left">
50
50
  {!isReadonlyMode && (
51
- <div className="tlui-toolbar__extras">
51
+ <div className="tlui-main-toolbar__extras">
52
52
  {showQuickActions && (
53
53
  <TldrawUiToolbar
54
- className="tlui-toolbar__extras__controls tlui-buttons__horizontal"
54
+ orientation="horizontal"
55
+ className="tlui-main-toolbar__extras__controls"
55
56
  label={msg('actions-menu.title')}
56
57
  >
57
58
  {QuickActions && <QuickActions />}
@@ -64,7 +65,7 @@ export const DefaultToolbar = memo(function DefaultToolbar({ children }: Default
64
65
  <OverflowingToolbar>{children ?? <DefaultToolbarContent />}</OverflowingToolbar>
65
66
  </div>
66
67
  {breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM && !isReadonlyMode && (
67
- <div className="tlui-toolbar__tools">
68
+ <div className="tlui-main-toolbar__tools">
68
69
  <MobileStylePanel />
69
70
  </div>
70
71
  )}
@@ -20,6 +20,7 @@ import {
20
20
  TldrawUiPopoverTrigger,
21
21
  } from '../primitives/TldrawUiPopover'
22
22
  import { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
23
+ import { TldrawUiRow } from '../primitives/layout'
23
24
  import { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'
24
25
 
25
26
  export const IsInOverflowContext = createContext(false)
@@ -61,15 +62,12 @@ export function OverflowingToolbar({ children }: OverflowingToolbarProps) {
61
62
  const activeCss = lastActiveOverflowItem ? `:not([data-value="${lastActiveOverflowItem}"])` : ''
62
63
 
63
64
  return `
64
- #${id}_main > *:nth-child(n + ${overflowIndex + (lastActiveOverflowItem ? 1 : 2)})${activeCss} {
65
+ #${id}_main > *:nth-of-type(n + ${overflowIndex + (lastActiveOverflowItem ? 1 : 2)}):not([data-radix-popper-content-wrapper])${activeCss} {
65
66
  display: none;
66
67
  }
67
- #${id}_more > *:nth-child(-n + ${overflowIndex}) {
68
+ #${id}_more > *:nth-of-type(-n + ${overflowIndex}):not([data-radix-popper-content-wrapper]) {
68
69
  display: none;
69
70
  }
70
- #${id}_more > *:nth-child(-n + ${overflowIndex + 4}) {
71
- margin-top: 0;
72
- }
73
71
  `
74
72
  }, [lastActiveOverflowItem, id, overflowIndex])
75
73
 
@@ -158,16 +156,17 @@ export function OverflowingToolbar({ children }: OverflowingToolbarProps) {
158
156
  <>
159
157
  <style nonce={editor.options.nonce}>{css}</style>
160
158
  <TldrawUiToolbar
161
- className={classNames('tlui-toolbar__tools', {
162
- 'tlui-toolbar__tools__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,
159
+ orientation="horizontal"
160
+ className={classNames('tlui-main-toolbar__tools', {
161
+ 'tlui-main-toolbar__tools__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,
163
162
  })}
164
163
  label={msg('tool-panel.title')}
165
164
  >
166
- <div id={`${id}_main`} ref={mainToolsRef} className="tlui-toolbar__tools__list">
165
+ <TldrawUiRow id={`${id}_main`} ref={mainToolsRef}>
167
166
  <TldrawUiMenuContextProvider type="toolbar" sourceId="toolbar">
168
167
  {children}
169
168
  </TldrawUiMenuContextProvider>
170
- </div>
169
+ </TldrawUiRow>
171
170
  {/* There is a +1 because if the menu is just one item, it's not necessary. */}
172
171
  {totalItems > overflowIndex + 1 && (
173
172
  <IsInOverflowContext.Provider value={true}>
@@ -176,7 +175,7 @@ export function OverflowingToolbar({ children }: OverflowingToolbarProps) {
176
175
  <TldrawUiToolbarButton
177
176
  title={msg('tool-panel.more')}
178
177
  type="tool"
179
- className="tlui-toolbar__overflow"
178
+ className="tlui-main-toolbar__overflow"
180
179
  data-testid="tools.more-button"
181
180
  >
182
181
  <TldrawUiButtonIcon icon="chevron-up" />
@@ -184,7 +183,7 @@ export function OverflowingToolbar({ children }: OverflowingToolbarProps) {
184
183
  </TldrawUiPopoverTrigger>
185
184
  <TldrawUiPopoverContent side="top" align="center">
186
185
  <TldrawUiToolbar
187
- className="tlui-buttons__grid"
186
+ orientation="grid"
188
187
  data-testid="tools.more-content"
189
188
  label={msg('tool-panel.more')}
190
189
  id={`${id}_more`}
@@ -5,6 +5,7 @@ import { useBreakpoint } from '../../context/breakpoints'
5
5
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
6
6
  import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
7
7
  import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
8
+ import { TldrawUiTooltip } from '../primitives/TldrawUiTooltip'
8
9
 
9
10
  /** @public */
10
11
  export interface ToggleToolLockedButtonProps {
@@ -25,16 +26,18 @@ export function ToggleToolLockedButton({ activeToolId }: ToggleToolLockedButtonP
25
26
  if (!activeToolId || !tool.isLockable) return null
26
27
 
27
28
  return (
28
- <TldrawUiButton
29
- type="normal"
30
- title={msg('action.toggle-tool-lock')}
31
- data-testid="tool-lock"
32
- className={classNames('tlui-toolbar__lock-button', {
33
- 'tlui-toolbar__lock-button__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,
34
- })}
35
- onClick={() => editor.updateInstanceState({ isToolLocked: !isToolLocked })}
36
- >
37
- <TldrawUiButtonIcon icon={isToolLocked ? 'lock' : 'unlock'} small />
38
- </TldrawUiButton>
29
+ <TldrawUiTooltip content={msg('action.toggle-tool-lock')}>
30
+ <TldrawUiButton
31
+ type="normal"
32
+ title={msg('action.toggle-tool-lock')}
33
+ data-testid="tool-lock"
34
+ className={classNames('tlui-main-toolbar__lock-button', {
35
+ 'tlui-main-toolbar__lock-button__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,
36
+ })}
37
+ onClick={() => editor.updateInstanceState({ isToolLocked: !isToolLocked })}
38
+ >
39
+ <TldrawUiButtonIcon icon={isToolLocked ? 'lock' : 'unlock'} small />
40
+ </TldrawUiButton>
41
+ </TldrawUiTooltip>
39
42
  )
40
43
  }
@@ -651,6 +651,14 @@ export function ToggleKeyboardShortcutsItem() {
651
651
  )
652
652
  }
653
653
 
654
+ /** @public @react */
655
+ export function ToggleUiLabelsItem() {
656
+ const editor = useEditor()
657
+ const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
658
+
659
+ return <TldrawUiMenuActionCheckboxItem actionId="toggle-ui-labels" checked={showUiLabels} />
660
+ }
661
+
654
662
  /** @public @react */
655
663
  export function ToggleDebugModeItem() {
656
664
  const editor = useEditor()
@@ -6,7 +6,6 @@ import {
6
6
  TLDefaultColorTheme,
7
7
  useEditor,
8
8
  } from '@tldraw/editor'
9
- import classNames from 'classnames'
10
9
  import { ReactElement, memo, useMemo, useRef } from 'react'
11
10
  import { StyleValuesForUi } from '../../../styles'
12
11
  import { PORTRAIT_BREAKPOINT } from '../../constants'
@@ -15,6 +14,7 @@ import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKe
15
14
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
16
15
  import { TldrawUiButtonIcon } from './Button/TldrawUiButtonIcon'
17
16
  import { TldrawUiToolbarToggleGroup, TldrawUiToolbarToggleItem } from './TldrawUiToolbar'
17
+ import { TldrawUiGrid, TldrawUiRow } from './layout'
18
18
 
19
19
  /** @public */
20
20
  export interface TLUiButtonPickerProps<T extends string> {
@@ -116,41 +116,43 @@ export const TldrawUiButtonPicker = memo(function TldrawUiButtonPicker<T extends
116
116
  }
117
117
  }, [editor, breakpoint, value, onHistoryMark, onValueChange, style])
118
118
 
119
+ const Wrapper = items.length > 4 ? TldrawUiGrid : TldrawUiRow
120
+
119
121
  return (
120
- <TldrawUiToolbarToggleGroup
121
- data-testid={`style.${uiType}`}
122
- type="single"
123
- className={classNames('tlui-buttons__grid')}
124
- value={value.type === 'shared' ? value.value : undefined}
125
- >
126
- {items.map((item) => {
127
- const label = title + ' — ' + msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)
128
- return (
129
- <TldrawUiToolbarToggleItem
130
- type="icon"
131
- key={item.value}
132
- data-id={item.value}
133
- data-testid={`style.${uiType}.${item.value}`}
134
- aria-label={label}
135
- value={item.value}
136
- data-state={value.type === 'shared' && value.value === item.value ? 'on' : 'off'}
137
- data-isactive={value.type === 'shared' && value.value === item.value}
138
- title={label}
139
- className={classNames('tlui-button-grid__button')}
140
- style={
141
- style === (DefaultColorStyle as StyleProp<unknown>)
142
- ? { color: theme[item.value as TLDefaultColorStyle].solid }
143
- : undefined
144
- }
145
- onPointerEnter={handleButtonPointerEnter}
146
- onPointerDown={handleButtonPointerDown}
147
- onPointerUp={handleButtonPointerUp}
148
- onClick={handleButtonClick}
149
- >
150
- <TldrawUiButtonIcon icon={item.icon} />
151
- </TldrawUiToolbarToggleItem>
152
- )
153
- })}
154
- </TldrawUiToolbarToggleGroup>
122
+ <Wrapper asChild>
123
+ <TldrawUiToolbarToggleGroup
124
+ data-testid={`style.${uiType}`}
125
+ type="single"
126
+ value={value.type === 'shared' ? value.value : undefined}
127
+ >
128
+ {items.map((item) => {
129
+ const label = title + ' — ' + msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)
130
+ return (
131
+ <TldrawUiToolbarToggleItem
132
+ type="icon"
133
+ key={item.value}
134
+ data-id={item.value}
135
+ data-testid={`style.${uiType}.${item.value}`}
136
+ aria-label={label}
137
+ value={item.value}
138
+ data-state={value.type === 'shared' && value.value === item.value ? 'on' : 'off'}
139
+ data-isactive={value.type === 'shared' && value.value === item.value}
140
+ title={label}
141
+ style={
142
+ style === (DefaultColorStyle as StyleProp<unknown>)
143
+ ? { color: theme[item.value as TLDefaultColorStyle].solid }
144
+ : undefined
145
+ }
146
+ onPointerEnter={handleButtonPointerEnter}
147
+ onPointerDown={handleButtonPointerDown}
148
+ onPointerUp={handleButtonPointerUp}
149
+ onClick={handleButtonClick}
150
+ >
151
+ <TldrawUiButtonIcon icon={item.icon} />
152
+ </TldrawUiToolbarToggleItem>
153
+ )
154
+ })}
155
+ </TldrawUiToolbarToggleGroup>
156
+ </Wrapper>
155
157
  )
156
158
  }) as <T extends string>(props: TLUiButtonPickerProps<T>) => ReactElement