tldraw 3.16.0-canary.6f3aedaa1c01 → 3.16.0-canary.7f4043b128a3

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 (60) hide show
  1. package/dist-cjs/index.d.ts +42 -3
  2. package/dist-cjs/index.js +4 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/ui/TldrawUi.js +14 -0
  5. package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
  6. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +10 -2
  7. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
  8. package/dist-cjs/lib/ui/components/MobileStylePanel.js +3 -1
  9. package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
  10. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -22
  11. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
  12. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +188 -78
  13. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
  14. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +15 -3
  15. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  16. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +84 -77
  17. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  18. package/dist-cjs/lib/ui/components/primitives/layout.js +30 -5
  19. package/dist-cjs/lib/ui/components/primitives/layout.js.map +2 -2
  20. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +30 -7
  21. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
  22. package/dist-cjs/lib/ui/version.js +3 -3
  23. package/dist-cjs/lib/ui/version.js.map +1 -1
  24. package/dist-esm/index.d.mts +42 -3
  25. package/dist-esm/index.mjs +8 -2
  26. package/dist-esm/index.mjs.map +2 -2
  27. package/dist-esm/lib/ui/TldrawUi.mjs +16 -2
  28. package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
  29. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +10 -2
  30. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
  31. package/dist-esm/lib/ui/components/MobileStylePanel.mjs +3 -1
  32. package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
  33. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -22
  34. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
  35. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -80
  36. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
  37. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +16 -4
  38. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  39. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +85 -78
  40. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  41. package/dist-esm/lib/ui/components/primitives/layout.mjs +31 -6
  42. package/dist-esm/lib/ui/components/primitives/layout.mjs.map +2 -2
  43. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +30 -7
  44. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
  45. package/dist-esm/lib/ui/version.mjs +3 -3
  46. package/dist-esm/lib/ui/version.mjs.map +1 -1
  47. package/package.json +3 -3
  48. package/src/index.ts +5 -0
  49. package/src/lib/ui/TldrawUi.tsx +17 -2
  50. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +13 -2
  51. package/src/lib/ui/components/MobileStylePanel.tsx +3 -2
  52. package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -24
  53. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +208 -56
  54. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +22 -5
  55. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +86 -75
  56. package/src/lib/ui/components/primitives/layout.tsx +79 -5
  57. package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +30 -7
  58. package/src/lib/ui/version.ts +3 -3
  59. package/src/lib/ui.css +127 -23
  60. package/tldraw.css +127 -23
@@ -1,7 +1,8 @@
1
1
  import { assert, Editor, uniqueId, useMaybeEditor, Vec } from '@tldraw/editor'
2
2
  import { Tooltip as _Tooltip } from 'radix-ui'
3
- import React, { createContext, useContext, useEffect, useRef, useState } from 'react'
3
+ import React, { createContext, forwardRef, useContext, useEffect, useRef, useState } from 'react'
4
4
  import { usePrefersReducedMotion } from '../../../shapes/shared/usePrefersReducedMotion'
5
+ import { useTldrawUiOrientation } from './layout'
5
6
 
6
7
  const DEFAULT_TOOLTIP_DELAY_MS = 700
7
8
 
@@ -247,86 +248,96 @@ function TooltipSingleton() {
247
248
  }
248
249
 
249
250
  /** @public @react */
