Skip to content

refactor: table drag preview using decorations#8597

Merged
Palanikannan1437 merged 3 commits intopreviewfrom
refactor/table-drag-preview
Feb 13, 2026
Merged

refactor: table drag preview using decorations#8597
Palanikannan1437 merged 3 commits intopreviewfrom
refactor/table-drag-preview

Conversation

@aaryan610
Copy link
Member

@aaryan610 aaryan610 commented Jan 29, 2026

Description

This PR improves the drag preview logic for table rows and columns-

  1. The earlier approach of using attributes to toggle cell visibility is removed as it had a chance to persist across sessions and also broadcasted to other users.
  2. We now add decorations to each cell as a pseudo

Type of Change

  • Improvement (change that would cause existing functionality to not work as expected)

Summary by CodeRabbit

  • New Features

    • Table drag now hides selected cell content locally during drag for a smoother, non-persistent preview.
  • Bug Fixes

    • Prevents hidden-content state from persisting after drag operations; content visibility reliably restores afterward.
  • Refactor

    • Simplified internal handling of cell content visibility, removing attribute-based persistence for a cleaner rendering behavior.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 29, 2026

📝 Walkthrough

Walkthrough

Table cell content hiding was changed from a persistent node attribute to transient ProseMirror decorations driven by transaction metadata via a new TableDragStatePlugin; drag handlers now compute selected cell positions and use utilities to hide/show content through the plugin.

Changes

Cohort / File(s) Summary
HTML Validator Configuration
apps/api/plane/utils/content_validator.py
Removed hideContent and hidecontent from allowed attributes on th and td.
Table Node Definitions
packages/editor/src/core/extensions/table/table-cell.ts, packages/editor/src/core/extensions/table/table-header.ts
Removed hideContent node attribute and stopped conditional injection of content-hidden class in renderHTML.
Drag-Handle Components
packages/editor/src/core/extensions/table/plugins/drag-handles/column/drag-handle.tsx, packages/editor/src/core/extensions/table/plugins/drag-handles/row/drag-handle.tsx
Replaced calls to updateCellContentVisibility with calls to showCellContent and adjusted imports.
Drag-Handle Utilities
packages/editor/src/core/extensions/table/plugins/drag-handles/column/utils.ts, packages/editor/src/core/extensions/table/plugins/drag-handles/row/utils.ts
Now compute selected cell positions and call hideCellContent(editor, cellPositions) when constructing drag preview instead of mutating node attributes.
Core Utilities & Plugin
packages/editor/src/core/extensions/table/plugins/drag-handles/utils.ts, packages/editor/src/core/extensions/table/plugins/drag-state.ts
Added getSelectedCellPositions, hideCellContent, showCellContent; introduced TableDragStatePlugin which stores hidden cell positions in transaction meta and applies decorations to hide content locally.
Plugin Registration
packages/editor/src/core/extensions/table/table/table.ts
Registered TableDragStatePlugin in the table extension's ProseMirror plugin list.

Sequence Diagram

sequenceDiagram
    participant Editor
    participant DragHandle as Drag Handle
    participant Utils as Cell Utils
    participant Plugin as TableDragStatePlugin
    participant Decorations as Decorations

    Note over Editor,Decorations: Drag start — build preview
    DragHandle->>Utils: constructDragPreview(selection, table)
    Utils->>Utils: getSelectedCellPositions(selection, table)
    Utils->>Plugin: hideCellContent(editor, cellPositions)
    Plugin->>Plugin: updateTransactionMeta(tr, cellPositions)
    Plugin->>Decorations: create decorations (apply "content-hidden" class)
    Decorations-->>Editor: render cells with hidden content (local)

    Note over Editor,Decorations: Drag end — restore
    DragHandle->>Utils: showCellContent(editor)
    Utils->>Plugin: showCellContent(editor)
    Plugin->>Plugin: updateTransactionMeta(tr, null)
    Plugin->>Decorations: clear decorations
    Decorations-->>Editor: restore normal rendering
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nibbled code and hopped around,
Swapped attributes for magic bound,
During drags the cells go shy,
Decorations hide them — then goodbye!

