Project

General

Profile

Actions

Patch #43641

open

Make the issues list header sticky on vertical scroll

Added by Takashi Kato 3 months ago. Updated about 16 hours ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
UI
Target version:
-

Description

This patch implements a sticky header for the issue list when scrolling.
While currently limited to issues, this approach can be applied to other list views as well.

Limitations

The header will not be fixed under the following conditions: When a horizontal scrollbar is present, the sticky header becomes detached from the table body.
Since it is impossible to synchronize the widths of the header and the table in this state, the feature is disabled for:

  • Narrow windows where a horizontal scrollbar is displayed.
  • Mobile mode.

State Transition Table

state state event event event
Horizontal scrollbar table and window start change state of a horizontal scrollbar change state of overlapping table and window
1 none not overlapping header: normal →2 set sticky →3
2 displayed not overlapping header: normal →1 →4
3 none overlapping header: sticky set header normal →4 set header normal →1
4 displayed overlapping header: normal set header sticky→3 →2

Files

Actions #1

Updated by Takashi Kato 3 months ago

The screencast is here.

Actions #2

Updated by Mizuki ISHIKAWA 14 days ago

This feature significantly improves the usability of tables in Redmine. Thank you for providing the patch.

After testing it locally, I encountered an issue when the % Done column is displayed. The problem occurs because the progress bar inside the % Done column is also recognized as column content. It seems that modifying the code as shown below resolves the issue.

diff --git a/app/javascript/controllers/sticky_table_header_controller.js b/app/javascript/controllers/sticky_table_header_controller.js
index ee804ae36..2f31c5bb1 100644
--- a/app/javascript/controllers/sticky_table_header_controller.js
+++ b/app/javascript/controllers/sticky_table_header_controller.js
@@ -20,7 +20,7 @@ export default class extends Controller {

   prepare() {
     if (!!this.prepared === false) {
-      this.bodyColumns = this.bodyTarget.querySelectorAll("tr:first-child td")
+      this.bodyColumns = this.bodyTarget.querySelectorAll(":scope > tr:first-child > td")

       this.stickyHeader = this.headTarget.cloneNode(true)
       this.stickyHeader.removeAttribute(`data-${this.identifier}-target`)

In addition, when "Group results by" is enabled, I noticed that the width of the sticky header is affected by the group rows.

Actions #3

Updated by Mizuki ISHIKAWA 2 days ago

Mizuki ISHIKAWA wrote in #note-2:

In addition, when "Group results by" is enabled, I noticed that the width of the sticky header is affected by the group rows.

I had previously pointed out the issue mentioned above, but I just checked again and was able to reproduce it. It might have been an issue specific to my environment.

Separately, I have written a patch to fix an issue where, in responsive mode with a small number of columns (so no horizontal scrolling occurs), the sticky header ends up hidden behind #project-jump and becomes invisible.

Actions #4

Updated by Takashi Kato about 16 hours ago

  • The issue mentioned in #note-2 occurs when the first tr element has a colspan attribute.
  • I have fixed the above issue and attached a new patch that includes the fix from #note-3.
  • This patch determines which row is referenced by the sticky header on the server side, making the Stimulus controller slightly simpler.
Actions

Also available in: Atom PDF