@dxos/plugin-navtree 0.7.4-staging.f7e8224 → 0.7.5-feature-compute.4d9d99a

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 (84) hide show
  1. package/dist/lib/browser/app-graph-builder-OF4MMBLH.mjs +42 -0
  2. package/dist/lib/browser/app-graph-builder-OF4MMBLH.mjs.map +7 -0
  3. package/dist/lib/browser/chunk-IMGT2LAL.mjs +658 -0
  4. package/dist/lib/browser/chunk-IMGT2LAL.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-PSVCPL4T.mjs → chunk-KOXMEAOS.mjs} +5 -3
  6. package/dist/lib/browser/chunk-KOXMEAOS.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-OI7AAA6Q.mjs +15 -0
  8. package/dist/lib/browser/chunk-OI7AAA6Q.mjs.map +7 -0
  9. package/dist/lib/browser/index.mjs +106 -1212
  10. package/dist/lib/browser/index.mjs.map +4 -4
  11. package/dist/lib/browser/intent-resolver-74JPWYBP.mjs +42 -0
  12. package/dist/lib/browser/intent-resolver-74JPWYBP.mjs.map +7 -0
  13. package/dist/lib/browser/keyboard-MUBRTPI5.mjs +46 -0
  14. package/dist/lib/browser/keyboard-MUBRTPI5.mjs.map +7 -0
  15. package/dist/lib/browser/meta.json +1 -1
  16. package/dist/lib/browser/react-surface-6QWXI53A.mjs +189 -0
  17. package/dist/lib/browser/react-surface-6QWXI53A.mjs.map +7 -0
  18. package/dist/lib/browser/state-HT65TAYL.mjs +111 -0
  19. package/dist/lib/browser/state-HT65TAYL.mjs.map +7 -0
  20. package/dist/types/src/NavTreePlugin.d.ts +1 -3
  21. package/dist/types/src/NavTreePlugin.d.ts.map +1 -1
  22. package/dist/types/src/capabilities/app-graph-builder.d.ts +181 -0
  23. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  24. package/dist/types/src/capabilities/capabilities.d.ts +17 -0
  25. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -0
  26. package/dist/types/src/capabilities/index.d.ts +195 -0
  27. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  28. package/dist/types/src/capabilities/intent-resolver.d.ts +4 -0
  29. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
  30. package/dist/types/src/capabilities/keyboard.d.ts +4 -0
  31. package/dist/types/src/capabilities/keyboard.d.ts.map +1 -0
  32. package/dist/types/src/capabilities/react-surface.d.ts +4 -0
  33. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  34. package/dist/types/src/capabilities/state.d.ts +17 -0
  35. package/dist/types/src/capabilities/state.d.ts.map +1 -0
  36. package/dist/types/src/components/CommandsTrigger.d.ts.map +1 -1
  37. package/dist/types/src/components/NavTree.d.ts +2 -2
  38. package/dist/types/src/components/NavTree.d.ts.map +1 -1
  39. package/dist/types/src/components/NavTreeContainer.d.ts.map +1 -1
  40. package/dist/types/src/components/NavTreeFooter.d.ts.map +1 -1
  41. package/dist/types/src/components/NavTreeItemAction.d.ts +4 -8
  42. package/dist/types/src/components/NavTreeItemAction.d.ts.map +1 -1
  43. package/dist/types/src/components/NavTreeItemAction.stories.d.ts +0 -5
  44. package/dist/types/src/components/NavTreeItemAction.stories.d.ts.map +1 -1
  45. package/dist/types/src/components/NotchStart.d.ts.map +1 -1
  46. package/dist/types/src/components/index.d.ts +1 -0
  47. package/dist/types/src/components/index.d.ts.map +1 -1
  48. package/dist/types/src/events.d.ts +4 -0
  49. package/dist/types/src/events.d.ts.map +1 -0
  50. package/dist/types/src/index.d.ts +3 -2
  51. package/dist/types/src/index.d.ts.map +1 -1
  52. package/dist/types/src/meta.d.ts +2 -2
  53. package/dist/types/src/meta.d.ts.map +1 -1
  54. package/dist/types/src/translations.d.ts +0 -1
  55. package/dist/types/src/translations.d.ts.map +1 -1
  56. package/dist/types/src/types.d.ts +1 -1
  57. package/dist/types/src/types.d.ts.map +1 -1
  58. package/dist/types/tsconfig.tsbuildinfo +1 -0
  59. package/package.json +31 -38
  60. package/src/NavTreePlugin.tsx +70 -287
  61. package/src/capabilities/app-graph-builder.ts +40 -0
  62. package/src/capabilities/capabilities.ts +18 -0
  63. package/src/capabilities/index.ts +13 -0
  64. package/src/capabilities/intent-resolver.ts +30 -0
  65. package/src/capabilities/keyboard.ts +54 -0
  66. package/src/capabilities/react-surface.tsx +82 -0
  67. package/src/capabilities/state.ts +100 -0
  68. package/src/components/CommandsDialog.tsx +3 -3
  69. package/src/components/CommandsTrigger.tsx +11 -8
  70. package/src/components/NavTree.tsx +6 -11
  71. package/src/components/NavTreeContainer.tsx +22 -56
  72. package/src/components/NavTreeFooter.tsx +21 -18
  73. package/src/components/NavTreeItemAction.stories.tsx +0 -2
  74. package/src/components/NavTreeItemAction.tsx +51 -317
  75. package/src/components/NotchStart.tsx +8 -7
  76. package/src/components/index.ts +1 -0
  77. package/src/events.ts +11 -0
  78. package/src/index.ts +3 -4
  79. package/src/meta.ts +3 -1
  80. package/src/translations.ts +0 -1
  81. package/src/types.ts +1 -1
  82. package/dist/lib/browser/chunk-PSVCPL4T.mjs.map +0 -7
  83. package/dist/lib/browser/meta.mjs +0 -11
  84. package/dist/lib/browser/meta.mjs.map +0 -7