🚥 Pre-merge checks | ✅ 1 | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (88 files):

⚔️ apps/api/plane/app/serializers/api.py (content)
⚔️ apps/api/plane/bgtasks/work_item_link_task.py (content)
⚔️ apps/api/plane/db/models/estimate.py (content)
⚔️ apps/api/plane/tests/contract/app/test_api_token.py (content)
⚔️ apps/api/plane/utils/content_validator.py (content)
⚔️ apps/api/requirements/base.txt (content)
⚔️ apps/live/src/lib/pdf/node-renderers.tsx (content)
⚔️ apps/live/src/services/page/core.service.ts (content)
⚔️ apps/live/tests/lib/pdf/pdf-rendering.test.ts (content)
⚔️ apps/web/app/(all)/[workspaceSlug]/(projects)/browse/[workItem]/page.tsx (content)
⚔️ apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/layout.tsx (content)
⚔️ apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/pages/(detail)/[pageId]/page.tsx (content)
⚔️ apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/layout.tsx (content)
⚔️ apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/[projectId]/members/page.tsx (content)
⚔️ apps/web/app/(all)/[workspaceSlug]/layout.tsx (content)
⚔️ apps/web/app/(all)/create-workspace/page.tsx (content)
⚔️ apps/web/app/(all)/invitations/page.tsx (content)
⚔️ apps/web/app/(all)/onboarding/page.tsx (content)
⚔️ apps/web/app/(all)/workspace-invitations/page.tsx (content)
⚔️ apps/web/ce/components/pages/editor/ai/menu.tsx (content)
⚔️ apps/web/ce/store/estimates/estimate.ts (content)
⚔️ apps/web/core/components/account/auth-forms/auth-header.tsx (content)
⚔️ apps/web/core/components/editor/lite-text/editor.tsx (content)
⚔️ apps/web/core/components/editor/rich-text/description-input/root.tsx (content)
⚔️ apps/web/core/components/home/widgets/recents/index.tsx (content)
⚔️ apps/web/core/components/inbox/content/issue-root.tsx (content)
⚔️ apps/web/core/components/inbox/modals/create-modal/issue-description.tsx (content)
⚔️ apps/web/core/components/issues/issue-detail-widgets/sub-issues/helper.ts (content)
⚔️ apps/web/core/components/issues/issue-layouts/filters/header/display-filters/display-properties.tsx (content)
⚔️ apps/web/core/components/issues/issue-layouts/spreadsheet/issue-column.tsx (content)
⚔️ apps/web/core/components/issues/issue-layouts/spreadsheet/spreadsheet-header-column.tsx (content)
⚔️ apps/web/core/components/issues/issue-modal/components/description-editor.tsx (content)
⚔️ apps/web/core/components/issues/issue-modal/context/issue-modal-context.tsx (content)
⚔️ apps/web/core/components/issues/peek-overview/view.tsx (content)
⚔️ apps/web/core/components/issues/title-input.tsx (content)
⚔️ apps/web/core/components/onboarding/create-or-join-workspaces.tsx (content)
⚔️ apps/web/core/components/onboarding/create-workspace.tsx (content)
⚔️ apps/web/core/components/onboarding/invitations.tsx (content)
⚔️ apps/web/core/components/onboarding/invite-members.tsx (content)
⚔️ apps/web/core/components/onboarding/steps/team/root.tsx (content)
⚔️ apps/web/core/components/onboarding/steps/workspace/create.tsx (content)
⚔️ apps/web/core/components/onboarding/steps/workspace/join-invites.tsx (content)
⚔️ apps/web/core/components/power-k/config/creation/command.ts (content)
⚔️ apps/web/core/components/power-k/ui/modal/search-menu.tsx (content)
⚔️ apps/web/core/components/power-k/ui/pages/open-entity/workspace-settings-menu.tsx (content)
⚔️ apps/web/core/components/power-k/ui/pages/work-item-selection-page.tsx (content)
⚔️ apps/web/core/components/project/settings/features-list.tsx (content)
⚔️ apps/web/core/components/project/settings/helper.tsx (content)
⚔️ apps/web/core/components/settings/profile/content/pages/preferences/default-list.tsx (content)
⚔️ apps/web/core/components/sidebar/resizable-sidebar.tsx (content)
⚔️ apps/web/core/components/work-item-filters/filters-hoc/project-level.tsx (content)
⚔️ apps/web/core/components/workspace/create-workspace-form.tsx (content)
⚔️ apps/web/core/components/workspace/sidebar/favorites/favorite-items/common/helper.tsx (content)
⚔️ apps/web/core/components/workspace/sidebar/workspace-menu-root.tsx (content)
⚔️ apps/web/core/hooks/use-issues-actions.tsx (content)
⚔️ apps/web/core/hooks/use-peek-overview-outside-click.tsx (content)
⚔️ apps/web/core/services/ai.service.ts (content)
⚔️ apps/web/core/store/estimates/estimate-point.ts (content)
⚔️ apps/web/core/store/estimates/project-estimate.store.ts (content)
⚔️ apps/web/core/store/global-view.store.ts (content)
⚔️ apps/web/core/store/issue/issue-details/relation.store.ts (content)
⚔️ apps/web/core/store/issue/project-views/filter.store.ts (content)
⚔️ apps/web/core/store/issue/workspace/filter.store.ts (content)
⚔️ apps/web/core/store/issue/workspace/issue.store.ts (content)
⚔️ apps/web/core/store/member/workspace/workspace-member.store.ts (content)
⚔️ apps/web/core/store/project-view.store.ts (content)
⚔️ apps/web/core/store/state.store.ts (content)
⚔️ apps/web/core/store/user/base-permissions.store.ts (content)
⚔️ apps/web/core/store/workspace/home.ts (content)
⚔️ apps/web/core/store/workspace/index.ts (content)
⚔️ apps/web/core/store/workspace/link.store.ts (content)
⚔️ apps/web/helpers/views.helper.ts (content)
⚔️ apps/web/tsconfig.json (content)
⚔️ deployments/cli/community/install.sh (content)
⚔️ package.json (content)
⚔️ packages/constants/src/issue/common.ts (content)
⚔️ packages/editor/src/core/extensions/table/plugins/drag-handles/column/drag-handle.tsx (content)
⚔️ packages/editor/src/core/extensions/table/plugins/drag-handles/column/utils.ts (content)
⚔️ packages/editor/src/core/extensions/table/plugins/drag-handles/row/drag-handle.tsx (content)
⚔️ packages/editor/src/core/extensions/table/plugins/drag-handles/row/utils.ts (content)
⚔️ packages/editor/src/core/extensions/table/plugins/drag-handles/utils.ts (content)
⚔️ packages/editor/src/core/extensions/table/table-cell.ts (content)
⚔️ packages/editor/src/core/extensions/table/table-header.ts (content)
⚔️ packages/editor/src/core/extensions/table/table/table.ts (content)
⚔️ packages/i18n/src/locales/ua/empty-state.ts (content)
⚔️ packages/i18n/src/locales/ua/translations.ts (content)
⚔️ packages/types/src/issues/issue_subscription.ts (content)
⚔️ pnpm-lock.yaml (content)

