Skip to content

Commit 8bd3897

Browse files
authored
refactor: make new tree sortable (#4145)
Added dnd support for the new tree with pragmatic-drag-and-drop. Can be tested in stories. New drop indicator reuse pragmatic utility and much simpler to maintain than previously used horizontal shift. https://github.com/user-attachments/assets/f3cdd80f-0c2d-4f4a-a140-aee66ad8b29f
1 parent d48149f commit 8bd3897

File tree

8 files changed

+544
-140
lines changed

8 files changed

+544
-140
lines changed

apps/builder/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"ci:migrate": "migrations migrate"
1818
},
1919
"dependencies": {
20-
"@atlaskit/pragmatic-drag-and-drop": "^1.1.11",
20+
"@atlaskit/pragmatic-drag-and-drop": "^1.3.1",
2121
"@codemirror/autocomplete": "^6.18.0",
2222
"@codemirror/commands": "^6.6.0",
2323
"@codemirror/lang-html": "^6.4.9",

packages/design-system/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
"react-dom": "18.3.0-canary-14898b6a9-20240318"
2929
},
3030
"dependencies": {
31+
"@atlaskit/pragmatic-drag-and-drop": "^1.3.1",
32+
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^1.4.0",
33+
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
3134
"@floating-ui/dom": "^1.6.5",
3235
"@radix-ui/colors": "^3.0.0",
3336
"@radix-ui/react-accessible-icon": "^1.1.0",

packages/design-system/src/components/__DEPRECATED__/tree/tree.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { ReactNode } from "react";
22
import { useState, useMemo, useRef, useCallback, useEffect } from "react";
33
import { createPortal } from "react-dom";
44
import { FocusScope, useFocusManager } from "@react-aria/focus";
5-
import { ListPositionIndicator } from "../../list-position-indicator";
5+
import { TreePositionIndicator } from "../../list-position-indicator";
66
import {
77
TreeNode,
88
INDENT,
@@ -373,11 +373,10 @@ export const Tree = <Data extends { id: string }>({
373373
<Box css={{ height: theme.spacing[7] }}></Box>
374374
{shiftedDropTarget?.placement &&
375375
createPortal(
376-
<ListPositionIndicator
376+
<TreePositionIndicator
377377
x={shiftedDropTarget.placement.x}
378378
y={shiftedDropTarget.placement.y}
379379
length={shiftedDropTarget.placement.length}
380-
withNub
381380
/>,
382381
document.body
383382
)}

packages/design-system/src/components/list-position-indicator.stories.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { ListPositionIndicator } from "./list-position-indicator";
1+
import {
2+
ListPositionIndicator,
3+
TreePositionIndicator,
4+
} from "./list-position-indicator";
25
import { StorySection, StoryGrid } from "./storybook";
36

47
export default {
@@ -31,7 +34,7 @@ export const Demo = () => (
3134
height: 30,
3235
}}
3336
>
34-
<ListPositionIndicator x={0} y={0} length={200} withNub />
37+
<TreePositionIndicator x={0} y={0} length={200} />
3538
</div>
3639
</StoryGrid>
3740
</StorySection>
@@ -56,7 +59,7 @@ export const Demo = () => (
5659
height: 30,
5760
}}
5861
>
59-
<ListPositionIndicator x={0} y={0} length={200} withNub />
62+
<TreePositionIndicator x={0} y={0} length={200} />
6063
</div>
6164
</StoryGrid>
6265
</StorySection>

packages/design-system/src/components/list-position-indicator.tsx

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,18 @@ const OUTLINE_WIDTH = 1;
1212

1313
// overlap the line with the circle by this much
1414
// to make sure they are connected
15-
const OVERLAP = 1;
15+
const OVERLAP = 2;
16+
17+
const Container = styled(Box, {
18+
position: "absolute",
19+
});
1620

1721
const CircleOutline = styled(Box, {
1822
width: CIRCLE_SIZE + OUTLINE_WIDTH * 2,
1923
height: CIRCLE_SIZE + OUTLINE_WIDTH * 2,
2024
position: "absolute",
25+
top: -CIRCLE_SIZE / 2 - OUTLINE_WIDTH,
26+
left: -CIRCLE_SIZE / 2 - OUTLINE_WIDTH,
2127
borderRadius: "50%",
2228
pointerEvents: "none",
2329
bc: theme.colors.borderContrast,
@@ -27,62 +33,61 @@ const Circle = styled(Box, {
2733
width: CIRCLE_SIZE,
2834
height: CIRCLE_SIZE,
2935
position: "absolute",
30-
border: `solid ${theme.colors.backgroundPrimary}`,
31-
borderWidth: 2,
36+
top: -CIRCLE_SIZE / 2,
37+
left: -CIRCLE_SIZE / 2,
38+
border: `2px solid ${theme.colors.backgroundPrimary}`,
3239
borderRadius: "50%",
3340
pointerEvents: "none",
3441
});
3542

3643
const Line = styled(Box, {
3744
boxSizing: "content-box",
3845
position: "absolute",
39-
background: theme.colors.backgroundPrimary,
46+
top: -LINE_THICKNESS / 2,
47+
left: 0,
48+
width: "100%",
49+
height: LINE_THICKNESS,
50+
backgroundColor: theme.colors.backgroundPrimary,
4051
pointerEvents: "none",
4152
outline: `solid ${theme.colors.borderContrast}`,
4253
outlineWidth: OUTLINE_WIDTH,
4354
});
4455

56+
const LineWithNub = styled(Line, {
57+
left: CIRCLE_SIZE / 2 - OVERLAP,
58+
width: `calc(100% - ${CIRCLE_SIZE / 2 - OVERLAP}px)`,
59+
});
60+
4561
export const ListPositionIndicator = ({
4662
x,
4763
y,
4864
length,
49-
withNub = false,
5065
}: {
51-
x: number;
52-
y: number;
53-
length: number;
54-
withNub?: boolean;
55-
}) =>
56-
withNub ? (
57-
<>
58-
<CircleOutline
59-
style={{
60-
top: y - CIRCLE_SIZE / 2 - OUTLINE_WIDTH,
61-
left: x - CIRCLE_SIZE / 2 - OUTLINE_WIDTH,
62-
}}
63-
/>
64-
<Line
65-
style={{
66-
top: y - LINE_THICKNESS / 2,
67-
left: x + (CIRCLE_SIZE / 2 - OVERLAP),
68-
width: length - (CIRCLE_SIZE / 2 - OVERLAP),
69-
height: LINE_THICKNESS,
70-
}}
71-
/>
72-
<Circle
73-
style={{
74-
top: y - CIRCLE_SIZE / 2,
75-
left: x - CIRCLE_SIZE / 2,
76-
}}
77-
/>
78-
</>
79-
) : (
80-
<Line
81-
style={{
82-
top: y - LINE_THICKNESS / 2,
83-
left: x,
84-
width: length,
85-
height: LINE_THICKNESS,
86-
}}
87-
/>
66+
x: number | string;
67+
y: number | string;
68+
length: number | string;
69+
}) => {
70+
return (
71+
<Container style={{ top: y, left: x, width: length }}>
72+
<Line />
73+
</Container>
74+
);
75+
};
76+
77+
export const TreePositionIndicator = ({
78+
x,
79+
y,
80+
length,
81+
}: {
82+
x: number | string;
83+
y: number | string;
84+
length: number | string;
85+
}) => {
86+
return (
87+
<Container style={{ top: y, left: x, width: length }}>
88+
<CircleOutline />
89+
<LineWithNub />
90+
<Circle />
91+
</Container>
8892
);
93+
};

0 commit comments

Comments
 (0)