250
- export function TldrawUiTooltip({
251
- children,
252
- content,
253
- side = 'bottom',
254
- sideOffset = 5,
255
- disabled = false,
256
- }: TldrawUiTooltipProps) {
257
- const editor = useMaybeEditor()
258
- const tooltipId = useRef<string>(uniqueId())
259
- const hasProvider = useContext(TooltipSingletonContext)
251
+ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProps>(
252
+ ({ children, content, side, sideOffset = 5, disabled = false }, ref) => {
253
+ const editor = useMaybeEditor()
254
+ const tooltipId = useRef<string>(uniqueId())
255
+ const hasProvider = useContext(TooltipSingletonContext)
256
+
257
+ const orientationCtx = useTldrawUiOrientation()
258
+ const sideToUse = side ?? orientationCtx.tooltipSide
259
+
260
+ useEffect(() => {
261
+ const currentTooltipId = tooltipId.current
262
+ return () => {
263
+ if (hasProvider) {
264
+ tooltipManager.hideTooltip(currentTooltipId, true)
265
+ }
266
+ }
267
+ }, [hasProvider])
260
268
 
261
- // Don't show tooltip if disabled, no content, or UI labels are disabled
262
- if (disabled || !content) {
263
- return <>{children}</>
264
- }
269
+ // Don't show tooltip if disabled, no content, or UI labels are disabled
270
+ if (disabled || !content) {
271
+ return <>{children}</>
272
+ }
265
273
 
266
- // Fallback to old behavior if no provider
267
- if (!hasProvider) {
268
- return (
269
- <_Tooltip.Root
270
- delayDuration={editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS}
271
- disableHoverableContent
272
- >
273
- <_Tooltip.Trigger asChild>{children}</_Tooltip.Trigger>
274
- <_Tooltip.Content
275
- className="tlui-tooltip"
276
- side={side}
277
- sideOffset={sideOffset}
278
- avoidCollisions
279
- collisionPadding={8}
280
- dir="ltr"
274
+ // Fallback to old behavior if no provider
275
+ if (!hasProvider) {
276
+ return (
277
+ <_Tooltip.Root
278
+ delayDuration={editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS}
279
+ disableHoverableContent
281
280
  >
282
- {content}
283
- <_Tooltip.Arrow className="tlui-tooltip__arrow" />
284
- </_Tooltip.Content>
285
- </_Tooltip.Root>
286
- )
287
- }
281
+ <_Tooltip.Trigger asChild ref={ref}>
282
+ {children}
283
+ </_Tooltip.Trigger>
284
+ <_Tooltip.Content
285
+ className="tlui-tooltip"
286
+ side={sideToUse}
287
+ sideOffset={sideOffset}
288
+ avoidCollisions
289
+ collisionPadding={8}
290
+ dir="ltr"
291
+ >
292
+ {content}
293
+ <_Tooltip.Arrow className="tlui-tooltip__arrow" />
294
+ </_Tooltip.Content>
295
+ </_Tooltip.Root>
296
+ )
297
+ }
288
298
 
289
- const child = React.Children.only(children)
290
- assert(React.isValidElement(child), 'TldrawUiTooltip children must be a single element')
291
-
292
- const handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {
293
- child.props.onMouseEnter?.(event)
294
- tooltipManager.showTooltip(
295
- tooltipId.current,
296
- content,
297
- event.currentTarget as HTMLElement,
298
- side,
299
- sideOffset
300
- )
301
- }
299
+ const child = React.Children.only(children)
300
+ assert(React.isValidElement(child), 'TldrawUiTooltip children must be a single element')
301
+
302
+ const handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {
303
+ child.props.onMouseEnter?.(event)
304
+ tooltipManager.showTooltip(
305
+ tooltipId.current,
306
+ content,
307
+ event.currentTarget as HTMLElement,
308
+ sideToUse,
309
+ sideOffset
310
+ )
311
+ }
302
312
 
303
- const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {
304
- child.props.onMouseLeave?.(event)
305
- tooltipManager.hideTooltip(tooltipId.current)
306
- }
313
+ const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {
314
+ child.props.onMouseLeave?.(event)
315
+ tooltipManager.hideTooltip(tooltipId.current)
316
+ }
307
317
 
308
- const handleFocus = (event: React.FocusEvent<HTMLElement>) => {
309
- child.props.onFocus?.(event)
310
- tooltipManager.showTooltip(
311
- tooltipId.current,
312
- content,
313
- event.currentTarget as HTMLElement,
314
- side,
315
- sideOffset
316
- )
317
- }
318
+ const handleFocus = (event: React.FocusEvent<HTMLElement>) => {
319
+ child.props.onFocus?.(event)
320
+ tooltipManager.showTooltip(
321
+ tooltipId.current,
322
+ content,
323
+ event.currentTarget as HTMLElement,
324
+ sideToUse,
325
+ sideOffset
326
+ )
327
+ }
318
328
 
319
- const handleBlur = (event: React.FocusEvent<HTMLElement>) => {
320
- child.props.onBlur?.(event)
321
- tooltipManager.hideTooltip(tooltipId.current)
322
- }
329
+ const handleBlur = (event: React.FocusEvent<HTMLElement>) => {
330
+ child.props.onBlur?.(event)
331
+ tooltipManager.hideTooltip(tooltipId.current)
332
+ }
323
333
 
324
- const childrenWithHandlers = React.cloneElement(children as React.ReactElement, {
325
- onMouseEnter: handleMouseEnter,
326
- onMouseLeave: handleMouseLeave,
327
- onFocus: handleFocus,
328
- onBlur: handleBlur,
329
- })
334
+ const childrenWithHandlers = React.cloneElement(children as React.ReactElement, {
335
+ onMouseEnter: handleMouseEnter,
336
+ onMouseLeave: handleMouseLeave,
337
+ onFocus: handleFocus,
338
+ onBlur: handleBlur,
339
+ })
330
340
 
331
- return childrenWithHandlers
332
- }
341
+ return childrenWithHandlers
342
+ }
343
+ )
@@ -1,10 +1,60 @@
1
1
  import classNames from 'classnames'