@@ -0,0 +1,100 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { effect } from '@preact/signals-core';
6
+
7
+ import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
8
+ import { type ReactiveObject, create } from '@dxos/live-object';
9
+ import { Path } from '@dxos/react-ui-mosaic';
10
+
11
+ import { NavTreeCapabilities } from './capabilities';
12
+ import { NAVTREE_PLUGIN } from '../meta';
13
+
14
+ const KEY = `${NAVTREE_PLUGIN}/state`;
15
+
16
+ const getInitialState = () => {
17
+ const stringified = localStorage.getItem(KEY);
18
+ if (!stringified) {
19
+ return;
20
+ }
21
+
22
+ try {
23
+ const cached: [string, { open: boolean; current: boolean }][] = JSON.parse(stringified);
24
+ return cached.map(
25
+ ([key, value]): [
26
+ string,
27
+ ReactiveObject<{
28
+ open: boolean;
29
+ current: boolean;
30
+ }>,
31
+ ] => [key, create({ open: value.open, current: false })],
32
+ );
33
+ } catch {}
34
+ };
35
+
36
+ export default (context: PluginsContext) => {
37
+ // TODO(wittjosiah): This currently needs to be not a ReactiveObject at the root.
38
+ // If it is a ReactiveObject then React errors when initializing new paths because of state change during render.
39
+ // Ideally this could be a ReactiveObject but be able to access and update the root level without breaking render.
40
+ // Wrapping accesses and updates in `untracked` didn't seem to work in all cases.
41
+ const state = new Map<string, ReactiveObject<{ open: boolean; current: boolean }>>(
42
+ getInitialState() ?? [
43
+ // TODO(thure): Initialize these dynamically.
44
+ ['root', create({ open: true, current: false })],
45
+ ['root~dxos.org/plugin/space-spaces', create({ open: true, current: false })],
46
+ ['root~dxos.org/plugin/files', create({ open: true, current: false })],
47
+ ],
48
+ );
49
+
50
+ const getItem = (_path: string[]) => {
51
+ const path = Path.create(..._path);
52
+ const value = state.get(path) ?? create({ open: false, current: false });
53
+ if (!state.has(path)) {
54
+ state.set(path, value);
55
+ }
56
+
57
+ return value;
58
+ };
59
+
60
+ const setItem = (path: string[], key: 'open' | 'current', next: boolean) => {
61
+ const value = getItem(path);
62
+ value[key] = next;
63
+
64
+ localStorage.setItem(KEY, JSON.stringify(Array.from(state.entries())));
65
+ };
66
+
67
+ const isOpen = (path: string[]) => getItem(path).open;
68
+ const isCurrent = (path: string[]) => getItem(path).current;
69
+
70
+ const location = context.requestCapability(Capabilities.Location);
71
+ const layout = context.requestCapability(Capabilities.Layout);
72
+
73
+ let previous: string[] = [];
74
+ const unsubscribe = effect(() => {
75
+ const part = layout.layoutMode === 'solo' ? 'solo' : 'main';
76
+ const current = location.active[part]?.map(({ id }) => id) ?? [];
77
+ const removed = previous.filter((id) => !current.includes(id));
78
+ previous = current;
79
+
80
+ // TODO(wittjosiah): This is setTimeout because there's a race between the keys be initialized.
81
+ // This could be avoided if the location was a path as well and not just an id.
82
+ setTimeout(() => {
83
+ removed.forEach((id) => {
84
+ const keys = Array.from(state.keys()).filter((key) => Path.last(key) === id);
85
+ keys.forEach((key) => {
86
+ setItem(Path.parts(key), 'current', false);
87
+ });
88
+ });
89
+
90
+ current.forEach((id) => {
91
+ const keys = Array.from(new Set([...state.keys(), id])).filter((key) => Path.last(key) === id);
92
+ keys.forEach((key) => {
93
+ setItem(Path.parts(key), 'current', true);
94
+ });
95
+ });
96
+ });
97
+ });
98
+
99
+ return contributes(NavTreeCapabilities.State, { state, getItem, setItem, isOpen, isCurrent }, () => unsubscribe());
100
+ };
@@ -4,7 +4,7 @@
4
4
 
