@dxos/plugin-navtree 0.8.4-main.bc674ce → 0.8.4-main.bcb3aa67d6

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 (187) hide show
  1. package/dist/lib/browser/index.mjs +137 -72
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
  5. package/dist/types/src/capabilities/app-graph-builder.d.ts +6 -0
  6. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  7. package/dist/types/src/capabilities/index.d.ts +7 -5
  8. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  9. package/dist/types/src/capabilities/keyboard.d.ts +5 -0
  10. package/dist/types/src/capabilities/keyboard.d.ts.map +1 -0
  11. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  12. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  13. package/dist/types/src/capabilities/react-surface.d.ts +5 -0
  14. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  15. package/dist/types/src/capabilities/state.d.ts +6 -0
  16. package/dist/types/src/capabilities/state.d.ts.map +1 -0
  17. package/dist/types/src/components/NavTree/NavTree.d.ts +10 -32
  18. package/dist/types/src/components/NavTree/NavTree.d.ts.map +1 -1
  19. package/dist/types/src/components/NavTree/NavTree.stories.d.ts +10 -14
  20. package/dist/types/src/components/NavTree/NavTree.stories.d.ts.map +1 -1
  21. package/dist/types/src/components/{NavTreeContext.d.ts → NavTreeContext/NavTreeContext.d.ts} +1 -1
  22. package/dist/types/src/components/NavTreeContext/NavTreeContext.d.ts.map +1 -0
  23. package/dist/types/src/components/NavTreeContext/index.d.ts +2 -0
  24. package/dist/types/src/components/NavTreeContext/index.d.ts.map +1 -0
  25. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts +11 -3
  26. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.d.ts.map +1 -1
  27. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts +1 -1
  28. package/dist/types/src/components/NavTreeItem/NavTreeItemAction.stories.d.ts.map +1 -1
  29. package/dist/types/src/components/NavTreeItem/NavTreeItemColumns.d.ts.map +1 -1
  30. package/dist/types/src/components/Sidebar/L0Menu.d.ts +4 -1
  31. package/dist/types/src/components/Sidebar/L0Menu.d.ts.map +1 -1
  32. package/dist/types/src/components/Sidebar/L1Panel.d.ts +3 -6
  33. package/dist/types/src/components/Sidebar/L1Panel.d.ts.map +1 -1
  34. package/dist/types/src/components/Sidebar/L1Tabs.d.ts +3 -2
  35. package/dist/types/src/components/Sidebar/L1Tabs.d.ts.map +1 -1
  36. package/dist/types/src/components/UserAccountAvatar/UserAccountAvatar.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/index.d.ts +0 -3
  38. package/dist/types/src/components/index.d.ts.map +1 -1
  39. package/dist/types/src/components/types.d.ts +5 -13
  40. package/dist/types/src/components/types.d.ts.map +1 -1
  41. package/dist/types/src/{components/CommandsDialog/CommandsDialog.d.ts → containers/CommandsDialogContent/CommandsDialogContent.d.ts} +1 -1
  42. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.d.ts.map +1 -0
  43. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.stories.d.ts +29 -0
  44. package/dist/types/src/containers/CommandsDialogContent/CommandsDialogContent.stories.d.ts.map +1 -0
  45. package/dist/types/src/containers/CommandsDialogContent/index.d.ts +3 -0
  46. package/dist/types/src/containers/CommandsDialogContent/index.d.ts.map +1 -0
  47. package/dist/types/src/containers/CommandsTrigger/CommandsTrigger.d.ts.map +1 -0
  48. package/dist/types/src/containers/CommandsTrigger/index.d.ts +3 -0
  49. package/dist/types/src/containers/CommandsTrigger/index.d.ts.map +1 -0
  50. package/dist/types/src/containers/NavTreeContainer/NavTreeContainer.d.ts +9 -0
  51. package/dist/types/src/containers/NavTreeContainer/NavTreeContainer.d.ts.map +1 -0
  52. package/dist/types/src/containers/NavTreeContainer/index.d.ts +3 -0
  53. package/dist/types/src/containers/NavTreeContainer/index.d.ts.map +1 -0
  54. package/dist/types/src/containers/NavTreeDocumentTitle/NavTreeDocumentTitle.d.ts.map +1 -0
  55. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts +3 -0
  56. package/dist/types/src/containers/NavTreeDocumentTitle/index.d.ts.map +1 -0
  57. package/dist/types/src/containers/index.d.ts +7 -0
  58. package/dist/types/src/containers/index.d.ts.map +1 -0
  59. package/dist/types/src/experimental/Tree.stories.d.ts +18 -4
  60. package/dist/types/src/experimental/Tree.stories.d.ts.map +1 -1
  61. package/dist/types/src/hooks/index.d.ts +5 -0
  62. package/dist/types/src/hooks/index.d.ts.map +1 -0
  63. package/dist/types/src/hooks/useActions.d.ts +5 -0
  64. package/dist/types/src/hooks/useActions.d.ts.map +1 -0
  65. package/dist/types/src/hooks/useLoadDescendents.d.ts +6 -0
  66. package/dist/types/src/hooks/useLoadDescendents.d.ts.map +1 -0
  67. package/dist/types/src/hooks/useNavTreeModel.d.ts +7 -0
  68. package/dist/types/src/hooks/useNavTreeModel.d.ts.map +1 -0
  69. package/dist/types/src/{hooks.d.ts → hooks/useNavTreeState.d.ts} +2 -14
  70. package/dist/types/src/hooks/useNavTreeState.d.ts.map +1 -0
  71. package/dist/types/src/meta.d.ts.map +1 -1
  72. package/dist/types/src/operations/expose.d.ts +5 -0
  73. package/dist/types/src/operations/expose.d.ts.map +1 -0
  74. package/dist/types/src/operations/index.d.ts +3 -0
  75. package/dist/types/src/operations/index.d.ts.map +1 -0
  76. package/dist/types/src/testing/app-graph-builder.d.ts.map +1 -1
  77. package/dist/types/src/testing/generator.d.ts +3 -3
  78. package/dist/types/src/testing/generator.d.ts.map +1 -1
  79. package/dist/types/src/translations.d.ts +9 -10
  80. package/dist/types/src/translations.d.ts.map +1 -1
  81. package/dist/types/src/types/events.d.ts.map +1 -1
  82. package/dist/types/src/util.d.ts +6 -2
  83. package/dist/types/src/util.d.ts.map +1 -1
  84. package/dist/types/tsconfig.tsbuildinfo +1 -1
  85. package/package.json +54 -43
  86. package/src/NavTreePlugin.tsx +26 -27
  87. package/src/capabilities/{app-graph-builder/app-graph-builder.ts → app-graph-builder.ts} +6 -5
  88. package/src/capabilities/index.ts +11 -5
  89. package/src/capabilities/{keyboard/keyboard.ts → keyboard.ts} +7 -6
  90. package/src/capabilities/operation-handler.ts +16 -0
  91. package/src/capabilities/{react-surface/react-surface.tsx → react-surface.tsx} +13 -14
  92. package/src/capabilities/{state/state.ts → state.ts} +43 -15
  93. package/src/components/NavTree/NavTree.stories.tsx +26 -24
  94. package/src/components/NavTree/NavTree.tsx +63 -22
  95. package/src/components/{NavTreeContext.tsx → NavTreeContext/NavTreeContext.tsx} +1 -1
  96. package/src/components/NavTreeContext/index.ts +5 -0
  97. package/src/components/NavTreeItem/NavTreeItemAction.stories.tsx +1 -3
  98. package/src/components/NavTreeItem/NavTreeItemAction.tsx +56 -39
  99. package/src/components/NavTreeItem/NavTreeItemColumns.tsx +42 -16
  100. package/src/components/Sidebar/L0Menu.tsx +99 -109
  101. package/src/components/Sidebar/L1Panel.tsx +252 -94
  102. package/src/components/Sidebar/L1Tabs.tsx +13 -3
  103. package/src/components/UserAccountAvatar/UserAccountAvatar.stories.tsx +2 -3
  104. package/src/components/UserAccountAvatar/UserAccountAvatar.tsx +1 -1
  105. package/src/components/index.ts +0 -3
  106. package/src/components/types.ts +12 -17
  107. package/src/containers/CommandsDialogContent/CommandsDialogContent.stories.tsx +46 -0
  108. package/src/{components/CommandsDialog/CommandsDialog.tsx → containers/CommandsDialogContent/CommandsDialogContent.tsx} +23 -21
  109. package/src/containers/CommandsDialogContent/index.ts +7 -0
  110. package/src/containers/CommandsTrigger/CommandsTrigger.tsx +28 -0
  111. package/src/containers/CommandsTrigger/index.ts +7 -0
  112. package/src/{components → containers/NavTreeContainer}/NavTreeContainer.tsx +76 -142
  113. package/src/containers/NavTreeContainer/index.ts +6 -0
  114. package/src/{components → containers/NavTreeDocumentTitle}/NavTreeDocumentTitle.tsx +2 -2
  115. package/src/containers/NavTreeDocumentTitle/index.ts +7 -0
  116. package/src/containers/index.ts +12 -0
  117. package/src/experimental/Tree.stories.tsx +54 -57
  118. package/src/experimental/Tree.tsx +3 -3
  119. package/src/hooks/index.ts +8 -0
  120. package/src/hooks/useActions.ts +34 -0
  121. package/src/hooks/useLoadDescendents.ts +23 -0
  122. package/src/hooks/useNavTreeModel.ts +118 -0
  123. package/src/{hooks.ts → hooks/useNavTreeState.ts} +3 -34
  124. package/src/meta.ts +2 -2
  125. package/src/operations/expose.ts +42 -0
  126. package/src/operations/index.ts +7 -0
  127. package/src/testing/app-graph-builder.ts +34 -30
  128. package/src/testing/generator.ts +4 -4
  129. package/src/translations.ts +9 -10
  130. package/src/types/capabilities.ts +2 -2
  131. package/src/types/events.ts +4 -3
  132. package/src/util.ts +19 -5
  133. package/dist/lib/browser/app-graph-builder-RSMA6I22.mjs +0 -43
  134. package/dist/lib/browser/app-graph-builder-RSMA6I22.mjs.map +0 -7
  135. package/dist/lib/browser/chunk-6YPQ625I.mjs +0 -1293
  136. package/dist/lib/browser/chunk-6YPQ625I.mjs.map +0 -7
  137. package/dist/lib/browser/chunk-AGQDZBPL.mjs +0 -23
  138. package/dist/lib/browser/chunk-AGQDZBPL.mjs.map +0 -7
  139. package/dist/lib/browser/chunk-YKTYPINZ.mjs +0 -19
  140. package/dist/lib/browser/chunk-YKTYPINZ.mjs.map +0 -7
  141. package/dist/lib/browser/keyboard-32EH3N4K.mjs +0 -52
  142. package/dist/lib/browser/keyboard-32EH3N4K.mjs.map +0 -7
  143. package/dist/lib/browser/operation-resolver-IB75DC5O.mjs +0 -52
  144. package/dist/lib/browser/operation-resolver-IB75DC5O.mjs.map +0 -7
  145. package/dist/lib/browser/react-surface-F6CVMS3Y.mjs +0 -58
  146. package/dist/lib/browser/react-surface-F6CVMS3Y.mjs.map +0 -7
  147. package/dist/lib/browser/state-EVYQOUI3.mjs +0 -120
  148. package/dist/lib/browser/state-EVYQOUI3.mjs.map +0 -7
  149. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts +0 -6
  150. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +0 -1
  151. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +0 -3
  152. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +0 -1
  153. package/dist/types/src/capabilities/keyboard/index.d.ts +0 -3
  154. package/dist/types/src/capabilities/keyboard/index.d.ts.map +0 -1
  155. package/dist/types/src/capabilities/keyboard/keyboard.d.ts +0 -5
  156. package/dist/types/src/capabilities/keyboard/keyboard.d.ts.map +0 -1
  157. package/dist/types/src/capabilities/operation-resolver/index.d.ts +0 -3
  158. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +0 -1
  159. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +0 -5
  160. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +0 -1
  161. package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
  162. package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
  163. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +0 -5
  164. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
  165. package/dist/types/src/capabilities/state/index.d.ts +0 -3
  166. package/dist/types/src/capabilities/state/index.d.ts.map +0 -1
  167. package/dist/types/src/capabilities/state/state.d.ts +0 -6
  168. package/dist/types/src/capabilities/state/state.d.ts.map +0 -1
  169. package/dist/types/src/components/CommandsDialog/CommandsDialog.d.ts.map +0 -1
  170. package/dist/types/src/components/CommandsDialog/CommandsTrigger.d.ts.map +0 -1
  171. package/dist/types/src/components/CommandsDialog/index.d.ts +0 -3
  172. package/dist/types/src/components/CommandsDialog/index.d.ts.map +0 -1
  173. package/dist/types/src/components/NavTreeContainer.d.ts +0 -16
  174. package/dist/types/src/components/NavTreeContainer.d.ts.map +0 -1
  175. package/dist/types/src/components/NavTreeContext.d.ts.map +0 -1
  176. package/dist/types/src/components/NavTreeDocumentTitle.d.ts.map +0 -1
  177. package/dist/types/src/hooks.d.ts.map +0 -1
  178. package/src/capabilities/app-graph-builder/index.ts +0 -7
  179. package/src/capabilities/keyboard/index.ts +0 -7
  180. package/src/capabilities/operation-resolver/index.ts +0 -7
  181. package/src/capabilities/operation-resolver/operation-resolver.ts +0 -41
  182. package/src/capabilities/react-surface/index.ts +0 -7
  183. package/src/capabilities/state/index.ts +0 -7
  184. package/src/components/CommandsDialog/CommandsTrigger.tsx +0 -26
  185. package/src/components/CommandsDialog/index.ts +0 -6
  186. /package/dist/types/src/{components/CommandsDialog → containers/CommandsTrigger}/CommandsTrigger.d.ts +0 -0
  187. /package/dist/types/src/{components → containers/NavTreeDocumentTitle}/NavTreeDocumentTitle.d.ts +0 -0
