Added back feature: Toggle Drag Handles. Improved positions of Add List etc buttons.

Thanks to xet7 !
This commit is contained in:
Lauri Ojansivu 2026-01-14 19:09:07 +02:00
parent 00793c39f8
commit 5cb712bee4
12 changed files with 85 additions and 86 deletions

View file

@ -68,6 +68,7 @@ Meteor.startup(() => {
Tracker.autorun(() => {
if (Meteor.userId()) {
Meteor.subscribe('userGreyIcons');
Meteor.subscribe('userDesktopDragHandles');
}
});

View file

@ -124,7 +124,8 @@ template(name='checklistItemDetail')
role="checkbox" aria-checked="{{#if item.isFinished }}true{{else}}false{{/if}}" tabindex="0")
if canModifyCard
span.check-box-unicode {{#if item.isFinished }}✅{{else}}⬜{{/if}}
span.checklistitem-handle(title="{{_ 'dragChecklistItem'}}") ↕️
if isTouchScreenOrShowDesktopDragHandles
span.checklistitem-handle(title="{{_ 'dragChecklistItem'}}") ↕️
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}")
+viewer
= item.title

View file

@ -44,10 +44,12 @@
}
}
.minicard-details-menu-with-handle {
float: right;
position: absolute;
right: 0.7vw;
top: 0.7vh;
font-size: clamp(14px, 3vw, 18px);
padding-right: 4vw;
padding-left: 0.7vw;
padding: 0;
z-index: 10;
}
.minicard-details-menu {
float: right;
@ -133,9 +135,10 @@
width: clamp(20px, 2.5vw, 28px);
height: clamp(20px, 2.5vw, 28px);
position: absolute;
right: 0.7vw;
right: 3vw;
top: 0.7vh;
display: none;
z-index: 10;
}
@media only screen {
.minicard .handle {

View file

@ -3,11 +3,12 @@ template(name="minicard")
class="{{#if isLinkedCard}}linked-card{{/if}}"
class="{{#if isLinkedBoard}}linked-board{{/if}}"
class="{{#if colorClass}}minicard-{{colorClass}}{{/if}}")
if canMoveCard
if isTouchScreenOrShowDesktopDragHandles
.handle
| ↕️
if canModifyCard
a.minicard-details-menu-with-handle.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") ☰
if canMoveCard
.handle
| ↕️
.dates
if getReceived
.date

View file

@ -179,56 +179,42 @@ body.list-resizing-active * {
margin-right: 120px !important;
}
/* Position drag handle at top-right corner for ALL lists */
.list-header .list-header-handle {
/* Position at top-right corner, aligned with title text top */
/* Position elements from right to left: hamburger, add card, drag handle */
.list-header .js-open-list-menu {
position: absolute !important;
top: 2.5vh !important;
right: 1.5vw !important;
/* Ensure it's above other elements */
z-index: 15 !important;
/* Remove margin since it's absolutely positioned */
margin-right: 0 !important;
/* Ensure proper display */
display: inline-block !important;
/* Ensure it's clickable and shows proper cursor */
cursor: move !important;
pointer-events: auto !important;
/* Add some padding for better clickability */
padding: 4px !important;
}
/* Ensure buttons maintain original positioning */
.js-swimlane .list[style*="--list-width"] .list-header .list-header-plus-top,
.js-swimlane .list[style*="--list-width"] .list-header .js-collapse,
.js-swimlane .list[style*="--list-width"] .list-header .js-open-list-menu,
.dragscroll .list[style*="--list-width"] .list-header .list-header-plus-top,
.dragscroll .list[style*="--list-width"] .list-header .js-collapse,
.dragscroll .list[style*="--list-width"] .list-header .js-open-list-menu,
[id^="swimlane-"] .list[style*="--list-width"] .list-header .list-header-plus-top,
[id^="swimlane-"] .list[style*="--list-width"] .list-header .js-collapse,
[id^="swimlane-"] .list[style*="--list-width"] .list-header .js-open-list-menu {
/* Use original positioning to maintain layout */
position: relative !important;
/* Maintain original spacing */
margin-right: 15px !important;
/* Ensure proper display */
.list-header .list-header-plus-top {
position: absolute !important;
top: 2.5vh !important;
right: 3.25vw !important;
z-index: 15 !important;
display: inline-block !important;
padding: 4px !important;
}
/* Ensure watch icon and card count maintain original positioning */
.js-swimlane .list[style*="--list-width"] .list-header .list-header-watch-icon,
.dragscroll .list[style*="--list-width"] .list-header .list-header-watch-icon,
[id^="swimlane-"] .list[style*="--list-width"] .list-header .list-header-watch-icon,
.js-swimlane .list[style*="--list-width"] .list-header .cardCount,
.dragscroll .list[style*="--list-width"] .list-header .cardCount,
[id^="swimlane-"] .list[style*="--list-width"] .list-header .cardCount {
/* Use original positioning to maintain layout */
position: relative !important;
/* Maintain original spacing */
margin-right: 15px !important;
/* Ensure proper display */
.list-header .list-header-handle-desktop {
position: absolute !important;
top: 2.5vh !important;
right: 6.5vw !important;
z-index: 15 !important;
display: inline-block !important;
cursor: move !important;
pointer-events: auto !important;
padding: 4px !important;
}
/* Anchor header action buttons within header during resize */
.list .list-header { position: relative; z-index: 5; }
.list .list-header .js-open-list-menu,
.list .list-header .list-header-plus-top,
.list .list-header .list-header-handle-desktop {
position: absolute !important;
}
[id^="swimlane-"] .list:first-child {
min-width: 2.5vw;

View file

@ -64,12 +64,9 @@ template(name="listHeader")
else
a.list-header-menu-icon.js-select-list ▶️
unless currentUser.isWorker
a.list-header-handle.handle.js-list-handle ↕️
else if currentUser.isBoardMember
if currentUser.isBoardMember
unless currentUser.isCommentOnly
unless currentUser.isWorker
if isTouchScreenOrShowDesktopDragHandles
a.list-header-handle.handle.js-list-handle ↕️
else if currentUser.isBoardMember
if isWatching
i.list-header-watch-icon | 👁️
unless collapsed
@ -77,10 +74,11 @@ template(name="listHeader")
unless currentUser.isCommentOnly
//if isBoardAdmin
// a.fa.js-list-star.list-header-plus-top(class="fa-star{{#unless starred}}-o{{/unless}}")
if isTouchScreenOrShowDesktopDragHandles
a.list-header-handle-desktop.handle.js-list-handle(title="{{_ 'drag-list'}}") ↕️
if canSeeAddCard
a.js-add-card.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}")
a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") ☰
a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") ☰
template(name="editListTitleForm")
.list-composer

View file

@ -30,6 +30,14 @@ template(name="header")
span.zoom-display {{zoomLevel}}%
input.zoom-input.js-zoom-input(type="number" value=zoomLevel min="50" max="300" step="10" style="display: none;")
// Drag handles toggle - between zoom and mobile mode toggle
a.board-header-btn.js-toggle-desktop-drag-handles(title="{{_ 'show-desktop-drag-handles'}}")
| ↕️
if isShowDesktopDragHandles
| ✅
unless isShowDesktopDragHandles
| 🚫
if isMiniScreen
ul.header-quick-access-list
if currentList
@ -44,12 +52,6 @@ template(name="header")
a(href="{{pathFor 'board' id=_id slug=slug}}")
+viewer
= title
//a.js-toggle-desktop-drag-handles(title="{{_ 'show-desktop-drag-handles'}}" alt="{{_ 'show-desktop-drag-handles'}}")
// i.fa.fa-arrows
// if isShowDesktopDragHandles
// i.fa.fa-check-square-o
// unless isShowDesktopDragHandles
// i.fa.fa-ban
#header-new-board-icon
else
ul.header-quick-access-list
@ -64,12 +66,7 @@ template(name="header")
= title
else
li.current.empty {{_ 'quick-access-description'}}
//a.js-toggle-desktop-drag-handles(title="{{_ 'show-desktop-drag-handles'}}" alt="{{_ 'show-desktop-drag-handles'}}")
// i.fa.fa-arrows
// if isShowDesktopDragHandles
// i.fa.fa-check-square-o
// unless isShowDesktopDragHandles
// i.fa.fa-ban
#header-new-board-icon
// Next line is used only for spacing at header,
// there is no visible clickable icon.
#header-new-board-icon

View file

@ -132,11 +132,10 @@ Template.header.events({
Session.set('currentCard', null);
},
'click .js-toggle-desktop-drag-handles'() {
//currentUser = Meteor.user();
//if (currentUser) {
// Meteor.call('toggleDesktopDragHandles');
//} else if (window.localStorage.getItem('showDesktopDragHandles')) {
if (window.localStorage.getItem('showDesktopDragHandles')) {
currentUser = Meteor.user();
if (currentUser) {
Meteor.call('toggleDesktopDragHandles');
} else if (window.localStorage.getItem('showDesktopDragHandles')) {
window.localStorage.removeItem('showDesktopDragHandles');
location.reload();
} else {

View file

@ -33,12 +33,13 @@ template(name="swimlaneFixedHeader")
| 🔽
a.js-open-add-swimlane-menu.swimlane-header-plus-icon(title="{{_ 'add-swimlane'}}")
|
unless isTouchScreen
a.swimlane-header-handle.handle.js-swimlane-header-handle
| ↕️
if isTouchScreen
a.swimlane-header-miniscreen-handle.handle.js-swimlane-header-handle
| ↕️
if isTouchScreenOrShowDesktopDragHandles
unless isTouchScreen
a.swimlane-header-handle.handle.js-swimlane-header-handle
| ↕️
if isTouchScreen
a.swimlane-header-miniscreen-handle.handle.js-swimlane-header-handle
| ↕️
a.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}")
| ☰

View file

@ -182,12 +182,12 @@ template(name="changeLanguagePopup")
template(name="changeSettingsPopup")
ul.pop-over-list
//li
// a.js-toggle-desktop-drag-handles
// i.fa.fa-arrows
// | {{_ 'show-desktop-drag-handles'}}
// if isShowDesktopDragHandles
// i.fa.fa-check
li
a.js-toggle-desktop-drag-handles
| ↕️
| {{_ 'show-desktop-drag-handles'}}
if isShowDesktopDragHandles
| ✅
unless currentUser.isWorker
li
label.bold.clear

View file

@ -648,14 +648,18 @@ Utils = {
// returns if desktop drag handles are enabled
isShowDesktopDragHandles() {
// Always show drag handles on all displays
return true;
const currentUser = Meteor.user();
if (currentUser) {
return currentUser.hasShowDesktopDragHandles();
} else {
// For non-logged-in users, check localStorage
return window.localStorage.getItem('showDesktopDragHandles') === 'true';
}
},
// returns if mini screen or desktop drag handles
isTouchScreenOrShowDesktopDragHandles() {
// Always enable drag handles for all displays
return true;
return Utils.isTouchScreen() || Utils.isShowDesktopDragHandles();
},
calculateIndexData(prevData, nextData, nItems = 1) {