5
5
  import React, { useMemo, useState } from 'react';
6
6
 
7
- import { useIntentDispatcher, LayoutAction } from '@dxos/app-framework';
7
+ import { useIntentDispatcher, LayoutAction, createIntent } from '@dxos/app-framework';
8
8
  import { type ActionLike, isActionGroup, isAction } from '@dxos/app-graph';
9
9
  import { Keyboard, keySymbols } from '@dxos/keyboard';
10
10
  import { useGraph } from '@dxos/plugin-graph';
@@ -19,7 +19,7 @@ import { KEY_BINDING, NAVTREE_PLUGIN } from '../meta';
19
19
  export const CommandsDialogContent = ({ selected: initial }: { selected?: string }) => {
20
20
  const { t } = useTranslation(NAVTREE_PLUGIN);
21
21
  const [selected, setSelected] = useState<string | undefined>(initial);
22
- const dispatch = useIntentDispatcher();
22
+ const { dispatchPromise: dispatch } = useIntentDispatcher();
23
23
  const { graph } = useGraph();
24
24
 
25
25
  // Traverse graph.
@@ -83,7 +83,7 @@ export const CommandsDialogContent = ({ selected: initial }: { selected?: string
83
83
  return;
84
84
  }
85
85
 
86
- void dispatch({ action: LayoutAction.SET_LAYOUT, data: { element: 'dialog', state: false } });
86
+ void dispatch(createIntent(LayoutAction.SetLayout, { element: 'dialog', state: false }));
87
87
  setTimeout(() => {
88
88
  const node = graph.nodes(group ?? action, { relation: 'inbound' })[0];
89
89
  void (node && isAction(action) && action.data({ node, caller: KEY_BINDING }));
@@ -5,24 +5,27 @@
5
5
  import { MagnifyingGlass } from '@phosphor-icons/react';
6
6
  import React from 'react';
7
7
 
8
- import { LayoutAction, useIntent } from '@dxos/app-framework';
8
+ import { createIntent, LayoutAction, useIntentDispatcher } from '@dxos/app-framework';
9
9
  import { Button, useTranslation } from '@dxos/react-ui';
10
10
  import { getSize } from '@dxos/react-ui-theme';
11
11
 
12
- import { NAVTREE_PLUGIN } from '../meta';
12
+ import { COMMANDS_DIALOG, NAVTREE_PLUGIN } from '../meta';
13
13
 
14
14
  // TODO(thure): Refactor to be handled by a more appropriate plugin.
15
15
  export const CommandsTrigger = () => {
16
- const { dispatch } = useIntent();
16
+ const { dispatchPromise: dispatch } = useIntentDispatcher();
17
17
  const { t } = useTranslation(NAVTREE_PLUGIN);
18
18
  return (
19
19
  <Button
20
- classNames='w-full h-full !rounded-none'
20
+ classNames='m-1 !pli-1 lg:!pli-2'
21
21
  onClick={() =>
22
- dispatch({
23
- action: LayoutAction.SET_LAYOUT,
24
- data: { element: 'dialog', component: `${NAVTREE_PLUGIN}/Commands`, dialogBlockAlign: 'start' },
25
- })
22
+ dispatch(
23
+ createIntent(LayoutAction.SetLayout, {
24
+ element: 'dialog',
25
+ component: COMMANDS_DIALOG,
26
+ dialogBlockAlign: 'start',
27
+ }),
28
+ )
26
29
  }
27
30
  >
28
31
  <span className='text-description font-normal grow text-start'>{t('command list input placeholder')}</span>
@@ -23,14 +23,13 @@ export type NavTreeProps = Omit<
23
23
 
24
24
  export const NavTree = ({ getActions, loadDescendents, renderItemEnd, popoverAnchorId, ...props }: NavTreeProps) => {
25
25
  const renderColumns = useCallback<NonNullable<TreeProps<NavTreeItemGraphNode>['renderColumns']>>(
26
- ({ item, path, menuOpen, setMenuOpen }) => {
26
+ ({ item, path, open }) => {
27
27
  return (
28
28
  <NavTreeColumns
29
29
  path={path}
30
30
  node={item}
31
31
  getActions={getActions}
32
- menuOpen={menuOpen}
33
- setMenuOpen={setMenuOpen}
32
+ open={open}
34
33
  loadDescendents={loadDescendents}
35
34
  renderItemEnd={renderItemEnd}
36
35
  popoverAnchorId={popoverAnchorId}
@@ -54,10 +53,9 @@ type NavTreeColumnsProps = {
54
53
  path: string[];
55
54
  node: Node;
56
55
  getActions: (node: Node) => FlattenedActions;
57
- menuOpen: boolean;
58
- setMenuOpen: (open: boolean) => void;
56
+ open: boolean;
59
57
  loadDescendents?: (node: Node) => MaybePromise<void>;
60
- renderItemEnd?: FC<{ node: Node }>;
58
+ renderItemEnd?: FC<{ node: Node; open: boolean }>;
61
59
  popoverAnchorId?: string;
62
60
  };
63
61
 
@@ -65,8 +63,7 @@ const NavTreeColumns = ({
65
63
  path,
66
64
  node,
67
65
  getActions,
68
- menuOpen,
69
- setMenuOpen,
66
+ open,
70
67
  loadDescendents,
71
68
  renderItemEnd: ItemEnd,
72
69
  popoverAnchorId,
@@ -123,14 +120,12 @@ const NavTreeColumns = ({
123
120
  menuActions={actions}
124
121
  menuType='dropdown'
125
122
  caller={NAV_TREE_ITEM}
126
- menuOpen={menuOpen}
127
- onChangeMenuOpen={setMenuOpen}
128
123
  />
129
124
  ) : (
130
125
  <Treegrid.Cell />
131
126
  )}
132
127
  </ActionRoot>
133
- {ItemEnd && <ItemEnd node={node} />}
128
+ {ItemEnd && <ItemEnd node={node} open={open} />}
134
129
  </>
135
130
  );
136
131
  };
@@ -7,17 +7,16 @@ import { extractInstruction, type Instruction } from '@atlaskit/pragmatic-drag-a
7
7
  import { untracked } from '@preact/signals-core';
8
8
  import React, { memo, useCallback, useEffect } from 'react';
9
9
 
10
- import { LayoutAction, NavigationAction, Surface, useIntentDispatcher } from '@dxos/app-framework';
10
+ import { createIntent, LayoutAction, NavigationAction, useIntentDispatcher, Surface } from '@dxos/app-framework';
11
11
  import { isAction, isActionLike, type Node } from '@dxos/app-graph';
12
12
  import { useGraph } from '@dxos/plugin-graph';
13
13
  import { isEchoObject, isSpace } from '@dxos/react-client/echo';
14
- import { ElevationProvider, useMediaQuery, useSidebars } from '@dxos/react-ui';
14
+ import { useMediaQuery, useSidebars } from '@dxos/react-ui';
15
15
  import { isTreeData, type TreeData, type PropsFromTreeItem } from '@dxos/react-ui-list';
16
16
  import { mx } from '@dxos/react-ui-theme';
17
17
  import { arrayMove } from '@dxos/util';
18
18
 
19
19
  import { NAV_TREE_ITEM, NavTree, type NavTreeProps } from './NavTree';
20
- import { NavTreeFooter } from './NavTreeFooter';
21
20
  import { NAVTREE_PLUGIN } from '../meta';
22
21
  import { type NavTreeItemGraphNode } from '../types';
23
22
  import {
@@ -32,8 +31,8 @@ import {
32
31
  // TODO(thure): Is NavTree truly authoritative in this regard?
33
32
  export const NODE_TYPE = 'dxos/app-graph/node';
34
33
 
35
- const renderItemEnd = ({ node }: { node: Node }) => (
36
- <Surface role='navtree-item-end' data={{ object: node.data, id: node.id }} />
34
+ const renderItemEnd = ({ node, open }: { node: Node; open: boolean }) => (
35
+ <Surface role='navtree-item-end' data={{ id: node.id, subject: node.data, open }} limit={1} />
37
36
  );
38
37
 
39
38
  export type NavTreeContainerProps = {
@@ -43,7 +42,7 @@ export type NavTreeContainerProps = {
43
42
  export const NavTreeContainer = memo(({ isCurrent, popoverAnchorId, ...props }: NavTreeContainerProps) => {
44
43
  const { closeNavigationSidebar } = useSidebars(NAVTREE_PLUGIN);
45
44
  const [isLg] = useMediaQuery('lg', { ssr: false });
46
- const dispatch = useIntentDispatcher();
45
+ const { dispatchPromise: dispatch } = useIntentDispatcher();
47
46
  const { graph } = useGraph();
48
47
 
49
48
  const getActions = useCallback((node: Node) => naturalGetActions(graph, node), [graph]);
@@ -124,28 +123,11 @@ export const NavTreeContainer = memo(({ isCurrent, popoverAnchorId, ...props }:
124
123
 
125
124
  const current = isCurrent(path, node);
126
125
  if (!current) {
127
- void dispatch({
128
- action: NavigationAction.OPEN,
129
- data: {
130
- activeParts: {
131
- main: [node.id],
132
- },
133
- },
134
- });
126
+ void dispatch(createIntent(NavigationAction.Open, { activeParts: { main: [node.id] } }));
135
127
  } else if (option) {
136
- void dispatch({
137
- action: NavigationAction.CLOSE,
138
- data: {
139
- activeParts: {
140
- main: [node.id],
141
- },
142
- },
143
- });
128
+ void dispatch(createIntent(NavigationAction.Close, { activeParts: { main: [node.id] } }));
144
129
  } else {
145
- void dispatch({
146
- action: LayoutAction.SCROLL_INTO_VIEW,
147
- data: { id: node.id },
148
- });
130
+ void dispatch(createIntent(LayoutAction.ScrollIntoView, { id: node.id }));
149
131
  }
150
132
 
151
133
  const defaultAction = graph.actions(node).find((action) => action.properties?.disposition === 'default');
@@ -219,36 +201,20 @@ export const NavTreeContainer = memo(({ isCurrent, popoverAnchorId, ...props }:
219
201
  });
220
202
  }, [graph]);
221
203
 
204
+ // TODO(thure): What gives this an inline `overflow: initial`?
222
205
  return (
223
- <ElevationProvider elevation='chrome'>
224
- <div
225
- role='none'
226
- className='grid grid-cols-1 grid-rows-[var(--rail-size)_1fr_min-content] bs-full overflow-hidden'
227
- >
228
- {/* TODO(wittjosiah): Factor out surfaces to layout? */}
229
- <div role='none' className='border-be border-separator'>
230
- <Surface role='search-input' limit={1} />
231
- </div>
232
-
233
- {/* TODO(thure): What gives this an inline `overflow: initial`? */}
234
- <div role='none' className='border-be border-separator !overflow-y-auto'>
235
- <NavTree
236
- id={graph.root.id}
237
- getActions={getActions}
238
- getItems={getItems}
239
- getProps={getProps}
240
- isCurrent={isCurrent}
241
- loadDescendents={loadDescendents}
242
- renderItemEnd={renderItemEnd}
243
- popoverAnchorId={popoverAnchorId}
244
- canDrop={canDrop}
245
- onSelect={handleSelect}
246
- {...props}
247
- />
248
- </div>
249
-
250
- <NavTreeFooter />
251
- </div>
252
- </ElevationProvider>
206
+ <NavTree
207
+ id={graph.root.id}
208
+ getActions={getActions}
209
+ getItems={getItems}
210
+ getProps={getProps}
211
+ isCurrent={isCurrent}
212
+ loadDescendents={loadDescendents}
213
+ renderItemEnd={renderItemEnd}
214
+ popoverAnchorId={popoverAnchorId}
215
+ canDrop={canDrop}
216
+ onSelect={handleSelect}
217
+ {...props}
218
+ />
253
219
  );
254
220
  });
@@ -2,16 +2,15 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { ArrowSquareOut, GearSix, Warning } from '@phosphor-icons/react';
6
5
  import { formatDistance } from 'date-fns/formatDistance';
7
6
  import React from 'react';
8
7
 
9
8
  import {
10
9
  type LayoutPart,
11
10
  SettingsAction,
12
- parseNavigationPlugin,
13
- useResolvePlugin,
14
11
  useIntentDispatcher,
12
+ createIntent,
13
+ usePluginManager,
15
14
  } from '@dxos/app-framework';
16
15
  import { useConfig } from '@dxos/react-client';
17
16
  import {
@@ -24,13 +23,15 @@ import {
24
23
  useDefaultValue,
25
24
  useSidebars,
26
25
  useTranslation,
26
+ Icon,
27
+ IconButton,
27
28
  } from '@dxos/react-ui';
28
29
  import { LayoutControls } from '@dxos/react-ui-stack';
29
- import { getSize, mx } from '@dxos/react-ui-theme';
30
+ import { mx } from '@dxos/react-ui-theme';
30
31
 
31
32
  import { NAVTREE_PLUGIN } from '../meta';
32
33
 
33
- const buttonStyles = 'pli-1.5 text-xs font-normal';
34
+ const buttonStyles = '!pli-1.5 text-xs font-normal';
34
35
 
35
36
  const repo = 'https://github.com/dxos/dxos';
36
37
 
@@ -41,9 +42,9 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
41
42
  const config = useConfig();
42
43
  const { t } = useTranslation(NAVTREE_PLUGIN);
43
44
  const { navigationSidebarOpen } = useSidebars(NAVTREE_PLUGIN);
44
- const dispatch = useIntentDispatcher();
45
+ const { dispatchPromise: dispatch } = useIntentDispatcher();
45
46
  const { version, timestamp, commitHash } = config.values.runtime?.app?.build ?? {};
46
- const navigationPlugin = useResolvePlugin(parseNavigationPlugin);
47
+ const manager = usePluginManager();
47
48
  const [_, v] = version?.match(VERSION_REGEX) ?? [];
48
49
 
49
50
  const releaseUrl =
@@ -57,7 +58,7 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
57
58
  <div
58
59
  role='none'
59
60
  className={mx(
60
- 'flex bs-[--rail-size] pbe-[env(safe-area-inset-bottom)] box-content justify-end',
61
+ 'flex pbe-[env(safe-area-inset-bottom)] box-content justify-end',
61
62
  layoutPart === 'complementary' && 'md:justify-end flex-row-reverse',
62
63
  )}
63
64
  >
@@ -75,7 +76,7 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
75
76
  >
76
77
  <Message.Root valence='warning' className='rounded-be-none p-5'>
77
78
  <Message.Title>
78
- <Warning weight='duotone' className='inline mie-2 is-6 bs-6' />
79
+ <Icon icon='ph--warning--duotone' size={6} classNames='inline mie-2' />
79
80
  <span>{t('warning title')}</span>
80
81
  </Message.Title>
81
82
  <Message.Body>
@@ -83,7 +84,7 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
83
84
  <br />
84
85
  <Link href={previewUrl} target='_blank' rel='noreferrer' variant='neutral'>
85
86
  {t('learn more label')}
86
- <ArrowSquareOut className='inline mis-1' weight='bold' />
87
+ <Icon icon='ph--arrow-square-out--bold' classNames='inline mis-1' />
87
88
  </Link>
88
89
  </Message.Body>
89
90
  </Message.Root>
@@ -96,7 +97,7 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
96
97
  <br />
97
98
  <Link href={releaseUrl} target='_blank' rel='noreferrer' variant='neutral'>
98
99
  {t('see release label')}
99
- <ArrowSquareOut className='inline mis-1' weight='bold' />
100
+ <Icon icon='ph--arrow-square-out--bold' classNames='inline mis-1' />
100
101
  </Link>
101
102
  </p>
102
103
  )}
@@ -120,17 +121,19 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
120
121
  <Tooltip.Root>
121
122
  <Tooltip.Trigger asChild>
122
123
  {/* TODO(burdon): Reconcile with action created by LayoutPlugin. */}
123
- <Button
124
+ <IconButton
125
+ icon='ph--gear-six--regular'
126
+ iconOnly
127
+ label={t('open settings label')}
128
+ size={4}
124
129
  variant='ghost'
125
130
  classNames={buttonStyles}
126
131
  data-testid='treeView.openSettings'
127
132
  data-joyride='welcome/settings'
128
133
  {...(!navigationSidebarOpen && { tabIndex: -1 })}
129
- onClick={() => dispatch({ action: SettingsAction.OPEN })}
130
- >
131
- <span className='sr-only'>{t('open settings label')}</span>
132
- <GearSix className={mx(getSize(5), 'rotate-90')} />
133
- </Button>
134
+ iconClassNames='rotate-90'
135
+ onClick={() => dispatch(createIntent(SettingsAction.Open))}
136
+ />
134
137
  </Tooltip.Trigger>
135
138
  <Tooltip.Portal>
136
139
  <Tooltip.Content classNames='z-[12]'>
@@ -141,7 +144,7 @@ export const NavTreeFooter = (props: { layoutPart?: LayoutPart }) => {
141
144
  </Tooltip.Root>
142
145
 
143
146
  {/* NOTE(thure): Unpinning from the NavTree’s default position in Deck is temporarily disabled. */}
144
- {navigationPlugin?.meta.id === 'dxos.org/plugin/deck' && (
147
+ {manager.enabled.includes('dxos.org/plugin/deck') && (
145
148
  <LayoutControls
146
149
  variant='hide-disabled'
147
150
  capabilities={{
@@ -53,5 +53,3 @@ export default {
53
53
  };
54
54
 
55
55
  export const Default = {};
56
-
57
- export const SearchList = { args: { menuType: 'searchList' } };