diff --git a/client/components/boards/boardBody.css b/client/components/boards/boardBody.css index 197d71ddb..32770eda6 100644 --- a/client/components/boards/boardBody.css +++ b/client/components/boards/boardBody.css @@ -6,6 +6,27 @@ bottom: 0; overflow-x: hidden; overflow-y: hidden; + width: 100%; + min-width: 100%; +} + +/* When zoom is 50% or lower, ensure full width like content */ +.board-wrapper[style*="transform: scale(0.5)"] { + width: 100% !important; + max-width: 100% !important; + margin: 0 !important; +} + +.board-wrapper[style*="transform: scale(0.4)"] { + width: 100% !important; + max-width: 100% !important; + margin: 0 !important; +} + +.board-wrapper[style*="transform: scale(0.3)"] { + width: 100% !important; + max-width: 100% !important; + margin: 0 !important; } .board-wrapper .board-canvas { position: absolute; @@ -15,6 +36,219 @@ bottom: 0; transition: margin 0.1s; overflow-y: auto; + width: 100%; + min-width: 100%; +} + +/* Ensure horizontal scrollbar is visible for high zoom levels */ +.board-wrapper .board-canvas[style*="overflow-x: auto"] { + overflow-x: auto !important; + overflow-y: auto !important; +} + +/* Style the scrollbar for better visibility */ +.board-wrapper .board-canvas::-webkit-scrollbar { + height: 12px; + width: 12px; +} + +.board-wrapper .board-canvas::-webkit-scrollbar-track { + background: #f1f1f1; + border-radius: 6px; +} + +.board-wrapper .board-canvas::-webkit-scrollbar-thumb { + background: #888; + border-radius: 6px; +} + +.board-wrapper .board-canvas::-webkit-scrollbar-thumb:hover { + background: #555; +} + +/* Ensure content area can scroll horizontally for high zoom levels */ +#content[style*="overflow-x: auto"] { + overflow-x: auto !important; + overflow-y: auto !important; +} + +/* Style content area scrollbar */ +#content::-webkit-scrollbar { + height: 12px; + width: 12px; +} + +#content::-webkit-scrollbar-track { + background: #f1f1f1; + border-radius: 6px; +} + +#content::-webkit-scrollbar-thumb { + background: #888; + border-radius: 6px; +} + +#content::-webkit-scrollbar-thumb:hover { + background: #555; +} + +/* Ensure scrollbars are always visible for high zoom levels */ +#content[style*="overflow-x: auto"] { + position: relative; +} + +#content[style*="overflow-x: auto"]::-webkit-scrollbar { + height: 12px; + width: 12px; +} + + /* Force vertical scrollbar to always be visible */ + #content[style*="overflow-y: auto"] { + overflow-y: scroll !important; + } + + /* Mobile - make all text 2x bigger inside #content by default (icons stay same size) */ + @media screen and (max-width: 800px), + screen and (max-device-width: 800px), + screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px), + screen and (max-width: 800px) and (orientation: portrait), + screen and (max-width: 800px) and (orientation: landscape) { + #content { + font-size: 2em !important; /* 2x bigger base font size for content area */ + } + + /* Make all text elements 2x bigger */ + #content h1, #content h2, #content h3, #content h4, #content h5, #content h6, + #content p, #content span, #content div, #content a, #content button, + #content .minicard, #content .list-header-name, #content .board-header-btn, + #content .card-title, #content .card-details, #content .card-description, + #content .swimlane-header, #content .list-title, #content .card-text, + #content .member, #content .member-name, #content .member-initials, + #content .checklist-item, #content .checklist-title, #content .comment, + #content .activity, #content .activity-text, #content .activity-time, + #content .board-title, #content .board-description, #content .list-name, + #content .card-text, #content .card-title, #content .card-description, + #content .swimlane-title, #content .swimlane-description, + #content .board-header-title, #content .board-header-description, + #content .card-detail-title, #content .card-detail-description, + #content .list-header-title, #content .list-header-description, + #content .swimlane-header-title, #content .swimlane-header-description, + #content .minicard-title, #content .minicard-description, + #content .card-comment, #content .card-comment-text, + #content .checklist-item-text, #content .checklist-item-title, + #content .activity-item, #content .activity-item-text, + #content .board-member, #content .board-member-name, + #content .team-member, #content .team-member-name, + #content .org-member, #content .org-member-name, + #content .template-member, #content .template-member-name, + #content .user-name, #content .user-email, #content .user-role, + #content .setting-title, #content .setting-description, + #content .popup-title, #content .popup-description, + #content .modal-title, #content .modal-description, + #content .notification-title, #content .notification-text, + #content .announcement-title, #content .announcement-text, + #content .offline-warning-title, #content .offline-warning-text, + #content .error-title, #content .error-text, + #content .success-title, #content .success-text, + #content .info-title, #content .info-text, + #content .warning-title, #content .warning-text { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + /* Keep icons the same size (don't scale them) */ + #content .fa, #content .icon, #content i { + font-size: 1em !important; /* Keep original icon size */ + } + + /* Reset specific icon sizes to prevent double scaling */ + #content .fa-home, #content .fa-bars, #content .fa-search, + #content .fa-bell, #content .fa-user, #content .fa-cog, + #content .fa-plus, #content .fa-minus, #content .fa-edit, + #content .fa-trash, #content .fa-save, #content .fa-cancel, + #content .fa-arrow-left, #content .fa-arrow-right, + #content .fa-arrow-up, #content .fa-arrow-down, + #content .fa-check, #content .fa-times, #content .fa-close, + #content .fa-star, #content .fa-heart, #content .fa-thumbs-up, + #content .fa-thumbs-down, #content .fa-comment, #content .fa-reply, + #content .fa-share, #content .fa-download, #content .fa-upload, + #content .fa-copy, #content .fa-paste, #content .fa-cut, + #content .fa-undo, #content .fa-redo, #content .fa-refresh, + #content .fa-sync, #content .fa-spinner, #content .fa-loading, + #content .fa-info, #content .fa-question, #content .fa-exclamation, + #content .fa-warning, #content .fa-error, #content .fa-success, + #content .fa-check-circle, #content .fa-times-circle, + #content .fa-exclamation-circle, #content .fa-question-circle, + #content .fa-info-circle, #content .fa-warning-circle, + #content .fa-error-circle, #content .fa-success-circle { + font-size: 1em !important; /* Keep original icon size */ + } + } + + /* Fallback for iPhone devices using JavaScript detection */ + .iphone-device #content { + font-size: 2em !important; /* 2x bigger base font size for content area */ + } + + .iphone-device #content h1, .iphone-device #content h2, .iphone-device #content h3, .iphone-device #content h4, .iphone-device #content h5, .iphone-device #content h6, + .iphone-device #content p, .iphone-device #content span, .iphone-device #content div, .iphone-device #content a, .iphone-device #content button, + .iphone-device #content .minicard, .iphone-device #content .list-header-name, .iphone-device #content .board-header-btn, + .iphone-device #content .card-title, .iphone-device #content .card-details, .iphone-device #content .card-description, + .iphone-device #content .swimlane-header, .iphone-device #content .list-title, .iphone-device #content .card-text, + .iphone-device #content .member, .iphone-device #content .member-name, .iphone-device #content .member-initials, + .iphone-device #content .checklist-item, .iphone-device #content .checklist-title, .iphone-device #content .comment, + .iphone-device #content .activity, .iphone-device #content .activity-text, .iphone-device #content .activity-time, + .iphone-device #content .board-title, .iphone-device #content .board-description, .iphone-device #content .list-name, + .iphone-device #content .card-text, .iphone-device #content .card-title, .iphone-device #content .card-description, + .iphone-device #content .swimlane-title, .iphone-device #content .swimlane-description, + .iphone-device #content .board-header-title, .iphone-device #content .board-header-description, + .iphone-device #content .card-detail-title, .iphone-device #content .card-detail-description, + .iphone-device #content .list-header-title, .iphone-device #content .list-header-description, + .iphone-device #content .swimlane-header-title, .iphone-device #content .swimlane-header-description, + .iphone-device #content .minicard-title, .iphone-device #content .minicard-description, + .iphone-device #content .card-comment, .iphone-device #content .card-comment-text, + .iphone-device #content .checklist-item-text, .iphone-device #content .checklist-item-title, + .iphone-device #content .activity-item, .iphone-device #content .activity-item-text, + .iphone-device #content .board-member, .iphone-device #content .board-member-name, + .iphone-device #content .team-member, .iphone-device #content .team-member-name, + .iphone-device #content .org-member, .iphone-device #content .org-member-name, + .iphone-device #content .template-member, .iphone-device #content .template-member-name, + .iphone-device #content .user-name, .iphone-device #content .user-email, .iphone-device #content .user-role, + .iphone-device #content .setting-title, .iphone-device #content .setting-description, + .iphone-device #content .popup-title, .iphone-device #content .popup-description, + .iphone-device #content .modal-title, .iphone-device #content .modal-description, + .iphone-device #content .notification-title, .iphone-device #content .notification-text, + .iphone-device #content .announcement-title, .iphone-device #content .announcement-text, + .iphone-device #content .offline-warning-title, .iphone-device #content .offline-warning-text, + .iphone-device #content .error-title, .iphone-device #content .error-text, + .iphone-device #content .success-title, .iphone-device #content .success-text, + .iphone-device #content .info-title, .iphone-device #content .info-text, + .iphone-device #content .warning-title, .iphone-device #content .warning-text { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + /* Keep icons the same size for iPhone devices */ + .iphone-device #content .fa, .iphone-device #content .icon, .iphone-device #content i { + font-size: 1em !important; /* Keep original icon size */ + } + +/* Ensure scrollbars are positioned correctly */ +#content[style*="overflow-x: auto"]::-webkit-scrollbar:vertical { + width: 12px; +} + +#content[style*="overflow-x: auto"]::-webkit-scrollbar:horizontal { + height: 12px; +} + +/* Force both scrollbars to always be visible for high zoom levels */ +#content[style*="overflow-x: auto"][style*="overflow-y: auto"] { + overflow-x: scroll !important; + overflow-y: scroll !important; +} + +/* Ensure the right scrollbar is always visible on the inner right edge */ +#content[style*="overflow-y: auto"] { + scrollbar-gutter: stable; } .board-wrapper .board-canvas .board-overlay { position: fixed; @@ -34,25 +268,57 @@ display: none; } /* Mobile view styles - applied when isMiniScreen is true (iPhone, etc.) */ +.board-wrapper.mobile-view { + width: 100% !important; + min-width: 100% !important; + left: 0 !important; + right: 0 !important; +} + +.board-wrapper.mobile-view .board-canvas { + width: 100% !important; + min-width: 100% !important; + left: 0 !important; + right: 0 !important; +} + .board-wrapper.mobile-view .board-canvas.mobile-view .swimlane { border-bottom: 1px solid #ccc; display: flex; flex-direction: column; margin: 0; - padding: 0 0px 0px 0; + padding: 0; overflow-x: hidden; overflow-y: auto; + width: 100%; + min-width: 100%; } @media screen and (max-width: 800px) { + .board-wrapper { + width: 100% !important; + min-width: 100% !important; + left: 0 !important; + right: 0 !important; + } + + .board-wrapper .board-canvas { + width: 100% !important; + min-width: 100% !important; + left: 0 !important; + right: 0 !important; + } + .board-wrapper .board-canvas .swimlane { border-bottom: 1px solid #ccc; display: flex; flex-direction: column; margin: 0; - padding: 0 0px 0px 0; + padding: 0; overflow-x: hidden; overflow-y: auto; + width: 100%; + min-width: 100%; } } .calendar-event-green { diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js index 8849798d2..639a75942 100644 --- a/client/components/boards/boardBody.js +++ b/client/components/boards/boardBody.js @@ -76,6 +76,15 @@ BlazeComponent.extendComponent({ } }, onRendered() { + // Initialize user settings (zoom and mobile mode) + Utils.initializeUserSettings(); + + // Detect iPhone devices and add class for better CSS targeting + const isIPhone = /iPhone|iPod/.test(navigator.userAgent); + if (isIPhone) { + document.body.classList.add('iphone-device'); + } + // Accessibility: Focus management for popups and menus function focusFirstInteractive(container) { if (!container) return; diff --git a/client/components/boards/boardHeader.css b/client/components/boards/boardHeader.css index 26a57608a..4964c3e73 100644 --- a/client/components/boards/boardHeader.css +++ b/client/components/boards/boardHeader.css @@ -21,3 +21,919 @@ margin-top: 0.7vh; padding: 0.7vh 0.7vw; } + +/* Zoom and Mobile Mode Controls */ +.board-header-btns.center { + display: flex; + align-items: center; + justify-content: center; + flex: 1; +} + +.zoom-controls { + display: flex; + align-items: center; + gap: 0.5vw; + background: rgba(255, 255, 255, 0.9); + padding: 0.5vh 1vw; + border-radius: 0.5vw; + box-shadow: 0 0.2vh 0.5vh rgba(0,0,0,0.1); +} + +.zoom-controls .board-header-btn { + padding: 0.5vh 0.8vw !important; + border-radius: 0.3vw !important; + background: #fff !important; + border: 1px solid #000 !important; + transition: all 0.2s ease !important; + color: #000 !important; + height: auto !important; + line-height: normal !important; + margin: 0 !important; + float: none !important; + overflow: visible !important; +} + +.zoom-controls .board-header-btn i { + color: #000 !important; + float: none !important; + display: inline !important; + line-height: normal !important; + margin: 0 !important; +} + +.zoom-controls .board-header-btn:hover { + background: #000 !important; + border-color: #000 !important; + color: #fff !important; +} + +.zoom-controls .board-header-btn:hover i { + color: #fff !important; +} + +.zoom-controls .board-header-btn.is-active { + background: #0079bf; + color: white; + border-color: #005a8a; +} + +.zoom-controls .board-header-btn.is-active i { + color: white; +} + +.zoom-level { + font-weight: bold; + color: #333; + min-width: 3vw; + text-align: center; + font-size: clamp(12px, 2vw, 14px); + cursor: pointer; + padding: 0.3vh 0.5vw; + border-radius: 0.3vw; + transition: all 0.2s ease; +} + +.zoom-level:hover { + background: #f0f0f0; + color: #000; +} + +/* Mobile Mode Styles */ +.mobile-mode .board-wrapper { + width: 100%; + height: 100%; +} + +.mobile-mode .board-canvas { + height: 100%; +} + +.mobile-mode .minicard { + font-size: clamp(16px, 4vw, 20px); + padding: 1.2vh 1.5vw 0.5vh; + min-height: 3vh; +} + +.mobile-mode .list-header-name { + font-size: clamp(18px, 4.5vw, 24px); +} + +.mobile-mode .board-header-btn { + padding: 1vh 1.5vw; + font-size: clamp(14px, 3.5vw, 18px); +} + +.mobile-mode .zoom-controls { + padding: 1vh 1.5vw; + gap: 1vw; +} + +.mobile-mode .zoom-controls .board-header-btn { + padding: 1vh 1.5vw !important; + font-size: clamp(14px, 3.5vw, 18px) !important; + background: #fff !important; + border: 1px solid #000 !important; + color: #000 !important; + height: auto !important; + line-height: normal !important; + margin: 0 !important; + float: none !important; + overflow: visible !important; +} + +.mobile-mode .zoom-controls .board-header-btn i { + color: #000 !important; + float: none !important; + display: inline !important; + line-height: normal !important; + margin: 0 !important; +} + +.mobile-mode .zoom-controls .board-header-btn:hover { + background: #000 !important; + border-color: #000 !important; + color: #fff !important; +} + +.mobile-mode .zoom-controls .board-header-btn:hover i { + color: #fff !important; +} + +.mobile-mode .zoom-level { + font-size: clamp(14px, 3.5vw, 18px); + min-width: 4vw; +} + +/* Comprehensive Mobile Mode Styles - Works on all screen sizes */ +.mobile-mode .board-wrapper { + width: 100% !important; + height: 100% !important; + transform: none !important; + transform-origin: initial !important; + max-width: 100% !important; +} + +.mobile-mode .board-canvas { + height: 100% !important; + overflow-x: hidden !important; + overflow-y: auto !important; + width: 100% !important; + max-width: 100% !important; +} + +.mobile-mode .swimlane { + width: 100% !important; + min-width: 100% !important; + max-width: 100% !important; + margin-bottom: 2rem !important; + display: block !important; + float: none !important; +} + +.mobile-mode .swimlane-header { + width: 100% !important; + min-width: 100% !important; + max-width: 100% !important; + font-size: clamp(18px, 2.5vw, 32px) !important; + padding: 1rem !important; + margin-bottom: 1rem !important; + display: block !important; +} + +.mobile-mode .list { + width: 100% !important; + min-width: 100% !important; + max-width: 100% !important; + display: block !important; + float: none !important; + margin-bottom: 2rem !important; + border-left: none !important; + border-bottom: 2px solid #ccc !important; + clear: both !important; +} + +.mobile-mode .list-header { + width: 100% !important; + min-width: 100% !important; + max-width: 100% !important; + padding: 1rem !important; + font-size: clamp(18px, 2.5vw, 32px) !important; + display: grid !important; + grid-template-columns: 30px 1fr auto auto !important; + gap: 10px !important; + align-items: center !important; + position: relative !important; +} + +.mobile-mode .list-header .list-header-name { + font-size: clamp(18px, 2.5vw, 32px) !important; + font-weight: bold !important; + grid-row: 1 !important; + grid-column: 2 !important; + align-self: end !important; + display: block !important; + visibility: visible !important; + opacity: 1 !important; +} + +.mobile-mode .list-header .cardCount { + font-size: clamp(14px, 2vw, 24px) !important; + grid-row: 2 !important; + grid-column: 2 !important; + align-self: start !important; + display: block !important; + visibility: visible !important; + opacity: 1 !important; +} + +.mobile-mode .list-header .list-header-menu-icon { + position: static !important; + right: auto !important; + top: auto !important; + transform: none !important; + grid-row: 1/3 !important; + grid-column: 3 !important; + padding: 14px !important; + font-size: clamp(24px, 3vw, 48px) !important; + text-align: center !important; + display: block !important; + visibility: visible !important; + opacity: 1 !important; +} + +.mobile-mode .list-header .list-header-handle { + position: static !important; + right: auto !important; + top: auto !important; + transform: none !important; + grid-row: 1/3 !important; + grid-column: 4 !important; + padding: 14px !important; + font-size: clamp(28px, 3.5vw, 56px) !important; + text-align: center !important; + display: block !important; + visibility: visible !important; + opacity: 1 !important; +} + +.mobile-mode .list-body { + width: 100% !important; + min-width: 100% !important; + max-width: 100% !important; + padding: 1rem !important; + display: block !important; +} + +.mobile-mode .minicard { + width: 100% !important; + min-width: 100% !important; + max-width: 100% !important; + font-size: clamp(16px, 2vw, 24px) !important; + padding: 1.2vh 1.5vw 0.5vh !important; + min-height: 3vh !important; + margin-bottom: 0.5rem !important; + display: block !important; + float: none !important; +} + +.mobile-mode .minicard .minicard-title { + font-size: clamp(16px, 2vw, 24px) !important; + font-weight: bold !important; +} + +.mobile-mode .minicard .minicard-members { + font-size: clamp(12px, 1.5vw, 18px) !important; +} + +.mobile-mode .minicard .minicard-lists { + font-size: clamp(12px, 1.5vw, 18px) !important; +} + +/* Desktop Mode Styles */ +.desktop-mode .board-wrapper { + width: auto !important; + height: auto !important; +} + +.desktop-mode .swimlane { + width: auto !important; + min-width: auto !important; +} + +.desktop-mode .list { + width: auto !important; + min-width: auto !important; + display: flex !important; + float: left !important; + margin-bottom: 0 !important; + border-left: 1px solid #ccc !important; + border-bottom: none !important; +} + +.desktop-mode .list-header { + width: auto !important; + min-width: auto !important; + padding: 2.5vh 1.5vw 0.5vh !important; + font-size: clamp(14px, 3vw, 18px) !important; + display: block !important; +} + +.desktop-mode .list-header .list-header-name { + font-size: clamp(14px, 3vw, 18px) !important; + display: inline !important; + grid-row: auto !important; + grid-column: auto !important; + align-self: auto !important; +} + +.desktop-mode .list-header .cardCount { + font-size: 12px !important; + grid-row: auto !important; + grid-column: auto !important; + align-self: auto !important; +} + +.desktop-mode .list-header .list-header-menu-icon { + position: absolute !important; + right: 60px !important; + top: 50% !important; + transform: translateY(-50%) !important; + grid-row: auto !important; + grid-column: auto !important; + padding: 14px !important; + font-size: 40px !important; +} + +.desktop-mode .list-header .list-header-handle { + position: absolute !important; + right: 10px !important; + top: 50% !important; + transform: translateY(-50%) !important; + grid-row: auto !important; + grid-column: auto !important; + padding: 14px !important; + font-size: 48px !important; +} + +.desktop-mode .list-body { + width: auto !important; + min-width: auto !important; + padding: 5px 11px !important; +} + +.desktop-mode .minicard { + width: auto !important; + min-width: auto !important; + font-size: clamp(12px, 2.5vw, 16px) !important; + padding: 0.5vh 0.8vw !important; + min-height: auto !important; + margin-bottom: 9px !important; +} + +.desktop-mode .minicard .minicard-title { + font-size: clamp(12px, 2.5vw, 16px) !important; +} + +.desktop-mode .minicard .minicard-members { + font-size: 10px !important; +} + +.desktop-mode .minicard .minicard-lists { + font-size: 10px !important; +} + +/* Additional Mobile Mode Styles for Other Elements - Works on all screen sizes */ +.mobile-mode .swimlane-header .swimlane-title { + font-size: clamp(18px, 2.5vw, 32px) !important; + font-weight: bold !important; + display: block !important; + visibility: visible !important; + opacity: 1 !important; +} + +.mobile-mode .swimlane-header .swimlane-description { + font-size: clamp(14px, 2vw, 24px) !important; + display: block !important; + visibility: visible !important; + opacity: 1 !important; +} + +.mobile-mode .board-header { + font-size: clamp(18px, 2.5vw, 32px) !important; + padding: 1rem !important; + width: 100% !important; + max-width: 100% !important; +} + +.mobile-mode .board-header .board-header-title { + font-size: clamp(18px, 2.5vw, 32px) !important; + font-weight: bold !important; + display: block !important; + visibility: visible !important; + opacity: 1 !important; +} + +.mobile-mode .board-header .board-header-description { + font-size: clamp(14px, 2vw, 24px) !important; + display: block !important; + visibility: visible !important; + opacity: 1 !important; +} + +.mobile-mode .board-header .board-header-btn { + font-size: clamp(14px, 2vw, 24px) !important; + padding: 1vh 1.5vw !important; + display: inline-block !important; + visibility: visible !important; + opacity: 1 !important; +} + +.mobile-mode .board-header .board-header-btn i { + font-size: clamp(14px, 2vw, 24px) !important; + display: inline !important; + visibility: visible !important; + opacity: 1 !important; +} + +/* Force mobile mode visibility on all screen sizes */ +.mobile-mode .list-header .fa-angle-right, +.mobile-mode .list-header .fa-arrows { + display: block !important; + visibility: visible !important; + opacity: 1 !important; + position: static !important; + right: auto !important; + top: auto !important; + transform: none !important; +} + +.mobile-mode .list-header .fa-angle-right { + grid-row: 1/3 !important; + grid-column: 3 !important; + padding: 14px !important; + font-size: clamp(24px, 3vw, 48px) !important; + text-align: center !important; +} + +.mobile-mode .list-header .fa-arrows { + grid-row: 1/3 !important; + grid-column: 4 !important; + padding: 14px !important; + font-size: clamp(28px, 3.5vw, 56px) !important; + text-align: center !important; +} + +/* Override any media queries that might hide elements in mobile mode */ +.mobile-mode * { + max-width: none !important; +} + +.mobile-mode .list, +.mobile-mode .swimlane, +.mobile-mode .board-wrapper, +.mobile-mode .board-canvas { + max-width: 100% !important; + width: 100% !important; + min-width: 100% !important; +} + +/* Force mobile mode list styling on all screen sizes - override desktop CSS */ +.mobile-mode .board-canvas { + display: block !important; + flex-direction: column !important; + flex-wrap: nowrap !important; + align-items: stretch !important; + justify-content: flex-start !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + overflow-x: hidden !important; + overflow-y: auto !important; +} + +.mobile-mode .swimlane { + display: block !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + margin: 0 0 2rem 0 !important; + padding: 0 !important; + float: none !important; + clear: both !important; +} + +.mobile-mode .swimlane .swimlane-header { + display: block !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + margin: 0 0 1rem 0 !important; + padding: 1rem !important; + font-size: clamp(18px, 2.5vw, 32px) !important; + font-weight: bold !important; + border-bottom: 2px solid #ccc !important; +} + +.mobile-mode .swimlane .lists { + display: block !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + margin: 0 !important; + padding: 0 !important; + flex-direction: column !important; + flex-wrap: nowrap !important; + align-items: stretch !important; + justify-content: flex-start !important; +} + +.mobile-mode .list { + display: block !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + margin: 0 0 2rem 0 !important; + padding: 0 !important; + float: none !important; + clear: both !important; + border-left: none !important; + border-right: none !important; + border-top: none !important; + border-bottom: 2px solid #ccc !important; + flex: none !important; + flex-basis: auto !important; + flex-grow: 0 !important; + flex-shrink: 0 !important; + position: static !important; + left: auto !important; + right: auto !important; + top: auto !important; + bottom: auto !important; + transform: none !important; +} + +.mobile-mode .list:first-child { + margin-left: 0 !important; + margin-top: 0 !important; +} + +.mobile-mode .list:last-child { + margin-right: 0 !important; + margin-bottom: 0 !important; +} + +.mobile-mode .list.ui-sortable-helper { + display: block !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + height: auto !important; + min-height: 60px !important; + margin: 0 0 2rem 0 !important; + padding: 0 !important; + float: none !important; + clear: both !important; + border-left: none !important; + border-right: none !important; + border-top: none !important; + border-bottom: 2px solid #ccc !important; + flex: none !important; +} + +.mobile-mode .list.placeholder { + display: block !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + height: auto !important; + min-height: 60px !important; + margin: 0 0 2rem 0 !important; + padding: 0 !important; + float: none !important; + clear: both !important; + border-left: none !important; + border-right: none !important; + border-top: none !important; + border-bottom: 2px solid #ccc !important; + flex: none !important; +} + +/* Override any existing responsive CSS that might interfere with mobile mode */ +.mobile-mode .board-canvas .swimlane .lists { + display: block !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + margin: 0 !important; + padding: 0 !important; + flex-direction: column !important; + flex-wrap: nowrap !important; + align-items: stretch !important; + justify-content: flex-start !important; + overflow: visible !important; +} + +.mobile-mode .board-canvas .swimlane .lists .list { + display: block !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + margin: 0 0 2rem 0 !important; + padding: 0 !important; + float: none !important; + clear: both !important; + border-left: none !important; + border-right: none !important; + border-top: none !important; + border-bottom: 2px solid #ccc !important; + flex: none !important; + flex-basis: auto !important; + flex-grow: 0 !important; + flex-shrink: 0 !important; + position: static !important; + left: auto !important; + right: auto !important; + top: auto !important; + bottom: auto !important; + transform: none !important; +} + +/* Force mobile mode to override any media query styles */ +@media screen and (min-width: 801px) { + .mobile-mode .board-canvas { + display: block !important; + flex-direction: column !important; + flex-wrap: nowrap !important; + align-items: stretch !important; + justify-content: flex-start !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + overflow-x: hidden !important; + overflow-y: auto !important; + } + + .mobile-mode .swimlane { + display: block !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + margin: 0 0 2rem 0 !important; + padding: 0 !important; + float: none !important; + clear: both !important; + } + + .mobile-mode .swimlane .lists { + display: block !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + margin: 0 !important; + padding: 0 !important; + flex-direction: column !important; + flex-wrap: nowrap !important; + align-items: stretch !important; + justify-content: flex-start !important; + } + + .mobile-mode .list { + display: block !important; + width: 100% !important; + max-width: 100% !important; + min-width: 100% !important; + margin: 0 0 2rem 0 !important; + padding: 0 !important; + float: none !important; + clear: both !important; + border-left: none !important; + border-right: none !important; + border-top: none !important; + border-bottom: 2px solid #ccc !important; + flex: none !important; + flex-basis: auto !important; + flex-grow: 0 !important; + flex-shrink: 0 !important; + position: static !important; + left: auto !important; + right: auto !important; + top: auto !important; + bottom: auto !important; + transform: none !important; + } +} + +/* Hide desktop-only elements in mobile mode (like mobile media queries do) */ +.mobile-mode .board-header-btn i.fa + span { + display: none !important; +} + +.mobile-mode .board-header-btn span { + display: none !important; +} + +.mobile-mode .board-header-btn .fa + span { + display: none !important; +} + +.mobile-mode .board-header-btn .fa + .board-header-btn-text { + display: none !important; +} + +.mobile-mode .board-header-btn .fa + .board-header-btn-label { + display: none !important; +} + +/* Show only icons in mobile mode */ +.mobile-mode .board-header-btn { + width: auto !important; + min-width: auto !important; + padding: 8px !important; + text-align: center !important; +} + +.mobile-mode .board-header-btn i { + display: inline-block !important; + margin: 0 !important; +} + +/* Hide desktop-specific elements that shouldn't show in mobile mode */ +.mobile-mode .desktop-only, +.mobile-mode .board-header .desktop-only { + display: none !important; +} + +.mobile-mode .board-header .board-header-btn.desktop-only { + display: none !important; +} + +/* Hide desktop-specific board header buttons in mobile mode */ +.mobile-mode .board-header-btns.left { + display: none !important; +} + +.mobile-mode .board-header-btns.center { + display: none !important; +} + +/* Show only the right section buttons in mobile mode, but hide text labels */ +.mobile-mode .board-header-btns.right { + display: block !important; +} + +.mobile-mode .board-header-btns.right .board-header-btn span { + display: none !important; +} + +.mobile-mode .board-header-btns.right .board-header-btn .fa + span { + display: none !important; +} + +.mobile-mode .board-header-btns.right .board-header-btn .fa + .board-header-btn-text { + display: none !important; +} + +.mobile-mode .board-header-btns.right .board-header-btn .fa + .board-header-btn-label { + display: none !important; +} + +/* Hide specific desktop-only buttons that shouldn't show in mobile mode */ +.mobile-mode .board-header-btn.js-star-board span, +.mobile-mode .board-header-btn.js-change-visibility span, +.mobile-mode .board-header-btn.js-watch-board span, +.mobile-mode .board-header-btn.js-sort-cards span { + display: none !important; +} + +/* Show only icons for mobile mode buttons */ +.mobile-mode .board-header-btns.right .board-header-btn { + width: auto !important; + min-width: auto !important; + padding: 8px !important; + text-align: center !important; + margin: 0 2px !important; +} + +.mobile-mode .board-header-btns.right .board-header-btn i { + display: inline-block !important; + margin: 0 !important; +} + +/* Ensure mobile mode looks like small screen mobile view */ +.mobile-mode .board-header { + height: 40px !important; +} + +.mobile-mode .board-header .board-header-btns { + margin-top: 0px !important; +} + +.mobile-mode .board-header .board-header-btn { + height: 32px !important; + line-height: 32px !important; + font-size: 15px !important; +} + +.mobile-mode .board-header .board-header-btn i.fa { + line-height: 32px !important; +} + +/* Copy mobile media query styles to mobile mode for consistent appearance */ +.mobile-mode .board-header { + height: 40px !important; + padding: 0 !important; + margin: 0 !important; +} + +.mobile-mode .board-header .board-header-btns { + margin-top: 0px !important; + height: 40px !important; + display: flex !important; + align-items: center !important; + justify-content: flex-end !important; +} + +.mobile-mode .board-header .board-header-btn { + height: 32px !important; + line-height: 32px !important; + font-size: 15px !important; + margin: 0 2px !important; + padding: 4px 8px !important; + border-radius: 4px !important; + background: rgba(255, 255, 255, 0.1) !important; + border: 1px solid rgba(255, 255, 255, 0.2) !important; + color: #fff !important; + text-decoration: none !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + min-width: 32px !important; + width: auto !important; +} + +.mobile-mode .board-header .board-header-btn:hover { + background: rgba(255, 255, 255, 0.2) !important; + border-color: rgba(255, 255, 255, 0.3) !important; +} + +.mobile-mode .board-header .board-header-btn i.fa { + line-height: 32px !important; + font-size: 15px !important; + margin: 0 !important; + padding: 0 !important; +} + +.mobile-mode .board-header .board-header-btn i.fa + span { + display: none !important; +} + +.mobile-mode .board-header .board-header-btn span { + display: none !important; +} + +/* Hide the board title in mobile mode to match mobile view */ +.mobile-mode .header-board-menu { + display: none !important; +} + +/* Ensure the board header takes full width in mobile mode */ +.mobile-mode .board-header { + width: 100% !important; + max-width: 100% !important; + display: flex !important; + align-items: center !important; + justify-content: space-between !important; + padding: 0 10px !important; +} + +/* Additional Desktop Mode Styles for Other Elements */ +.desktop-mode .swimlane-header .swimlane-title { + font-size: clamp(14px, 3vw, 18px) !important; +} + +.desktop-mode .swimlane-header .swimlane-description { + font-size: 12px !important; +} + +.desktop-mode .board-header { + font-size: clamp(14px, 3vw, 18px) !important; + padding: 2.5vh 1.5vw 0.5vh !important; +} + +.desktop-mode .board-header .board-header-title { + font-size: clamp(14px, 3vw, 18px) !important; +} + +.desktop-mode .board-header .board-header-description { + font-size: 12px !important; +} + +.desktop-mode .board-header .board-header-btn { + font-size: clamp(12px, 2.5vw, 16px) !important; + padding: 0.5vh 0.8vw !important; +} + +.desktop-mode .board-header .board-header-btn i { + font-size: clamp(12px, 2.5vw, 16px) !important; +} diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade index ef6738fa1..740696c0f 100644 --- a/client/components/boards/boardHeader.jade +++ b/client/components/boards/boardHeader.jade @@ -51,6 +51,8 @@ template(name="boardHeaderBar") i.fa.fa-sign-in span {{_ 'log-in'}} + .board-header-btns.center + .board-header-btns.right if currentBoard if isMiniScreen diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js index 01859ead5..5d54c2dd3 100644 --- a/client/components/boards/boardHeader.js +++ b/client/components/boards/boardHeader.js @@ -33,6 +33,8 @@ BlazeComponent.extendComponent({ return currentBoard && currentBoard.getWatchLevel(Meteor.userId()); }, + + isStarred() { const boardId = Session.get('currentBoard'); const user = ReactiveCache.getCurrentUser(); diff --git a/client/components/boards/boardsList.css b/client/components/boards/boardsList.css index eeba4d11c..995b22445 100644 --- a/client/components/boards/boardsList.css +++ b/client/components/boards/boardsList.css @@ -1,5 +1,86 @@ @import url("../../../css/reset.css") print, screen; +/* Board List Header with Zoom Controls */ +.board-list-header { + display: flex; + justify-content: center; + margin: 1vh 0 2vh 0; + padding: 1vh 0; +} + +.zoom-controls { + display: flex; + align-items: center; + gap: 0.5vw; + background: rgba(255, 255, 255, 0.9); + padding: 0.5vh 1vw; + border-radius: 0.5vw; + box-shadow: 0 0.2vh 0.5vh rgba(0,0,0,0.1); +} + +.zoom-controls .board-header-btn { + padding: 0.5vh 0.8vw !important; + border-radius: 0.3vw !important; + background: #fff !important; + border: 1px solid #000 !important; + transition: all 0.2s ease !important; + text-decoration: none !important; + color: #000 !important; + display: flex !important; + align-items: center !important; + gap: 0.3vw !important; + height: auto !important; + line-height: normal !important; + margin: 0 !important; + float: none !important; + overflow: visible !important; +} + +.zoom-controls .board-header-btn i { + color: #000 !important; + float: none !important; + display: inline !important; + line-height: normal !important; + margin: 0 !important; +} + +.zoom-controls .board-header-btn:hover { + background: #000 !important; + border-color: #000 !important; + color: #fff !important; +} + +.zoom-controls .board-header-btn:hover i { + color: #fff !important; +} + +.zoom-controls .board-header-btn.is-active { + background: #0079bf; + color: white; + border-color: #005a8a; +} + +.zoom-controls .board-header-btn.is-active i { + color: white; +} + +.zoom-level { + font-weight: bold; + color: #333; + min-width: 3vw; + text-align: center; + font-size: clamp(12px, 2vw, 14px); + cursor: pointer; + padding: 0.3vh 0.5vw; + border-radius: 0.3vw; + transition: all 0.2s ease; +} + +.zoom-level:hover { + background: #f0f0f0; + color: #000; +} + .board-list { margin: 0 8px; } @@ -194,15 +275,33 @@ } /* Mobile view styles - applied when isMiniScreen is true (iPhone, etc.) */ .board-list.mobile-view { - height: 100%; - overflow: scroll; + height: calc(100vh - 120px); + overflow-y: scroll !important; + overflow-x: hidden; + padding: 0 1rem; + margin: 0; + scrollbar-width: auto !important; + scrollbar-color: #888 #f1f1f1; } .board-list.mobile-view li { - width: 50%; + width: 100%; + float: none; + display: block; + margin-bottom: 1rem; + padding-right: 50px; /* Space for drag handle */ } .board-list.mobile-view .board-list-item { - overflow: hidden; + overflow: visible; height: 8rem; + width: 100%; + margin: 0; + padding-right: 50px; /* Ensure content doesn't overlap with drag handle */ +} + +.board-list.mobile-view .board-list-item .details { + padding-right: 50px; /* Extra space for drag handle */ + width: 100%; + box-sizing: border-box; } .board-list.mobile-view .board-list-item-sub-name { position: relative; @@ -216,19 +315,89 @@ transform: translateY(-50%); right: 10px; font-size: 24px; + color: #fff; + background: rgba(0,0,0,0.3); + border-radius: 50%; + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + z-index: 10; + transition: background-color 0.2s ease; } -@media screen and (max-width: 800px) { +.board-list.mobile-view .board-handle:hover { + background: rgba(255, 255, 0, 0.8) !important; /* Yellow hover */ +} + +/* Force scrollbar to be visible on mobile view */ +.board-list.mobile-view::-webkit-scrollbar { + width: 12px !important; + display: block !important; + visibility: visible !important; +} + +.board-list.mobile-view::-webkit-scrollbar-track { + background: #f1f1f1 !important; + border-radius: 6px !important; + display: block !important; + visibility: visible !important; +} + +.board-list.mobile-view::-webkit-scrollbar-thumb { + background: #888 !important; + border-radius: 6px !important; + display: block !important; + visibility: visible !important; +} + +.board-list.mobile-view::-webkit-scrollbar-thumb:hover { + background: #555 !important; +} + +/* Force mobile view to have scrollable content */ +.board-list.mobile-view { + min-height: 100vh; /* Force content to be tall enough to scroll */ +} + +.board-list.mobile-view::after { + content: ''; + display: block; + height: 100px; +} + +@media screen and (max-width: 800px), + screen and (max-device-width: 800px), + screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px), + screen and (max-width: 800px) and (orientation: portrait), + screen and (max-width: 800px) and (orientation: landscape) { .board-list { height: 100%; - overflow: scroll; + overflow-y: auto; + overflow-x: hidden; + padding: 0 1rem; + margin: 0; } .board-list li { - width: 50%; + width: 100%; + float: none; + display: block; + margin-bottom: 1rem; + padding-right: 50px; /* Space for drag handle */ } .board-list .board-list-item { - overflow: hidden; + overflow: visible; height: 8rem; + width: 100%; + margin: 0; + padding-right: 50px; /* Ensure content doesn't overlap with drag handle */ + } + + .board-list .board-list-item .details { + padding-right: 50px; /* Extra space for drag handle */ + width: 100%; + box-sizing: border-box; } .board-list .board-list-item-sub-name { position: relative; @@ -242,32 +411,296 @@ transform: translateY(-50%); right: 10px; font-size: 24px; + color: #fff; + background: rgba(0,0,0,0.3); + border-radius: 50%; + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + z-index: 10; + transition: background-color 0.2s ease; } -} -/* Mobile view styles for very small screens - applied when isMiniScreen is true */ -.board-list.mobile-view li { - width: 50%; -} -.board-list.mobile-view .board-handle { - position: absolute; - padding: 7px; - top: 50%; - transform: translateY(-50%); - right: 10px; - font-size: 24px; -} -@media screen and (max-width: 360px) { - li { - width: 100%; + .board-list .board-handle:hover { + background: rgba(255, 255, 0, 0.8) !important; /* Yellow hover */ } - .board-handle { +} +/* Very small screens - ensure one board per row */ +@media screen and (max-width: 360px) { + .board-list li { + width: 100% !important; + float: none !important; + display: block !important; + } + .board-list .board-handle { position: absolute; padding: 7px; top: 50%; transform: translateY(-50%); right: 10px; font-size: 24px; + color: #fff; + background: rgba(0,0,0,0.3); + border-radius: 50%; + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + } +} + +/* Mobile - make all text and icons 2x bigger above #content on All Boards page */ +@media screen and (max-width: 800px), + screen and (max-device-width: 800px), + screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px), + screen and (max-width: 800px) and (orientation: portrait), + screen and (max-width: 800px) and (orientation: landscape) { + .wrapper { + font-size: 2em !important; /* 2x bigger base font size for All Boards page */ + } + + .wrapper * { + font-size: inherit !important; /* Inherit the 2x scaling */ + } + + .wrapper .fa, .wrapper .icon { + font-size: 2em !important; /* 2x bigger icons */ + } + + .board-list-header { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .board-list-header h1 { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .AllBoardTeamsOrgs { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .AllBoardTeamsOrgs select { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .AllBoardTeamsOrgs input { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .AllBoardTeamsOrgs .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .board-list { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .board-list .board-list-item { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .board-list .board-list-item-name { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .board-list .board-list-item-desc { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .board-list .minicard-members { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .board-list .minicard-lists { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .board-list .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .board-list .board-handle { + font-size: 1em !important; /* Use inherited 2x scaling */ + } +} + +/* Fallback for iPhone devices using JavaScript detection - All Boards page */ +.iphone-device .wrapper { + font-size: 2em !important; /* 2x bigger base font size for All Boards page */ +} + +.iphone-device .wrapper * { + font-size: inherit !important; /* Inherit the 2x scaling */ +} + +.iphone-device .wrapper .fa, .iphone-device .wrapper .icon { + font-size: 2em !important; /* 2x bigger icons */ +} + +.iphone-device .board-list-header { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .board-list-header h1 { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .AllBoardTeamsOrgs { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .AllBoardTeamsOrgs select { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .AllBoardTeamsOrgs input { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .AllBoardTeamsOrgs .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .board-list { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .board-list .board-list-item { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .board-list .board-list-item-name { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .board-list .board-list-item-desc { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .board-list .minicard-members { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .board-list .minicard-lists { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .board-list .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +.iphone-device .board-list .board-handle { + font-size: 1em !important; /* Use inherited 2x scaling */ +} + +/* iPhone 12 Mini and very small screens - make everything much larger */ +@media screen and (max-width: 400px) and (max-height: 900px) { + .board-list { + height: calc(100vh - 120px) !important; + overflow-y: scroll !important; + overflow-x: hidden !important; + -webkit-overflow-scrolling: touch; + padding: 0 0.5rem; + } + + .board-list li { + width: 100% !important; + float: none !important; + display: block !important; + margin-bottom: 1.5rem !important; + } + + .board-list .board-list-item { + height: 12rem !important; /* Much taller */ + width: 100% !important; + margin: 0 !important; + padding: 1rem !important; /* More padding */ + font-size: 18px !important; /* Much larger text */ + line-height: 1.4 !important; + } + + .board-list .board-list-item .board-list-item-name { + font-size: 20px !important; /* Larger board names */ + font-weight: bold !important; + margin-bottom: 0.5rem !important; + } + + .board-list .board-list-item .board-list-item-desc { + font-size: 16px !important; /* Larger descriptions */ + line-height: 1.3 !important; + } + + .board-list .board-list-item .minicard-members { + font-size: 14px !important; /* Larger member avatars */ + } + + .board-list .board-list-item .minicard-lists { + font-size: 14px !important; /* Larger list counters */ + } + + .board-list .board-handle { + position: absolute; + padding: 10px !important; + top: 50%; + transform: translateY(-50%); + right: 15px !important; + font-size: 28px !important; /* Much larger drag handle */ + color: #fff; + background: rgba(0,0,0,0.4) !important; + border-radius: 50%; + width: 50px !important; /* Larger handle */ + height: 50px !important; + display: flex; + align-items: center; + justify-content: center; + z-index: 10; + transition: background-color 0.2s ease; + } + + .board-list .board-handle:hover { + background: rgba(255, 255, 0, 0.8) !important; /* Yellow hover */ + } + + /* Force scrollbar to be visible and larger */ + .board-list::-webkit-scrollbar { + width: 16px !important; /* Much wider scrollbar */ + display: block !important; + visibility: visible !important; + } + + .board-list::-webkit-scrollbar-track { + background: #f1f1f1 !important; + border-radius: 8px !important; + display: block !important; + visibility: visible !important; + } + + .board-list::-webkit-scrollbar-thumb { + background: #666 !important; /* Darker for better visibility */ + border-radius: 8px !important; + display: block !important; + visibility: visible !important; + min-height: 50px !important; /* Minimum thumb size */ + } + + .board-list::-webkit-scrollbar-thumb:hover { + background: #333 !important; + } + + /* Ensure scrollbar is always visible */ + .board-list { + scrollbar-gutter: stable; + scrollbar-width: auto !important; + min-height: 100vh !important; + } + + .board-list::after { + content: ''; + display: block; + height: 200px !important; /* More space to ensure scrolling */ } } .AllBoardTeamsOrgs { @@ -318,3 +751,78 @@ padding-right: 6px; text-align: center; } + +/* Fix multiple scrollbars issue on mobile */ +@media screen and (max-width: 800px), + screen and (max-device-width: 800px), + screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px), + screen and (max-width: 800px) and (orientation: portrait), + screen and (max-width: 800px) and (orientation: landscape) { + .wrapper { + overflow: hidden; + height: 100vh; + } + + .board-list { + overflow-y: scroll !important; + overflow-x: hidden !important; + -webkit-overflow-scrolling: touch; + scrollbar-width: thin; + scrollbar-color: #888 #f1f1f1; + height: calc(100vh - 120px); /* Ensure there's content to scroll */ + } + + /* Force scrollbar to always be visible */ + .board-list::-webkit-scrollbar { + width: 12px !important; + display: block !important; + visibility: visible !important; + } + + .board-list::-webkit-scrollbar-track { + background: #f1f1f1 !important; + border-radius: 6px !important; + display: block !important; + visibility: visible !important; + } + + .board-list::-webkit-scrollbar-thumb { + background: #888 !important; + border-radius: 6px !important; + display: block !important; + visibility: visible !important; + } + + .board-list::-webkit-scrollbar-thumb:hover { + background: #555 !important; + } + + /* Ensure scrollbar is always visible */ + .board-list::-webkit-scrollbar-corner { + background: #f1f1f1 !important; + } + + /* Force scrollbar to be visible */ + .board-list { + scrollbar-gutter: stable; + scrollbar-width: auto !important; + min-height: 100vh; /* Force content to be tall enough to scroll */ + } + + /* Ensure there's always content to scroll */ + .board-list::after { + content: ''; + display: block; + height: 100px; + } + + /* Ensure only one scrollbar is visible */ + body { + overflow: hidden; + } + + #content { + overflow: hidden; + } +} + diff --git a/client/components/boards/boardsList.jade b/client/components/boards/boardsList.jade index cd2fe9b8a..f5fb4522e 100644 --- a/client/components/boards/boardsList.jade +++ b/client/components/boards/boardsList.jade @@ -1,5 +1,7 @@ template(name="boardList") .wrapper + .board-list-header + ul.AllBoardTeamsOrgs li.AllBoardTeams if userHasTeams diff --git a/client/components/boards/boardsList.js b/client/components/boards/boardsList.js index bfcab9ddd..1d655fd11 100644 --- a/client/components/boards/boardsList.js +++ b/client/components/boards/boardsList.js @@ -22,6 +22,9 @@ Template.boardListHeaderBar.events({ }, }); +Template.boardList.events({ +}); + Template.boardListHeaderBar.helpers({ title() { //if (FlowRouter.getRouteName() === 'template-container') { diff --git a/client/components/lists/list.css b/client/components/lists/list.css index 168f90f5b..c81551aaf 100644 --- a/client/components/lists/list.css +++ b/client/components/lists/list.css @@ -219,6 +219,7 @@ flex: 0 0 60px; height: auto; width: 100%; + min-width: 100%; border-left: 0px; border-bottom: 1px solid #ccc; } @@ -226,6 +227,7 @@ display: contents; flex-basis: auto; width: 100%; + min-width: 100%; border-left: 0px; } .list.mobile-view:first-child { @@ -250,6 +252,8 @@ } .list.mobile-view .list-body { padding: 15px 19px; + width: 100%; + min-width: 100%; } .list.mobile-view .list-header { /*Updated padding values for mobile devices, this should fix text grouping issue*/ @@ -258,6 +262,8 @@ min-height: 30px; margin-top: 10px; align-items: center; + width: 100%; + min-width: 100%; /* Force grid layout for iPhone */ display: grid !important; grid-template-columns: 30px 1fr auto auto !important; @@ -338,6 +344,7 @@ flex: 0 0 60px; height: auto; width: 100%; + min-width: 100%; border-left: 0px; border-bottom: 1px solid #ccc; } @@ -345,6 +352,7 @@ display: contents; flex-basis: auto; width: 100%; + min-width: 100%; border-left: 0px; } .list:first-child { @@ -369,6 +377,8 @@ } .list-body { padding: 15px 19px; + width: 100%; + min-width: 100%; } .list-header { /*Updated padding values for mobile devices, this should fix text grouping issue*/ @@ -377,6 +387,8 @@ min-height: 30px; margin-top: 10px; align-items: center; + width: 100%; + min-width: 100%; } .list-header .list-header-left-icon { padding: 7px; @@ -451,6 +463,132 @@ align-items: initial; } } + +/* iPhone 12 Mini specific - fix icon positioning in stacked lists view */ +@media screen and (device-width: 375px) and (device-height: 812px), /* iPhone 12 Mini exact */ + screen and (max-width: 375px) and (max-height: 812px), /* iPhone 12 Mini viewport */ + screen and (-webkit-min-device-pixel-ratio: 3) and (max-width: 375px) /* iPhone 12 Mini Retina */ { + .list.mobile-view .list-header { + /* Force grid layout for iPhone 12 Mini */ + display: grid !important; + grid-template-columns: 30px 1fr auto auto !important; + gap: 10px !important; + align-items: center !important; + } + + .list.mobile-view .list-header .list-header-menu-icon { + /* Remove absolute positioning for iPhone 12 Mini */ + position: static !important; + right: auto !important; + top: auto !important; + transform: none !important; + /* Use grid positioning */ + grid-row: 1/3 !important; + grid-column: 3 !important; + padding: 14px !important; + font-size: 40px !important; + text-align: center !important; + } + + .list.mobile-view .list-header .list-header-handle { + /* Remove absolute positioning for iPhone 12 Mini */ + position: static !important; + right: auto !important; + top: auto !important; + transform: none !important; + /* Use grid positioning */ + grid-row: 1/3 !important; + grid-column: 4 !important; + padding: 14px !important; + font-size: 48px !important; + text-align: center !important; + } + + .list.mobile-view .list-header .list-header-name { + grid-row: 1 !important; + grid-column: 2 !important; + align-self: end !important; + font-size: 20px !important; + font-weight: bold !important; + line-height: 1.2 !important; + padding-bottom: 2px !important; + } + + .list.mobile-view .list-header .cardCount { + grid-row: 2 !important; + grid-column: 2 !important; + align-self: start !important; + font-size: 16px !important; + line-height: 1.2 !important; + } + + .list.mobile-view .list-header .list-header-left-icon { + display: grid !important; + grid-row: 1/3 !important; + grid-column: 1 !important; + } +} + +/* iPhone device JavaScript detection fallback - fix icon positioning */ +.iphone-device .list.mobile-view .list-header { + /* Force grid layout for iPhone devices */ + display: grid !important; + grid-template-columns: 30px 1fr auto auto !important; + gap: 10px !important; + align-items: center !important; +} + +.iphone-device .list.mobile-view .list-header .list-header-menu-icon { + /* Remove absolute positioning for iPhone devices */ + position: static !important; + right: auto !important; + top: auto !important; + transform: none !important; + /* Use grid positioning */ + grid-row: 1/3 !important; + grid-column: 3 !important; + padding: 14px !important; + font-size: 40px !important; + text-align: center !important; +} + +.iphone-device .list.mobile-view .list-header .list-header-handle { + /* Remove absolute positioning for iPhone devices */ + position: static !important; + right: auto !important; + top: auto !important; + transform: none !important; + /* Use grid positioning */ + grid-row: 1/3 !important; + grid-column: 4 !important; + padding: 14px !important; + font-size: 48px !important; + text-align: center !important; +} + +.iphone-device .list.mobile-view .list-header .list-header-name { + grid-row: 1 !important; + grid-column: 2 !important; + align-self: end !important; + font-size: 20px !important; + font-weight: bold !important; + line-height: 1.2 !important; + padding-bottom: 2px !important; +} + +.iphone-device .list.mobile-view .list-header .cardCount { + grid-row: 2 !important; + grid-column: 2 !important; + align-self: start !important; + font-size: 16px !important; + line-height: 1.2 !important; +} + +.iphone-device .list.mobile-view .list-header .list-header-left-icon { + display: grid !important; + grid-row: 1/3 !important; + grid-column: 1 !important; +} .link-board-wrapper { display: flex; align-items: baseline; diff --git a/client/components/main/header.css b/client/components/main/header.css index 815260db4..cb6be4e88 100644 --- a/client/components/main/header.css +++ b/client/components/main/header.css @@ -99,7 +99,36 @@ display: flex; z-index: 1000; padding: 10px 0px; + align-items: center; + flex-wrap: wrap; /* Allow wrapping on mobile */ + min-height: 28px; /* Allow height to grow */ } +#header-quick-access .home-icon { + display: flex; + align-items: center; + margin-right: 1rem; + flex-shrink: 0; +} + +#header-quick-access .home-icon a { + display: flex; + align-items: center; + text-decoration: none; + color: #fff; + padding: 4px 8px; + border-radius: 4px; + transition: background-color 0.2s ease; +} + +#header-quick-access .home-icon a:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +#header-quick-access .home-icon .fa-home { + font-size: 16px; + margin-right: 4px; +} + #header-quick-access .allBoards { font-size: 14px; padding: 4px 15px; @@ -196,6 +225,197 @@ margin: 4px 8px 0 0; float: left; } + +/* Zoom Controls in Header */ +#header-quick-access .zoom-controls { + display: flex; + align-items: center; + gap: 0.5vw; + background: rgba(255, 255, 255, 0.9); + padding: 0.5vh 1vw; + border-radius: 0.5vw; + box-shadow: 0 0.2vh 0.5vh rgba(0,0,0,0.1); + margin: 0 1vw; + float: left; +} + +#header-quick-access .zoom-controls .board-header-btn { + padding: 0.5vh 0.8vw !important; + border-radius: 0.3vw !important; + background: #fff !important; + border: 1px solid #000 !important; + transition: all 0.2s ease !important; + color: #000 !important; + height: auto !important; + line-height: normal !important; + margin: 0 !important; + float: none !important; + overflow: visible !important; + text-decoration: none !important; + display: flex !important; + align-items: center !important; + gap: 0.3vw !important; +} + +#header-quick-access .zoom-controls .board-header-btn i { + color: #000 !important; + float: none !important; + display: inline !important; + line-height: normal !important; + margin: 0 !important; +} + +#header-quick-access .zoom-controls .board-header-btn:hover { + background: #000 !important; + border-color: #000 !important; + color: #fff !important; +} + +#header-quick-access .zoom-controls .board-header-btn:hover i { + color: #fff !important; +} + +#header-quick-access .zoom-controls .zoom-level { + font-weight: bold; + color: #333; + min-width: 3vw; + text-align: center; + font-size: clamp(12px, 2vw, 14px); + cursor: pointer; + padding: 0.3vh 0.5vw; + border-radius: 0.3vw; + transition: all 0.2s ease; + position: relative; + display: flex; + align-items: center; + justify-content: center; +} + +#header-quick-access .zoom-controls .zoom-level:hover { + background: #f0f0f0; + color: #000; +} + +#header-quick-access .zoom-controls .zoom-display { + display: inline-block; +} + + #header-quick-access .zoom-controls .zoom-input { + background: #fff; + color: #000; + border: 1px solid #ccc; + border-radius: 0.3vw; + padding: 0.3vh 0.5vw; + font-weight: bold; + text-align: center; + width: 100%; + min-width: 3vw; + font-size: clamp(12px, 2vw, 14px); + } + + /* Make zoom input wider on all mobile screens */ + @media screen and (max-width: 800px) { + #header-quick-access .zoom-controls .zoom-input { + min-width: 50px !important; /* Wider on mobile */ + width: 50px !important; /* Fixed width to show all numbers */ + font-size: 14px !important; /* Slightly larger text */ + } + } + +#header-quick-access .zoom-controls .zoom-input:focus { + outline: 2px solid #005fcc; + outline-offset: 1px; +} + +/* Mobile Mode Toggle in Header */ +#header-quick-access .mobile-mode-toggle { + display: flex; + align-items: center; + margin: 0 1vw; + float: left; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn { + padding: 0.5vh 0.8vw !important; + border-radius: 0.3vw !important; + background: #fff !important; + border: 1px solid #000 !important; + transition: all 0.2s ease !important; + color: #000 !important; + height: auto !important; + line-height: normal !important; + margin: 0 !important; + float: none !important; + overflow: visible !important; + text-decoration: none !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + gap: 6px !important; + position: relative !important; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn i { + color: #666 !important; + float: none !important; + display: inline !important; + line-height: normal !important; + margin: 0 !important; + transition: all 0.2s ease !important; + font-size: clamp(14px, 2.8vw, 18px) !important; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn i.active { + color: #000 !important; + font-weight: bold !important; + transform: scale(1.1) !important; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn:hover { + background: #000 !important; + border-color: #000 !important; + color: #fff !important; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn:hover i { + color: #ccc !important; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn:hover i.active { + color: #fff !important; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn.mobile-active { + background: #fff !important; + border-color: #000 !important; + color: #000 !important; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn.mobile-active i.mobile-icon { + color: #000 !important; + font-weight: bold !important; + transform: scale(1.1) !important; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn.mobile-active i.desktop-icon { + color: #666 !important; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn.desktop-active { + background: #fff !important; + border-color: #000 !important; + color: #000 !important; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn.desktop-active i.mobile-icon { + color: #666 !important; +} + +#header-quick-access .mobile-mode-toggle .board-header-btn.desktop-active i.desktop-icon { + color: #000 !important; + font-weight: bold !important; + transform: scale(1.1) !important; +} #header-quick-access #header-user-bar .header-user-bar-name i.fa-chevron-down { margin-right: 4px; } @@ -227,6 +447,650 @@ width: 100%; z-index: 30; } + + /* Mobile home icon styling */ + #header-quick-access .home-icon { + margin-right: 0.5rem; + } + + #header-quick-access .home-icon .fa-home { + font-size: 16px; + margin-right: 4px; + } + + #header-quick-access .home-icon a { + padding: 4px 8px; + font-size: 12px; + } + + /* Ensure All Boards text is visible on mobile */ + #header-quick-access .home-icon.allBoards { + display: flex; + align-items: center; + } + + /* Adjust for very small screens */ + @media screen and (max-width: 480px) { + #header-quick-access .home-icon a { + font-size: 11px; + padding: 3px 6px; + } + + #header-quick-access .home-icon .fa-home { + font-size: 14px; + margin-right: 3px; + } + } + + /* Mobile - make all text and icons 2x bigger above #content by default */ + @media screen and (max-width: 800px), + screen and (max-device-width: 800px), + screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px), + screen and (max-width: 800px) and (orientation: portrait), + screen and (max-width: 800px) and (orientation: landscape) { + #header-quick-access { + height: auto !important; /* Allow height to grow */ + min-height: 48px !important; /* Minimum height for mobile */ + flex-wrap: wrap !important; /* Force wrapping */ + align-items: flex-start !important; /* Align to top when wrapping */ + padding: 8px 0px !important; /* Adjust padding for mobile */ + } + #header-quick-access { + font-size: 2em !important; /* 2x bigger base font size */ + } + + #header-quick-access * { + font-size: inherit !important; /* Inherit the 2x scaling */ + } + + #header-quick-access .fa, + #header-quick-access .icon { + font-size: 2em !important; /* 2x bigger icons */ + } + + #header-quick-access .home-icon a { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .home-icon .fa-home { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .zoom-controls { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .zoom-controls .zoom-level { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .zoom-controls .zoom-input { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .mobile-mode-toggle .board-header-btn { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .mobile-mode-toggle .board-header-btn i { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + /* Mobile header wrapping and spacing */ + #header-quick-access .home-icon { + flex-shrink: 0 !important; + margin-right: 0.5rem !important; + margin-bottom: 4px !important; + } + + #header-quick-access .zoom-controls { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 4px !important; + } + + #header-quick-access .mobile-mode-toggle { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 4px !important; + } + + #header-quick-access #notifications { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 4px !important; + } + + #header-quick-access #header-user-bar { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 4px !important; + } + + #header-quick-access ul.header-quick-access-list { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 4px !important; + width: auto !important; + } + } + + /* Mobile All Boards page - make logo row elements 2x bigger */ + @media screen and (max-width: 800px), + screen and (max-device-width: 800px), + screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 800px), + screen and (max-width: 800px) and (orientation: portrait), + screen and (max-width: 800px) and (orientation: landscape) { + .wrapper ~ #header-quick-access, + body:not(.board-view) #header-quick-access { + font-size: 2em !important; /* 2x bigger base font size for logo row */ + } + + /* iPhone 12 Mini specific - 3x bigger for All Boards page */ + @media screen and (device-width: 375px) and (device-height: 812px), /* iPhone 12 Mini exact */ + screen and (max-width: 375px) and (max-height: 812px), /* iPhone 12 Mini viewport */ + screen and (-webkit-min-device-pixel-ratio: 3) and (max-width: 375px) /* iPhone 12 Mini Retina */ { + .wrapper ~ #header-quick-access, + body:not(.board-view) #header-quick-access { + font-size: 3em !important; /* 3x bigger base font size for iPhone 12 Mini All Boards page */ + } + } + + .wrapper ~ #header-quick-access *, + body:not(.board-view) #header-quick-access * { + font-size: inherit !important; /* Inherit the 2x scaling */ + } + + .wrapper ~ #header-quick-access .fa, + .wrapper ~ #header-quick-access .icon, + body:not(.board-view) #header-quick-access .fa, + body:not(.board-view) #header-quick-access .icon { + font-size: 2em !important; /* 2x bigger icons in logo row */ + } + + .wrapper ~ #header-quick-access .home-icon a, + body:not(.board-view) #header-quick-access .home-icon a { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .wrapper ~ #header-quick-access .home-icon .fa-home, + body:not(.board-view) #header-quick-access .home-icon .fa-home { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .wrapper ~ #header-quick-access .zoom-controls, + body:not(.board-view) #header-quick-access .zoom-controls { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .wrapper ~ #header-quick-access .zoom-controls .zoom-level, + body:not(.board-view) #header-quick-access .zoom-controls .zoom-level { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .wrapper ~ #header-quick-access .zoom-controls .zoom-input, + body:not(.board-view) #header-quick-access .zoom-controls .zoom-input { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .wrapper ~ #header-quick-access .mobile-mode-toggle .board-header-btn, + body:not(.board-view) #header-quick-access .mobile-mode-toggle .board-header-btn { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .wrapper ~ #header-quick-access .mobile-mode-toggle .board-header-btn i, + body:not(.board-view) #header-quick-access .mobile-mode-toggle .board-header-btn i { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .wrapper ~ #header-quick-access #notifications, + body:not(.board-view) #header-quick-access #notifications { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .wrapper ~ #header-quick-access #notifications .fa, + body:not(.board-view) #header-quick-access #notifications .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .wrapper ~ #header-quick-access #header-user-bar, + body:not(.board-view) #header-quick-access #header-user-bar { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .wrapper ~ #header-quick-access #header-user-bar .fa, + body:not(.board-view) #header-quick-access #header-user-bar .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + } + + /* iPhone 12 Mini specific - make header elements 3x bigger */ + @media screen and (device-width: 375px) and (device-height: 812px), /* iPhone 12 Mini exact */ + screen and (max-width: 375px) and (max-height: 812px), /* iPhone 12 Mini viewport */ + screen and (-webkit-min-device-pixel-ratio: 3) and (max-width: 375px), /* iPhone 12 Mini Retina */ + screen and (max-width: 375px) and (orientation: portrait), /* iPhone 12 Mini portrait */ + screen and (max-width: 375px) and (orientation: landscape) /* iPhone 12 Mini landscape */ { + #header-quick-access { + font-size: 3em !important; /* 3x bigger base font size for iPhone 12 Mini */ + height: auto !important; /* Allow height to grow */ + min-height: 84px !important; /* Much taller minimum height for iPhone 12 Mini */ + flex-wrap: wrap !important; /* Force wrapping */ + align-items: flex-start !important; /* Align to top when wrapping */ + padding: 18px 0px !important; /* More padding for iPhone 12 Mini */ + } + + #header-quick-access * { + font-size: inherit !important; /* Inherit the 2x scaling */ + } + + #header-quick-access .fa, + #header-quick-access .icon { + font-size: 3em !important; /* 3x bigger icons for iPhone 12 Mini */ + } + + #header-quick-access .home-icon a { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .home-icon .fa-home { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .zoom-controls { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .zoom-controls .zoom-level { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .zoom-controls .zoom-input { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .mobile-mode-toggle .board-header-btn { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access .mobile-mode-toggle .board-header-btn i { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access #notifications { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access #notifications .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access #header-user-bar { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + #header-quick-access #header-user-bar .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + /* iPhone 12 Mini header wrapping and spacing */ + #header-quick-access .home-icon { + flex-shrink: 0 !important; + margin-right: 0.5rem !important; + margin-bottom: 6px !important; + } + + #header-quick-access .zoom-controls { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 6px !important; + } + + #header-quick-access .mobile-mode-toggle { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 6px !important; + } + + #header-quick-access #notifications { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 6px !important; + } + + #header-quick-access #header-user-bar { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 6px !important; + } + + #header-quick-access ul.header-quick-access-list { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 6px !important; + width: auto !important; + } + } + + /* iPhone 12 Mini and very small screens - make header elements much larger */ + @media screen and (max-width: 400px) and (max-height: 900px), + screen and (max-device-width: 400px) and (max-device-height: 900px), + screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 400px), + screen and (max-width: 400px) and (orientation: portrait), + screen and (max-width: 400px) and (orientation: landscape), + screen and (max-width: 430px) and (max-height: 950px), /* iPhone 12 Mini range */ + screen and (max-width: 450px) and (max-height: 1000px), /* iPhone range */ + screen and (-webkit-min-device-pixel-ratio: 3) and (max-width: 450px), /* Retina displays */ + screen and (device-width: 375px) and (device-height: 812px), /* iPhone 12 Mini exact */ + screen and (device-width: 390px) and (device-height: 844px), /* iPhone 12/13 */ + screen and (device-width: 428px) and (device-height: 926px) /* iPhone 12 Pro Max */ { + #header-quick-access { + height: 40px !important; /* Taller header */ + padding: 12px 0px !important; + } + + #header-quick-access .home-icon a { + font-size: 16px !important; /* Much larger text */ + padding: 8px 12px !important; + } + + #header-quick-access .home-icon .fa-home { + font-size: 20px !important; /* Much larger icon */ + margin-right: 6px !important; + } + + #header-quick-access .home-icon { + margin-right: 1rem !important; + } + + /* Make zoom controls larger */ + #header-quick-access .zoom-controls { + padding: 0.8vh 1.5vw !important; + margin: 0 1.5vw !important; + } + + #header-quick-access .zoom-controls .zoom-level { + font-size: 16px !important; /* Larger zoom text */ + padding: 0.5vh 0.8vw !important; + min-width: 4vw !important; + } + + #header-quick-access .zoom-controls .zoom-input { + font-size: 16px !important; /* Larger input text */ + padding: 0.5vh 0.8vw !important; + min-width: 6vw !important; /* Much wider for mobile */ + width: 60px !important; /* Fixed width to show all numbers */ + } + + /* Make mobile mode toggle larger */ + #header-quick-access .mobile-mode-toggle .board-header-btn { + padding: 0.8vh 1.2vw !important; + font-size: 16px !important; + } + + #header-quick-access .mobile-mode-toggle .board-header-btn i { + font-size: 18px !important; + } + } + + /* Fallback for iPhone devices using JavaScript detection */ + .iphone-device #header-quick-access { + font-size: 2em !important; /* 2x bigger base font size */ + height: auto !important; /* Allow height to grow */ + min-height: 48px !important; /* Minimum height for mobile */ + flex-wrap: wrap !important; /* Force wrapping */ + align-items: flex-start !important; /* Align to top when wrapping */ + padding: 8px 0px !important; /* Adjust padding for mobile */ + } + + .iphone-device #header-quick-access * { + font-size: inherit !important; /* Inherit the 2x scaling */ + } + + .iphone-device #header-quick-access .fa, + .iphone-device #header-quick-access .icon { + font-size: 2em !important; /* 2x bigger icons */ + } + + .iphone-device #header-quick-access .home-icon a { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .home-icon .fa-home { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .zoom-controls { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .zoom-controls .zoom-level { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .zoom-controls .zoom-input { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .mobile-mode-toggle .board-header-btn { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .mobile-mode-toggle .board-header-btn i { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + /* iPhone device header wrapping and spacing */ + .iphone-device #header-quick-access .home-icon { + flex-shrink: 0 !important; + margin-right: 0.5rem !important; + margin-bottom: 4px !important; + } + + .iphone-device #header-quick-access .zoom-controls { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 4px !important; + } + + .iphone-device #header-quick-access .mobile-mode-toggle { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 4px !important; + } + + .iphone-device #header-quick-access #notifications { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 4px !important; + } + + .iphone-device #header-quick-access #header-user-bar { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 4px !important; + } + + .iphone-device #header-quick-access ul.header-quick-access-list { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 4px !important; + width: auto !important; + } + + /* iPhone 12 Mini specific - JavaScript detection fallback */ + .iphone-device #header-quick-access { + font-size: 3em !important; /* 3x bigger base font size for iPhone 12 Mini */ + height: auto !important; /* Allow height to grow */ + min-height: 84px !important; /* Much taller minimum height for iPhone 12 Mini */ + flex-wrap: wrap !important; /* Force wrapping */ + align-items: flex-start !important; /* Align to top when wrapping */ + padding: 18px 0px !important; /* More padding for iPhone 12 Mini */ + } + + .iphone-device #header-quick-access * { + font-size: inherit !important; /* Inherit the 2x scaling */ + } + + .iphone-device #header-quick-access .fa, + .iphone-device #header-quick-access .icon { + font-size: 3em !important; /* 3x bigger icons for iPhone 12 Mini */ + } + + .iphone-device #header-quick-access .home-icon a { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .home-icon .fa-home { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .zoom-controls { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .zoom-controls .zoom-level { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .zoom-controls .zoom-input { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .mobile-mode-toggle .board-header-btn { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access .mobile-mode-toggle .board-header-btn i { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access #notifications { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access #notifications .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access #header-user-bar { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device #header-quick-access #header-user-bar .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + /* iPhone 12 Mini header wrapping and spacing - JavaScript fallback */ + .iphone-device #header-quick-access .home-icon { + flex-shrink: 0 !important; + margin-right: 0.5rem !important; + margin-bottom: 6px !important; + } + + .iphone-device #header-quick-access .zoom-controls { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 6px !important; + } + + .iphone-device #header-quick-access .mobile-mode-toggle { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 6px !important; + } + + .iphone-device #header-quick-access #notifications { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 6px !important; + } + + .iphone-device #header-quick-access #header-user-bar { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 6px !important; + } + + .iphone-device #header-quick-access ul.header-quick-access-list { + flex-shrink: 0 !important; + margin: 0 0.5rem !important; + margin-bottom: 6px !important; + width: auto !important; + } + + /* iPhone 12 Mini All Boards page - make logo row elements 3x bigger */ + .iphone-device .wrapper ~ #header-quick-access, + .iphone-device body:not(.board-view) #header-quick-access { + font-size: 3em !important; /* 3x bigger base font size for logo row */ + } + + .iphone-device .wrapper ~ #header-quick-access *, + .iphone-device body:not(.board-view) #header-quick-access * { + font-size: inherit !important; /* Inherit the 2x scaling */ + } + + .iphone-device .wrapper ~ #header-quick-access .fa, + .iphone-device .wrapper ~ #header-quick-access .icon, + .iphone-device body:not(.board-view) #header-quick-access .fa, + .iphone-device body:not(.board-view) #header-quick-access .icon { + font-size: 2em !important; /* 2x bigger icons in logo row */ + } + + .iphone-device .wrapper ~ #header-quick-access .home-icon a, + .iphone-device body:not(.board-view) #header-quick-access .home-icon a { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device .wrapper ~ #header-quick-access .home-icon .fa-home, + .iphone-device body:not(.board-view) #header-quick-access .home-icon .fa-home { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device .wrapper ~ #header-quick-access .zoom-controls, + .iphone-device body:not(.board-view) #header-quick-access .zoom-controls { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device .wrapper ~ #header-quick-access .zoom-controls .zoom-level, + .iphone-device body:not(.board-view) #header-quick-access .zoom-controls .zoom-level { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device .wrapper ~ #header-quick-access .zoom-controls .zoom-input, + .iphone-device body:not(.board-view) #header-quick-access .zoom-controls .zoom-input { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device .wrapper ~ #header-quick-access .mobile-mode-toggle .board-header-btn, + .iphone-device body:not(.board-view) #header-quick-access .mobile-mode-toggle .board-header-btn { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device .wrapper ~ #header-quick-access .mobile-mode-toggle .board-header-btn i, + .iphone-device body:not(.board-view) #header-quick-access .mobile-mode-toggle .board-header-btn i { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device .wrapper ~ #header-quick-access #notifications, + .iphone-device body:not(.board-view) #header-quick-access #notifications { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device .wrapper ~ #header-quick-access #notifications .fa, + .iphone-device body:not(.board-view) #header-quick-access #notifications .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device .wrapper ~ #header-quick-access #header-user-bar, + .iphone-device body:not(.board-view) #header-quick-access #header-user-bar { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + + .iphone-device .wrapper ~ #header-quick-access #header-user-bar .fa, + .iphone-device body:not(.board-view) #header-quick-access #header-user-bar .fa { + font-size: 1em !important; /* Use inherited 2x scaling */ + } + #header-quick-access ul { width: calc(100% - 60px); margin-right: 10px; @@ -237,12 +1101,6 @@ #header-quick-access ul li a { height: 100%; } - #header-quick-access span .fa-home { - font-size: 26px; - margin-top: -2px; - margin-right: 10px; - margin-left: 10px; - } #header-quick-access #header-new-board-icon { display: none; } diff --git a/client/components/main/header.jade b/client/components/main/header.jade index b9e61dea9..0ceb2ae9d 100644 --- a/client/components/main/header.jade +++ b/client/components/main/header.jade @@ -6,10 +6,31 @@ template(name="header") The first link goes to the boards page. if currentUser #header-quick-access(class=currentBoard.colorClass) + // Home icon - always at left side of logo + span.home-icon.allBoards + a(href="{{pathFor 'home'}}") + span.fa.fa-home + | {{_ 'all-boards'}} + + // Logo - always visible in desktop mode + unless currentSetting.hideLogo + if currentSetting.customTopLeftCornerLogoImageUrl + if currentSetting.customTopLeftCornerLogoLinkUrl + a(href="{{currentSetting.customTopLeftCornerLogoLinkUrl}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") + img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0") + unless currentSetting.customTopLeftCornerLogoLinkUrl + img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") + unless currentSetting.customTopLeftCornerLogoImageUrl + div#headerIsSettingDatabaseCallDone + img(src="{{pathFor '/logo-header.png'}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") + + // Zoom controls - always visible + .zoom-controls + span.zoom-level.js-zoom-level-click(title="{{_ 'click-to-change-zoom'}}") + span.zoom-display {{zoomLevel}}% + input.zoom-input.js-zoom-input(type="number" value=zoomLevel min="50" max="300" step="10" style="display: none;") + if isMiniScreen - span - a(href="{{pathFor 'home'}}") - span.fa.fa-home ul.header-quick-access-list if currentList each currentBoard.lists @@ -31,24 +52,6 @@ template(name="header") // i.fa.fa-ban #header-new-board-icon else - //- - On sandstorm, the logo shouldn't be clickable, because we only have one - page/document on it, and we don't want to see the home page containing - the list of all boards. - unless currentSetting.hideLogo - if currentSetting.customTopLeftCornerLogoImageUrl - if currentSetting.customTopLeftCornerLogoLinkUrl - a(href="{{currentSetting.customTopLeftCornerLogoLinkUrl}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") - img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0") - unless currentSetting.customTopLeftCornerLogoLinkUrl - img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") - unless currentSetting.customTopLeftCornerLogoImageUrl - div#headerIsSettingDatabaseCallDone - img(src="{{pathFor '/logo-header.png'}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") - span.allBoards - a(href="{{pathFor 'home'}}") - span.fa.fa-home - | {{_ 'all-boards'}} ul.header-quick-access-list //li // a(href="{{pathFor 'public'}}") @@ -75,6 +78,10 @@ template(name="header") //a#header-new-board-icon.js-create-board // i.fa.fa-plus(title="Create a new board") + .mobile-mode-toggle + a.board-header-btn.js-mobile-mode-toggle(title="{{_ 'mobile-desktop-toggle'}}" class="{{#if mobileMode}}mobile-active{{else}}desktop-active{{/if}}") + i.fa.fa-mobile.mobile-icon(class="{{#if mobileMode}}active{{/if}}") + i.fa.fa-desktop.desktop-icon(class="{{#unless mobileMode}}active{{/unless}}") +notifications if currentSetting.customHelpLinkUrl diff --git a/client/components/main/header.js b/client/components/main/header.js index 077c72caa..f56a47f44 100644 --- a/client/components/main/header.js +++ b/client/components/main/header.js @@ -44,10 +44,66 @@ Template.header.helpers({ const announcements = Announcements.findOne(); return announcements && announcements.body; }, + + zoomLevel() { + const sessionZoom = Session.get('wekan-zoom-level'); + if (sessionZoom !== undefined) { + return Math.round(sessionZoom * 100); + } + return Math.round(Utils.getZoomLevel() * 100); + }, + + mobileMode() { + const sessionMode = Session.get('wekan-mobile-mode'); + if (sessionMode !== undefined) { + return sessionMode; + } + return Utils.getMobileMode(); + }, }); Template.header.events({ 'click .js-create-board': Popup.open('headerBarCreateBoard'), + 'click .js-zoom-level-click'(evt) { + const $zoomDisplay = $(evt.currentTarget).find('.zoom-display'); + const $zoomInput = $(evt.currentTarget).find('.zoom-input'); + + // Hide display, show input + $zoomDisplay.hide(); + $zoomInput.show().focus().select(); + }, + + 'keypress .js-zoom-input'(evt) { + if (evt.which === 13) { // Enter key + const newZoomPercent = parseInt(evt.target.value); + + if (!isNaN(newZoomPercent) && newZoomPercent >= 50 && newZoomPercent <= 300) { + const newZoom = newZoomPercent / 100; + Utils.setZoomLevel(newZoom); + + // Hide input, show display + const $zoomDisplay = $(evt.target).siblings('.zoom-display'); + const $zoomInput = $(evt.target); + $zoomInput.hide(); + $zoomDisplay.show(); + } else { + alert('Please enter a zoom level between 50% and 300%'); + evt.target.focus().select(); + } + } + }, + + 'blur .js-zoom-input'(evt) { + // When input loses focus, hide it and show display + const $zoomDisplay = $(evt.target).siblings('.zoom-display'); + const $zoomInput = $(evt.target); + $zoomInput.hide(); + $zoomDisplay.show(); + }, + 'click .js-mobile-mode-toggle'() { + const currentMode = Utils.getMobileMode(); + Utils.setMobileMode(!currentMode); + }, 'click .js-close-announcement'() { $('.announcement').hide(); }, diff --git a/client/components/sidebar/sidebar.jade b/client/components/sidebar/sidebar.jade index f71808765..f648b69bb 100644 --- a/client/components/sidebar/sidebar.jade +++ b/client/components/sidebar/sidebar.jade @@ -652,6 +652,7 @@ template(name="addMemberPopup") p.quiet {{_ 'no-results'}} button.js-email-invite.primary.full {{_ 'email-invite'}} + template(name="changePermissionsPopup") ul.pop-over-list li diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js index e0a37ebbb..e03fcac65 100644 --- a/client/components/sidebar/sidebar.js +++ b/client/components/sidebar/sidebar.js @@ -1948,3 +1948,4 @@ Template.changePermissionsPopup.helpers({ ); }, }); + diff --git a/client/components/swimlanes/swimlanes.css b/client/components/swimlanes/swimlanes.css index 39db99f0d..d3a2e2d46 100644 --- a/client/components/swimlanes/swimlanes.css +++ b/client/components/swimlanes/swimlanes.css @@ -50,6 +50,8 @@ flex-direction: row; flex: 1 0 100%; background-color: #ccc; + width: 100%; + min-width: 100%; } .swimlane .swimlane-header-wrap .swimlane-header { font-size: 14px; diff --git a/client/lib/utils.js b/client/lib/utils.js index 487961ab4..503e998fc 100644 --- a/client/lib/utils.js +++ b/client/lib/utils.js @@ -51,6 +51,146 @@ Utils = { const ret = ReactiveCache.getCard(cardId); return ret; }, + + // Zoom and mobile mode utilities + getZoomLevel() { + const user = ReactiveCache.getCurrentUser(); + if (user && user.profile && user.profile.zoomLevel !== undefined) { + return user.profile.zoomLevel; + } + // For non-logged-in users, check localStorage + const stored = localStorage.getItem('wekan-zoom-level'); + return stored ? parseFloat(stored) : 1.0; + }, + + setZoomLevel(level) { + const user = ReactiveCache.getCurrentUser(); + if (user) { + // Update user profile + user.setZoomLevel(level); + } else { + // Store in localStorage for non-logged-in users + localStorage.setItem('wekan-zoom-level', level.toString()); + } + Utils.applyZoomLevel(level); + + // Trigger reactive updates for UI components + Session.set('wekan-zoom-level', level); + }, + + getMobileMode() { + const user = ReactiveCache.getCurrentUser(); + if (user && user.profile && user.profile.mobileMode !== undefined) { + return user.profile.mobileMode; + } + // For non-logged-in users, check localStorage + const stored = localStorage.getItem('wekan-mobile-mode'); + return stored ? stored === 'true' : false; + }, + + setMobileMode(enabled) { + const user = ReactiveCache.getCurrentUser(); + if (user) { + // Update user profile + user.setMobileMode(enabled); + } else { + // Store in localStorage for non-logged-in users + localStorage.setItem('wekan-mobile-mode', enabled.toString()); + } + Utils.applyMobileMode(enabled); + // Trigger reactive updates for UI components + Session.set('wekan-mobile-mode', enabled); + }, + + applyZoomLevel(level) { + const boardWrapper = document.querySelector('.board-wrapper'); + const body = document.body; + const isMobileMode = body.classList.contains('mobile-mode'); + + if (boardWrapper) { + if (isMobileMode) { + // On mobile mode, only apply zoom to text and icons, not the entire layout + // Remove any existing transform from board-wrapper + boardWrapper.style.transform = ''; + boardWrapper.style.transformOrigin = ''; + + // Apply zoom to text and icon elements instead + const textElements = boardWrapper.querySelectorAll('h1, h2, h3, h4, h5, h6, p, span, div, .minicard, .list-header-name, .board-header-btn, .fa, .icon'); + textElements.forEach(element => { + element.style.transform = `scale(${level})`; + element.style.transformOrigin = 'center'; + }); + + // Reset board-canvas height + const boardCanvas = document.querySelector('.board-canvas'); + if (boardCanvas) { + boardCanvas.style.height = ''; + } + } else { + // Desktop mode: apply zoom to entire board-wrapper as before + boardWrapper.style.transform = `scale(${level})`; + boardWrapper.style.transformOrigin = 'top left'; + + // If zoom is 50% or lower, make board wrapper full width like content + if (level <= 0.5) { + boardWrapper.style.width = '100%'; + boardWrapper.style.maxWidth = '100%'; + boardWrapper.style.margin = '0'; + } else { + // Reset to normal width for higher zoom levels + boardWrapper.style.width = ''; + boardWrapper.style.maxWidth = ''; + boardWrapper.style.margin = ''; + } + + // Adjust container height to prevent scroll issues + const boardCanvas = document.querySelector('.board-canvas'); + if (boardCanvas) { + boardCanvas.style.height = `${100 / level}%`; + + // For high zoom levels (200%+), enable both horizontal and vertical scrolling + if (level >= 2.0) { + boardCanvas.style.overflowX = 'auto'; + boardCanvas.style.overflowY = 'auto'; + // Ensure the content area can scroll both horizontally and vertically + const content = document.querySelector('#content'); + if (content) { + content.style.overflowX = 'auto'; + content.style.overflowY = 'auto'; + } + } else { + // Reset overflow for normal zoom levels + boardCanvas.style.overflowX = ''; + boardCanvas.style.overflowY = ''; + const content = document.querySelector('#content'); + if (content) { + content.style.overflowX = ''; + content.style.overflowY = ''; + } + } + } + } + } + }, + + applyMobileMode(enabled) { + const body = document.body; + if (enabled) { + body.classList.add('mobile-mode'); + body.classList.remove('desktop-mode'); + } else { + body.classList.add('desktop-mode'); + body.classList.remove('mobile-mode'); + } + }, + + initializeUserSettings() { + // Apply saved settings on page load + const zoomLevel = Utils.getZoomLevel(); + const mobileMode = Utils.getMobileMode(); + Utils.applyZoomLevel(zoomLevel); + Utils.applyMobileMode(mobileMode); + }, getCurrentList() { const listId = this.getCurrentListId(); let ret = null; @@ -376,7 +516,8 @@ Utils = { // returns if mini screen or desktop drag handles isTouchScreenOrShowDesktopDragHandles() { - return this.isTouchScreen(); + // Always enable drag handles for mobile screens (touch devices) + return this.isTouchScreen() || this.isMiniScreen(); //return this.isTouchScreen() || this.isShowDesktopDragHandles(); //return this.isShowDesktopDragHandles(); }, diff --git a/imports/i18n/data/en.i18n.json b/imports/i18n/data/en.i18n.json index 55cdb8cb9..4f6dd193d 100644 --- a/imports/i18n/data/en.i18n.json +++ b/imports/i18n/data/en.i18n.json @@ -177,6 +177,14 @@ "boardChangeViewPopup-title": "Board View", "boards": "Boards", "board-view": "Board View", + "desktop-mode": "Desktop Mode", + "mobile-mode": "Mobile Mode", + "mobile-desktop-toggle": "Toggle between Mobile and Desktop Mode", + "zoom-in": "Zoom In", + "zoom-out": "Zoom Out", + "click-to-change-zoom": "Click to change zoom level", + "zoom-level": "Zoom Level", + "enter-zoom-level": "Enter zoom level (50-300%):", "board-view-cal": "Calendar", "board-view-swimlanes": "Swimlanes", "board-view-collapse": "Collapse", diff --git a/models/users.js b/models/users.js index 404a332d8..64de5267c 100644 --- a/models/users.js +++ b/models/users.js @@ -465,6 +465,22 @@ Users.attachSchema( type: Boolean, defaultValue: true, }, + 'profile.zoomLevel': { + /** + * User-specified zoom level for board view (1.0 = 100%, 1.5 = 150%, etc.) + */ + type: Number, + defaultValue: 1.0, + min: 0.5, + max: 3.0, + }, + 'profile.mobileMode': { + /** + * User-specified mobile/desktop mode toggle + */ + type: Boolean, + defaultValue: false, + }, services: { /** * services field of the user @@ -612,6 +628,8 @@ Users.safeFields = { 'profile.fullname': 1, 'profile.avatarUrl': 1, 'profile.initials': 1, + 'profile.zoomLevel': 1, + 'profile.mobileMode': 1, orgs: 1, teams: 1, authenticationMethod: 1, @@ -1277,6 +1295,22 @@ Users.mutations({ }, }; }, + + setZoomLevel(level) { + return { + $set: { + 'profile.zoomLevel': level, + }, + }; + }, + + setMobileMode(enabled) { + return { + $set: { + 'profile.mobileMode': enabled, + }, + }; + }, }); Meteor.methods({ @@ -1332,6 +1366,16 @@ Meteor.methods({ const user = ReactiveCache.getCurrentUser(); user.setSwimlaneHeight(boardId, swimlaneId, height); }, + setZoomLevel(level) { + check(level, Number); + const user = ReactiveCache.getCurrentUser(); + user.setZoomLevel(level); + }, + setMobileMode(enabled) { + check(enabled, Boolean); + const user = ReactiveCache.getCurrentUser(); + user.setMobileMode(enabled); + }, }); if (Meteor.isServer) {