chore: drag overlay style updates and accessibility improvements (CODAP-566)#2514
chore: drag overlay style updates and accessibility improvements (CODAP-566)#2514
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates CODAP’s drag-and-drop styling and accessibility, focusing on clearer drop-zone highlighting, better-aligned graph drop zones, and improved screen reader output during drags.
Changes:
- Adds localized screen reader announcements and
aria-roledescriptionfor draggable attributes. - Restyles drag overlay preview and standardizes drop-zone highlight styles across graph/map overlays.
- Adjusts graph drop zone sizing/alignment using plot bounds and adds plot drop-zone insets to avoid overlap with adjacent zones.
- Disables case table scrolling during attribute drags to prevent keyboard drag interactions from scrolling the table.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| v3/src/utilities/translation/lang/en-US.json5 | Adds localized strings for DnD roledescription + announcements. |
| v3/src/lib/dnd-kit/codap-dnd-context.tsx | Adds dnd-kit accessibility announcements for drag start/end/cancel. |
| v3/src/hooks/use-drag-drop.ts | Adds localized aria-roledescription for draggable attributes. |
| v3/src/components/vars.scss | Introduces shared drop-zone-states mixin + highlight token. |
| v3/src/components/graph/graphing-types.ts | Adds shared TS constants for drop zone sizing/gaps. |
| v3/src/components/graph/components/graph.tsx | Computes plot drop-zone insets and passes right-zone presence to add-attribute droppables. |
| v3/src/components/graph/components/graph.scss | Updates add-attribute drop zone dimensions + uses shared mixin. |
| v3/src/components/graph/components/droppable-plot.tsx | Plumbs optional insets through to DroppableSvg. |
| v3/src/components/graph/components/droppable-add-attribute.tsx | Sizes add-attribute drop zones using plot bounds + 1px gap behavior. |
| v3/src/components/drag-drop/attribute-drag-overlay.tsx | Adds drag-indicator icon to the attribute drag overlay. |
| v3/src/components/drag-drop/attribute-drag-overlay.scss | Restyles the drag overlay to match updated visual specs. |
| v3/src/components/data-display/components/droppable-svg.tsx | Adds IDropInsets and applies inset math to overlay bounds. |
| v3/src/components/data-display/components/droppable-svg.scss | Switches to shared drop-zone highlight mixin. |
| v3/src/components/case-table/case-table.tsx | Disables case-table scrolling during attribute drags via a .dragging class. |
| v3/src/components/case-table/case-table.scss | Implements scroll disabling via .case-table.dragging * { overflow: hidden !important; }. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2514 +/- ##
==========================================
+ Coverage 86.90% 86.91% +0.01%
==========================================
Files 785 785
Lines 44388 44457 +69
Branches 11136 10746 -390
==========================================
+ Hits 38577 38642 +65
- Misses 5798 5804 +6
+ Partials 13 11 -2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
codap-v3
|
||||||||||||||||||||||||||||
| Project |
codap-v3
|
| Branch Review |
main
|
| Run status |
|
| Run duration | 02m 10s |
| Commit |
|
| Committer | github-actions[bot] |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
0
|
|
|
0
|
|
|
0
|
|
|
4
|
| View all changes introduced in this branch ↗︎ | |
| "V3.CaseTable.attributeAriaLabel": "Attribute %@, open menu", | ||
| "V3.CaseTable.attributeDragInstructions": "Press Space to drag the attribute within the table or to a graph. Press Enter to open the attribute menu.", | ||
| "V3.DnD.draggableAttribute": "draggable attribute", | ||
| "V3.DnD.onDragStart": "Picked up attribute %@.", |
There was a problem hiding this comment.
Not really a code question, but is there a reason this isn't "Dragging attribute %@.", since click-to-pickup hasn't been implemented.
There was a problem hiding this comment.
kswenson
left a comment
There was a problem hiding this comment.
👍 Looks good -- the following review, developed in conjunction with Claude Code 🤖, identifies a couple of issues worth considering. The horizontal dragging issue seems worth fixing. The dynamically-adjustable drop zones on narrow graphs should be logged as a Jira story if not addressed here.
PR Review Summary
Changes: 15 files, +185 / -65 lines
What it does
Updates the attribute drag overlay and drop-zone styles to match a new Zeplin design, and bundles several keyboard/a11y improvements for attribute dragging. New overlay uses accent border, drop shadow, and a drag-indicator icon; graph add-attribute drop zones get outline-based highlighting and are sized to the plot bounds with a 1px gap between adjacent zones; the table is prevented from scrolling during attribute drags; and dnd-kit now emits localized screen-reader announcements that include the attribute name instead of the raw drag ID.
The approach
- Shared SCSS mixin (
vars.scss): newdrop-zone-statesmixin centralizes the.active/.overstyling previously copy-pasted ingraph.scssanddroppable-svg.scss. Good consolidation. - Plot-bound drop zones:
DroppableAddAttribute(droppable-add-attribute.tsx:55) now readslayout.getComputedBounds("plot")and constrains its dimensions to the plot area, inset bykDropZoneGap.DroppablePlotaccepts anIDropInsetsprop forwarded throughDroppableSvgso the plot drop zone shrinks to leave room for neighboring zones. - Conditional inset calculation (
graph.tsx:399-419): Graph usesuseDndContext()to read the active drag, then asksplaceCanAcceptAttributeIDDropwhether the top/right zones would actually accept this attribute, and only insets the plot drop zone when they would. This avoids visual gaps when no add-attribute zone is showing. - Table scroll suppression (
case-table.tsx:49-67):useDndMonitortoggles adraggingclass on the root via ref;.dragging *forcesoverflow: hidden !importanton all descendants. Direct DOM class manipulation (rather than React state) avoids triggering a re-render of the whole table on every drag. - Screen reader support (
codap-dnd-context.tsx:36-52): customAnnouncementsobject returns localized strings with the attribute name for attribute drags, and returnsundefinedotherwise so dnd-kit's defaults apply to non-attribute drags.onDragOverreturnsundefinedto suppress dnd-kit's per-pixel spam.aria-roledescription="draggable attribute"added viauseDraggableAttribute.
Assessment
Clean, focused PR. The abstractions pay for themselves (shared mixin, IDropInsets prop, single announcement handler). Key design choices that merit attention:
kDropZoneSizeduplicated in SCSS:graph.scsshardcodes50pxfor top/yPlus/right zones whilegraphing-types.tsexportskDropZoneSize = 50. The code comment flags this. Minor drift risk, but acceptable given SCSS/TS boundary.useDndContext()in Graph: reads the full dnd context on every render.activeis reference-stable during a drag, so this triggers renders on drag start/end, not per pixel — fine.- Direct DOM class toggling on the table: unusual for a React component but intentional (performance).
tableRefsurvives because the same element is owned for the tile's lifetime. tabIndex: -1override:useDraggableAttributestill forcestabIndex: -1(RDG compatibility); keyboard drag is initiated elsewhere. Not regressed by this PR.aria-hidden="true"on the drag-indicator icon: correct — the attribute name is the label.
No test changes, which is appropriate for this visual/a11y polish PR — the behavior changes are in CSS/DOM and the screen-reader text.
Issues
- Table
.dragging *blocks horizontal scroll needed to reorder attributes.case-table.scssusesoverflow: hidden !important, which kills both axes. During an attribute drag within a wide table, users need horizontal scrolling to reach a drop target that's off-screen horizontally (drag-to-reorder within the table). Please change tooverflow-y: hidden !importantso vertical scroll is suppressed (the original motivation) while horizontal scroll is preserved. - Fixed 50px drop-zone size is cramped on narrow graphs. In the standard Mammals document, the middle (LifeSpan) graph is ~115px wide. Adding a numeric X attribute to make a scatter plot leaves the yPlus (left) and rightNumeric (right) zones at 50px each, leaving only ~15px for the plot drop zone. The size should probably scale down (or the add-attribute zones should cap at some fraction of the plot width) when space is tight. OK to leave as a future refinement, but worth noting.
Minor notes:
- The SCSS/TS drop-zone-size duplication would be marginally safer as a CSS custom property or SCSS variable consumed from TS. Leave as-is unless convenient.
hasRightDropZoneis computed inGraphand passed as a prop to eachDroppableAddAttribute; each child already callsuseGraphLayoutContext. Fine, but if the plot inset logic grows, consider hoisting more of it.
@kswenson Thanks for catching the horizontal scroll issue. That's fixed in 41acbc2. I'm going to have to skip the dynamically-adjustable drop zones issue, but I made a Jira story for it. |
8b46366 to
cc4cdf1
Compare
CODAP-566
Updates attribute drag overlay and drop zone styles to match new design spec. Also implements some accessibility improvements in support of keyboard dragging.
aria-roledescriptionto draggable attribute elements