These conflicts must be resolved before merging into preview.
Resolve conflicts locally and push changes to this branch.
Description check ❓ Inconclusive The description covers the key motivation (removing persistent attributes) and new approach (using decorations), but is incomplete—the second section is cut off mid-sentence and lacks test scenarios and references. Complete the description by finishing the sentence about decorations, adding test scenarios validating the new decoration-based approach, and referencing any related issues.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'refactor: table drag preview using decorations' clearly summarizes the main change—replacing attribute-based cell visibility with decoration-based visibility for table drag previews.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/table-drag-preview
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch refactor/table-drag-preview
  • Create stacked PR with resolved conflicts
  • Post resolved changes as copyable diffs in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
packages/editor/src/core/extensions/table/plugins/drag-handles/utils.ts (1)

77-93: Consider a small helper to reduce duplicated transaction boilerplate.

hideCellContent and showCellContent share the same create-tr → set meta → disable history → dispatch pattern. A thin shared helper would make future changes (e.g., adding another meta key) less error-prone.

♻️ Optional: extract shared dispatch helper
+const dispatchDragStateMeta = (editor: Editor, hiddenCellPositions: number[] | null): void => {
+  const tr = editor.view.state.tr;
+  updateTransactionMeta(tr, hiddenCellPositions);
+  tr.setMeta(CORE_EDITOR_META.ADD_TO_HISTORY, false);
+  editor.view.dispatch(tr);
+};
+
-export const hideCellContent = (editor: Editor, cellPositions: number[]): void => {
-  const tr = editor.view.state.tr;
-  updateTransactionMeta(tr, cellPositions);
-  tr.setMeta(CORE_EDITOR_META.ADD_TO_HISTORY, false);
-  editor.view.dispatch(tr);
-};
+export const hideCellContent = (editor: Editor, cellPositions: number[]): void => {
+  dispatchDragStateMeta(editor, cellPositions);
+};
 