@@ -11,10 +11,12 @@ import {
11
11
  attachClosestEdge,
12
12
  extractClosestEdge,
13
13
  } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
14
+ import { useAtomValue } from '@effect-atom/atom-react';
14
15
  import React, {
15
16
  type MouseEvent,
16
17
  type PropsWithChildren,
17
18
  forwardRef,
19
+ memo,
18
20
  useCallback,
19
21
  useLayoutEffect,
20
22
  useMemo,
@@ -27,6 +29,7 @@ import { DxAvatar } from '@dxos/lit-ui/react';
27
29
  import { useActionRunner } from '@dxos/plugin-graph';
28
30
  import {
29
31
  Icon,
32
+ IconButton,
30
33
  ListItem,
31
34
  ScrollArea,
32
35
  type ThemedClassName,
@@ -35,14 +38,14 @@ import {
35
38
  useMediaQuery,
36
39
  useTranslation,
37
40
  } from '@dxos/react-ui';
38
- import { DropdownMenu, type MenuItem, MenuProvider } from '@dxos/react-ui-menu';
41
+ import { Menu, type MenuItem } from '@dxos/react-ui-menu';
39
42
  import type { StackItemRearrangeHandler } from '@dxos/react-ui-stack';
40
43
  import { Tabs } from '@dxos/react-ui-tabs';
41
44
  import { mx } from '@dxos/ui-theme';
42
45
  import { arrayMove } from '@dxos/util';
43
46
 
44
- import { useNavTreeState } from '../../hooks';
45
- import { meta } from '../../meta';
47
+ import { useNavTreeState } from '#hooks';
48
+ import { meta } from '#meta';
46
49
  import { l0ItemType } from '../../util';
47
50
  import { useNavTreeContext } from '../NavTreeContext';
48
51
  import { UserAccountAvatar } from '../UserAccountAvatar';
@@ -60,6 +63,7 @@ type L0ItemRootProps = {
60
63
  item: Node.Node;
61
64
  parent?: Node.Node;
62
65
  path: string[];
66
+ onMouseEnter?: () => void;
63
67
  };
64
68
 
65
69
  type L0ItemProps = L0ItemRootProps & {
@@ -68,10 +72,11 @@ type L0ItemProps = L0ItemRootProps & {
68
72
  path: string[];
69
73
  pinned?: boolean;
70
74
  onRearrange?: StackItemRearrangeHandler<L0ItemData>;
75
+ onItemHover?: (params: { item: Node.Node }) => void;
71
76
  };
72
77
 
73
78
  const useL0ItemClick = ({ item, parent, path }: L0ItemProps, type: string) => {
74
- const { tab, onSelect, onTabChange } = useNavTreeContext();
79
+ const { onSelect, onTabChange } = useNavTreeContext();
75
80
  const { getItem } = useNavTreeState();
76
81
  const [isLg] = useMediaQuery('lg');
77
82
  const runAction = useActionRunner();
@@ -81,17 +86,15 @@ const useL0ItemClick = ({ item, parent, path }: L0ItemProps, type: string) => {
81
86
  switch (type) {
82
87
  case 'action': {
83
88
  const { properties: { caller } = {} } = item;
84
- return void runAction(item as Node.Action, caller ? { parent, caller } : { parent });
89
+ return void runAction(item as Node.Action, caller ? { parent, path, caller } : { parent, path });
85
90
  }
86
-
87
91
  case 'tab':
88
92
  return onTabChange?.(item);
89
-
90
93
  case 'link':
91
94
  return onSelect?.({ item, path, current: !getItem(path).current, option: event.altKey });
92
95
  }
93
96
  },
94
- [item, parent, type, tab, getItem, onSelect, onTabChange, isLg, runAction],
97
+ [item, parent, type, getItem, onSelect, onTabChange, isLg, runAction],
95
98
  );
96
99
  };
97
100
 
@@ -99,62 +102,62 @@ const l0Breakpoints: Record<string, string> = {
99
102
  lg: 'hidden lg:grid',
100
103
  };
101
104
 
102
- const l0ItemRoot =
103
- 'group/l0item flex is-full justify-center items-center relative data[type!="collection"]:cursor-pointer app-no-drag dx-focus-ring-group';
104
-
105
- const l0ItemContent = 'flex justify-center items-center dx-focus-ring-group-indicator transition-colors rounded-sm';
106
-
107
- const L0ItemRoot = forwardRef<HTMLElement, PropsWithChildren<L0ItemRootProps>>(
108
- ({ item, parent, path, children }, forwardedRef) => {
109
- const { getProps } = useNavTreeContext();
110
- const { id, testId } = getProps?.(item, path) ?? {};
111
- const type = l0ItemType(item);
112
- const itemPath = useMemo(() => [...path, item.id], [item.id, path]);
113
-
114
- const { t } = useTranslation(meta.id);
115
- const localizedString = toLocalizedString(item.properties.label, t);
116
-
117
- const handleClick = useL0ItemClick({ item, parent, path: itemPath }, type);
118
- const rootProps =
119
- type === 'tab'
120
- ? { value: item.id, tabIndex: 0, onClick: handleClick, 'data-testid': testId, 'data-object-id': id }
121
- : { onClick: handleClick, 'data-testid': testId, 'data-object-id': id };
122
-
123
- return (
124
- <Tooltip.Trigger asChild delayDuration={0} side='right' content={localizedString}>
125
- <Tabs.TabPrimitive
126
- {...(rootProps as any)}
127
- data-type={type}
128
- className={mx(l0ItemRoot, l0Breakpoints[item.properties.l0Breakpoint])}
129
- ref={forwardedRef}
130
- >
131
- {children}
132
- </Tabs.TabPrimitive>
133
- </Tooltip.Trigger>
134
- );
135
- },
105
+ const L0ItemRoot = memo(
106
+ forwardRef<HTMLButtonElement, PropsWithChildren<L0ItemRootProps>>(
107
+ ({ item, parent, path, onMouseEnter, children }, forwardedRef) => {
108
+ const { t } = useTranslation(meta.id);
109
+ const { model } = useNavTreeContext();
110
+ const itemPath = useMemo(() => [...path, item.id], [item.id, path]);
111
+ const { id, testId } = useAtomValue(model.itemProps(itemPath));
112
+ const localizedString = toLocalizedString(item.properties.label, t);
113
+
114
+ const type = l0ItemType(item);
115
+ const handleClick = useL0ItemClick({ item, parent, path: itemPath }, type);
116
+
117
+ return (
118
+ <Tooltip.Trigger asChild delayDuration={0} side='right' content={localizedString}>
119
+ <Tabs.TabPrimitive
120
+ className={mx(
121
+ 'group/l0item flex w-full justify-center items-center relative',
122
+ 'dx-app-no-drag dx-focus-ring-group data[type!="collection"]:cursor-pointer',
123
+ l0Breakpoints[item.properties.l0Breakpoint],
124
+ )}
125
+ tabIndex={type === 'tab' ? 0 : undefined}
126
+ data-type={type}
127
+ data-testid={testId}
128
+ data-object-id={id}
129
+ value={item.id}
130
+ onClick={handleClick}
131
+ onMouseEnter={onMouseEnter}
132
+ ref={forwardedRef}
133
+ >
134
+ {children}
135
+ </Tabs.TabPrimitive>
136
+ </Tooltip.Trigger>
137
+ );
138
+ },
139
+ ),
136
140
  );
137
141
 
138
142
  export const L0ItemActiveTabIndicator = ({ classNames }: ThemedClassName<{}>) => (
139
143
  <div
140
144
  role='none'
141
145
  className={mx(
142
- 'hidden group-aria-selected/l0item:block absolute inline-start-0 inset-block-2 is-1 bg-accentSurface rounded-ie',
146
+ 'hidden group-aria-selected/l0item:block absolute start-0 h-6 w-1.5 bg-accent-surface rounded-sm',
143
147
  classNames,
144
148
  )}
145
149
  />
146
150
  );
147
151
 
148
152
  // TODO(burdon): Factor out pinned (non-draggable) items.
149
- const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
153
+ const L0Item = memo(({ item, parent, path, pinned, onRearrange, onItemHover }: L0ItemProps) => {
150
154
  const { t } = useTranslation(meta.id);
151
- const itemElement = useRef<HTMLElement | null>(null);
155
+ const itemElement = useRef<HTMLButtonElement | null>(null);
152
156
  const [closestEdge, setEdge] = useState<Edge | null>(null);
153
157
  const localizedString = toLocalizedString(item.properties.label, t);
154
158
  const hue = item.properties.hue ?? null;
155
159
 
156
160
  useLayoutEffect(() => {
157
- // NOTE(thure): This is copied from StackItem, perhaps this should be DRYed out.
158
161
  if (!itemElement.current || !onRearrange) {
159
162
  return;
160
163
  }
@@ -209,17 +212,19 @@ const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
209
212
  );
210
213
  }, [item, onRearrange]);
211
214
 
215
+ const handleMouseEnter = useCallback(() => onItemHover?.({ item }), [item, onItemHover]);
216
+
212
217
  return (
213
- <L0ItemRoot ref={itemElement} item={item} parent={parent} path={path}>
218
+ <L0ItemRoot ref={itemElement} item={item} parent={parent} path={path} onMouseEnter={handleMouseEnter}>
214
219
  <div
215
220
  role='none'
216
221
  data-frame={true}
217
- {...(hue && { style: { background: `var(--dx-${hue}Surface)` } })}
222
+ {...(hue && { style: { background: `var(--color-${hue}-surface)` } })}
218
223
  className={mx(
219
- l0ItemContent,
224
+ 'flex justify-center items-center dx-focus-ring-group-indicator transition-colors rounded-sm',
220
225
  pinned
221
- ? 'p-2 group-hover/l0item:bg-activeSurface'
222
- : 'is-[--l0-avatar-size] bs-[--l0-avatar-size] bg-activeSurface',
226
+ ? 'p-2 group-hover/l0item:bg-active-surface'
227
+ : 'w-(--dx-l0-avatar-size) h-(--dx-l0-avatar-size) bg-active-surface',
223
228
  )}
224
229
  >
225
230
  <ItemAvatar item={item} />
@@ -231,17 +236,19 @@ const L0Item = ({ item, parent, path, pinned, onRearrange }: L0ItemProps) => {
231
236
  {closestEdge && <ListItem.DropIndicator edge={closestEdge} />}
232
237
  </L0ItemRoot>
233
238
  );
234
- };
239
+ });
235
240
 
236
241
  const ItemAvatar = ({ item }: Pick<L0ItemProps, 'item'>) => {
237
242
  const { t } = useTranslation(meta.id);
238
- const type = l0ItemType(item);
243
+
244
+ // Actions.
239
245
  if (item.properties.icon) {
240
246
  const hue = item.properties.hue ?? null;
241
- const hueFgStyle = hue && { style: { color: `var(--dx-${hue}SurfaceText)` } };
247
+ const hueFgStyle = hue && { style: { color: `var(--color-${hue}-surface-text)` } };
242
248
  return <Icon icon={item.properties.icon} size={6} {...hueFgStyle} />;
243
249
  }
244
250
 
251
+ const type = l0ItemType(item);
245
252
  if (type === 'tab' && item.properties.disposition !== 'pin-end') {
246
253
  const hue = item.properties.hue ?? null;
247
254
  const localizedString = toLocalizedString(item.properties.label, t);
@@ -262,9 +269,18 @@ export type L0MenuProps = {
262
269
  userAccountItem?: Node.Node;
263
270
  parent?: Node.Node;
264
271
  path: string[];
272
+ onItemHover?: (params: { item: Node.Node }) => void;
265
273
  };
266
274
 
267
- export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountItem, parent, path }: L0MenuProps) => {
275
+ export const L0Menu = ({
276
+ menuActions,
277
+ topLevelItems,
278
+ pinnedItems,
279
+ userAccountItem,
280
+ parent,
281
+ path,
282
+ onItemHover,
283
+ }: L0MenuProps) => {
268
284
  const { t } = useTranslation(meta.id);
269
285
  const runAction = useActionRunner();
270
286
  const handleAction = useCallback(
@@ -299,76 +315,50 @@ export const L0Menu = ({ menuActions, topLevelItems, pinnedItems, userAccountIte
299
315
 
300
316
  return (
301
317
  <Tabs.Tablist
318
+ data-tauri-drag-region
302
319
  classNames={[
303
- 'group/l0 absolute z-[1] inset-block-0 inline-start-0 rounded-is',
304
- 'grid grid-cols-[var(--l0-size)] grid-rows-[var(--rail-size)_1fr_min-content_var(--l0-size)] contain-layout',
305
- '!is-[--l0-size] bg-baseSurface border-ie border-subduedSeparator app-drag pbe-[env(safe-area-inset-bottom)]',
320
+ 'group/l0 absolute z-[1] inset-y-0 start-0 rounded-is',
321
+ 'grid grid-cols-[var(--dx-l0-size)] grid-rows-[var(--dx-rail-size)_1fr_min-content_var(--dx-l0-size)] dx-contain-layout',
322
+ 'w-(--dx-l0-size) bg-toolbar-surface dx-app-drag pb-[env(safe-area-inset-bottom)]',
323
+ '[body[data-platform="macos"]_&]:pt-[30px]',
324
+ '[body[data-platform="ios"]_&]:pt-[max(env(safe-area-inset-top),0.25rem)]',
306
325
  ]}
307
326
  >
308
327
  {/* TODO(wittjosiah): Use L0Item trigger. */}
309
- <MenuProvider onAction={handleAction}>
310
- <DropdownMenu.Root group={parent} items={menuActions}>
311
- <Tooltip.Trigger content={t('app menu label')} side='right' asChild>
312
- <Tabs.TabPrimitive value='options' asChild role='button'>
313
- <DropdownMenu.Trigger
314
- data-testid='spacePlugin.addSpace'
315
- className={mx(
316
- l0ItemRoot,
317
- 'grid place-items-center dx-focus-ring-group',
318
- '[body[data-platform="macos"]_&]:mt-[30px]',
319
- )}
320
- >
321
- <div
322
- role='none'
323
- className={mx(
324
- l0ItemContent,
325
- 'is-[--rail-action] bs-[--rail-action] group-hover/l0item:bg-hoverSurface',
326
- )}
327
- >
328
- <Icon icon='ph--list--regular' size={5} />
329
- </div>
330
- </DropdownMenu.Trigger>
331
- </Tabs.TabPrimitive>
332
- </Tooltip.Trigger>
333
- </DropdownMenu.Root>
334
- </MenuProvider>
328
+ <Menu.Root onAction={handleAction}>
329
+ <Menu.Trigger asChild data-testid='spacePlugin.addSpace'>
330
+ <div role='none' className='grid place-items-center'>
331
+ <IconButton variant='ghost' icon='ph--list--regular' iconOnly label={t('app-menu.label')} />
332
+ </div>
333
+ </Menu.Trigger>
334
+ <Menu.Content group={parent} items={menuActions} />
335
+ </Menu.Root>
335
336
 
336
337
  {/* Space list. */}
337
- <ScrollArea.Root>
338
- <ScrollArea.Viewport>
339
- <div
340
- role='none'
341
- className={mx([
342
- 'flex flex-col gap-1 pbs-1',
343
- '[body[data-platform="macos"]_&]:pbs-[30px]',
344
- '[body[data-platform="ios"]_&]:pbs-[max(env(safe-area-inset-top),0.25rem)]',
345
- ])}
346
- >
347
- {topLevelItems.map((item) => (
348
- <L0Item
349
- key={item.id}
350
- item={item}
351
- parent={parent}
352
- path={path}
353
- {...(hasRearrangeableItems && { onRearrange: handleRearrange })}
354
- />
355
- ))}
356
- </div>
357
- <ScrollArea.Scrollbar orientation='vertical'>
358
- <ScrollArea.Thumb />
359
- </ScrollArea.Scrollbar>
338
+ <ScrollArea.Root centered thin orientation='vertical'>
339
+ <ScrollArea.Viewport classNames='flex flex-col gap-2 py-1'>
340
+ {topLevelItems.map((item) => (
341
+ <L0Item
342
+ key={item.id}
343
+ item={item}
344
+ parent={parent}
345
+ path={path}
346
+ onItemHover={onItemHover}
347
+ {...(hasRearrangeableItems && { onRearrange: handleRearrange })}
348
+ />
349
+ ))}
360
350
  </ScrollArea.Viewport>
361
351
  </ScrollArea.Root>
362
352
 
363
353
  {/* Actions. */}
364
- <div role='none' className='grid grid-cols-1 auto-rows-[--rail-action] pbs-2'>
354
+ <div role='none' className='grid grid-cols-1 auto-rows-(--dx-rail-action) pt-2'>
365
355
  {pinnedItems.map((item) => (
366
356
  <L0Item key={item.id} item={item} parent={parent} path={path} pinned />
367
357
  ))}
368
358
  </div>
369
359
 
370
360
  {userAccountItem && (
371
- <div role='none' className='grid app-no-drag'>
361
+ <div role='none' className='grid dx-app-no-drag'>
372
362
  <L0ItemRoot key={userAccountItem.id} item={userAccountItem} parent={parent} path={path}>
373
363
  <UserAccountAvatar
374
364
  userId={userAccountItem.properties.userId}