# Canvas Panel - Known Issues and TODOs
This document catalogs all known issues, limitations, and TODO items found in the Canvas panel codebase.
## Critical/High Priority TODOs
### Dashboard Scenes Migration
**Location:** `public/app/features/canvas/runtime/scene.tsx:117`
```typescript
// TODO: Will need to update this approach for dashboard scenes
// migration (new dashboard edit experience)
const dashboard = getDashboardSrv().getCurrent();
```
**Impact:** The Canvas panel's editing detection relies on the legacy dashboard service. This will need updating for the new dashboard scenes architecture.
### Connection Anchor Stacking Context
**Location:** `public/app/features/canvas/runtime/scene.tsx:239-242`
```typescript
// TODO: This is a workaround to apply styles to the elements after the size update.
// Remove this after dealing with the connection anchors stacking context issue.
if (this.connections.connectionAnchorDiv) {
this.connections.connectionAnchorDiv.style.display = 'none';
}
```
**Impact:** Connection anchors are hidden during size updates as a workaround. This affects UX during panel resize.
### Frame Functionality
**Location:** `public/app/plugins/panel/canvas/editor/layer/TreeNavigationEditor.tsx:128`
```typescript
// TODO: This functionality is currently kinda broken / no way to decouple / delete created frames at this time
const onFrameSelection = () => {
```
**Impact:** Users cannot properly manage frame (group) elements. This limits the nested element feature.
---
## Medium Priority TODOs
### Rotation with Constraints
**Location:** `public/app/features/canvas/runtime/element.tsx:415`
```typescript
// For elements with rotation, a delta needs to be applied to account for bounding box rotation
// TODO: Fix behavior for top+bottom, left+right, center, and scale constraints
```
**Impact:** Elements with rotation behave unexpectedly when using non-simple constraints.
### SVG Element Style Handling
**Location:** `public/app/features/canvas/runtime/element.tsx:242, 368`
```typescript
// TODO: This is a hack, we should have a better way to handle this
const elementType = this.options.type;
if (!SVGElements.has(elementType)) {
applyStyles(this.dataStyle, this.div);
} else {
removeStyles(this.dataStyle, this.div);
}
```
**Impact:** SVG and non-SVG elements require different style handling, leading to maintenance burden.
### Connection Vertex Cleanup
**Location:** `public/app/plugins/panel/canvas/components/connections/Connections.tsx:444`
```typescript
// TODO for vertex removal, clear out originals?
if (deleteVertex) {
currentVertices.splice(vertexIndex, 1);
}
```
**Impact:** When vertices are removed, the original source/target coordinates may become stale.
### Connection Coordinate Utility
**Location:** `public/app/plugins/panel/canvas/components/connections/Connections.tsx:245`
```typescript
// Convert from DOM coords to connection coords
// TODO: Break this out into util function and add tests
```
**Impact:** Coordinate conversion logic is duplicated and untested.
### Move Event Optimization
**Location:** `public/app/features/canvas/runtime/sceneAbleManagement.ts:312, 331`
```typescript
scene.moved.next(Date.now()); // TODO only on end
```
**Impact:** The `moved` event fires during resize, not just at the end, potentially causing excessive updates.
---
## Low Priority TODOs
### Element-Specific Icons
**Location:** `public/app/plugins/panel/canvas/editor/layer/TreeNavigationEditor.tsx:100`
```typescript
// TODO: Implement element specific icons
return <></>;
```
**Impact:** Tree navigation shows generic icons instead of element-type-specific ones.
### Non-Root Navigation
**Location:** `public/app/plugins/panel/canvas/editor/layer/layerEditor.tsx:69`
```typescript
if (currentLayer && !currentLayer.isRoot()) {
// TODO: the non-root nav option
}
```
**Impact:** Navigation within nested frames is incomplete.
### Action Variables
**Location:** `public/app/features/canvas/runtime/element.tsx:1047`
```typescript
body={action.confirmation(/** TODO: implement actionVars */)}
```
**Impact:** Action confirmation doesn't display variable values.
### Division by Zero
**Location:** `public/app/plugins/panel/canvas/utils.ts:194`
```typescript
// TODO look into a better way to avoid division by zero
if (x2 - x1 === 0) {
x2 += 1;
}
```
**Impact:** Edge case handling is simplistic; could affect connection rendering in edge cases.
### Style Parsing
**Location:** `public/app/plugins/panel/canvas/utils.ts:243`
```typescript
// TODO: there sould be a better way than parseFloat
const width = parseFloat(style.width);
```
**Impact:** Minor - style parsing could be more robust.
### Row Index
**Location:** `public/app/plugins/panel/canvas/utils.ts:325`
```typescript
// @TODO revisit, currently returning last row index for field
export const getRowIndex = (fieldName: string | undefined, scene: Scene) => {
```
**Impact:** Data links may use unexpected row index for fields.
### Pan Workaround
**Location:** `public/app/features/canvas/runtime/sceneAbleManagement.ts:460`
```typescript
// TODO: It was implemented as a workaround to unblock left click metricsValue dropdown,
// but it should be replaced with a more robust solution that doesn't interfere with left click interactions.
function startPanning(e: MouseEvent) {
```
**Impact:** Panning gesture conflicts with element interactions.
### Selection Clear on Zoom
**Location:** `public/app/features/canvas/runtime/sceneAbleManagement.ts:541`
```typescript
// TODO: clear current selection is default behaviour on zoom-in or zoom-out,
// but looks like we prevented this event to trigger at some point
scene.clearCurrentSelection(true);
```
**Impact:** Selection behavior during zoom may be inconsistent.
---
## Accessibility TODOs
### Reduced Motion
**Locations:**
- `public/app/features/canvas/elements/droneTop.tsx:184-189`
- `public/app/features/canvas/elements/droneSide.tsx:125`
- `public/app/features/canvas/elements/droneFront.tsx:126`
```typescript
// TODO: figure out what styles to apply when prefers-reduced-motion is set
// eslint-disable-next-line @grafana/no-unreduced-motion
animationDirection: 'normal',
```
**Impact:** Animated elements don't respect user preference for reduced motion.
---
## Schema TODOs
### Element Config Type
**Location:** `public/app/plugins/panel/canvas/panelcfg.gen.ts:100`
```typescript
/**
* TODO: figure out how to define this (element config(s))
*/
config?: unknown;
```
**Impact:** Element configs are not properly typed in the schema, reducing type safety.
### Default Root Value
**Location:** `public/app/plugins/panel/canvas/panelcfg.gen.ts:130`
```typescript
/**
* The root element of canvas (frame), where all canvas elements are nested
* TODO: Figure out how to define a default value for this
*/
root: {...}
```
**Impact:** No schema-level default for root element structure.
---
## Legacy Migration TODOs
### Color String Migration
**Location:** `public/app/plugins/panel/canvas/utils.ts:117`
```typescript
// @TODO Remove after v10.x
if (isString(c.color)) {
c.color = { fixed: c.color };
}
```
**Impact:** Legacy data format still being converted at runtime. Should be removed in future version.
---
## Workarounds in Place
### Size Update Styles
**Location:** `public/app/features/canvas/runtime/scene.tsx:234-238`
```typescript
// TODO: This is a workaround to apply styles to the elements after the size update.
// It's a good to go approach used by movable creator, but maybe we can find a better way.
this.root.elements.forEach((el) => {
el.applyLayoutStylesToDiv(false);
});
```
**Status:** Working workaround, but could be improved.
### Connection Type Unknown
**Location:** `public/app/plugins/panel/canvas/editor/connectionEditor.tsx:27`
```typescript
// TODO: Fix this unknown (maybe a dimension supplier?)
onChange: (path: string, value: unknown) => {
```
**Status:** Type safety issue in connection editor.
---
## Feature Limitations
### Not Implemented
1. **Curved Connections:** Only straight-line paths supported
2. **Orthogonal Connections:** No auto-routing around elements
3. **Frame Duplication:** Cannot duplicate frame (group) elements
4. **Undo/Redo:** No history for canvas changes
5. **Copy/Paste Between Panels:** Cannot copy elements across panels
6. **Element Grouping UX:** Frame creation/deletion is limited
### Partially Implemented
1. **Nested Frames:** Feature-flagged, incomplete functionality
2. **Pan/Zoom + Selection:** Some interaction conflicts
3. **Rotation + Constraints:** Works but has edge cases
### Known Bugs
1. **Selection on Resize:** Selection may clear unexpectedly during panel resize
2. **Connection Anchors:** May display incorrectly after element rotation
3. **SVG Icon Blinking:** Fixed in #99941 but was a streaming data issue
---
## Performance Concerns
### Identified Issues
1. **Constraint Recalculation:** All elements recalculate position on resize
2. **Connection Updates:** All connections recalculate on any element move
3. **Streaming Data:** Frequent updates can cause excessive re-renders
4. **Large Element Count:** No virtualization for many elements
### Recommendations
1. Debounce resize calculations
2. Only update affected connections
3. Add element virtualization for large canvases
4. Consider caching constraint calculations
---
## Testing Gaps
Based on code analysis, the following areas lack or have minimal testing:
1. Coordinate conversion functions
2. Constraint calculations with rotation
3. Connection vertex manipulation
4. Pan/zoom interactions
5. Multi-element selection operations
6. Frame/nesting operations
---
## Priority Matrix
| Issue | Impact | Effort | Priority |
|-------|--------|--------|----------|
| Dashboard Scenes Migration | High | High | **P0** |
| Frame Functionality | High | Medium | **P1** |
| Rotation + Constraints | Medium | High | **P2** |
| Accessibility (reduced motion) | Medium | Low | **P2** |
| Connection Anchor Stacking | Low | Medium | **P3** |
| Legacy Migration Cleanup | Low | Low | **P3** |
| Element Icons in Tree | Low | Low | **P4** |