-export const showCellContent = (editor: Editor): void => {
-  const tr = editor.view.state.tr;
-  updateTransactionMeta(tr, null);
-  tr.setMeta(CORE_EDITOR_META.ADD_TO_HISTORY, false);
-  editor.view.dispatch(tr);
-};
+export const showCellContent = (editor: Editor): void => {
+  dispatchDragStateMeta(editor, null);
+};

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors table row/column drag previews to use ProseMirror decorations instead of node attributes, ensuring drag-only visual states are local, non-persistent, and not broadcast to other users.

Changes:

  • Introduces a TableDragStatePlugin that applies a content-hidden decoration to selected table cells during drag operations.
  • Removes the hideContent attribute from table header and cell node schemas and from the HTML sanitization allowlist, relying solely on decorations and CSS for hiding content.
  • Updates row and column drag handle utilities/components to compute selected cell positions, hide them via the new plugin on drag start, and restore them on drag end.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/editor/src/core/extensions/table/table/table.ts Registers the new TableDragStatePlugin in the table extension’s ProseMirror plugins to manage drag-related decorations.
packages/editor/src/core/extensions/table/table-header.ts Simplifies TableHeader attrs and render logic by removing hideContent and the conditional content-hidden class.
packages/editor/src/core/extensions/table/table-cell.ts Removes hideContent from TableCell attrs and rendering, keeping only style-based background/text color configuration.
packages/editor/src/core/extensions/table/plugins/drag-state.ts Adds a dedicated plugin keyed by tableDragState that tracks hidden cell positions in transaction meta and applies/remaps content-hidden node decorations.
packages/editor/src/core/extensions/table/plugins/drag-handles/utils.ts Provides shared helpers to clone cells, compute selected cell positions, and hide/show cell content via transaction meta and CORE_EDITOR_META.ADD_TO_HISTORY.
packages/editor/src/core/extensions/table/plugins/drag-handles/row/utils.ts Refactors row drag preview construction to use getSelectedCellPositions/hideCellContent instead of node attribute updates.
packages/editor/src/core/extensions/table/plugins/drag-handles/row/drag-handle.tsx On row drag completion, clears drag/drop markers and restores cell visibility via showCellContent.
packages/editor/src/core/extensions/table/plugins/drag-handles/column/utils.ts Mirrors the row logic for columns, using decorations to hide selected column cells during drag preview.
packages/editor/src/core/extensions/table/plugins/drag-handles/column/drag-handle.tsx On column drag completion, removes markers and clears decoration-based hiding with showCellContent.
apps/api/plane/utils/content_validator.py Aligns HTML sanitization rules with the new model by removing hideContent/hidecontent from allowed <th>/<td> attributes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Palanikannan1437 Palanikannan1437 merged commit d497304 into preview Feb 13, 2026
11 checks passed
@Palanikannan1437 Palanikannan1437 deleted the refactor/table-drag-preview branch February 13, 2026 12:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants