Skip to content

Commit dca813f

Browse files
authored
Grid ruler markers (#6654)
**Problem:** Selected grid items should show ruler markers on the borders of the grid to indicate their placement properties. **Fix:** Add the ruler markers to the grid controls for items. **Notes:** - markers currently target the cell bounds, it should change to the middle of the space between cells when we have offset indicator lines (future PR) https://github.com/user-attachments/assets/b0dd3450-70fa-47cc-b627-e9f792f13ad8 **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Play mode Fixes #6656
1 parent 3af65db commit dca813f

File tree

5 files changed

+401
-14
lines changed

5 files changed

+401
-14
lines changed

editor/src/components/canvas/canvas-strategies/strategies/grid-cell-bounds.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,25 @@ export function getClosestGridCellToPointFromMetadata(
6868
return null
6969
}
7070

71-
return getClosestGridCellToPoint(gridCellGlobalFrames, point)
71+
return getClosestGridCellToPoint(gridCellGlobalFrames, point, 'exclusive')
7272
}
7373

7474
export function getClosestGridCellToPoint(
7575
gridCellGlobalFrames: GridCellGlobalFrames,
7676
point: CanvasPoint,
77+
distanceMatch: 'inclusive' | 'exclusive',
7778
): TargetGridCellData | null {
7879
let closestCell: TargetGridCellData | null = null
7980
let closestDistance = Infinity
8081

8182
for (let i = 0; i < gridCellGlobalFrames.length; i++) {
8283
for (let j = 0; j < gridCellGlobalFrames[i].length; j++) {
8384
const currentDistance = distanceFromPointToRectangle(point, gridCellGlobalFrames[i][j])
84-
if (currentDistance < closestDistance) {
85+
const closeEnough =
86+
distanceMatch === 'inclusive'
87+
? currentDistance <= closestDistance
88+
: currentDistance < closestDistance
89+
if (closeEnough) {
8590
closestCell = {
8691
gridCellCoordinates: gridCellCoordinates(i + 1, j + 1),
8792
cellCanvasRectangle: gridCellGlobalFrames[i][j],
@@ -102,7 +107,7 @@ export function getGridChildCellCoordBoundsFromCanvas(
102107
return null
103108
}
104109

105-
const cellOrigin = getClosestGridCellToPoint(gridCellGlobalFrames, cellFrame)
110+
const cellOrigin = getClosestGridCellToPoint(gridCellGlobalFrames, cellFrame, 'inclusive')
106111
if (cellOrigin == null) {
107112
return null
108113
}
@@ -114,7 +119,7 @@ export function getGridChildCellCoordBoundsFromCanvas(
114119
y: cellFrame.height,
115120
}),
116121
)
117-
const cellEnd = getClosestGridCellToPoint(gridCellGlobalFrames, cellEndPoint)
122+
const cellEnd = getClosestGridCellToPoint(gridCellGlobalFrames, cellEndPoint, 'exclusive')
118123
if (cellEnd == null) {
119124
return null
120125
}

editor/src/components/canvas/canvas-strategies/strategies/grid-helpers.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export function gridPositionToValue(
7373
return p.numericalPosition
7474
}
7575

76-
export function isAutoGridPin(v: GridPositionOrSpan): boolean {
76+
export function isAutoGridPin(v: GridPositionOrSpan | null): boolean {
7777
return isCSSKeyword(v) && v.value === 'auto'
7878
}
7979

@@ -498,6 +498,7 @@ export function getOriginalElementGridConfiguration(
498498
const draggingFromCellCoords = getClosestGridCellToPoint(
499499
gridCellGlobalFrames,
500500
interactionData.dragStart,
501+
'exclusive',
501502
)?.gridCellCoordinates
502503
if (draggingFromCellCoords == null) {
503504
return null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import React from 'react'
2+
import { colorTheme } from '../../../uuiui'
3+
4+
export type RulerMarkerType = 'span-start' | 'span-end' | 'auto' | 'pinned'
5+
6+
const upFacingTriangle = (
7+
<svg width='11' height='11' xmlns='http://www.w3.org/2000/svg'>
8+
<polygon
9+
points='5,1 10,10 0,10'
10+
fill={colorTheme.primary.value}
11+
stroke={colorTheme.white.value}
12+
strokeWidth='0.5'
13+
/>
14+
</svg>
15+
)
16+
17+
const rightFacingTriangle = (
18+
<svg width='11' height='11' xmlns='http://www.w3.org/2000/svg'>
19+
<polygon
20+
points='10,5 0,0 0,10'
21+
fill={colorTheme.primary.value}
22+
stroke={colorTheme.white.value}
23+
strokeWidth='0.5'
24+
/>
25+
</svg>
26+
)
27+
28+
const downFacingTriangle = (
29+
<svg width='11' height='11' xmlns='http://www.w3.org/2000/svg'>
30+
<polygon
31+
points='5,10 0,0 10,0'
32+
fill={colorTheme.primary.value}
33+
stroke={colorTheme.white.value}
34+
strokeWidth='0.5'
35+
/>
36+
</svg>
37+
)
38+
39+
const leftFacingTriangle = (
40+
<svg width='11' height='11' xmlns='http://www.w3.org/2000/svg'>
41+
<polygon
42+
points='0,5 10,0 10,10'
43+
fill={colorTheme.primary.value}
44+
stroke={colorTheme.white.value}
45+
strokeWidth='0.5'
46+
/>
47+
</svg>
48+
)
49+
50+
const verticalPipe = (
51+
<svg width='4' height='11' xmlns='http://www.w3.org/2000/svg'>
52+
<rect
53+
x='0.25'
54+
y='0.25'
55+
width='3'
56+
height='10'
57+
fill={colorTheme.primary.value}
58+
stroke={colorTheme.white.value}
59+
strokeWidth='0.5'
60+
/>
61+
</svg>
62+
)
63+
64+
const horizontalPipe = (
65+
<svg width='11' height='11' xmlns='http://www.w3.org/2000/svg'>
66+
<rect
67+
x='0.25'
68+
y='3.50'
69+
width='10'
70+
height='3'
71+
fill={colorTheme.primary.value}
72+
stroke={colorTheme.white.value}
73+
strokeWidth='0.5'
74+
/>
75+
</svg>
76+
)
77+
78+
export const rulerMarkerIcons: {
79+
[key in RulerMarkerType]: { column: React.ReactNode; row: React.ReactNode }
80+
} = {
81+
'span-start': {
82+
column: rightFacingTriangle,
83+
row: downFacingTriangle,
84+
},
85+
'span-end': {
86+
column: leftFacingTriangle,
87+
row: upFacingTriangle,
88+
},
89+
auto: {
90+
column: verticalPipe,
91+
row: horizontalPipe,
92+
},
93+
pinned: {
94+
column: downFacingTriangle,
95+
row: rightFacingTriangle,
96+
},
97+
}

0 commit comments

Comments
 (0)