Skip to content

feat: add touch support for reorderable and resizable features #181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

ColinFrick
Copy link

  • Enabled touch event handling in key directives such as draggable, resizeable, and long-press, ensuring compatibility with touch devices.
  • Introduced utility functions for identifying touch events and extracting event coordinates.
  • Updated styles to enhance usability on touch devices.

What kind of change does this PR introduce? (check one with "x")

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe:

What is the current behavior? (You can also link to an open issue here)
Columns can't be resized or reordered.

What is the new behavior?
Columns can be resized and reordered.

Does this PR introduce a breaking change? (check one with "x")

  • Yes
  • No

If this PR contains a breaking change, please describe the impact and migration path for existing applications: ...

Other information:

Enabled touch event handling in key directives such as draggable, resizeable, and long-press, ensuring compatibility with touch devices.
Introduced utility functions for identifying touch events and extracting event coordinates.
Updated styles to enhance usability on touch devices.
@CLAassistant
Copy link

CLAassistant commented Mar 20, 2025

CLA assistant check
All committers have signed the CLA.

Copy link
Member

@spike-rabbit spike-rabbit left a comment

Choose a reason for hiding this comment

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

Thx a lot for your contribution. This is highly appreciated and it works very well.

Beside the two very minor comments, this needs some automated testing.
There are resize and drag and drop tests in the playwright directory.
Would be awesome if you can add tests using touch events there.
As our git-lfs setup is weird due to github fork restrictions, you won't be able to push screenshots. So please put await si.runVisualAndA11yTests('***'); where needed but comment those lines, so I can later create screenshots and push them on your behalf after merging this PR.

Since this project currently has very poor unit testing, I think it is fine omitting unit test for now (unless you want to do it). We will introduce them later.

@fh1ch fh1ch added the enhancement New feature or request label Mar 24, 2025
@ColinFrick
Copy link
Author

Sure I'll look into Playwright some time this week.

I did find an open issue talking about support for Touch Events: microsoft/playwright#2903
But I'll investigate further if there is a workaround.

@spike-rabbit
Copy link
Member

I think in that case you can also skip adding playwright tests. Since we anyway have to construct the event manually unit tests will do. But there is now one existing test failing (e2e/sorting.spec.ts:85 ). This is the relevant error message:

Error: Timed out 5000ms waiting for expect(locator).toHaveClass(expected)