2
2
  import { Slot } from 'radix-ui'
3
- import { HTMLAttributes, ReactNode, forwardRef } from 'react'
3
+ import { HTMLAttributes, ReactNode, createContext, forwardRef, useContext } from 'react'
4
+
5
+ /** @public */
6
+ export interface TldrawUiOrientationContext {
7
+ orientation: 'horizontal' | 'vertical'
8
+ tooltipSide: 'top' | 'right' | 'bottom' | 'left'
9
+ }
10
+
11
+ const TldrawUiOrientationContext = createContext<TldrawUiOrientationContext>({
12
+ orientation: 'horizontal',
13
+ tooltipSide: 'bottom',
14
+ })
15
+
16
+ /** @public */
17
+ export interface TldrawUiOrientationProviderProps {
18
+ children: ReactNode
19
+ orientation: 'horizontal' | 'vertical'
20
+ tooltipSide?: 'top' | 'right' | 'bottom' | 'left'
21
+ }
22
+ /** @public @react */
23
+ export function TldrawUiOrientationProvider({
24
+ children,
25
+ orientation,
26
+ tooltipSide,
27
+ }: TldrawUiOrientationProviderProps) {
28
+ const prevContext = useTldrawUiOrientation()
29
+ // generally, we want tooltip side to cascade down through the layout - apart from when the
30
+ // orientation changes. If the tooltip side is "bottom", and then I include some vertical layout
31
+ // elements, keeping the tooltip side as bottom will cause the tooltip to overlap elements
32
+ // stacked on top of each other. In the absence of a tooltip side, we pick a default side based
33
+ // on the orientation whenever the orientation changes.
34
+ const tooltipSideToUse =
35
+ tooltipSide ??
36
+ (orientation === prevContext.orientation
37
+ ? prevContext.tooltipSide
38
+ : orientation === 'horizontal'
39
+ ? 'bottom'
40
+ : 'right')
41
+
42
+ return (
43
+ <TldrawUiOrientationContext.Provider value={{ orientation, tooltipSide: tooltipSideToUse }}>
44
+ {children}
45
+ </TldrawUiOrientationContext.Provider>
46
+ )
47
+ }
48
+
49
+ /** @public */
50
+ export function useTldrawUiOrientation() {
51
+ return useContext(TldrawUiOrientationContext)
52
+ }
4
53
 
5
54
  /** @public */
6
55
  export interface TLUiLayoutProps extends HTMLAttributes<HTMLDivElement> {
7
56
  children: ReactNode
57
+ tooltipSide?: 'top' | 'right' | 'bottom' | 'left'
8
58
  asChild?: boolean
9
59
  }
10
60
 
@@ -14,9 +64,29 @@ export interface TLUiLayoutProps extends HTMLAttributes<HTMLDivElement> {
14
64
  * @public @react
15
65
  */
16
66
  export const TldrawUiRow = forwardRef<HTMLDivElement, TLUiLayoutProps>(
17
- ({ asChild, className, ...props }, ref) => {
67
+ ({ asChild, className, tooltipSide, ...props }, ref) => {
68
+ const Component = asChild ? Slot.Root : 'div'
69
+ return (
70
+ <TldrawUiOrientationProvider orientation="horizontal" tooltipSide={tooltipSide}>
71
+ <Component ref={ref} className={classNames('tlui-row', className)} {...props} />
72
+ </TldrawUiOrientationProvider>
73
+ )
74
+ }
75
+ )
76
+
77
+ /**
78
+ * A column, usually of UI controls like buttons, select dropdown, checkboxes, etc.
79
+ *
80
+ * @public @react
81
+ */
82
+ export const TldrawUiColumn = forwardRef<HTMLDivElement, TLUiLayoutProps>(
83
+ ({ asChild, className, tooltipSide, ...props }, ref) => {
18
84
  const Component = asChild ? Slot.Root : 'div'
19
- return <Component ref={ref} className={classNames('tlui-row', className)} {...props} />
85
+ return (
86
+ <TldrawUiOrientationProvider orientation="vertical" tooltipSide={tooltipSide}>
87
+ <Component ref={ref} className={classNames('tlui-column', className)} {...props} />
88
+ </TldrawUiOrientationProvider>
89
+ )
20
90
  }
21
91
  )
22
92
 
@@ -26,8 +96,12 @@ export const TldrawUiRow = forwardRef<HTMLDivElement, TLUiLayoutProps>(
26
96
  *
27
97
  * @public @react */
28
98
  export const TldrawUiGrid = forwardRef<HTMLDivElement, TLUiLayoutProps>(
29
- ({ asChild, className, ...props }, ref) => {
99
+ ({ asChild, className, tooltipSide, ...props }, ref) => {
30
100
  const Component = asChild ? Slot.Root : 'div'
31
- return <Component ref={ref} className={classNames('tlui-grid', className)} {...props} />
101
+ return (
102
+ <TldrawUiOrientationProvider orientation="horizontal" tooltipSide={tooltipSide}>
103
+ <Component ref={ref} className={classNames('tlui-grid', className)} {...props} />
104
+ </TldrawUiOrientationProvider>
105
+ )
32
106
  }
33
107
  )
@@ -3,6 +3,7 @@ import { ReactNode } from 'react'
3
3
  import { unwrapLabel } from '../../../context/actions'
4
4
  import { TLUiTranslationKey } from '../../../hooks/useTranslation/TLUiTranslationKey'
5
5
  import { useTranslation } from '../../../hooks/useTranslation/useTranslation'
6
+ import { TldrawUiColumn, TldrawUiGrid, TldrawUiRow, useTldrawUiOrientation } from '../layout'
6
7
  import { TldrawUiDropdownMenuGroup } from '../TldrawUiDropdownMenu'
7
8
  import { useTldrawUiMenuContext } from './TldrawUiMenuContext'
8
9
 
@@ -19,17 +20,18 @@ export interface TLUiMenuGroupProps<TranslationKey extends string = string> {
19
20
 
20
21
  /** @public @react */
21
22
  export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGroupProps) {
22
- const { type: menuType, sourceId } = useTldrawUiMenuContext()
23
+ const menu = useTldrawUiMenuContext()
24
+ const { orientation } = useTldrawUiOrientation()
23
25
  const msg = useTranslation()
24
- const labelToUse = unwrapLabel(label, menuType)
26
+ const labelToUse = unwrapLabel(label, menu.type)
25
27
  const labelStr = labelToUse ? msg(labelToUse as TLUiTranslationKey) : undefined
26
28
 
27
- switch (menuType) {
29
+ switch (menu.type) {
28
30
  case 'panel': {
29
31
  return (
30
32
  <div
31
33
  className={classNames('tlui-menu__group', className)}
32
- data-testid={`${sourceId}-group.${id}`}
34
+ data-testid={`${menu.sourceId}-group.${id}`}
33
35
  >
34
36
  {children}
35
37
  </div>
@@ -37,7 +39,10 @@ export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGr
37
39
  }
38
40
  case 'menu': {
39
41
  return (
40
- <TldrawUiDropdownMenuGroup className={className} data-testid={`${sourceId}-group.${id}`}>
42
+ <TldrawUiDropdownMenuGroup
43
+ className={className}
44
+ data-testid={`${menu.sourceId}-group.${id}`}
45
+ >
41
46
  {children}
42
47
  </TldrawUiDropdownMenuGroup>
43
48
  )
@@ -47,7 +52,7 @@ export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGr
47
52
  <div
48
53
  dir="ltr"
49
54
  className={classNames('tlui-menu__group', className)}
50
- data-testid={`${sourceId}-group.${id}`}
55
+ data-testid={`${menu.sourceId}-group.${id}`}
51
56
  >
52
57
  {children}
53
58
  </div>
@@ -56,12 +61,30 @@ export function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGr
56
61
  case 'keyboard-shortcuts': {
57
62
  // todo: if groups need a label, let's give em a label
58
63
  return (
59
- <div className="tlui-shortcuts-dialog__group" data-testid={`${sourceId}-group.${id}`}>
64
+ <div className="tlui-shortcuts-dialog__group" data-testid={`${menu.sourceId}-group.${id}`}>
60
65
  <h2 className="tlui-shortcuts-dialog__group__title">{labelStr}</h2>
61
66
  <div className="tlui-shortcuts-dialog__group__content">{children}</div>
62
67
  </div>
63
68
  )
64
69
  }
70
+ case 'toolbar': {
71
+ const Layout = orientation === 'horizontal' ? TldrawUiRow : TldrawUiColumn
72
+ return (
73
+ <Layout className="tlui-main-toolbar__group" data-testid={`${menu.sourceId}-group.${id}`}>
74
+ {children}
75
+ </Layout>
76
+ )
77
+ }
78
+ case 'toolbar-overflow': {
79
+ return (
80
+ <TldrawUiGrid
81
+ className="tlui-main-toolbar__group"
82
+ data-testid={`${menu.sourceId}-group.${id}`}
83
+ >
84
+ {children}
85
+ </TldrawUiGrid>
86
+ )
87
+ }
65
88
  default: {
66
89
  return children
67
90
  }
@@ -1,9 +1,9 @@
1
1
  // This file is automatically generated by internal/scripts/refresh-assets.ts.
2
2
  // Do not edit manually. Or do, I'm a comment, not a cop.
3
3
 
4
- export const version = '3.16.0-canary.6f3aedaa1c01'
4
+ export const version = '3.16.0-canary.7f4043b128a3'
5
5
  export const publishDates = {
6
6
  major: '2024-09-13T14:36:29.063Z',
7
- minor: '2025-08-11T09:05:51.468Z',
8
- patch: '2025-08-11T09:05:51.468Z',
7
+ minor: '2025-08-12T08:51:53.161Z',
8
+ patch: '2025-08-12T08:51:53.161Z',
9
9
  }
package/src/lib/ui.css CHANGED
@@ -203,15 +203,23 @@
203
203
 
204
204
  .tlui-main-toolbar__lock-button {
205
205
  position: absolute;
206
- top: 4px;
207
- right: 0px;
208
206
  pointer-events: all;
209
207
  height: 40px;
210
208
  width: 40px;
211
- min-width: 0px;
212
209
  border-radius: var(--radius-2);
213
210
  }
214
211
 
212
+ .tlui-main-toolbar--horizontal .tlui-main-toolbar__lock-button {
213
+ top: 4px;
214
+ right: 0px;
215
+ min-width: 0px;
216
+ }
217
+
218
+ .tlui-main-toolbar--vertical .tlui-main-toolbar__lock-button {
219
+ bottom: 0px;
220
+ min-height: 0px;
221
+ }
222
+
215
223
  .tlui-main-toolbar__lock-button::after {
216
224
  top: 4px;
217
225
  left: 8px;
@@ -244,12 +252,12 @@
244
252
  opacity: 1;
245
253
  }
246
254
 
247
- .tlui-layout__mobile .tlui-button__tool {
255
+ .tlui-layout__mobile .tlui-main-toolbar--horizontal .tlui-button__tool {
248
256
  height: 48px;
249
257
  width: 43px;
250
258
  }
251
259
 
252
- .tlui-layout__mobile .tlui-button__tool > .tlui-icon {
260
+ .tlui-layout__mobile .tlui-main-toolbar--horizontal .tlui-button__tool > .tlui-icon {
253
261
  height: 16px;
254
262
  width: 16px;
255
263
  }
@@ -266,6 +274,18 @@
266
274
  margin-right: -2px;
267
275
  }
268
276
 
277
+ /* Column layout */
278
+
279
+ .tlui-column {
280
+ display: flex;
281
+ flex-direction: column;
282
+ padding: 2px 0;
283
+ }
284
+ .tlui-column > * {
285
+ margin-top: -2px;
286
+ margin-bottom: -2px;
287
+ }
288
+
269
289
  /* Grid layout */
270
290
 
271
291
  .tlui-grid {
@@ -1057,11 +1077,12 @@
1057
1077
 
1058
1078
  .tlui-layout__bottom {
1059
1079
  grid-row: 2;
1080
+ width: 100%;
1081
+ overflow: hidden;
1060
1082
  }
1061
1083
 
1062
1084
  .tlui-layout__bottom__main {
1063
1085
  width: 100%;
1064
- position: relative;
1065
1086
  display: flex;
1066
1087
  align-items: flex-end;
1067
1088
  justify-content: center;
@@ -1077,7 +1098,6 @@
1077
1098
  pointer-events: all;
1078
1099
  position: absolute;
1079
1100
  left: 0px;
1080
- bottom: 0px;
1081
1101
  }
1082
1102
 
1083
1103
  .tlui-navigation-panel::before {
@@ -1124,7 +1144,23 @@
1124
1144
  align-items: center;
1125
1145
  justify-content: center;
1126
1146
  flex-grow: 2;
1147
+ }
1148
+
1149
+ .tlui-main-toolbar--horizontal {
1127
1150
  padding-bottom: calc(var(--space-3) + var(--sab));
1151
+ max-width: 100%;
1152
+ }
1153
+
1154
+ .tlui-main-toolbar--vertical {
1155
+ position: absolute;
1156
+ left: 0;
1157
+ top: 90px; /* height of page menu + 'back to content' button */
1158
+ bottom: 140px; /* height of expanded mini-map */
1159
+ padding-left: calc(var(--space-3) + var(--sab));
1160
+ }
1161
+
1162
+ [data-breakpoints-below*='6'] .tlui-main-toolbar--vertical {
1163
+ bottom: 90px; /* collapsed mini-map, but same as top to keep things looking even */
1128
1164
  }
1129
1165
 
1130
1166
  /* Centered Content */
@@ -1133,46 +1169,69 @@
1133
1169
  width: fit-content;
1134
1170
  display: flex;
1135
1171
  gap: var(--space-3);
1136
- align-items: flex-end;
1172
+ align-items: flex-start;
1173
+ }
1174
+
1175
+ .tlui-main-toolbar--vertical .tlui-main-toolbar__inner {
1176
+ flex-direction: column;
1137
1177
  }
1138
1178
 
1139
- .tlui-main-toolbar__left {
1179
+ .tlui-main-toolbar--horizontal .tlui-main-toolbar__left {
1140
1180
  width: fit-content;
1141
1181
  }
1182
+ .tlui-main-toolbar--vertical .tlui-main-toolbar__left {
1183
+ display: flex;
1184
+ height: fit-content;
1185
+ }
1142
1186
 
1143
1187
  /* Row of controls + lock button */
1144
1188
  .tlui-main-toolbar__extras {
1145
1189
  position: relative;
1146
1190
  z-index: var(--layer-above);
1147
- width: 100%;
1148
1191
  pointer-events: none;
1149
- top: 6px;
1150
- height: 48px;
1192
+ align-self: stretch;
1151
1193
  }
1152
1194
 
1153
1195
  .tlui-main-toolbar__extras:empty {
1154
1196
  display: none;
1155
1197
  }
1156
1198
 
1199
+ .tlui-main-toolbar--horizontal .tlui-main-toolbar__extras {
1200
+ height: 48px;
1201
+ top: 6px;
1202
+ }
1203
+
1204
+ .tlui-main-toolbar--vertical .tlui-main-toolbar__extras {
1205
+ width: 48px;
1206
+ order: 1;
1207
+ }
1208
+
1157
1209
  .tlui-main-toolbar__extras__controls {
1158
- display: flex;
1159
1210
  position: relative;
1160
- flex-direction: row;
1161
1211
  z-index: var(--layer-above);
1162
1212
  background-color: var(--color-low);
1213
+ border: 2px solid var(--color-background);
1214
+ pointer-events: all;
1215
+ }
1216
+
1217
+ .tlui-main-toolbar--horizontal .tlui-main-toolbar__extras__controls {
1163
1218
  border-top-left-radius: var(--radius-4);
1164
1219
  border-top-right-radius: var(--radius-4);
1165
- border: 2px solid var(--color-background);
1166
1220
  margin-left: 8px;
1167
1221
  margin-right: 0px;
1168
- pointer-events: all;
1222
+ width: fit-content;
1223
+ }
1224
+
1225
+ .tlui-main-toolbar--vertical .tlui-main-toolbar__extras__controls {
1226
+ border-top-right-radius: var(--radius-4);
1227
+ border-bottom-right-radius: var(--radius-4);
1228
+ margin-top: 8px;
1229
+ margin-left: -2px;
1230
+ margin-bottom: 0px;
1169
1231
  width: fit-content;
1170
1232
  }
1171
1233
 
1172
1234
  .tlui-main-toolbar__tools {
1173
- display: flex;
1174
- flex-direction: row;
1175
- align-items: center;
1176
1235
  border-radius: var(--radius-4);
1177
1236
  z-index: var(--layer-panels);
1178
1237
  pointer-events: all;
@@ -1181,26 +1240,71 @@
1181
1240
  box-shadow: var(--shadow-2);
1182
1241
  }
1183
1242
 
1184
- .tlui-main-toolbar__overflow {
1243
+ .tlui-main-toolbar--horizontal .tlui-main-toolbar__mobile-style-panel {
1244
+ align-self: flex-end;
1245
+ }
1246
+ .tlui-main-toolbar--vertical .tlui-main-toolbar__mobile-style-panel {
1247
+ align-self: flex-start;
1248
+ }
1249
+
1250
+ .tlui-main-toolbar--horizontal .tlui-main-toolbar__overflow {
1185
1251
  width: 40px;
1186
1252
  margin-left: 2px;
1187
1253
  }
1254
+ .tlui-main-toolbar--vertical .tlui-main-toolbar__overflow {
1255
+ height: 40px;
1256
+ margin-top: 2px;
1257
+ }
1188
1258
 
1189
- .tlui-layout__mobile .tlui-main-toolbar__overflow {
1259
+ .tlui-layout__mobile .tlui-main-toolbar--horizontal .tlui-main-toolbar__overflow {
1190
1260
  width: 32px;
1191
1261
  padding: 0px;
1192
1262
  }
1193
1263
 
1194
- .tlui-main-toolbar *[data-state='open']::after {
1264
+ .tlui-main-toolbar--horizontal *[data-state='open']::after {
1195
1265
  background: linear-gradient(0deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%);
1196
1266
  opacity: 1;
1197
1267
  }
1268
+ .tlui-main-toolbar--vertical *[data-state='open']::after {
1269
+ background: linear-gradient(90deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%);
1270
+ opacity: 1;
1271
+ }
1272
+
1273
+ .tlui-main-toolbar__tools [data-toolbar-visible='false'],
1274
+ .tlui-main-toolbar__overflow-content [data-toolbar-visible='false'] {
1275
+ display: none;
1276
+ }
1277
+
1278
+ .tlui-main-toolbar__group:empty {
1279
+ display: none;
1280
+ }
1281
+ .tlui-row.tlui-main-toolbar__group:not(:nth-last-child(-n + 1 of [data-toolbar-visible='true'])) {
1282
+ border-right: 1px solid var(--color-divider);
1283
+ margin-right: 2px;
1284
+ }
1285
+ .tlui-column.tlui-main-toolbar__group:not(
1286
+ :nth-last-child(-n + 1 of [data-toolbar-visible='true'])
1287
+ ) {
1288
+ border-bottom: 1px solid var(--color-divider);
1289
+ margin-bottom: 2px;
1290
+ }
1291
+ .tlui-grid.tlui-main-toolbar__group {
1292
+ grid-column: 1 / span 4;
1293
+ }
1294
+ .tlui-grid.tlui-main-toolbar__group:not(:nth-last-child(-n + 1 of [data-toolbar-visible='true'])) {
1295
+ border-bottom: 1px solid var(--color-divider);
1296
+ margin-bottom: 2px;
1297
+ }
1198
1298
 
1199
1299
  @media (hover: hover) {
1200
- .tlui-main-toolbar *[data-state='open']:not(:hover)::after {
1300
+ .tlui-main-toolbar--horizontal *[data-state='open']:not(:hover)::after {
1201
1301
  background: linear-gradient(0deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%);
1202
1302
  opacity: 1;
1203
1303
  }
1304
+ .tlui-main-toolbar--vertical *[data-state='open']:not(:hover)::after {
1305
+ background: linear-gradient(90deg, rgba(144, 144, 144, 0) 0%, var(--color-muted-2) 100%);
1306
+ opacity: 1;
1307
+ }
1204
1308
  }
1205
1309
 
1206
1310
  /* ------------------- Tooltip -------------------- */