Locator: locator('datatable-header-cell[title="Company"]')
Expected pattern: /sort-desc/
Received string:  "datatable-header-cell resizeable sortable sort-active sort-asc longpress"
Call log:
  - expect.toHaveClass with timeout 5000ms
  - waiting for locator('datatable-header-cell[title="Company"]')
  -   locator resolved to <datatable-header-cell draggable="" tabindex="0" resizeable="" long-press="" title="Company" role="columnheader" ng-reflect-drag-x="true" ng-reflect-drag-y="false" ng-reflect-sort-type="single" ng-reflect-press-enabled="true" ng-reflect-header-height="50px" ng-reflect-resize-enabled="true" ng-reflect-sorts="[object Object]" ng-reflect-column="[object Object]" ng-reflect-all-rows-selected="false" ng-reflect-drag-model="[object Object]" ng-reflect-press-model="[object Object]" ng-reflect-enable-clearing-sort-state="fa…>…</datatable-header-cell>
  -   unexpected value "datatable-header-cell resizeable sortable sort-active sort-asc"
  -   locator resolved to <datatable-header-cell draggable="" tabindex="0" resizeable="" long-press="" title="Company" role="columnheader" ng-reflect-drag-x="true" ng-reflect-drag-y="false" ng-reflect-sort-type="single" ng-reflect-press-enabled="true" ng-reflect-header-height="50px" ng-reflect-resize-enabled="true" ng-reflect-sorts="[object Object]" ng-reflect-column="[object Object]" ng-reflect-all-rows-selected="false" ng-reflect-drag-model="[object Object]" ng-reflect-press-model="[object Object]" ng-reflect-enable-clearing-sort-state="fa…>…</datatable-header-cell>
  -   unexpected value "datatable-header-cell resizeable sortable sort-active sort-asc"
  -   locator resolved to <datatable-header-cell draggable="" tabindex="0" resizeable="" long-press="" title="Company" role="columnheader" ng-reflect-drag-x="true" ng-reflect-drag-y="false" ng-reflect-sort-type="single" ng-reflect-press-enabled="true" ng-reflect-header-height="50px" ng-reflect-resize-enabled="true" ng-reflect-sorts="[object Object]" ng-reflect-column="[object Object]" ng-reflect-all-rows-selected="false" ng-reflect-drag-model="[object Object]" ng-reflect-press-model="[object Object]" ng-reflect-enable-clearing-sort-state="fa…>…</datatable-header-cell>
  -   unexpected value "datatable-header-cell resizeable sortable sort-active sort-asc"
  -   locator resolved to <datatable-header-cell draggable="" tabindex="0" resizeable="" long-press="" title="Company" role="columnheader" ng-reflect-drag-x="true" ng-reflect-drag-y="false" ng-reflect-sort-type="single" ng-reflect-press-enabled="true" ng-reflect-header-height="50px" ng-reflect-resize-enabled="true" ng-reflect-sorts="[object Object]" ng-reflect-column="[object Object]" ng-reflect-all-rows-selected="false" ng-reflect-drag-model="[object Object]" ng-reflect-press-model="[object Object]" ng-reflect-enable-clearing-sort-state="fa…>…</datatable-header-cell>
  -   unexpected value "datatable-header-cell resizeable sortable sort-active sort-asc"
  -   locator resolved to <datatable-header-cell draggable="" tabindex="0" resizeable="" long-press="" title="Company" role="columnheader" ng-reflect-drag-x="true" ng-reflect-drag-y="false" ng-reflect-sort-type="single" ng-reflect-press-enabled="true" ng-reflect-header-height="50px" ng-reflect-resize-enabled="true" ng-reflect-sorts="[object Object]" ng-reflect-column="[object Object]" ng-reflect-all-rows-selected="false" ng-reflect-drag-model="[object Object]" ng-reflect-press-model="[object Object]" ng-reflect-enable-clearing-sort-state="fa…>…</datatable-header-cell>
  -   unexpected value "datatable-header-cell resizeable sortable sort-active sort-asc longpress"
  -   locator resolved to <datatable-header-cell draggable="" tabindex="0" resizeable="" long-press="" title="Company" role="columnheader" ng-reflect-drag-x="true" ng-reflect-drag-y="false" ng-reflect-sort-type="single" ng-reflect-press-enabled="true" ng-reflect-header-height="50px" ng-reflect-resize-enabled="true" ng-reflect-sorts="[object Object]" ng-reflect-column="[object Object]" ng-reflect-all-rows-selected="false" ng-reflect-drag-model="[object Object]" ng-reflect-press-model="[object Object]" ng-reflect-enable-clearing-sort-state="fa…>…</datatable-header-cell>
  -   unexpected value "datatable-header-cell resizeable sortable sort-active sort-asc longpress"
  -   locator resolved to <datatable-header-cell draggable="" tabindex="0" resizeable="" long-press="" title="Company" role="columnheader" ng-reflect-drag-x="true" ng-reflect-drag-y="false" ng-reflect-sort-type="single" ng-reflect-press-enabled="true" ng-reflect-header-height="50px" ng-reflect-resize-enabled="true" ng-reflect-sorts="[object Object]" ng-reflect-column="[object Object]" ng-reflect-all-rows-selected="false" ng-reflect-drag-model="[object Object]" ng-reflect-press-model="[object Object]" ng-reflect-enable-clearing-sort-state="fa…>…</datatable-header-cell>
  -   unexpected value "datatable-header-cell resizeable sortable sort-active sort-asc longpress"
  -   locator resolved to <datatable-header-cell draggable="" tabindex="0" resizeable="" long-press="" title="Company" role="columnheader" ng-reflect-drag-x="true" ng-reflect-drag-y="false" ng-reflect-sort-type="single" ng-reflect-press-enabled="true" ng-reflect-header-height="50px" ng-reflect-resize-enabled="true" ng-reflect-sorts="[object Object]" ng-reflect-column="[object Object]" ng-reflect-all-rows-selected="false" ng-reflect-drag-model="[object Object]" ng-reflect-press-model="[object Object]" ng-reflect-enable-clearing-sort-state="fa…>…</datatable-header-cell>
  -   unexpected value "datatable-header-cell resizeable sortable sort-active sort-asc longpress"
  -   locator resolved to <datatable-header-cell draggable="" tabindex="0" resizeable="" long-press="" title="Company" role="columnheader" ng-reflect-drag-x="true" ng-reflect-drag-y="false" ng-reflect-sort-type="single" ng-reflect-press-enabled="true" ng-reflect-header-height="50px" ng-reflect-resize-enabled="true" ng-reflect-sorts="[object Object]" ng-reflect-column="[object Object]" ng-reflect-all-rows-selected="false" ng-reflect-drag-model="[object Object]" ng-reflect-press-model="[object Object]" ng-reflect-enable-clearing-sort-state="fa…>…</datatable-header-cell>
  -   unexpected value "datatable-header-cell resizeable sortable sort-active sort-asc longpress"


  106 |
  107 |       await expect(companyHeader).toHaveClass(/sort-active/);
> 108 |       await expect(companyHeader).toHaveClass(/sort-desc/);
      |                                   ^
  109 |
  110 |       await expect(loadingIndicator).toBeVisible();
  111 |

    at /e2e/playwright/e2e/sorting.spec.ts:108:35

@spike-rabbit
Copy link
Member

Just one more thing, my previous comment broke the code on Firefox. Seems like the desktop version does not support ToucheEvent, so please write the check like this: const isMouse = event instanceof MouseEvent;

@ColinFrick
Copy link
Author

I have updated the PR with the MouseEvent change, but sadly the latest changes completely broke the PR.

I'll have to look over, and re-implement some stuff.

And I still haven't found any option for playwright touch events.

@ColinFrick ColinFrick marked this pull request as draft April 3, 2025 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants