From 97dd5d206406e93e77f46da476960968e42bc141 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 16:30:08 +0000 Subject: [PATCH] Resolve merge conflicts by accepting PR #6131 changes Co-authored-by: xet7 <15545+xet7@users.noreply.github.com> --- client/components/activities/activities.css | 22 +- client/components/activities/activities.js | 7 +- client/components/activities/comments.css | 101 +- client/components/activities/comments.jade | 4 +- client/components/boardConversionProgress.css | 26 +- client/components/boards/boardArchive.jade | 2 +- client/components/boards/boardBody.css | 320 +- client/components/boards/boardBody.jade | 34 +- client/components/boards/boardBody.js | 118 +- client/components/boards/boardColors.css | 5524 ++++++++--------- client/components/boards/boardHeader.css | 988 +-- client/components/boards/boardHeader.jade | 241 +- client/components/boards/boardHeader.js | 7 +- client/components/boards/boardsList.css | 967 +-- client/components/boards/boardsList.jade | 140 +- client/components/boards/boardsList.js | 81 +- .../boards/originalPositionsView.css | 54 +- client/components/cards/attachments.css | 168 +- client/components/cards/attachments.jade | 10 +- client/components/cards/cardDate.css | 7 +- client/components/cards/cardDate.js | 58 +- client/components/cards/cardDescription.css | 19 +- client/components/cards/cardDetails.css | 837 ++- client/components/cards/cardDetails.jade | 1201 ++-- client/components/cards/cardDetails.js | 270 +- client/components/cards/cardTime.css | 2 +- client/components/cards/checklists.css | 93 +- client/components/cards/checklists.jade | 69 +- client/components/cards/checklists.js | 14 +- client/components/cards/labels.css | 120 +- client/components/cards/minicard.css | 374 +- client/components/cards/minicard.jade | 418 +- client/components/cards/minicard.js | 87 +- client/components/cards/resultCard.css | 3 +- client/components/cards/resultCard.js | 7 - client/components/cards/subtasks.css | 27 +- client/components/cards/subtasks.jade | 27 +- client/components/common/originalPosition.css | 20 +- client/components/forms/datepicker.css | 40 +- client/components/forms/forms.css | 184 +- client/components/gantt/gantt.css | 12 +- client/components/lists/list.css | 1105 +--- client/components/lists/list.jade | 5 +- client/components/lists/list.js | 448 +- client/components/lists/listBody.jade | 197 +- client/components/lists/listBody.js | 242 +- client/components/lists/listHeader.jade | 107 +- client/components/lists/listHeader.js | 26 +- client/components/main/accessibility.css | 11 +- client/components/main/editor.css | 33 +- client/components/main/editor.jade | 8 +- client/components/main/editor.js | 1 - client/components/main/globalSearch.css | 13 +- client/components/main/header.css | 1113 +--- client/components/main/header.jade | 141 +- client/components/main/header.js | 57 +- client/components/main/keyboardShortcuts.css | 2 +- client/components/main/layouts.css | 484 +- client/components/main/layouts.jade | 101 +- client/components/main/myCards.css | 76 +- client/components/main/myCards.jade | 19 +- client/components/main/popup.css | 670 +- client/components/main/popup.js | 731 ++- client/components/main/popup.tpl.jade | 24 - client/components/main/spinner_wave.css | 2 +- .../notifications/notifications.css | 49 +- .../notifications/notifications.jade | 5 +- .../notifications/notificationsDrawer.css | 50 +- .../notifications/notificationsDrawer.jade | 8 +- .../components/rules/actions/cardActions.jade | 3 +- client/components/rules/rules.css | 18 +- client/components/settings/cronSettings.css | 120 +- .../components/settings/migrationProgress.css | 54 +- client/components/settings/peopleBody.css | 5 +- client/components/settings/settingBody.css | 45 +- client/components/settings/settingHeader.css | 11 +- .../components/settings/translationBody.css | 3 - client/components/sidebar/sidebar.css | 59 +- client/components/sidebar/sidebar.jade | 15 +- client/components/sidebar/sidebar.js | 389 +- client/components/sidebar/sidebarSearches.css | 3 - client/components/sidebar/sidebarSearches.js | 7 +- .../components/swimlanes/swimlaneHeader.jade | 91 +- client/components/swimlanes/swimlaneHeader.js | 2 +- client/components/swimlanes/swimlanes.css | 283 +- client/components/swimlanes/swimlanes.jade | 91 +- client/components/swimlanes/swimlanes.js | 570 +- client/components/users/userAvatar.css | 70 +- client/components/users/userAvatar.jade | 4 +- client/components/users/userForm.css | 196 +- client/components/users/userHeader.jade | 110 +- client/components/users/userHeader.js | 1 + client/lib/boardConverter.js | 14 +- client/lib/dialogWithBoardSwimlaneList.js | 32 +- client/lib/dialogWithBoardSwimlaneListCard.js | 4 +- client/lib/escapeActions.js | 16 +- client/lib/inlinedform.js | 24 +- client/lib/keyboard.js | 1 + client/lib/modal.js | 1 - client/lib/popup.js | 258 +- client/lib/utils.js | 489 +- config/router.js | 3 +- imports/i18n/data/ace.i18n.json | 8 +- imports/i18n/data/af.i18n.json | 13 +- imports/i18n/data/af_ZA.i18n.json | 13 +- imports/i18n/data/ar-DZ.i18n.json | 13 +- imports/i18n/data/ar-EG.i18n.json | 13 +- imports/i18n/data/ar.i18n.json | 13 +- imports/i18n/data/ary.i18n.json | 13 +- imports/i18n/data/ast-ES.i18n.json | 13 +- imports/i18n/data/az-AZ.i18n.json | 13 +- imports/i18n/data/az-LA.i18n.json | 13 +- imports/i18n/data/az.i18n.json | 13 +- imports/i18n/data/bg.i18n.json | 13 +- imports/i18n/data/br.i18n.json | 13 +- imports/i18n/data/ca.i18n.json | 13 +- imports/i18n/data/ca@valencia.i18n.json | 13 +- imports/i18n/data/ca_ES.i18n.json | 13 +- imports/i18n/data/cmn.i18n.json | 13 +- imports/i18n/data/cs-CZ.i18n.json | 13 +- imports/i18n/data/cs.i18n.json | 13 +- imports/i18n/data/cy-GB.i18n.json | 13 +- imports/i18n/data/cy.i18n.json | 13 +- imports/i18n/data/da.i18n.json | 13 +- imports/i18n/data/de-AT.i18n.json | 13 +- imports/i18n/data/de-CH.i18n.json | 13 +- imports/i18n/data/de.i18n.json | 13 +- imports/i18n/data/de_DE.i18n.json | 13 +- imports/i18n/data/el-GR.i18n.json | 13 +- imports/i18n/data/el.i18n.json | 13 +- imports/i18n/data/en-BR.i18n.json | 13 +- imports/i18n/data/en-DE.i18n.json | 13 +- imports/i18n/data/en-GB.i18n.json | 13 +- imports/i18n/data/en-IT.i18n.json | 13 +- imports/i18n/data/en-MY.i18n.json | 13 +- imports/i18n/data/en-YS.i18n.json | 13 +- imports/i18n/data/en.i18n.json | 13 +- imports/i18n/data/en_AU.i18n.json | 13 +- imports/i18n/data/en_ID.i18n.json | 13 +- imports/i18n/data/en_SG.i18n.json | 13 +- imports/i18n/data/en_TR.i18n.json | 13 +- imports/i18n/data/en_ZA.i18n.json | 13 +- imports/i18n/data/eo.i18n.json | 13 +- imports/i18n/data/es-AR.i18n.json | 13 +- imports/i18n/data/es-CL.i18n.json | 13 +- imports/i18n/data/es-LA.i18n.json | 13 +- imports/i18n/data/es-MX.i18n.json | 13 +- imports/i18n/data/es-PE.i18n.json | 13 +- imports/i18n/data/es-PY.i18n.json | 13 +- imports/i18n/data/es.i18n.json | 13 +- imports/i18n/data/es_CO.i18n.json | 13 +- imports/i18n/data/et-EE.i18n.json | 13 +- imports/i18n/data/eu.i18n.json | 13 +- imports/i18n/data/fa-IR.i18n.json | 13 +- imports/i18n/data/fa.i18n.json | 13 +- imports/i18n/data/fi.i18n.json | 11 +- imports/i18n/data/fr-CH.i18n.json | 13 +- imports/i18n/data/fr-FR.i18n.json | 13 +- imports/i18n/data/fr.i18n.json | 13 +- imports/i18n/data/fy-NL.i18n.json | 13 +- imports/i18n/data/fy.i18n.json | 13 +- imports/i18n/data/gl-ES.i18n.json | 13 +- imports/i18n/data/gl.i18n.json | 13 +- imports/i18n/data/gu-IN.i18n.json | 13 +- imports/i18n/data/he-IL.i18n.json | 13 +- imports/i18n/data/he.i18n.json | 13 +- imports/i18n/data/hi-IN.i18n.json | 13 +- imports/i18n/data/hi.i18n.json | 13 +- imports/i18n/data/hr.i18n.json | 13 +- imports/i18n/data/hu.i18n.json | 13 +- imports/i18n/data/hy.i18n.json | 13 +- imports/i18n/data/id.i18n.json | 13 +- imports/i18n/data/ig.i18n.json | 13 +- imports/i18n/data/it.i18n.json | 13 +- imports/i18n/data/ja-HI.i18n.json | 13 +- imports/i18n/data/ja.i18n.json | 13 +- imports/i18n/data/ka.i18n.json | 13 +- imports/i18n/data/km.i18n.json | 13 +- imports/i18n/data/km_KH.i18n.json | 13 +- imports/i18n/data/ko-KR.i18n.json | 13 +- imports/i18n/data/ko.i18n.json | 13 +- imports/i18n/data/lt.i18n.json | 13 +- imports/i18n/data/lv.i18n.json | 13 +- imports/i18n/data/mk.i18n.json | 13 +- imports/i18n/data/mn.i18n.json | 13 +- imports/i18n/data/ms-MY.i18n.json | 13 +- imports/i18n/data/ms.i18n.json | 13 +- imports/i18n/data/nb.i18n.json | 13 +- imports/i18n/data/nl-NL.i18n.json | 13 +- imports/i18n/data/nl.i18n.json | 13 +- imports/i18n/data/oc.i18n.json | 13 +- imports/i18n/data/or_IN.i18n.json | 13 +- imports/i18n/data/pa.i18n.json | 13 +- imports/i18n/data/pl-PL.i18n.json | 13 +- imports/i18n/data/pl.i18n.json | 13 +- imports/i18n/data/pt-BR.i18n.json | 13 +- imports/i18n/data/pt.i18n.json | 13 +- imports/i18n/data/pt_PT.i18n.json | 13 +- imports/i18n/data/ro-RO.i18n.json | 13 +- imports/i18n/data/ro.i18n.json | 13 +- imports/i18n/data/ru-UA.i18n.json | 13 +- imports/i18n/data/ru.i18n.json | 13 +- imports/i18n/data/ru_RU.i18n.json | 13 +- imports/i18n/data/sk.i18n.json | 13 +- imports/i18n/data/sl.i18n.json | 13 +- imports/i18n/data/sl_SI.i18n.json | 8 +- imports/i18n/data/sr.i18n.json | 10 +- imports/i18n/data/sv.i18n.json | 13 +- imports/i18n/data/sw.i18n.json | 13 +- imports/i18n/data/ta.i18n.json | 13 +- imports/i18n/data/te-IN.i18n.json | 13 +- imports/i18n/data/th.i18n.json | 13 +- imports/i18n/data/tk_TM.i18n.json | 13 +- imports/i18n/data/tlh.i18n.json | 13 +- imports/i18n/data/tr.i18n.json | 13 +- imports/i18n/data/ug.i18n.json | 13 +- imports/i18n/data/uk-UA.i18n.json | 13 +- imports/i18n/data/uk.i18n.json | 13 +- imports/i18n/data/uz-AR.i18n.json | 13 +- imports/i18n/data/uz-LA.i18n.json | 13 +- imports/i18n/data/uz-UZ.i18n.json | 13 +- imports/i18n/data/uz.i18n.json | 13 +- imports/i18n/data/ve-CC.i18n.json | 13 +- imports/i18n/data/ve-PP.i18n.json | 13 +- imports/i18n/data/ve.i18n.json | 13 +- imports/i18n/data/vi-VN.i18n.json | 13 +- imports/i18n/data/vi.i18n.json | 13 +- imports/i18n/data/vl-SS.i18n.json | 13 +- imports/i18n/data/vo.i18n.json | 13 +- imports/i18n/data/wa-RR.i18n.json | 13 +- imports/i18n/data/wa.i18n.json | 13 +- imports/i18n/data/wo.i18n.json | 13 +- imports/i18n/data/wuu-Hans.i18n.json | 13 +- imports/i18n/data/xh.i18n.json | 13 +- imports/i18n/data/yi.i18n.json | 13 +- imports/i18n/data/yo.i18n.json | 13 +- imports/i18n/data/yue_CN.i18n.json | 13 +- imports/i18n/data/zgh.i18n.json | 13 +- imports/i18n/data/zh-CN.i18n.json | 13 +- imports/i18n/data/zh-GB.i18n.json | 13 +- imports/i18n/data/zh-HK.i18n.json | 13 +- imports/i18n/data/zh-Hans.i18n.json | 13 +- imports/i18n/data/zh-Hant.i18n.json | 13 +- imports/i18n/data/zh-TW.i18n.json | 13 +- imports/i18n/data/zh.i18n.json | 13 +- imports/i18n/data/zh_SG.i18n.json | 13 +- imports/i18n/data/zu-ZA.i18n.json | 13 +- imports/i18n/data/zu.i18n.json | 13 +- models/boards.js | 37 +- models/cardComments.js | 37 +- models/cards.js | 65 +- models/lib/fileStoreStrategy.js | 4 +- models/users.js | 101 +- packages/wekan-accounts-cas/cas_client.js | 2 + .../fullcalendar/fullcalendar.css | 4 +- popup.jade | 21 + public/css/reset.css | 9 +- 257 files changed, 9483 insertions(+), 14103 deletions(-) delete mode 100644 client/components/main/popup.tpl.jade create mode 100644 popup.jade diff --git a/client/components/activities/activities.css b/client/components/activities/activities.css index 08c9eea08..f1e461cfa 100644 --- a/client/components/activities/activities.css +++ b/client/components/activities/activities.css @@ -1,16 +1,22 @@ .activity-title { - margin: 0 0.7vw 1vh; display: flex; + gap: 0.5lh; justify-content: space-between; } +.reactions-popup { + display: flex; + gap: 1ch; + flex-wrap: wrap; + margin: 0.5lh 0.5ch; + max-width: 80vw; +} .reactions-popup .add-comment-reaction { display: inline-block; cursor: pointer; border-radius: 0.7vw; - font-size: clamp(18px, 4vw, 22px); text-align: center; line-height: 1.3; - width: 5vw; + font-size: 1.2em; } .reactions-popup .add-comment-reaction:hover { background-color: #b0c4de; @@ -18,20 +24,20 @@ .activities { clear: both; } +.activity { + display: flex; +} .activities .activity { margin: 0.1vh 0; padding: 0.8vh 0; display: flex; -} -.activities .activity .member { - width: 4vw; - height: 4vw; + font-size: 0.8em; } .activities .activity .activity-member { font-weight: 700; } .activities .activity .activity-desc { - word-wrap: break-word; + overflow-wrap: break-word; overflow: hidden; flex: 1; align-self: center; diff --git a/client/components/activities/activities.js b/client/components/activities/activities.js index 5a0a81315..4f829d7b1 100644 --- a/client/components/activities/activities.js +++ b/client/components/activities/activities.js @@ -275,7 +275,7 @@ Template.commentReactions.events({ cardComment.toggleReaction(codepoint); } }, - 'click .open-comment-reaction-popup': Popup.open('addReaction'), + 'click .open-comment-reaction-popup': Popup.open('addReaction', {showHeader: false}) }) Template.addReactionPopup.events({ @@ -306,6 +306,11 @@ Template.addReactionPopup.helpers({ '😊', '🤔', '😔']; + }, + hasUserReacted(codepoint) { + const commentId = Template.instance().data.commentId; + const cardComment = ReactiveCache.getCardComment(commentId); + return cardComment.hasUserReacted(codepoint); } }) diff --git a/client/components/activities/comments.css b/client/components/activities/comments.css index de0189de7..de7512e03 100644 --- a/client/components/activities/comments.css +++ b/client/components/activities/comments.css @@ -1,12 +1,12 @@ .new-comment { position: relative; - margin: 0 0 20px 38px; + display: flex; + align-items: center; + justify-content: stretch; + gap: 1ch; } .new-comment .member { opacity: 0.7; - position: absolute; - top: 1px; - left: -38px; } .new-comment.is-open .member { opacity: 1; @@ -14,34 +14,44 @@ .new-comment.is-open .helper { display: inline-block; } -.new-comment.is-open textarea { - min-height: 100px; - color: #4d4d4d; - cursor: auto; - overflow: hidden; - word-wrap: break-word; + +.new-comment, .comment { + .is-open textarea { + min-height: 100px; + color: #4d4d4d; + cursor: auto; + overflow-wrap: break-word; + } + textarea { + grid-area: editor; + background-color: #fff; + border: 0; + box-shadow: 0 1px 2px rgba(0,0,0,0.23); + min-height: 3lh; + &:hover, &.is-open { + cursor: auto; + background-color: #fff; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.33); + border: 0; + cursor: pointer; + } + } } + .new-comment .too-long { margin-top: 8px; } -.new-comment textarea { - background-color: #fff; - border: 0; - box-shadow: 0 1px 2px rgba(0,0,0,0.23); - height: 36px; - margin: 4px 4px 6px 0; - padding: 9px 11px; - width: 100%; -} -.new-comment textarea:hover, -.new-comment textarea:is-open { - background-color: #fff; - box-shadow: 0 1px 3px rgba(0,0,0,0.33); - border: 0; - cursor: pointer; -} -.new-comment textarea:is-open { - cursor: auto; + +.js-new-comment-form, .js-edit-comment { + display: grid !important; + grid-template-areas: + "editor editor editor editor" + "main-controls main-controls link-controls editor-controls"; + grid-auto-columns: 1fr; + grid-auto-rows: min-content; + align-items: center; + flex: 1; + gap: 0.3lh; } .comment-item { background-color: #fff; @@ -65,31 +75,30 @@ } .comments { clear: both; + display: flex; + flex-direction: column; + gap: 1lh; + padding-top: 1lh; } .comments .comment { - margin: 0.5px 0; - padding: 6px 0; display: flex; + gap: 1ch; } -.comments .comment .member { - width: 32px; - height: 32px; -} + .comments .comment .comment-member { font-weight: 700; } .comments .comment .comment-desc { - word-wrap: break-word; - overflow: hidden; + overflow-wrap: break-word; flex: 1; align-self: center; margin: 0; - margin-left: 3px; - overflow: hidden; - word-break: break-word; + display: flex; + flex-direction: column; + gap: 0.3lh; } .comments .comment .comment-desc .comment-text { - display: block; + display: flex; border-radius: 3px; background: #fff; text-decoration: none; @@ -101,6 +110,7 @@ display: flex; margin-top: 5px; gap: 5px; + align-items: center; } .comments .comment .comment-desc .reactions .open-comment-reaction-popup { display: flex; @@ -110,7 +120,6 @@ } .comments .comment .comment-desc .reactions .open-comment-reaction-popup span { display: inline-block; - font-size: clamp(14px, 2vw, 18px); font-weight: 500; line-height: 1; margin-left: 4px; @@ -128,10 +137,14 @@ .comments .comment .comment-desc .reactions .reaction:hover { background-color: #b0c4de; } -.comments .comment .comment-desc .reactions .reaction .reaction-count { - font-size: 12px; -} .comments .comment .comment-desc .comment-meta { font-size: 0.8em; color: #999; + display: grid; + grid-auto-flow: column; + grid-auto-columns: max-content; + gap: 1ch; + align-items: center; + /* #FIXME maybe put date outside of comment body ?*/ + margin-inline-start: -10vw; } diff --git a/client/components/activities/comments.jade b/client/components/activities/comments.jade index 1860eb4f4..5f317a261 100644 --- a/client/components/activities/comments.jade +++ b/client/components/activities/comments.jade @@ -64,5 +64,5 @@ template(name="commentReactions") template(name="addReactionPopup") .reactions-popup each codepoint in codepoints - span.add-comment-reaction(data-codepoint="#{codepoint}") !{codepoint} - + unless (hasUserReacted codepoint) + span.add-comment-reaction(data-codepoint="#{codepoint}") !{codepoint} diff --git a/client/components/boardConversionProgress.css b/client/components/boardConversionProgress.css index fd186908f..de79d13a4 100644 --- a/client/components/boardConversionProgress.css +++ b/client/components/boardConversionProgress.css @@ -18,7 +18,7 @@ .board-conversion-modal { background: white; - border-radius: 8px; + border-radius: 0.8ch; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); max-width: 500px; width: 90%; @@ -47,7 +47,7 @@ .board-conversion-header h3 { margin: 0 0 8px 0; color: #333; - font-size: 20px; + font-weight: 500; } @@ -59,7 +59,7 @@ .board-conversion-header p { margin: 0; color: #666; - font-size: 14px; + } .board-conversion-content { @@ -74,7 +74,7 @@ width: 100%; height: 8px; background-color: #e0e0e0; - border-radius: 4px; + border-radius: 0.4ch; overflow: hidden; margin-bottom: 8px; } @@ -82,7 +82,7 @@ .progress-fill { height: 100%; background: linear-gradient(90deg, #2196F3, #21CBF3); - border-radius: 4px; + border-radius: 0.4ch; transition: width 0.3s ease; position: relative; } @@ -116,14 +116,14 @@ text-align: center; font-weight: 600; color: #2196F3; - font-size: 16px; + } .conversion-status { text-align: center; margin-bottom: 16px; color: #333; - font-size: 16px; + } .conversion-status i { @@ -134,10 +134,10 @@ .conversion-time { text-align: center; color: #666; - font-size: 14px; + background-color: #f5f5f5; padding: 8px 12px; - border-radius: 4px; + border-radius: 0.4ch; margin-bottom: 16px; } @@ -155,7 +155,7 @@ .conversion-info { text-align: center; color: #666; - font-size: 13px; + line-height: 1.4; } @@ -170,15 +170,15 @@ width: 95%; margin: 20px; } - + .board-conversion-header, .board-conversion-content, .board-conversion-footer { padding-left: 16px; padding-right: 16px; } - + .board-conversion-header h3 { - font-size: 18px; + } } diff --git a/client/components/boards/boardArchive.jade b/client/components/boards/boardArchive.jade index 839f183e1..761736e81 100644 --- a/client/components/boards/boardArchive.jade +++ b/client/components/boards/boardArchive.jade @@ -1,7 +1,7 @@ template(name="archivedBoards") h2 span(title="{{_ 'archived-boards'}}") - i.fa.fa-archive + i.fa.fa-archive | {{_ 'archived-boards'}} ul.archived-lists diff --git a/client/components/boards/boardBody.css b/client/components/boards/boardBody.css index b23d7f4d8..1bbb3d595 100644 --- a/client/components/boards/boardBody.css +++ b/client/components/boards/boardBody.css @@ -1,43 +1,25 @@ +.swim-flex { + display: flex; + flex: 1; + flex-direction: column; + align-items: stretch; + padding-bottom: 40vw; +} + .board-wrapper { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - overflow-x: hidden; - overflow-y: hidden; - width: 100%; - min-width: 100%; + display: flex; + flex: 1; + overflow: auto; } -/* 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; - left: 0; - right: 0; - top: 0; - bottom: 0; transition: margin 0.1s; overflow-y: auto; - width: 100%; - min-width: 100%; + overflow-x: hidden; + display: flex; + /* don't stretch vertically if not needed (e.g collapsed) */ + align-self: start; + flex: 1; } /* Ensure horizontal scrollbar is visible for high zoom levels */ @@ -97,172 +79,12 @@ 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; } - /* 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 */ - } - -/* Mobile iPhone: scale card details text and icons to 2x */ -body.mobile-mode.iphone-device .card-details { - font-size: 2em !important; -} -body.mobile-mode.iphone-device .card-details .fa, -body.mobile-mode.iphone-device .card-details .icon, -body.mobile-mode.iphone-device .card-details i, -body.mobile-mode.iphone-device .card-details .emoji-icon, -body.mobile-mode.iphone-device .card-details a, -body.mobile-mode.iphone-device .card-details p, -body.mobile-mode.iphone-device .card-details span, -body.mobile-mode.iphone-device .card-details div, -body.mobile-mode.iphone-device .card-details button, -body.mobile-mode.iphone-device .card-details input, -body.mobile-mode.iphone-device .card-details select, -body.mobile-mode.iphone-device .card-details textarea { - font-size: inherit !important; -} -/* Section titles slightly larger than content but not as big as card title */ -body.mobile-mode.iphone-device .card-details .card-details-item-title { - font-size: 1.1em !important; - font-weight: bold; -} - -/* 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"] { @@ -274,36 +96,6 @@ body.mobile-mode.iphone-device .card-details .card-details-item-title { #content[style*="overflow-y: auto"] { scrollbar-gutter: stable; } -.board-wrapper .board-canvas .board-overlay { - position: fixed; - left: 0; - right: 0; - top: 0; - bottom: 0; - top: -100px; - right: -400px; - background: #000; - opacity: 0.33; - animation: fadeIn 0.2s; - z-index: 16; -} - -/* Fix for mobile Safari: ensure overlay stays behind card details */ -@media screen and (max-width: 800px) { - .board-wrapper .board-canvas .board-overlay { - z-index: 17 !important; - } - - /* In desktop mode on small screens, still keep overlay behind card */ - body.desktop-mode .board-wrapper .board-canvas .board-overlay { - z-index: 17 !important; - } -} - -/* In mobile mode, lower the overlay z-index to stay behind card details */ -body.mobile-mode .board-wrapper .board-canvas .board-overlay { - z-index: 17 !important; -} /* iPhone in desktop mode: remove overlay to avoid blocking card */ body.desktop-mode.iphone-device .board-wrapper .board-canvas .board-overlay { @@ -320,73 +112,14 @@ body.desktop-mode .board-wrapper .board-canvas .board-overlay { .board-wrapper .board-canvas.is-dragging-active .minicard-wrapper.is-checked { display: none; } -/* Mobile view styles - applied when isMiniScreen is true (iPhone, etc.) */ -.board-wrapper.mobile-view { - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - left: 0 !important; - right: 0 !important; - overflow-x: hidden !important; - overflow-y: auto !important; -} - -.board-wrapper.mobile-view .board-canvas { - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - left: 0 !important; - right: 0 !important; - overflow-x: hidden !important; - overflow-y: auto !important; -} - -.board-wrapper.mobile-view .board-canvas.mobile-view .swimlane { - border-bottom: 1px solid #ccc; - display: block !important; - flex-direction: column; - margin: 0; - padding: 0; - overflow-x: hidden !important; - overflow-y: auto; - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; -} @media screen and (max-width: 800px), screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - .board-wrapper { - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - left: 0 !important; - right: 0 !important; - overflow-x: hidden !important; - overflow-y: auto !important; - } - .board-wrapper .board-canvas { - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - left: 0 !important; - right: 0 !important; - overflow-x: hidden !important; - overflow-y: auto !important; - } - - .board-wrapper .board-canvas .swimlane { - border-bottom: 1px solid #ccc; - display: block !important; - flex-direction: column; - margin: 0; - padding: 0; - overflow-x: hidden !important; - overflow-y: auto; - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; +.board-wrapper .board-canvas .swimlane { + /* this effectively prevents board + to shrink */ + min-width: 100vw; } } .calendar-event-green { @@ -545,7 +278,6 @@ body.desktop-mode .board-wrapper .board-canvas .board-overlay { justify-content: center; align-items: center; margin: 0; - font-size: 18px; } .modal-footer { display: flex; @@ -558,10 +290,6 @@ body.desktop-mode .board-wrapper .board-canvas .board-overlay { display: flex; justify-content: center; align-items: center; - position: absolute; - top: 5px; - right: 5px; - font-size: 25px; cursor: pointer; } diff --git a/client/components/boards/boardBody.jade b/client/components/boards/boardBody.jade index 4af638f08..f965a55a3 100644 --- a/client/components/boards/boardBody.jade +++ b/client/components/boards/boardBody.jade @@ -1,13 +1,9 @@ template(name="board") - if isConverting.get +boardConversionProgress else if isBoardReady.get if currentBoard - if onlyShowCurrentCard - +cardDetails(currentCard) - else - +boardBody + +boardBody else //-- XXX We need a better error message in case the board has been archived +message(label="board-not-found") @@ -17,32 +13,32 @@ template(name="board") template(name="boardBody") if notDisplayThisBoard - | {{_ 'tableVisibilityMode-allowPrivateOnly'}} + | {{_ 'tableVisibilityMode-allowPrivateOnly'}} else - // Debug information (remove in production) + //- Debug information (remove in production) if debugBoardState + //- Debug information (remove in production) .debug-info(style="position: fixed; top: 0; left: 0; background: rgba(0,0,0,0.8); color: white; padding: 10px; z-index: 9999; font-size: 12px;") | {{_ 'board'}}: {{currentBoard.title}} | {{_ 'view'}}: {{boardView}} | {{_ 'has-swimlanes'}}: {{hasSwimlanes}} | {{_ 'swimlanes'}}: {{currentBoard.swimlanes.length}} .board-wrapper(class=currentBoard.colorClass class="{{#if isMiniScreen}}mobile-view{{/if}}") .board-canvas.js-swimlanes( class="{{#if hasSwimlanes}}dragscroll{{/if}}" - class="{{#if Sidebar.isOpen}}is-sibling-sidebar-open{{/if}}" class="{{#if MultiSelection.isActive}}is-multiselection-active{{/if}}" class="{{#if draggingActive.get}}is-dragging-active{{/if}}" class="{{#unless isVerticalScrollbars}}no-scrollbars{{/unless}}" class="{{#if isMiniScreen}}mobile-view{{/if}}") - if showOverlay.get - .board-overlay if currentBoard.isTemplatesBoard - each currentBoard.swimlanes - +swimlane(this) - else if isViewSwimlanes - if hasSwimlanes + .swim-flex each currentBoard.swimlanes +swimlane(this) - else - // Fallback: If no swimlanes exist, show lists instead of empty message - +listsGroup(currentBoard) + else if isViewSwimlanes + .swim-flex + if hasSwimlanes + each currentBoard.swimlanes + +swimlane(this) + else + // Fallback: If no swimlanes exist, show lists instead of empty message + +listsGroup(currentBoard) else if isViewLists +listsGroup(currentBoard) else if isViewCalendar @@ -56,10 +52,6 @@ template(name="boardBody") +swimlane(this) else +listsGroup(currentBoard) - //- Render multiple open cards in desktop mode - unless isMiniScreen - each openCards - +cardDetails(this cardIndex=@index) +sidebar template(name="calendarView") diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js index a5d6b9760..c5144f5f5 100644 --- a/client/components/boards/boardBody.js +++ b/client/components/boards/boardBody.js @@ -27,16 +27,16 @@ BlazeComponent.extendComponent({ this.autorun(() => { const currentBoardId = Session.get('currentBoard'); if (!currentBoardId) return; - + const handle = subManager.subscribe('board', currentBoardId, false); - + // Use a separate autorun for subscription ready state to avoid reactive loops this.subscriptionReadyAutorun = Tracker.autorun(() => { if (handle.ready()) { if (!this._boardProcessed || this._lastProcessedBoardId !== currentBoardId) { this._boardProcessed = true; this._lastProcessedBoardId = currentBoardId; - + // Ensure default swimlane exists (only once per board) this.ensureDefaultSwimlane(currentBoardId); // Check if board needs conversion @@ -67,7 +67,7 @@ BlazeComponent.extendComponent({ if (!board) return; const swimlanes = board.swimlanes(); - + if (swimlanes.length === 0) { // Check if any swimlane exists in the database to avoid race conditions const existingSwimlanes = ReactiveCache.getSwimlanes({ boardId }); @@ -105,7 +105,6 @@ BlazeComponent.extendComponent({ this.isBoardReady.set(true); // Show board even if conversion check failed } }, - onlyShowCurrentCard() { const isMiniScreen = Utils.isMiniScreen(); const currentCardId = Utils.getCurrentCardId(true); @@ -114,7 +113,7 @@ BlazeComponent.extendComponent({ openCards() { // In desktop mode, return array of all open cards - const isMobile = Utils.getMobileMode(); + const isMobile = Utils.isMiniScreen(); if (!isMobile) { const openCardIds = Session.get('openCards') || []; return openCardIds.map(id => ReactiveCache.getCard(id)).filter(card => card); @@ -123,7 +122,7 @@ BlazeComponent.extendComponent({ }, goHome() { - FlowRouter.go('home'); + FlowRouter.go('home') }, isConverting() { @@ -195,7 +194,7 @@ BlazeComponent.extendComponent({ } }, onRendered() { - // Initialize user settings (zoom and mobile mode) + // Initialize user settings (mobile mode) Utils.initializeUserSettings(); // Detect iPhone devices and add class for better CSS targeting @@ -221,9 +220,9 @@ BlazeComponent.extendComponent({ const popupObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { mutation.addedNodes.forEach(function(node) { - if (node.nodeType === 1 && + if (node.nodeType === 1 && (node.classList.contains('popup') || node.classList.contains('modal') || node.classList.contains('menu')) && - !node.closest('.js-swimlanes') && + !node.closest('.js-swimlanes') && !node.closest('.swimlane') && !node.closest('.list') && !node.closest('.minicard')) { @@ -391,23 +390,24 @@ BlazeComponent.extendComponent({ helper(evt, item) { const helper = $(`
`); + max-height: 30vh; + width: 100vw; + overflow: hidden; z-index: 100;"/>`); helper.append(item.clone()); // Also grab the list of lists of cards const list = item.next(); helper.append(list.clone()); return helper; }, - items: '.swimlane:not(.placeholder)', + items: '.swimlane-container', placeholder: 'swimlane placeholder', distance: 7, start(evt, ui) { const listDom = ui.placeholder.next('.js-swimlane'); const parentOffset = ui.item.parent().offset(); - ui.placeholder.height(ui.helper.height()); + height = ui.helper.height(); + ui.placeholder[0].setAttribute('style', `height: ${height}px !important;`); EscapeActions.executeUpTo('popup-close'); listDom.addClass('moving-swimlane'); boardComponent.setIsDragging(true); @@ -415,40 +415,19 @@ BlazeComponent.extendComponent({ ui.placeholder.insertAfter(ui.placeholder.next()); boardComponent.origPlaceholderIndex = ui.placeholder.index(); - // resize all swimlanes + headers to be a total of 150 px per row - // this could be achieved by setIsDragging(true) but we want immediate - // result - ui.item - .siblings('.js-swimlane') - .css('height', `${swimlaneWhileSortingHeight - 26}px`); - - // set the new scroll height after the resize and insertion of - // the placeholder. We want the element under the cursor to stay - // at the same place on the screen - ui.item.parent().get(0).scrollTop = - ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY; }, beforeStop(evt, ui) { - const parentOffset = ui.item.parent().offset(); const siblings = ui.item.siblings('.js-swimlane'); siblings.css('height', ''); - // compute the new scroll height after the resize and removal of - // the placeholder - const scrollTop = - ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY; - // then reset the original view of the swimlane siblings.removeClass('moving-swimlane'); - - // and apply the computed scrollheight - ui.item.parent().get(0).scrollTop = scrollTop; }, stop(evt, ui) { // To attribute the new index number, we need to get the DOM element // of the previous and the following card -- if any. - const prevSwimlaneDom = ui.item.prevAll('.js-swimlane').get(0); - const nextSwimlaneDom = ui.item.nextAll('.js-swimlane').get(0); + const prevSwimlaneDom = ui.item.prevAll('.swimlane-container').get(0); + const nextSwimlaneDom = ui.item.nextAll('.swimlane-container').get(0); const sortIndex = calculateIndex(prevSwimlaneDom, nextSwimlaneDom, 1); $swimlanesDom.sortable('cancel'); @@ -464,39 +443,7 @@ BlazeComponent.extendComponent({ boardComponent.setIsDragging(false); }, sort(evt, ui) { - // get the mouse position in the sortable - const parentOffset = ui.item.parent().offset(); - const cursorY = - evt.pageY - parentOffset.top + ui.item.parent().scrollTop(); - - // compute the intended index of the placeholder (we need to skip the - // slots between the headers and the list of cards) - const newplaceholderIndex = Math.floor( - cursorY / swimlaneWhileSortingHeight, - ); - let destPlaceholderIndex = (newplaceholderIndex + 1) * 2; - - // if we are scrolling far away from the bottom of the list - if (destPlaceholderIndex >= ui.item.parent().get(0).childElementCount) { - destPlaceholderIndex = ui.item.parent().get(0).childElementCount - 1; - } - - // update the placeholder position in the DOM tree - if (destPlaceholderIndex !== ui.placeholder.index()) { - if (destPlaceholderIndex < boardComponent.origPlaceholderIndex) { - ui.placeholder.insertBefore( - ui.placeholder - .siblings() - .slice(destPlaceholderIndex - 2, destPlaceholderIndex - 1), - ); - } else { - ui.placeholder.insertAfter( - ui.placeholder - .siblings() - .slice(destPlaceholderIndex - 1, destPlaceholderIndex), - ); - } - } + Utils.scrollIfNeeded(evt); }, }); @@ -505,10 +452,10 @@ BlazeComponent.extendComponent({ dragscroll.reset(); if ($swimlanesDom.data('uiSortable') || $swimlanesDom.data('sortable')) { - if (Utils.isTouchScreenOrShowDesktopDragHandles()) { + if (Utils.isMiniScreen()) { $swimlanesDom.sortable('option', 'handle', '.js-swimlane-header-handle'); } else { - $swimlanesDom.sortable('option', 'handle', '.swimlane-header'); + $swimlanesDom.sortable('option', 'handle', '.swimlane-header-wrap'); } // Disable drag-dropping if the current user is not a board member @@ -540,57 +487,57 @@ BlazeComponent.extendComponent({ isViewSwimlanes() { const currentUser = ReactiveCache.getCurrentUser(); let boardView; - + if (currentUser) { boardView = (currentUser.profile || {}).boardView; } else { boardView = window.localStorage.getItem('boardView'); } - + // If no board view is set, default to swimlanes if (!boardView) { boardView = 'board-view-swimlanes'; } - + return boardView === 'board-view-swimlanes'; }, isViewLists() { const currentUser = ReactiveCache.getCurrentUser(); let boardView; - + if (currentUser) { boardView = (currentUser.profile || {}).boardView; } else { boardView = window.localStorage.getItem('boardView'); } - + return boardView === 'board-view-lists'; }, isViewCalendar() { const currentUser = ReactiveCache.getCurrentUser(); let boardView; - + if (currentUser) { boardView = (currentUser.profile || {}).boardView; } else { boardView = window.localStorage.getItem('boardView'); } - + return boardView === 'board-view-cal'; }, isViewGantt() { const currentUser = ReactiveCache.getCurrentUser(); let boardView; - + if (currentUser) { boardView = (currentUser.profile || {}).boardView; } else { boardView = window.localStorage.getItem('boardView'); } - + return boardView === 'board-view-gantt'; }, @@ -602,7 +549,7 @@ BlazeComponent.extendComponent({ } return false; } - + try { const swimlanes = currentBoard.swimlanes(); const hasSwimlanes = swimlanes && swimlanes.length > 0; @@ -638,7 +585,7 @@ BlazeComponent.extendComponent({ const isBoardReady = this.isBoardReady.get(); const isConverting = this.isConverting.get(); const boardView = Utils.boardView(); - + if (process.env.DEBUG === 'true') { console.log('=== BOARD DEBUG STATE ==='); console.log('currentBoardId:', currentBoardId); @@ -648,7 +595,7 @@ BlazeComponent.extendComponent({ console.log('boardView:', boardView); console.log('========================'); } - + return { currentBoardId, hasCurrentBoard: !!currentBoard, @@ -1025,4 +972,3 @@ BlazeComponent.extendComponent({ * Gantt View Component * Displays cards as a Gantt chart with start/due dates */ - diff --git a/client/components/boards/boardColors.css b/client/components/boards/boardColors.css index 641f85ad7..c8aa230ff 100644 --- a/client/components/boards/boardColors.css +++ b/client/components/boards/boardColors.css @@ -8,43 +8,52 @@ THEME - NEPHRITIS .board-list .board-color-nephritis a { background-color: #27ae60; } + .board-color-nephritis .is-selected .minicard { border-left: 3px solid #27ae60; } + .board-color-nephritis .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-nephritis button[type=submit].primary, .board-color-nephritis input[type=submit].primary, .board-color-nephritis .sidebar .sidebar-content .sidebar-btn { background-color: #1f8b4d; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-nephritis.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-nephritis .sidebar .sidebar-content .sidebar-btn:hover, .board-color-nephritis .sidebar-list li a:hover { background-color: #2cc66d; } + .board-color-nephritis#header ul li.current, .board-color-nephritis#header-quick-access ul li.current { border-bottom: 2px solid #2cc66d; } + .board-color-nephritis#header-quick-access { background: #239d56; color: #fff; } + .board-color-nephritis#header #header-main-bar .board-header-btn.emphasis { background: #ae2775; } + .board-color-nephritis#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-nephritis#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #9d2369; } + .board-color-nephritis#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #8b1f5e; } + .board-color-nephritis .materialCheckBox.is-checked { border-bottom: 2px solid #27ae60; border-right: 2px solid #27ae60; @@ -58,24 +67,30 @@ THEME - NEPHRITIS .board-color-nephritis .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e7faef; } -.board-color-nephritis .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-nephritis .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f8fdfa; } + .board-color-nephritis .toggle-label:after { background-color: #1f8b4d; } -.board-color-nephritis .toggle-switch:checked ~ .toggle-label { + +.board-color-nephritis .toggle-switch:checked~.toggle-label { background-color: #3dd37c; } -.board-color-nephritis .toggle-switch:checked ~ .toggle-label:after { + +.board-color-nephritis .toggle-switch:checked~.toggle-label:after { background-color: #1f8b4d; } + @media screen and (max-width: 800px) { .board-color-nephritis.pop-over .header { background: #27ae60; color: #fff; } } + .board-color-nephritis#header ul li.current, .board-color-nephritis#header-quick-access ul li.current { border-bottom: 4px solid #3dd37c; @@ -96,12 +111,9 @@ THEME - NEPHRITIS .board-color-nephritis .list { border-left: none; - padding-bottom: 8px; } -.board-color-nephritis .list-body { - margin-top: 8px; -} + /* === END NEPHRITIS THEME === */ @@ -115,43 +127,52 @@ THEME - Pomegranate .board-list .board-color-pomegranate a { background-color: #c0392b; } + .board-color-pomegranate .is-selected .minicard { border-left: 3px solid #c0392b; } + .board-color-pomegranate .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-pomegranate button[type=submit].primary, .board-color-pomegranate input[type=submit].primary, .board-color-pomegranate .sidebar .sidebar-content .sidebar-btn { background-color: #9a2e22; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-pomegranate.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-pomegranate .sidebar .sidebar-content .sidebar-btn:hover, .board-color-pomegranate .sidebar-list li a:hover { background-color: #d24435; } + .board-color-pomegranate#header ul li.current, .board-color-pomegranate#header-quick-access ul li.current { border-bottom: 2px solid #d24435; } + .board-color-pomegranate#header-quick-access { background: #ad3327; color: #fff; } + .board-color-pomegranate#header #header-main-bar .board-header-btn.emphasis { background: #2bb2c0; } + .board-color-pomegranate#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-pomegranate#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #27a0ad; } + .board-color-pomegranate#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #228e9a; } + .board-color-pomegranate .materialCheckBox.is-checked { border-bottom: 2px solid #c0392b; border-right: 2px solid #c0392b; @@ -165,24 +186,30 @@ THEME - Pomegranate .board-color-pomegranate .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #faeae9; } -.board-color-pomegranate .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-pomegranate .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #fdf9f8; } + .board-color-pomegranate .toggle-label:after { background-color: #9a2e22; } -.board-color-pomegranate .toggle-switch:checked ~ .toggle-label { + +.board-color-pomegranate .toggle-switch:checked~.toggle-label { background-color: #d7584b; } -.board-color-pomegranate .toggle-switch:checked ~ .toggle-label:after { + +.board-color-pomegranate .toggle-switch:checked~.toggle-label:after { background-color: #9a2e22; } + @media screen and (max-width: 800px) { .board-color-pomegranate.pop-over .header { background: #c0392b; color: #fff; } } + .board-color-pomegranate#header ul li.current, .board-color-pomegranate#header-quick-access ul li.current { border-bottom: 4px solid #d7584b; @@ -203,12 +230,9 @@ THEME - Pomegranate .board-color-pomegranate .list { border-left: none; - padding-bottom: 8px; } -.board-color-pomegranate .list-body { - margin-top: 8px; -} + /* === END Pomegranate THEME === */ @@ -222,43 +246,53 @@ THEME - Belize .board-list .board-color-belize a { background-color: #2980b9; } + .board-color-belize .is-selected .minicard { border-left: 3px solid #2980b9; } + .board-color-belize .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-belize button[type=submit].primary, .board-color-belize input[type=submit].primary, .board-color-belize .sidebar .sidebar-content .sidebar-btn { background-color: #216694; - border-radius: 7px; + border-radius: 0.6ch; + color: #eee; } + .board-color-belize.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-belize .sidebar .sidebar-content .sidebar-btn:hover, .board-color-belize .sidebar-list li a:hover { background-color: #2e90d0; } + .board-color-belize#header ul li.current, .board-color-belize#header-quick-access ul li.current { border-bottom: 2px solid #2e90d0; } + .board-color-belize#header-quick-access { background: #2573a7; color: #fff; } + .board-color-belize#header #header-main-bar .board-header-btn.emphasis { background: #b96229; } + .board-color-belize#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-belize#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #a75825; } + .board-color-belize#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #944e21; } + .board-color-belize .materialCheckBox.is-checked { border-bottom: 2px solid #2980b9; border-right: 2px solid #2980b9; @@ -272,24 +306,30 @@ THEME - Belize .board-color-belize .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e8f3fa; } -.board-color-belize .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-belize .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f8fbfd; } + .board-color-belize .toggle-label:after { background-color: #216694; } -.board-color-belize .toggle-switch:checked ~ .toggle-label { + +.board-color-belize .toggle-switch:checked~.toggle-label { background-color: #459cd6; } -.board-color-belize .toggle-switch:checked ~ .toggle-label:after { + +.board-color-belize .toggle-switch:checked~.toggle-label:after { background-color: #216694; } + @media screen and (max-width: 800px) { .board-color-belize.pop-over .header { background: #2980b9; color: #fff; } } + .board-color-belize#header ul li.current, .board-color-belize#header-quick-access ul li.current { border-bottom: 4px solid #459cd6; @@ -310,11 +350,6 @@ THEME - Belize .board-color-belize .list { border-left: none; - padding-bottom: 8px; -} - -.board-color-belize .list-body { - margin-top: 8px; } /* === END Belize THEME === */ @@ -329,43 +364,52 @@ THEME - Wisteria .board-list .board-color-wisteria a { background-color: #8e44ad; } + .board-color-wisteria .is-selected .minicard { border-left: 3px solid #8e44ad; } + .board-color-wisteria .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-wisteria button[type=submit].primary, .board-color-wisteria input[type=submit].primary, .board-color-wisteria .sidebar .sidebar-content .sidebar-btn { background-color: #72368a; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-wisteria.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-wisteria .sidebar .sidebar-content .sidebar-btn:hover, .board-color-wisteria .sidebar-list li a:hover { background-color: #9c51bb; } + .board-color-wisteria#header ul li.current, .board-color-wisteria#header-quick-access ul li.current { border-bottom: 2px solid #9c51bb; } + .board-color-wisteria#header-quick-access { background: #803d9c; color: #fff; } + .board-color-wisteria#header #header-main-bar .board-header-btn.emphasis { background: #63ad44; } + .board-color-wisteria#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-wisteria#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #599c3d; } + .board-color-wisteria#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #4f8a36; } + .board-color-wisteria .materialCheckBox.is-checked { border-bottom: 2px solid #8e44ad; border-right: 2px solid #8e44ad; @@ -379,24 +423,30 @@ THEME - Wisteria .board-color-wisteria .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #f4ecf7; } -.board-color-wisteria .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-wisteria .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #fcf9fd; } + .board-color-wisteria .toggle-label:after { background-color: #72368a; } -.board-color-wisteria .toggle-switch:checked ~ .toggle-label { + +.board-color-wisteria .toggle-switch:checked~.toggle-label { background-color: #a765c2; } -.board-color-wisteria .toggle-switch:checked ~ .toggle-label:after { + +.board-color-wisteria .toggle-switch:checked~.toggle-label:after { background-color: #72368a; } + @media screen and (max-width: 800px) { .board-color-wisteria.pop-over .header { background: #8e44ad; color: #fff; } } + .board-color-wisteria#header ul li.current, .board-color-wisteria#header-quick-access ul li.current { border-bottom: 4px solid #a765c2; @@ -417,12 +467,9 @@ THEME - Wisteria .board-color-wisteria .list { border-left: none; - padding-bottom: 8px; } -.board-color-wisteria .list-body { - margin-top: 8px; -} + /* === END Wisteria THEME === */ @@ -436,43 +483,52 @@ THEME - Midnight .board-list .board-color-midnight a { background-color: #2c3e50; } + .board-color-midnight .is-selected .minicard { border-left: 3px solid #2c3e50; } + .board-color-midnight .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-midnight button[type=submit].primary, .board-color-midnight input[type=submit].primary, .board-color-midnight .sidebar .sidebar-content .sidebar-btn { background-color: #233240; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-midnight.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-midnight .sidebar .sidebar-content .sidebar-btn:hover, .board-color-midnight .sidebar-list li a:hover { background-color: #3a5169; } + .board-color-midnight#header ul li.current, .board-color-midnight#header-quick-access ul li.current { border-bottom: 2px solid #3a5169; } + .board-color-midnight#header-quick-access { background: #283848; color: #fff; } + .board-color-midnight#header #header-main-bar .board-header-btn.emphasis { background: #503e2c; } + .board-color-midnight#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-midnight#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #483828; } + .board-color-midnight#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #403223; } + .board-color-midnight .materialCheckBox.is-checked { border-bottom: 2px solid #2c3e50; border-right: 2px solid #2c3e50; @@ -486,24 +542,30 @@ THEME - Midnight .board-color-midnight .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e6ecf1; } -.board-color-midnight .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-midnight .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f8f9fb; } + .board-color-midnight .toggle-label:after { background-color: #233240; } -.board-color-midnight .toggle-switch:checked ~ .toggle-label { + +.board-color-midnight .toggle-switch:checked~.toggle-label { background-color: #476582; } -.board-color-midnight .toggle-switch:checked ~ .toggle-label:after { + +.board-color-midnight .toggle-switch:checked~.toggle-label:after { background-color: #233240; } + @media screen and (max-width: 800px) { .board-color-midnight.pop-over .header { background: #2c3e50; color: #fff; } } + .board-color-midnight#header ul li.current, .board-color-midnight#header-quick-access ul li.current { border-bottom: 4px solid #476582; @@ -524,12 +586,9 @@ THEME - Midnight .board-color-midnight .list { border-left: none; - padding-bottom: 8px; } -.board-color-midnight .list-body { - margin-top: 8px; -} + /* === END Midnight THEME === */ @@ -543,43 +602,52 @@ THEME - Pumpkin .board-list .board-color-pumpkin a { background-color: #e67e22; } + .board-color-pumpkin .is-selected .minicard { border-left: 3px solid #e67e22; } + .board-color-pumpkin .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-pumpkin button[type=submit].primary, .board-color-pumpkin input[type=submit].primary, .board-color-pumpkin .sidebar .sidebar-content .sidebar-btn { background-color: #be6415; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-pumpkin.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-pumpkin .sidebar .sidebar-content .sidebar-btn:hover, .board-color-pumpkin .sidebar-list li a:hover { background-color: #e98b38; } + .board-color-pumpkin#header ul li.current, .board-color-pumpkin#header-quick-access ul li.current { border-bottom: 2px solid #e98b38; } + .board-color-pumpkin#header-quick-access { background: #d57118; color: #fff; } + .board-color-pumpkin#header #header-main-bar .board-header-btn.emphasis { background: #228ae6; } + .board-color-pumpkin#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-pumpkin#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #187dd5; } + .board-color-pumpkin#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #156fbe; } + .board-color-pumpkin .materialCheckBox.is-checked { border-bottom: 2px solid #e67e22; border-right: 2px solid #e67e22; @@ -593,24 +661,30 @@ THEME - Pumpkin .board-color-pumpkin .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #fdf2e9; } -.board-color-pumpkin .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-pumpkin .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #fefbf8; } + .board-color-pumpkin .toggle-label:after { background-color: #be6415; } -.board-color-pumpkin .toggle-switch:checked ~ .toggle-label { + +.board-color-pumpkin .toggle-switch:checked~.toggle-label { background-color: #eb984e; } -.board-color-pumpkin .toggle-switch:checked ~ .toggle-label:after { + +.board-color-pumpkin .toggle-switch:checked~.toggle-label:after { background-color: #be6415; } + @media screen and (max-width: 800px) { .board-color-pumpkin.pop-over .header { background: #e67e22; color: #fff; } } + .board-color-pumpkin#header ul li.current, .board-color-pumpkin#header-quick-access ul li.current { border-bottom: 4px solid #eb984e; @@ -631,12 +705,9 @@ THEME - Pumpkin .board-color-pumpkin .list { border-left: none; - padding-bottom: 8px; } -.board-color-pumpkin .list-body { - margin-top: 8px; -} + /* === END Pumpkin THEME === */ @@ -650,43 +721,52 @@ THEME - Moderate Pink .board-list .board-color-moderatepink a { background-color: #cd5a91; } + .board-color-moderatepink .is-selected .minicard { border-left: 3px solid #cd5a91; } + .board-color-moderatepink .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-moderatepink button[type=submit].primary, .board-color-moderatepink input[type=submit].primary, .board-color-moderatepink .sidebar .sidebar-content .sidebar-btn { background-color: #b53773; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-moderatepink.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-moderatepink .sidebar .sidebar-content .sidebar-btn:hover, .board-color-moderatepink .sidebar-list li a:hover { background-color: #d26b9c; } + .board-color-moderatepink#header ul li.current, .board-color-moderatepink#header-quick-access ul li.current { border-bottom: 2px solid #d26b9c; } + .board-color-moderatepink#header-quick-access { background: #c64382; color: #fff; } + .board-color-moderatepink#header #header-main-bar .board-header-btn.emphasis { background: #5acd96; } + .board-color-moderatepink#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-moderatepink#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #43c688; } + .board-color-moderatepink#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #37b579; } + .board-color-moderatepink .materialCheckBox.is-checked { border-bottom: 2px solid #cd5a91; border-right: 2px solid #cd5a91; @@ -700,24 +780,30 @@ THEME - Moderate Pink .board-color-moderatepink .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #faeef4; } -.board-color-moderatepink .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-moderatepink .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #fefafc; } + .board-color-moderatepink .toggle-label:after { background-color: #b53773; } -.board-color-moderatepink .toggle-switch:checked ~ .toggle-label { + +.board-color-moderatepink .toggle-switch:checked~.toggle-label { background-color: #d77ba7; } -.board-color-moderatepink .toggle-switch:checked ~ .toggle-label:after { + +.board-color-moderatepink .toggle-switch:checked~.toggle-label:after { background-color: #b53773; } + @media screen and (max-width: 800px) { .board-color-moderatepink.pop-over .header { background: #cd5a91; color: #fff; } } + .board-color-moderatepink#header ul li.current, .board-color-moderatepink#header-quick-access ul li.current { border-bottom: 4px solid #d77ba7; @@ -738,12 +824,9 @@ THEME - Moderate Pink .board-color-moderatepink .list { border-left: none; - padding-bottom: 8px; } -.board-color-moderatepink .list-body { - margin-top: 8px; -} + /* === END Moderatepink THEME === */ @@ -757,43 +840,52 @@ THEME - Strong Cyan .board-list .board-color-strongcyan a { background-color: #00aecc; } + .board-color-strongcyan .is-selected .minicard { border-left: 3px solid #00aecc; } + .board-color-strongcyan .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-strongcyan button[type=submit].primary, .board-color-strongcyan input[type=submit].primary, .board-color-strongcyan .sidebar .sidebar-content .sidebar-btn { background-color: #008ba3; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-strongcyan.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-strongcyan .sidebar .sidebar-content .sidebar-btn:hover, .board-color-strongcyan .sidebar-list li a:hover { background-color: #00c8eb; } + .board-color-strongcyan#header ul li.current, .board-color-strongcyan#header-quick-access ul li.current { border-bottom: 2px solid #00c8eb; } + .board-color-strongcyan#header-quick-access { background: #009db8; color: #fff; } + .board-color-strongcyan#header #header-main-bar .board-header-btn.emphasis { background: #cc1e00; } + .board-color-strongcyan#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-strongcyan#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #b81b00; } + .board-color-strongcyan#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #a31800; } + .board-color-strongcyan .materialCheckBox.is-checked { border-bottom: 2px solid #00aecc; border-right: 2px solid #00aecc; @@ -807,24 +899,30 @@ THEME - Strong Cyan .board-color-strongcyan .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e0fbff; } -.board-color-strongcyan .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-strongcyan .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f6feff; } + .board-color-strongcyan .toggle-label:after { background-color: #008ba3; } -.board-color-strongcyan .toggle-switch:checked ~ .toggle-label { + +.board-color-strongcyan .toggle-switch:checked~.toggle-label { background-color: #0adbff; } -.board-color-strongcyan .toggle-switch:checked ~ .toggle-label:after { + +.board-color-strongcyan .toggle-switch:checked~.toggle-label:after { background-color: #008ba3; } + @media screen and (max-width: 800px) { .board-color-strongcyan.pop-over .header { background: #00aecc; color: #fff; } } + .board-color-strongcyan#header ul li.current, .board-color-strongcyan#header-quick-access ul li.current { border-bottom: 4px solid #0adbff; @@ -838,19 +936,16 @@ THEME - Strong Cyan /* Apply scrollbar to sidebar content*/ .board-color-strongcyan .sidebar .sidebar-content { - scrollbar-color: #00aeccf2 #e4e4e400; + scrollbar-color: #00aeccf2 #e4e4e400; } /* Remove margins in between columns/fix spacing */ .board-color-strongcyan .list { border-left: none; - padding-bottom: 8px; } -.board-color-strongcyan .list-body { - margin-top: 8px; -} + /* === END Strongcyan THEME === */ @@ -864,43 +959,52 @@ THEME - Lime Green .board-list .board-color-limegreen a { background-color: #4bbf6b; } + .board-color-limegreen .is-selected .minicard { border-left: 3px solid #4bbf6b; } + .board-color-limegreen .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-limegreen button[type=submit].primary, .board-color-limegreen input[type=submit].primary, .board-color-limegreen .sidebar .sidebar-content .sidebar-btn { background-color: #389d54; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-limegreen.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-limegreen .sidebar .sidebar-content .sidebar-btn:hover, .board-color-limegreen .sidebar-list li a:hover { background-color: #5dc57a; } + .board-color-limegreen#header ul li.current, .board-color-limegreen#header-quick-access ul li.current { border-bottom: 2px solid #5dc57a; } + .board-color-limegreen#header-quick-access { background: #3fb15e; color: #fff; } + .board-color-limegreen#header #header-main-bar .board-header-btn.emphasis { background: #bf4b9f; } + .board-color-limegreen#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-limegreen#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #b13f91; } + .board-color-limegreen#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #9d3881; } + .board-color-limegreen .materialCheckBox.is-checked { border-bottom: 2px solid #4bbf6b; border-right: 2px solid #4bbf6b; @@ -914,24 +1018,30 @@ THEME - Lime Green .board-color-limegreen .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #edf9f0; } -.board-color-limegreen .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-limegreen .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #fafdfb; } + .board-color-limegreen .toggle-label:after { background-color: #389d54; } -.board-color-limegreen .toggle-switch:checked ~ .toggle-label { + +.board-color-limegreen .toggle-switch:checked~.toggle-label { background-color: #6fcc89; } -.board-color-limegreen .toggle-switch:checked ~ .toggle-label:after { + +.board-color-limegreen .toggle-switch:checked~.toggle-label:after { background-color: #389d54; } + @media screen and (max-width: 800px) { .board-color-limegreen.pop-over .header { background: #4bbf6b; color: #fff; } } + .board-color-limegreen#header ul li.current, .board-color-limegreen#header-quick-access ul li.current { border-bottom: 4px solid #6fcc89; @@ -952,12 +1062,9 @@ THEME - Lime Green .board-color-limegreen .list { border-left: none; - padding-bottom: 8px; } -.board-color-limegreen .list-body { - margin-top: 8px; -} + /* === END Limegreen THEME === */ @@ -971,44 +1078,53 @@ THEME - Dark .board-list .board-color-dark a { background-color: #2c3e51; } + .board-color-dark .is-selected .minicard { border-left: 3px solid #2c3e51; } + .board-color-dark .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); background-color: rgb(255 255 255 / 90%); } + .board-color-dark button[type=submit].primary, .board-color-dark input[type=submit].primary, .board-color-dark .sidebar .sidebar-content .sidebar-btn { background-color: #233241; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-dark.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-dark .sidebar .sidebar-content .sidebar-btn:hover, .board-color-dark .sidebar-list li a:hover { background-color: #3a516a; } + .board-color-dark#header ul li.current, .board-color-dark#header-quick-access ul li.current { border-bottom: 2px solid #3a516a; } + .board-color-dark#header-quick-access { background: #283849; color: #fff; } + .board-color-dark#header #header-main-bar .board-header-btn.emphasis { background: #513f2c; } + .board-color-dark#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-dark#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #493928; } + .board-color-dark#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #413223; } + .board-color-dark .materialCheckBox.is-checked { border-bottom: 2px solid #2c3e51; border-right: 2px solid #2c3e51; @@ -1022,24 +1138,30 @@ THEME - Dark .board-color-dark .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e6ecf1; } -.board-color-dark .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-dark .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f8f9fb; } + .board-color-dark .toggle-label:after { background-color: #233241; } -.board-color-dark .toggle-switch:checked ~ .toggle-label { + +.board-color-dark .toggle-switch:checked~.toggle-label { background-color: #476483; } -.board-color-dark .toggle-switch:checked ~ .toggle-label:after { + +.board-color-dark .toggle-switch:checked~.toggle-label:after { background-color: #233241; } + @media screen and (max-width: 800px) { .board-color-dark.pop-over .header { background: #2c3e51; color: #fff; } } + .board-color-dark#header ul li.current, .board-color-dark#header-quick-access ul li.current { border-bottom: 4px solid #476483; @@ -1047,13 +1169,13 @@ THEME - Dark /* Board Wrapper background fix for dark theme */ .board-color-dark.board-wrapper { - background-color: #2c3e50; + background-color: #2c3e50; } .board-color-dark .swimlane, -.board-color-dark .swimlane >.swimlane-header-wrap, -.board-color-dark .swimlane >.list.js-list, -.board-color-dark .swimlane >.list-composer.js-list-composer, +.board-color-dark .swimlane>.swimlane-header-wrap, +.board-color-dark .swimlane>.list.js-list, +.board-color-dark .swimlane>.list-composer.js-list-composer, .board-color-dark .list-body, .board-color-dark .list, .board-color-dark .list-composer, @@ -1061,6 +1183,7 @@ THEME - Dark .board-color-dark .card-details { background-color: #2c3e50; } + .board-color-dark .card-details h3, .board-color-dark .card-details-left p, .board-color-dark .card-details-items, @@ -1070,49 +1193,63 @@ THEME - Dark .board-color-dark .material-toggle-switch { color: #bbb; } + .board-color-dark .list-header { background-color: #888; } + .board-color-dark .board-widget, .board-color-dark .board-widget-labels, .board-color-dark .board-widget-members { color: #aaa; } -.board-color-dark .pop-over >.header { + +.board-color-dark .pop-over>.header { display: none; } + .board-color-dark #header-quick-access .fa-plus { display: none; } + .board-color-dark #header-quick-access:hover .fa-plus { display: inherit; } + .board-color-dark .open-minicard-composer { visibility: hidden; } + .board-color-dark .list.js-list:hover .open-minicard-composer { visibility: visible; } + .board-color-dark .list-header-menu { visibility: hidden; } + .board-color-dark .list.js-list:hover .list-header-menu { visibility: visible; } -.board-color-dark .list.js-list-composer >.list-header { + +.board-color-dark .list.js-list-composer>.list-header { visibility: hidden; } -.board-color-dark .list.js-list-composer:hover >.list-header { + +.board-color-dark .list.js-list-composer:hover>.list-header { visibility: visible; } + .board-color-dark #header-quick-access, .board-color-dark #header { - background-color: rgba(0,0,0,0.75) !important; + background-color: rgba(0, 0, 0, 0.75) !important; } + .board-color-dark #header .board-header-btn:hover { - background-color: rgba(255,255,255,0.3) !important; + background-color: rgba(255, 255, 255, 0.3) !important; } -.board-color-dark .list >.list-header, + +.board-color-dark .list>.list-header, /* Comment out, fixed white swimlane text not visible https://github.com/wekan/wekan/issues/4451 .board-color-dark .swimlane-header { color: rgba(255,255,255,0.7); @@ -1122,26 +1259,31 @@ THEME - Dark .board-color-dark .minicard:hover, .board-color-dark .minicard-composer.js-composer, .board-color-dark .open-minicard-composer:hover { - background-color: rgba(255,255,255,0.8) !important; + background-color: rgba(255, 255, 255, 0.8) !important; color: #000; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-dark .minicard:hover .badge, .board-color-dark .minicard-wrapper.is-selected .badge { color: #000; } + .board-color-dark .card-details .card-details-header { background-color: #ccc; } + .board-color-dark .sidebar-tongue, .board-color-dark .sidebar-shadow { background-color: #666 !important; } + .board-color-dark .sidebar-content h3, .board-color-dark .sidebar-content h2, .board-color-dark .sidebar-content { - color: rgba(255,255,255,0.7) !important; + color: rgba(255, 255, 255, 0.7) !important; } + .board-color-dark .card-details .activities .activity .activity-desc .activity-comment { background-color: #ccc; color: #222; @@ -1161,13 +1303,11 @@ THEME - Dark /* Remove margins in between columns/fix spacing */ .board-color-dark .list { - border-left: none; /* Remove this property to bring back lines in-between columns if needed*/ - padding: 0px 1px 8px 1px; /* Improves spacing between columns due to no borders, 8px padding at bottom to separate horizontal scrollbar/lists */ + border-left: none; + /* Remove this property to bring back lines in-between columns if needed*/ } -.board-color-dark .list-body { - margin-top: 8px; -} + /* === END Dark THEME === */ @@ -1181,43 +1321,52 @@ THEME - Relax .board-list .board-color-relax a { background-color: #27ae61; } + .board-color-relax .is-selected .minicard { border-left: 3px solid #27ae61; } + .board-color-relax .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); } + .board-color-relax button[type=submit].primary, .board-color-relax input[type=submit].primary, .board-color-relax .sidebar .sidebar-content .sidebar-btn { background-color: #1f8b4e; - border-radius: 7px; + border-radius: 0.6ch; } + .board-color-relax.pop-over .pop-over-list li a:not(.disabled):hover, .board-color-relax .sidebar .sidebar-content .sidebar-btn:hover, .board-color-relax .sidebar-list li a:hover { background-color: #2cc66f; } + .board-color-relax#header ul li.current, .board-color-relax#header-quick-access ul li.current { border-bottom: 2px solid #2cc66f; } + .board-color-relax#header-quick-access { background: #239d57; color: #fff; } + .board-color-relax#header #header-main-bar .board-header-btn.emphasis { background: #ae2774; } + .board-color-relax#header #header-main-bar .board-header-btn.emphasis:hover, .board-color-relax#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { background: #9d2368; } + .board-color-relax#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { background: #8b1f5d; } + .board-color-relax .materialCheckBox.is-checked { border-bottom: 2px solid #27ae61; border-right: 2px solid #27ae61; @@ -1231,56 +1380,64 @@ THEME - Relax .board-color-relax .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { background: #e7faef; } -.board-color-relax .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + +.board-color-relax .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { background: #f8fdfa; } + .board-color-relax .toggle-label:after { background-color: #1f8b4e; } -.board-color-relax .toggle-switch:checked ~ .toggle-label { + +.board-color-relax .toggle-switch:checked~.toggle-label { background-color: #3dd37e; } -.board-color-relax .toggle-switch:checked ~ .toggle-label:after { + +.board-color-relax .toggle-switch:checked~.toggle-label:after { background-color: #1f8b4e; } + @media screen and (max-width: 800px) { .board-color-relax.pop-over .header { background: #27ae61; color: #fff; } } + .board-color-relax#header ul li.current, .board-color-relax#header-quick-access ul li.current { border-bottom: 4px solid #3dd37e; } + .board-color-relax .board-wrapper { background-color: #a7e366; } + .board-color-relax .list-header { background-color: #a7e366; } + .board-color-relax .list-body { background-color: #a7e366; } + .board-color-relax .list { border-left: 1px dotted #000; } -.board-color-relax .card-details .card-details-items ~ .js-open-inlined-form .viewer { + +.board-color-relax .card-details .card-details-items~.js-open-inlined-form .viewer { background-color: #fff !important; - padding: 15px !important; border: 1px solid #000 !important; - word-wrap: break-word; + overflow-wrap: break-word; } + .board-color-relax .minicard .badges .badge .badge-icon.badge-comment, .board-color-relax .minicard .badges .badge .badge-text.badge-comment { display: block; - border-radius: 4px; - padding: 1px 3px; - margin-bottom: 0.3rem; + border-radius: 0.4ch; color: #f00; background-color: #fff; font-weight: bold; - font-size: 11pt; } /* Transparent modern scrollbar - relax*/ @@ -1298,123 +1455,133 @@ THEME - Relax .board-color-relax .list { border-left: none; - /* padding-bottom: 8px; - Removed to get rid of grey bars for relax theme */ -} + /* } + -.board-color-relax .list-body { - margin-top: 8px; -} /* === END Relax THEME === */ -/* =============== + /* =============== THEME - Corteza =================*/ -.board-color-corteza#header, -.board-color-corteza.sk-spinner div, -.board-backgrounds-list .board-color-corteza.background-box, -.board-list .board-color-corteza a { - background-color: #568ba2; -} -.board-color-corteza .is-selected .minicard { - border-left: 3px solid #568ba2; -} -.board-color-corteza .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); -} -.board-color-corteza button[type=submit].primary, -.board-color-corteza input[type=submit].primary, -.board-color-corteza .sidebar .sidebar-content .sidebar-btn { - background-color: #456f82; - border-radius: 7px; -} -.board-color-corteza.pop-over .pop-over-list li a:not(.disabled):hover, -.board-color-corteza .sidebar .sidebar-content .sidebar-btn:hover, -.board-color-corteza .sidebar-list li a:hover { - background-color: #6597ad; -} -.board-color-corteza#header ul li.current, -.board-color-corteza#header-quick-access ul li.current { - border-bottom: 2px solid #6597ad; -} -.board-color-corteza#header-quick-access { - background: #4d7d92; - color: #fff; -} -.board-color-corteza#header #header-main-bar .board-header-btn.emphasis { - background: #a26d56; -} -.board-color-corteza#header #header-main-bar .board-header-btn.emphasis:hover, -.board-color-corteza#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { - background: #92624d; -} -.board-color-corteza#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { - background: #825745; -} -.board-color-corteza .materialCheckBox.is-checked { - border-bottom: 2px solid #568ba2; - border-right: 2px solid #568ba2; -} -.board-color-corteza .checklist-progress-bar { + .board-color-corteza#header, + .board-color-corteza.sk-spinner div, + .board-backgrounds-list .board-color-corteza.background-box, + .board-list .board-color-corteza a { + background-color: #568ba2; + } + + .board-color-corteza .is-selected .minicard { + border-left: 3px solid #568ba2; + } + + .board-color-corteza .minicard { + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); + } + + .board-color-corteza button[type=submit].primary, + .board-color-corteza input[type=submit].primary, + .board-color-corteza .sidebar .sidebar-content .sidebar-btn { + background-color: #456f82; + border-radius: 0.6ch; + } + + .board-color-corteza.pop-over .pop-over-list li a:not(.disabled):hover, + .board-color-corteza .sidebar .sidebar-content .sidebar-btn:hover, + .board-color-corteza .sidebar-list li a:hover { + background-color: #6597ad; + } + + .board-color-corteza#header ul li.current, + .board-color-corteza#header-quick-access ul li.current { + border-bottom: 2px solid #6597ad; + } + + .board-color-corteza#header-quick-access { + background: #4d7d92; + color: #fff; + } + + .board-color-corteza#header #header-main-bar .board-header-btn.emphasis { + background: #a26d56; + } + + .board-color-corteza#header #header-main-bar .board-header-btn.emphasis:hover, + .board-color-corteza#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { + background: #92624d; + } + + .board-color-corteza#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { + background: #825745; + } + + .board-color-corteza .materialCheckBox.is-checked { + border-bottom: 2px solid #568ba2; + border-right: 2px solid #568ba2; + } + + .board-color-corteza .checklist-progress-bar { background-color: #dce6ec !important; } .board-color-corteza .checklist-progress-bar .checklist-progress { background-color: #568ba2 !important; } -.board-color-corteza .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { - background: #eef3f6; -} -.board-color-corteza .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { - background: #fafcfc; -} -.board-color-corteza .toggle-label:after { - background-color: #456f82; -} -.board-color-corteza .toggle-switch:checked ~ .toggle-label { - background-color: #76a3b6; -} -.board-color-corteza .toggle-switch:checked ~ .toggle-label:after { - background-color: #456f82; -} -@media screen and (max-width: 800px) { - .board-color-corteza.pop-over .header { - background: #568ba2; - color: #fff; +.board-color-corteza .is-multiselection-active .multi-selection-checkbox.is-checked+.minicard { + background: #eef3f6; } -} -.board-color-corteza#header ul li.current, -.board-color-corteza#header-quick-access ul li.current { - border-bottom: 4px solid #76a3b6; -} -/* Transparent modern scrollbar - corteza*/ -.board-color-corteza .board-canvas { + .board-color-corteza .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { + background: #fafcfc; + } + + .board-color-corteza .toggle-label:after { + background-color: #456f82; + } + + .board-color-corteza .toggle-switch:checked~.toggle-label { + background-color: #76a3b6; + } + + .board-color-corteza .toggle-switch:checked~.toggle-label:after { + background-color: #456f82; + } + + @media screen and (max-width: 800px) { + .board-color-corteza.pop-over .header { + background: #568ba2; + color: #fff; + } + } + + .board-color-corteza#header ul li.current, + .board-color-corteza#header-quick-access ul li.current { + border-bottom: 4px solid #76a3b6; + } + + /* Transparent modern scrollbar - corteza*/ + .board-color-corteza .board-canvas { scrollbar-color: #568ba2f2 #e4e4e400; -} + } -/* Apply scrollbar to sidebar content*/ -.board-color-corteza .sidebar .sidebar-content { - scrollbar-color: #568ba2f2 #e4e4e400; -} + /* Apply scrollbar to sidebar content*/ + .board-color-corteza .sidebar .sidebar-content { + scrollbar-color: #568ba2f2 #e4e4e400; + } -/* Remove margins in between columns/fix spacing */ + /* Remove margins in between columns/fix spacing */ -.board-color-corteza .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-corteza .list { + border-left: none; + } -.board-color-corteza .list-body { - margin-top: 8px; -} -/* === END Corteza THEME === */ -/* =============== + /* === END Corteza THEME === */ + + /* =============== THEME - Clear Blue =================*/ @@ -1452,9 +1619,6 @@ THEME - Clear Blue .board-color-clearblue#header #header-main-bar { background: linear-gradient(180deg, #499bea 0%, #00aecc 100%); } -.board-color-clearblue#header #header-main-bar p { - margin-bottom: 6px; -} .board-color-clearblue#header #header-main-bar .board-header-btn.emphasis { background: #00c8eb; } @@ -1494,16 +1658,10 @@ THEME - Clear Blue background: none; } .board-color-clearblue .swimlane .list:first-child { - min-width: 20px; - margin-left: 10px; /* Added 10px margin left to stop lists being butted up against the edge of the screen */ border-left: none; } -.board-color-clearblue .swimlane .list:nth-child { - flex: 0 0 265px; -} .board-color-clearblue .list { background: rgba(255,255,255,0.35); - margin: 10px 0; border: 0; border-radius: 14px; } @@ -1511,15 +1669,11 @@ THEME - Clear Blue background: rgba(255,255,255,0.1); height: min-content; flex: unset; - padding-bottom: 16px; - min-width: 20px; - margin-left: 0px; border-left: none; } .board-color-clearblue .list.list-composer .open-list-composer { - border-radius: 7px; + border-radius: 0.6ch; color: rgba(0,0,0,0.3); - padding: 7px 10px; display: block; } .board-color-clearblue .list.list-composer .open-list-composer:hover i, @@ -1538,24 +1692,19 @@ THEME - Clear Blue .board-color-clearblue .list-header .list-header-name { color: rgba(0,0,0,0.6); } -.board-color-clearblue .list-body { - padding: 11px; } .board-color-clearblue .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; + border-radius: 0.6ch; box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); color: #222; } .board-color-clearblue .card-details { border-radius: 0 0 14px 14px; box-shadow: 0 0 7px 0 rgba(0,0,0,0.5); - margin-left: -10px; } .board-color-clearblue .list-body .open-minicard-composer { - border-radius: 7px; + border-radius: 0.6ch; color: rgba(0,0,0,0.3); - margin-bottom: 11px; } .board-color-clearblue .list-body .open-minicard-composer:hover { background: rgba(255,255,255,0.7); @@ -1566,7 +1715,7 @@ THEME - Clear Blue box-shadow: none; background-color: rgba(255,255,255,0.5); color: rgba(0,0,0,0.55); - border-radius: 7px; + border-radius: 0.6ch; border: 0; } .board-color-clearblue button[type="submit"].primary:hover, @@ -1574,7 +1723,7 @@ THEME - Clear Blue background-color: rgba(255,255,255,0.7); color: rgba(0,0,0,0.8); box-shadow: 0 1px 2px rgba(0,0,0,0.2); - border-radius: 7px; + border-radius: 0.6ch; } .board-color-clearblue .quiet, .board-color-clearblue .quiet a { @@ -1583,8 +1732,6 @@ THEME - Clear Blue .board-color-clearblue .list-header .list-header-watch-icon { color: rgba(0,0,0,0.5); position: absolute; - margin-top: -34px; - margin-left: -11px; } .board-color-clearblue a.fa, .board-color-clearblue a i.fa { @@ -1595,13 +1742,13 @@ THEME - Clear Blue .board-color-clearblue a:not(.disabled):hover.fa, .board-color-clearblue a:not(.disabled):hover i.fa { color: rgba(0,0,0,0.6); - border-radius: 7px; + border-radius: 0.6ch; } .board-color-clearblue input[type="email"], .board-color-clearblue input[type="password"], .board-color-clearblue input[type="text"] { border: 0; - border-radius: 7px; + border-radius: 0.6ch; } .board-color-clearblue .sidebar-shadow { box-shadow: none; @@ -1645,12 +1792,6 @@ THEME - Clear Blue display: inline-block; vertical-align: middle; } -.board-color-clearblue .swimlane-header-wrap .primary.confirm { - margin-right: 0; -} -.board-color-clearblue .swimlane-header-wrap .fa.fa-times-thin { - margin-top: 2px; -} .board-color-clearblue .list.ui-sortable-helper, .board-color-clearblue .list.ui-sortable-helper .list-header.ui-sortable-handle, .board-color-clearblue .list.ui-sortable-helper .viewer { @@ -1658,1590 +1799,1570 @@ THEME - Clear Blue cursor: grabbing; } -/* Transparent modern scrollbar - clearblue*/ -.board-color-clearblue .board-canvas { - scrollbar-color: #ffffffdb #ffffff00; - scrollbar-width: thin; -} + /* Transparent modern scrollbar - clearblue*/ + .board-color-clearblue .board-canvas { + scrollbar-color: #ffffffdb #ffffff00; + scrollbar-width: thin; + } -.board-color-clearblue .list-body { - scrollbar-width: thin; -} + .board-color-clearblue .list-body { + scrollbar-width: thin; + } -/* Apply scrollbar to sidebar content*/ -.board-color-clearblue .sidebar .sidebar-content { - scrollbar-color: #00aecc #ffffff00; -} + /* Apply scrollbar to sidebar content*/ + .board-color-clearblue .sidebar .sidebar-content { + scrollbar-color: #00aecc #ffffff00; + } -/* Remove margins in between columns/fix spacing */ + /* Remove margins in between columns/fix spacing */ -.board-color-clearblue .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-clearblue .list { + border-left: none; + } -.board-color-clearblue .list-body { - margin-top: 8px; -} -/* === END Clearblue THEME === */ -/* =============== + /* === END Clearblue THEME === */ + + /* =============== THEME - Natural =================*/ -.board-color-natural#header, -.board-color-natural.sk-spinner div, -.board-backgrounds-list .board-color-natural.background-box, -.board-list .board-color-natural a { - background-color: #596557; -} -.board-color-natural .is-selected .minicard { - border-left: 3px solid #596557; -} -.board-color-natural .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); -} -.board-color-natural button[type=submit].primary, -.board-color-natural input[type=submit].primary, -.board-color-natural .sidebar .sidebar-content .sidebar-btn { - background-color: #475146; - border-radius: 7px; -} -.board-color-natural.pop-over .pop-over-list li a:not(.disabled):hover, -.board-color-natural .sidebar .sidebar-content .sidebar-btn:hover, -.board-color-natural .sidebar-list li a:hover { - background-color: #687666; -} -.board-color-natural#header ul li.current, -.board-color-natural#header-quick-access ul li.current { - border-bottom: 2px solid #687666; -} -.board-color-natural#header-quick-access { - background: #505b4e; - color: #fff; -} -.board-color-natural#header #header-main-bar .board-header-btn.emphasis { - background: #635765; -} -.board-color-natural#header #header-main-bar .board-header-btn.emphasis:hover, -.board-color-natural#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { - background: #594e5b; -} -.board-color-natural#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { - background: #4f4651; -} -.board-color-natural .materialCheckBox.is-checked { - border-bottom: 2px solid #596557; - border-right: 2px solid #596557; -} + .board-color-natural#header, + .board-color-natural.sk-spinner div, + .board-backgrounds-list .board-color-natural.background-box, + .board-list .board-color-natural a { + background-color: #596557; + } + + .board-color-natural .is-selected .minicard { + border-left: 3px solid #596557; + } + + .board-color-natural .minicard { + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); + } + + .board-color-natural button[type=submit].primary, + .board-color-natural input[type=submit].primary, + .board-color-natural .sidebar .sidebar-content .sidebar-btn { + background-color: #475146; + border-radius: 0.6ch; + } + + .board-color-natural.pop-over .pop-over-list li a:not(.disabled):hover, + .board-color-natural .sidebar .sidebar-content .sidebar-btn:hover, + .board-color-natural .sidebar-list li a:hover { + background-color: #687666; + } + + .board-color-natural#header ul li.current, + .board-color-natural#header-quick-access ul li.current { + border-bottom: 2px solid #687666; + } + + .board-color-natural#header-quick-access { + background: #505b4e; + color: #fff; + } + + .board-color-natural#header #header-main-bar .board-header-btn.emphasis { + background: #635765; + } + + .board-color-natural#header #header-main-bar .board-header-btn.emphasis:hover, + .board-color-natural#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { + background: #594e5b; + } + + .board-color-natural#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { + background: #4f4651; + } + + .board-color-natural .materialCheckBox.is-checked { + border-bottom: 2px solid #596557; + border-right: 2px solid #596557; + } .board-color-natural .checklist-progress-bar { background-color: #dee0dd !important; } .board-color-natural .checklist-progress-bar .checklist-progress { background-color: #596557 !important; } -.board-color-natural .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { - background: #eef0ee; -} -.board-color-natural .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { - background: #fafbfa; -} -.board-color-natural .toggle-label:after { - background-color: #475146; -} -.board-color-natural .toggle-switch:checked ~ .toggle-label { - background-color: #778875; -} -.board-color-natural .toggle-switch:checked ~ .toggle-label:after { - background-color: #475146; -} -@media screen and (max-width: 800px) { - .board-color-natural.pop-over .header { - background: #596557; - color: #fff; + + .board-color-natural .is-multiselection-active .multi-selection-checkbox.is-checked+.minicard { + background: #eef0ee; } -} -.board-color-natural#header ul li.current, -.board-color-natural#header-quick-access ul li.current { - border-bottom: 4px solid #778875; -} -.board-color-natural#header-quick-access { - background-color: #2d392b; -} -.board-color-natural.board-wrapper { - background-color: #dedede; -} -.board-color-natural .swimlane .swimlane-header-wrap { - background-color: #c2c0ab; -} -/* Transparent modern scrollbar - natural*/ -.board-color-natural .board-canvas { - scrollbar-color: #596557f2 #e4e4e400; -} + .board-color-natural .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { + background: #fafbfa; + } + + .board-color-natural .toggle-label:after { + background-color: #475146; + } + + .board-color-natural .toggle-switch:checked~.toggle-label { + background-color: #778875; + } + + .board-color-natural .toggle-switch:checked~.toggle-label:after { + background-color: #475146; + } + + @media screen and (max-width: 800px) { + .board-color-natural.pop-over .header { + background: #596557; + color: #fff; + } + } + + .board-color-natural#header ul li.current, + .board-color-natural#header-quick-access ul li.current { + border-bottom: 4px solid #778875; + } + + .board-color-natural#header-quick-access { + background-color: #2d392b; + } + + .board-color-natural.board-wrapper { + background-color: #dedede; + } + + .board-color-natural .swimlane .swimlane-header-wrap { + background-color: #c2c0ab; + } + + /* Transparent modern scrollbar - natural*/ + .board-color-natural .board-canvas { + scrollbar-color: #596557f2 #e4e4e400; + } -/* Apply scrollbar to sidebar content*/ -.board-color-natural .sidebar .sidebar-content { - scrollbar-color: #596557f2 #e4e4e400; -} + /* Apply scrollbar to sidebar content*/ + .board-color-natural .sidebar .sidebar-content { + scrollbar-color: #596557f2 #e4e4e400; + } -/* Remove margins in between columns/fix spacing */ + /* Remove margins in between columns/fix spacing */ -.board-color-natural .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-natural .list { + border-left: none; + } -.board-color-natural .list-body { - margin-top: 8px; -} -/* === END Natural THEME === */ -/* =============== + /* === END Natural THEME === */ + + /* =============== THEME - Modern =================*/ -.board-color-modern#header, -.board-color-modern.sk-spinner div, -.board-backgrounds-list .board-color-modern.background-box, -.board-list .board-color-modern a { - background-color: #2a80b8; -} -.board-color-modern .is-selected .minicard { - border-left: 3px solid #2a80b8; -} -.board-color-modern .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); -} -.board-color-modern button[type=submit].primary, -.board-color-modern input[type=submit].primary, -.board-color-modern .sidebar .sidebar-content .sidebar-btn { - background-color: #226693; - border-radius: 7px; -} -.board-color-modern.pop-over .pop-over-list li a:not(.disabled):hover, -.board-color-modern .sidebar .sidebar-content .sidebar-btn:hover, -.board-color-modern .sidebar-list li a:hover { - background-color: #2f90cf; -} -.board-color-modern#header ul li.current, -.board-color-modern#header-quick-access ul li.current { - border-bottom: 2px solid #2f90cf; -} -.board-color-modern#header-quick-access { - background: #2673a6; - color: #fff; -} -.board-color-modern#header #header-main-bar .board-header-btn.emphasis { - background: #b8622a; -} -.board-color-modern#header #header-main-bar .board-header-btn.emphasis:hover, -.board-color-modern#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { - background: #a65826; -} -.board-color-modern#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { - background: #934e22; -} -.board-color-modern .materialCheckBox.is-checked { - border-bottom: 2px solid #2a80b8; - border-right: 2px solid #2a80b8; -} + .board-color-modern#header, + .board-color-modern.sk-spinner div, + .board-backgrounds-list .board-color-modern.background-box, + .board-list .board-color-modern a { + background-color: #2a80b8; + } + + .board-color-modern .is-selected .minicard { + border-left: 3px solid #2a80b8; + } + + .board-color-modern .minicard { + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); + } + + .board-color-modern button[type=submit].primary, + .board-color-modern input[type=submit].primary, + .board-color-modern .sidebar .sidebar-content .sidebar-btn { + background-color: #226693; + color: #fff; + } + + .board-color-modern { + + button, + input { + border-radius: 0.6ch; + } + } + + .board-color-modern.pop-over .pop-over-list li a:not(.disabled):hover, + .board-color-modern .sidebar .sidebar-content .sidebar-btn:hover, + .board-color-modern .sidebar-list li a:hover { + background-color: #2f90cf; + } + + .board-color-modern#header ul li.current, + .board-color-modern#header-quick-access ul li.current { + border-bottom: 2px solid #2f90cf; + } + + .board-color-modern#header-quick-access { + background: #2673a6; + color: #fff; + } + + .board-color-modern#header #header-main-bar .board-header-btn.emphasis { + background: #b8622a; + } + + .board-color-modern#header #header-main-bar .board-header-btn.emphasis:hover, + .board-color-modern#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { + background: #a65826; + } + + .board-color-modern#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { + background: #934e22; + } + + .board-color-modern .materialCheckBox.is-checked { + border-bottom: 2px solid #2a80b8; + border-right: 2px solid #2a80b8; + } .board-color-modern .checklist-progress-bar { background-color: #d1e7f5 !important; } .board-color-modern .checklist-progress-bar .checklist-progress { background-color: #2a80b8 !important; } -.board-color-modern .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { - background: #e8f3fa; -} -.board-color-modern .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { - background: #f8fbfd; -} -.board-color-modern .toggle-label:after { - background-color: #226693; -} -.board-color-modern .toggle-switch:checked ~ .toggle-label { - background-color: #469cd5; -} -.board-color-modern .toggle-switch:checked ~ .toggle-label:after { - background-color: #226693; -} -@media screen and (max-width: 800px) { - .board-color-modern.pop-over .header { - background: #2a80b8; + + .board-color-modern .is-multiselection-active .multi-selection-checkbox.is-checked+.minicard { + background: #e8f3fa; + } + + .board-color-modern .is-multiselection-active .multi-selection-checkbox:not(.is-checked)+.minicard:hover:not(.minicard-composer) { + background: #f8fbfd; + } + + .board-color-modern .toggle-label:after { + background-color: #226693; + } + + .board-color-modern .toggle-switch:checked~.toggle-label { + background-color: #469cd5; + } + + .board-color-modern .toggle-switch:checked~.toggle-label:after { + background-color: #226693; + } + + @media screen and (max-width: 800px) { + .board-color-modern.pop-over .header { + background: #2a80b8; + color: #fff; + } + } + + .board-color-modern#header ul li.current, + .board-color-modern#header-quick-access ul li.current { + border-bottom: 4px solid #469cd5; + } + + .board-color-modern body { + background: #f5f5f5; + } + + .board-color-modern#header-quick-access { + background: #333 !important; + } + + .board-color-modern#header-quick-access ul { + overflow: visible; + } + + .board-color-modern#header-quick-access ul li.current { + border: 0 !important; + font-weight: bold; + } + + .board-color-modern#header-quick-access ul li.separator { + display: none; + } + + + .board-color-modern#header-quick-access ul li a { + border-radius: 2px; + } + + .board-color-modern#header-quick-access ul li.current a { + border-radius: 2px; + background: rgba(255, 255, 255, 0.2); + } + + .board-color-modern#header #header-main-bar h1 { + /* font-family: Poppins; */ + font-weight: bold; + } + + .board-color-modern section#notifications-drawer { + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + max-width: 100%; + } + + .board-color-modern section#notifications-drawer .header { + border-radius: 0 3px; + background: #f7f7f7; + } + + .board-color-modern.board-wrapper { + background: #f5f5f5; + } + + .board-color-modern .swimlane { + background: none; + } + + .board-color-modern .swimlane .swimlane-header-wrap .swimlane-header { + /* font-family: Poppins; */ + } + + + .board-color-modern .list-body .open-minicard-composer:hover { + background: none; + box-shadow: none; + } + + .board-color-modern .swimlane .list:first-child { + border-left: none; + } + + .board-color-modern .swimlane .list:nth-child { + flex: 0 0 265px; + } + + .board-color-modern .list.list-composer.js-list-composer { + transition: all 0.3s ease; + } + + .board-color-modern .open-list-composer.js-open-inlined-form:hover { + color: #222; + } + + .board-color-modern { + + .list-header, + .list-composer { + background: #f5f5f5f2; + /*Added background colour same colour as base board background, prevents poor text visibility when bgd image applied*/ + } + } + + .board-color-modern .list-header .list-header-name { + /* font-family: Poppins; */ + color: #000; + font-weight: 500; + } + + .board-color-modern .minicard { + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.05); + } + + .board-color-modern .minicard-plum:hover:not(.minicard-composer), + .board-color-modern .is-selected .minicard-plum, + .board-color-modern .draggable-hover-card .minicard-plum { + background: none; + } + + .board-color-modern .minicard-title { + line-height: 1.5em; + } + + .board-color-modern .minicard .minicard-cover { + background-size: cover; + } + + .board-color-modern .card-label-orange { color: #fff; } -} -.board-color-modern#header ul li.current, -.board-color-modern#header-quick-access ul li.current { - border-bottom: 4px solid #469cd5; -} -.board-color-modern body { - background: #f5f5f5; -} -.board-color-modern#header-quick-access { - padding: 10px; - font-size: 14px; - background: #333 !important; -} -.board-color-modern#header-quick-access ul { - overflow: visible; -} -.board-color-modern#header-quick-access ul li.current { - border: 0 !important; - font-weight: bold; -} -.board-color-modern#header-quick-access ul li.separator { - display: none; -} -.board-color-modern#header-quick-access ul li:nth-child(3) { - margin-right: 10px; -} -.board-color-modern#header-quick-access ul li a { - padding: 5px 10px; - border-radius: 2px; -} -.board-color-modern#header-quick-access ul li.current a { - border-radius: 2px; - background: rgba(255,255,255,0.2); -} -.board-color-modern#header #header-main-bar h1 { -/* font-family: Poppins; */ - font-weight: bold; -} -.board-color-modern#header-quick-access #header-user-bar { - position: relative; -} -.board-color-modern#header-quick-access #header-user-bar .header-user-bar-name { - margin: 5px 3px 0 0; -} -.board-color-modern section#notifications-drawer { - top: 46px; - box-shadow: 0 4px 20px rgba(0,0,0,0.1); - max-width: 100%; -} -.board-color-modern section#notifications-drawer .header { - top: 46px; - border-radius: 0 3px; - height: 21px; - background: #f7f7f7; -} -.board-color-modern.board-wrapper { - background: #f5f5f5; -} -.board-color-modern .swimlane { - background: none; -} -.board-color-modern .swimlane .swimlane-header-wrap .swimlane-header { - /* font-family: Poppins; */ -} -.board-color-modern .board-list .board-list-item { - padding: 20px; -} -.board-color-modern .board-list-item-name { - /* font-family: Poppins; */ -} -.board-color-modern .list { - background: transparent; - border-left: 0; - margin: 10px 0; - padding: 0px; - border-radius: 5px; - min-width: 300px; -} -.board-color-modern .list-body .open-minicard-composer:hover { - background: none; - box-shadow: none; -} -.board-color-modern .swimlane .list:first-child { - min-width: 20px; - margin-left: 0px; - border-left: none; -} -.board-color-modern .swimlane .list:nth-child { - flex: 0 0 265px; - } -.board-color-modern .list.list-composer.js-list-composer { - transition: all 0.3s ease; - min-width: 20px; -} -.board-color-modern .open-list-composer.js-open-inlined-form:hover { - color: #222; -} -.board-color-modern .list-header { - background: #f5f5f5f2; /*Added background colour same colour as base board background, prevents poor text visibility when bgd image applied*/ -} -.board-color-modern .list-header .list-header-name { - /* font-family: Poppins; */ - color: #000; - font-weight: 500; -} -.board-color-modern .minicard { - padding: 15px 15px 10px; - box-shadow: 0 3px 8px rgba(0,0,0,0.05); -} -.board-color-modern .minicard-plum:hover:not(.minicard-composer), -.board-color-modern .is-selected .minicard-plum, -.board-color-modern .draggable-hover-card .minicard-plum { - background: none; -} -.board-color-modern .minicard-title { - line-height: 1.5em; -} -.board-color-modern .minicard .minicard-cover { - background-size: cover; - margin: -15px -15px 10px; - height: 100px; -} -.board-color-modern .card-label-orange { - color: #fff; -} -.board-color-modern .card-date { - font-size: 12px; - padding: 3px 5px; -} -.board-color-modern .header-title { - /* font-family: Poppins; */ - font-size: 16px; - color: #333; -} -.board-color-modern .pop-over { - box-shadow: 0 4px 20px rgba(0,0,0,0.2); - border: 0; - border-radius: 5px; -} -.board-color-modern .pop-over .header { - padding: 10px; - border-bottom: 0; - border-radius: 5px 5px 0 0; - background: #eee; -} -.board-color-modern .pop-over .header .header-title { - /* font-family: Poppins; */ - font-size: 16px; - color: #333; -} -.board-color-modern .pop-over .header .close-btn { - font-size: 20px; - top: 6px; - right: 8px; -} -.board-color-modern .pop-over .content-container .content { - padding: 5px 20px 20px; - width: 260px; -} -.board-color-modern .pop-over-list li > a { - border-radius: 5px; -} -.board-color-modern .pop-over-list li > a > i { - margin-right: 5px; -} -.board-color-modern .pop-over-list li>a .sub-name { - margin-bottom: 8px; -} -.board-color-modern .sidebar { - box-shadow: 0 0 60px rgba(0,0,0,0.2); -} -.board-color-modern .board-color-modern section#notifications-drawer { - border-radius: 5px; -} -.board-color-modern .board-color-modern section#notifications-drawer .header { - padding: 18px 16px; - border-bottom: 0; - border-radius: 5px 5px 0 0; - background: #eee; -} -.board-color-modern .board-color-modern section#notifications-drawer .header h5 { - /* font-family: Poppins; */ - font-weight: bold; -} -.board-color-modern .board-color-modern section#notifications-drawer .header .close { - font-size: 20px; - top: 14px; -} -.board-color-modern section#notifications-drawer .header .toggle-read { - top: 18px; -} -/* Transparent modern scrollbar - modern*/ -.board-color-modern .board-canvas { - scrollbar-color: #333333f2 #e4e4e400; -} + .board-color-modern .header-title { + /* font-family: Poppins; */ + color: #333; + } + + .board-color-modern .pop-over { + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2); + border: 0; + border-radius: 5px; + } + + .board-color-modern .pop-over .header { + border-bottom: 0; + border-radius: 5px 5px 0 0; + background: #eee; + } + + .board-color-modern .pop-over .header .header-title { + /* font-family: Poppins; */ + color: #333; + } -/* Apply scrollbar to sidebar content*/ -.board-color-modern .sidebar .sidebar-content { - scrollbar-color: #333333f2 #e4e4e400; -} + .board-color-modern .pop-over-list li>a { + border-radius: 5px; + padding: 0.3lh 0; + } -/* Remove margins in between columns/fix spacing */ -.board-color-modern .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-modern .sidebar { + box-shadow: 0 0 60px rgba(0, 0, 0, 0.2); + } -.board-color-modern .list-body { - margin-top: 8px; -} + .board-color-modern .board-color-modern section#notifications-drawer { + border-radius: 5px; + } -/* === END Modern THEME === */ + .board-color-modern .board-color-modern section#notifications-drawer .header { + border-bottom: 0; + border-radius: 5px 5px 0 0; + background: #eee; + } -/* =============== + .board-color-modern .board-color-modern section#notifications-drawer .header h5 { + /* font-family: Poppins; */ + font-weight: bold; + } + + + /* Transparent modern scrollbar - modern*/ + .board-color-modern .board-canvas { + scrollbar-color: #333333f2 #e4e4e400; + } + + + /* Apply scrollbar to sidebar content*/ + .board-color-modern .sidebar .sidebar-content { + scrollbar-color: #333333f2 #e4e4e400; + } + + /* === END Modern THEME === */ + + /* =============== THEME - Modern Dark =================*/ -.board-color-moderndark#header, -.board-color-moderndark.sk-spinner div, -.board-backgrounds-list .board-color-moderndark.background-box, -.board-list .board-color-moderndark a { - background-color: #2a2a2a; -} -.board-color-moderndark .is-selected .minicard { - border-left: 3px solid #2a2a2a; -} -.board-color-moderndark .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); -} -.board-color-moderndark button[type=submit].primary, -.board-color-moderndark input[type=submit].primary, -.board-color-moderndark .sidebar .sidebar-content .sidebar-btn { - background-color: #222; - border-radius: 7px; -} -.board-color-moderndark.pop-over .pop-over-list li a:not(.disabled):hover, -.board-color-moderndark .sidebar .sidebar-content .sidebar-btn:hover, -.board-color-moderndark .sidebar-list li a:hover { - background-color: #3f3f3f; -} -.board-color-moderndark#header ul li.current, -.board-color-moderndark#header-quick-access ul li.current { - border-bottom: 2px solid #3f3f3f; -} -.board-color-moderndark#header-quick-access { - background: #262626; - color: #fff; -} -@media screen and (min-width: 801px) { - .board-color-moderndark .js-toggle-desktop-drag-handles { - padding-top: 6px + .board-color-moderndark#header, + .board-color-moderndark.sk-spinner div, + .board-backgrounds-list .board-color-moderndark.background-box, + .board-list .board-color-moderndark a { + background-color: #2a2a2a; + } + + .board-color-moderndark .is-selected .minicard { + border-left: 3px solid #2a2a2a; + } + + .board-color-moderndark .minicard { + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); + } + + .board-color-moderndark button[type=submit].primary, + .board-color-moderndark input[type=submit].primary, + .board-color-moderndark .sidebar .sidebar-content .sidebar-btn { + background-color: #222; + border-radius: 0.6ch; + } + + .board-color-moderndark.pop-over .pop-over-list li a:not(.disabled):hover, + .board-color-moderndark .sidebar .sidebar-content .sidebar-btn:hover, + .board-color-moderndark .sidebar-list li a:hover { + background-color: #3f3f3f; + } + + .board-color-moderndark#header ul li.current, + .board-color-moderndark#header-quick-access ul li.current { + border-bottom: 2px solid #3f3f3f; + } + + .board-color-moderndark#header-quick-access { + background: #262626; + color: #fff; + } + + .board-color-moderndark#header #header-main-bar .board-header-btn.emphasis { + background: #2a2a2a; + } + + .board-color-moderndark#header #header-main-bar .board-header-btn.emphasis:hover, + .board-color-moderndark#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { + background: #262626; + } + + .board-color-moderndark#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { + background: #222; + } + + .board-color-moderndark .materialCheckBox.is-checked { + border-bottom: 2px solid #2a2a2a; + border-right: 2px solid #2a2a2a; } -} -.board-color-moderndark#header #header-main-bar .board-header-btn.emphasis { - background: #2a2a2a; -} -.board-color-moderndark#header #header-main-bar .board-header-btn.emphasis:hover, -.board-color-moderndark#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { - background: #262626; -} -.board-color-moderndark#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { - background: #222; -} -.board-color-moderndark .materialCheckBox.is-checked { - border-bottom: 2px solid #2a2a2a; - border-right: 2px solid #2a2a2a; -} .board-color-moderndark .checklist-progress-bar { background-color: #d1d1d1 !important; } .board-color-moderndark .checklist-progress-bar .checklist-progress { background-color: #2a2a2a !important; } -.board-color-moderndark .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { - background: #eaeaea; -} -.board-color-moderndark .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { - background: #f9f9f9; -} -.board-color-moderndark .toggle-label:after { - background-color: #222; -} -.board-color-moderndark .toggle-switch:checked ~ .toggle-label { - background-color: #555; -} -.board-color-moderndark .toggle-switch:checked ~ .toggle-label:after { - background-color: #222; -} -@media screen and (max-width: 800px) { - .board-color-moderndark.pop-over .header { + + .board-color-moderndark .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { + background: #eaeaea; + } + + .board-color-moderndark .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + background: #f9f9f9; + } + + .board-color-moderndark .toggle-label:after { + background-color: #222; + } + + .board-color-moderndark .toggle-switch:checked ~ .toggle-label { + background-color: #555; + } + + .board-color-moderndark .toggle-switch:checked ~ .toggle-label:after { + background-color: #222; + } + + @media screen and (max-width: 800px) { + .board-color-moderndark.pop-over .header { + background: #2a2a2a; + color: #fff; + } + + #header.board-color-moderndark #header-main-bar .board-header-btn i.fa {} + } + + .board-color-moderndark#header ul li.current, + .board-color-moderndark#header-quick-access ul li.current { + border-bottom: 4px solid #555; + } + + .board-color-moderndark body { background: #2a2a2a; - color: #fff; } - #header.board-color-moderndark #header-main-bar .board-header-btn i.fa { - margin: 0 8px; + + .board-color-moderndark button[type=submit].primary, + .board-color-moderndark .board-color-modern input[type=submit].primary { + background-color: #777; + border-radius: 0.6ch; } -} -.board-color-moderndark#header ul li.current, -.board-color-moderndark#header-quick-access ul li.current { - border-bottom: 4px solid #555; -} -.board-color-moderndark body { - background: #2a2a2a; -} -.board-color-moderndark .board-wrapper .board-canvas .board-overlay { - opacity: 0.6; -} -.board-color-moderndark button[type=submit].primary, -.board-color-moderndark .board-color-modern input[type=submit].primary { - background-color: #777; - border-radius: 7px; -} -.board-color-moderndark .toggle-switch:checked~.toggle-label { - background-color: #f7f7f7; -} -.board-color-moderndark .toggle-label:after, -.board-color-moderndark .board-color-modern .toggle-switch:checked~.toggle-label:after { - background-color: #777 !important; -} -.board-color-moderndark button, -.board-color-moderndark input:not([type=file]), -.board-color-moderndark select, -.board-color-moderndark textarea { - border-radius: 7px; -} -.board-color-moderndark#header { - background-color: #262626; - border-bottom: 1px solid #555; - border-top: 1px solid #555; -} -.board-color-moderndark#header-quick-access, -.board-color-moderndark .background-box, -.board-color-moderndark #header { - background-color: #333; -} -.board-color-moderndark#header-quick-access { - padding: 4px; - font-size: 14px; -} -@media screen and (max-width: 800px) { - .board-color-moderndark#header-quick-access { - padding: 0; + + .board-color-moderndark .toggle-switch:checked~.toggle-label { + background-color: #f7f7f7; } -} -.board-color-moderndark#header-quick-access .allBoards { - padding: 5px 10px 0 10px; -} -.board-color-moderndark#header-quick-access ul.header-quick-access-list { - margin: -5px 0 -5px 0; -} -.board-color-moderndark#header #header-main-bar { - padding-top: 3px; - padding-bottom: 3px; -} -.board-color-moderndark#header-quick-access ul { - overflow: visible; -} -.board-color-moderndark#header-quick-access ul li.current { - border: 0 !important; - font-weight: bold; -} -.board-color-moderndark#header-quick-access ul li.separator { - display: none; -} -.board-color-moderndark#header-quick-access ul li:nth-child(3) { - margin-right: 10px; -} -.board-color-moderndark#header-quick-access ul li a { - padding: 5px 10px; - border-radius: 2px; -} -.board-color-moderndark#header-quick-access ul li.current a { - border-radius: 2px; - background: rgba(255,255,255,0.2); -} -.board-color-moderndark#header #header-main-bar h1 { - font-weight: bold; - line-height: 0.8em; - padding-top: 10px; -} -.board-color-moderndark.board-wrapper { - background: #2a2a2a; -} -.board-color-moderndark .swimlane .swimlane-header-wrap { - background-color: #494949; - color: #ccc; - padding: 4px 0; -} -.board-color-moderndark .swimlane .swimlane-header-wrap .swimlane-header-menu { - padding: 6px; - font-size: 16px; -} -.board-color-moderndark .swimlane .swimlane-header-wrap .swimlane-header-plus-icon { - font-size: 16px; -} -.board-color-moderndark .swimlane { - background: #2a2a2a; - line-height: 18px; - max-height: 100%; -} -.board-color-moderndark .swimlane .list { - background: #666; - border-radius: 0; - border: 0px solid #666; -} -.board-color-moderndark .swimlane .list:first-child { - color: #eee; - min-width: 20px; - margin-left: 0px; - border-left: none; -} -.board-color-moderndark .swimlane .list-composer .list-header-add .inlined-form .edit-controls .quiet, -.board-color-moderndark .swimlane .list-composer .list-header-add .inlined-form .edit-controls .quiet a.js-list-template { - color: #eee; -} -.board-color-moderndark .swimlane .list:nth-child { - flex: 0 0 265px; -} -.board-color-moderndark .swimlane .list:nth-child(even) .list-header, -.board-color-moderndark .swimlane .list:nth-child(even) .list-body { - background: #6a6a6a; -} -.board-color-moderndark .swimlane .list:nth-child(odd) .list-header, -.board-color-moderndark .swimlane .list:nth-child(odd) .list-body { - background: #555; -} -.board-color-moderndark .list-header { - background: #6a6a6a; -} -.board-color-moderndark .list-header .viewer { - padding-left: 10px; -} -.board-color-moderndark .list-header .list-header-name, -.board-color-moderndark .minicard { - line-height: 14px; - color: #eee; -} -@media screen and (max-width: 800px) { - .board-color-moderndark .list-header .list-header-name { - line-height: unset; - padding-top: 10px; + + .board-color-moderndark .toggle-label:after, + .board-color-moderndark .board-color-modern .toggle-switch:checked~.toggle-label:after { + background-color: #777 !important; } - .board-color-moderndark .list-header-black, .board-color-moderndark .mini-list { + + .board-color-moderndark button, + .board-color-moderndark input:not([type=file]), + .board-color-moderndark select, + .board-color-moderndark textarea { + border-radius: 0.6ch; + } + + .board-color-moderndark#header { + background-color: #262626; + border-bottom: 1px solid #555; + border-top: 1px solid #555; + } + + .board-color-moderndark#header-quick-access, + .board-color-moderndark .background-box, + .board-color-moderndark #header { + background-color: #333; + } + + + @media screen and (max-width: 800px) { + .board-color-moderndark#header-quick-access { + padding: 0; + } + } + + + .board-color-moderndark#header-quick-access ul { + overflow: visible; + } + + .board-color-moderndark#header-quick-access ul li.current { + border: 0 !important; + font-weight: bold; + } + + .board-color-moderndark#header-quick-access ul li.separator { + display: none; + } + + + .board-color-moderndark#header-quick-access ul li a { + border-radius: 2px; + } + + .board-color-moderndark#header-quick-access ul li.current a { + border-radius: 2px; + background: rgba(255, 255, 255, 0.2); + } + + .board-color-moderndark#header #header-main-bar h1 { + font-weight: bold; + line-height: 0.8em; + } + + .board-color-moderndark.board-wrapper { + background: #2a2a2a; + } + + .board-color-moderndark .swimlane .swimlane-header-wrap { + background-color: #494949; + color: #ccc; + } + + + .board-color-moderndark .swimlane { + background: #2a2a2a; + max-height: 100%; + } + + .board-color-moderndark .swimlane .list { + background: #666; + border-radius: 0; + border: 0px solid #666; + } + + .board-color-moderndark .swimlane .list:first-child { + color: #eee; + border-left: none; + } + + .board-color-moderndark .swimlane .list-composer .list-header-add .inlined-form .edit-controls .quiet, + .board-color-moderndark .swimlane .list-composer .list-header-add .inlined-form .edit-controls .quiet a.js-list-template { + color: #eee; + } + + .board-color-moderndark .swimlane .list:nth-child { + flex: 0 0 265px; + } + + .board-color-moderndark .swimlane .list:nth-child(even) .list-header, + .board-color-moderndark .swimlane .list:nth-child(even) .list-body { + background: #6a6a6a; + } + + .board-color-moderndark .swimlane .list:nth-child(odd) .list-header, + .board-color-moderndark .swimlane .list:nth-child(odd) .list-body { + background: #555; + } + + .board-color-moderndark .list-header { + background: #6a6a6a; + } + + + .board-color-moderndark .list-header .list-header-name, + .board-color-moderndark .minicard { + color: #eee; + } + + @media screen and (max-width: 800px) { + .board-color-moderndark .list-header .list-header-name { + line-height: unset; + } + + .board-color-moderndark .list-header-black, .board-color-moderndark .mini-list { + border-bottom: 0; + } + } + + .board-color-moderndark .list-header .list-header-plus-top { + color: #a6a6a6; + } + + .board-color-moderndark .list-body { + scrollbar-width: thin; + scrollbar-color: #343434 #999; + } + + + .board-color-moderndark .list-body::-webkit-scrollbar-track { + background: #343434; + border-radius: 3px; + } + + .board-color-moderndark .list-body::-webkit-scrollbar-thumb { + background-color: #999; + border-radius: 6px; + border: 3px solid #343434; + } + + .board-color-moderndark .list-body .open-minicard-composer:hover { + background: none; + box-shadow: none; border-bottom: 0; } -} -@media screen and (min-width: 801px) { - .board-color-moderndark .list-header .list-header-name { - float: left; + + .board-color-moderndark .list-body a.open-minicard-composer, + .board-color-moderndark .list-body a.open-minicard-composer i, + .board-color-moderndark .list .list-composer .open-list-composer i { + color: #bbb; } - .board-color-moderndark .list-header .list-header-menu { - padding: 0 10px 10px; + + .board-color-moderndark .swimlane .list:first-child .open-list-composer:hover i, + .board-color-moderndark .list-body a.open-minicard-composer:hover, + .board-color-moderndark .list-body a.open-minicard-composer:hover i, + .board-color-moderndark .list .list-composer .open-list-composer:hover i { + color: #fff; + border-radius: 0.6ch; } -} -.board-color-moderndark .list-header .list-header-menu { - top: 0; -} -.board-color-moderndark .list-header .list-header-plus-top { - color: #a6a6a6; -} -.board-color-moderndark .list-body { - scrollbar-width: thin; - scrollbar-color: #343434 #999; -} -.board-color-moderndark .list-body::-webkit-scrollbar { - width: 10px; -} -.board-color-moderndark .list-body::-webkit-scrollbar-track { - background: #343434; - border-radius: 3px; - margin: 4px 0; -} -.board-color-moderndark .list-body::-webkit-scrollbar-thumb { - background-color: #999; - border-radius: 6px; - border: 3px solid #343434; -} -.board-color-moderndark .list-body .open-minicard-composer:hover { - background: none; - box-shadow: none; - border-bottom: 0; -} -.board-color-moderndark .list-body a.open-minicard-composer, -.board-color-moderndark .list-body a.open-minicard-composer i, -.board-color-moderndark .list .list-composer .open-list-composer i { - color: #bbb; -} -.board-color-moderndark .swimlane .list:first-child .open-list-composer:hover i, -.board-color-moderndark .list-body a.open-minicard-composer:hover, -.board-color-moderndark .list-body a.open-minicard-composer:hover i, -.board-color-moderndark .list .list-composer .open-list-composer:hover i { - color: #fff; - border-radius: 7px; -} -.board-color-moderndark .minicard-wrapper { - margin-bottom: 12px; -} -.board-color-moderndark .minicard { - background-color: #444; - color: #ccc; - border-radius: 2px; - font-size: 0.95em; - box-shadow: 0 4px 3px -3px rgba(0,0,0,0.8); - border-bottom: 1px solid #666; - padding: 8px; -} -.board-color-moderndark .minicard:hover { - color: #f7f7f7; - background-color: #4d4d4d !important; -} -.board-color-moderndark .minicard .minicard-labels { - margin: 8px 0 4px; -} -.board-color-moderndark .minicard .card-label { - font-size: 11px; - font-weight: 400; - padding: 1px 6px 0; - border-radius: 2px; - line-height: 18px; -} -.board-color-moderndark .minicard .badges { - color: #bbb; -} -.board-color-moderndark .minicard .date { - margin-bottom: 10px; - font-size: 11px; -} -.board-color-moderndark .card-date { - color: #444; - border-radius: 2px; -} -.board-color-moderndark .card-date.almost-due { - color: #444; -} -.board-color-moderndark .minicard.minicard-composer textarea.minicard-composer-textarea:focus { - background-color: #eee; - color: #333; - padding: 6px; -} -.board-color-moderndark .is-selected .minicard { - background-color: #666; -} -.board-color-moderndark .card-details { - background-color: #454545; - color: #ccc; - box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19); - border: 1px solid #111; - z-index: 100 !important; -} -@media screen and (max-width: 800px) { + + + .board-color-moderndark .minicard { + background-color: #444; + color: #ccc; + border-radius: 2px; + box-shadow: 0 4px 3px -3px rgba(0, 0, 0, 0.8); + border-bottom: 1px solid #666; + } + + .board-color-moderndark .minicard:hover { + color: #f7f7f7; + background-color: #4d4d4d !important; + } + + + .board-color-moderndark .minicard .card-label { + + font-weight: 400; + border-radius: 2px; + } + + .board-color-moderndark .minicard .badges { + color: #bbb; + } + + + .board-color-moderndark .card-date { + color: #444; + border-radius: 2px; + } + + .board-color-moderndark .card-date.almost-due { + color: #444; + } + + .board-color-moderndark .minicard.minicard-composer textarea.minicard-composer-textarea:focus { + background-color: #eee; + color: #333; + } + + .board-color-moderndark .is-selected .minicard { + background-color: #666; + } + .board-color-moderndark .card-details { - width: 94%; + background-color: #454545; + color: #ccc; + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); + border: 1px solid #111; + z-index: 100 !important; } - .board-color-moderndark .card-details-popup { - padding: 0; - } - .board-color-moderndark .card-details-left, .board-color-moderndark .card-details-right { - padding: 0px 20px; - } - .board-color-moderndark .card-details .card-details-header .card-details-menu-mobile-web { - margin-right: 0; - } - .board-color-moderndark .pop-over > .content-wrapper > .popup-container-depth-0 > .content { - width: calc(100% - 20px); - } -} -@media screen and (min-width: 801px) { + .board-color-moderndark .card-details { - position: fixed; - top: 82px; - left: calc(50% - 384px); - width: 768px; - max-height: calc(100% - 60px); + scrollbar-width: thin; + scrollbar-color: #343434 #999; } -} -.board-color-moderndark .card-details { - scrollbar-width: thin; - scrollbar-color: #343434 #999; -} -.board-color-moderndark .card-details::-webkit-scrollbar { - width: 16px; -} -.board-color-moderndark .card-details::-webkit-scrollbar-track { - background: #343434; -} -.board-color-moderndark .card-details::-webkit-scrollbar-thumb { - background-color: #999; - border-radius: 6px; - border: 4px solid #343434; -} -.board-color-moderndark .card-details .card-details-header { - background: #333; - color: #ccc; - border-bottom: 2px solid #2d2d2d; -} -.board-color-moderndark .card-details hr { - background: #2d2d2d; -} -.board-color-moderndark .card-details .card-details-item-title { - color: #fff; -} -.board-color-moderndark .card-details .new-description textarea, -.board-color-moderndark .card-details .new-comment textarea { - background-color: #ddd; - color: #111; -} -.board-color-moderndark .card-details .checklist { - background-color: transparent; - margin-bottom: 10px; -} -.board-color-moderndark .card-details .checklist-item { - background-color: rgba(255,255,255,0.1); - padding: 4px 8px; - border-radius: 2px; - font-size: 13px; - margin-top: 5px; -} -.board-color-moderndark .card-details .checklist-item:hover { - background-color: rgba(255,255,255,0.2); -} -.board-color-moderndark .card-details .checklist-item .item-title .viewer p { - max-width: auto; -} -.board-color-moderndark .card-details .check-box.materialCheckBox { - border-color: #fff; -} -.board-color-moderndark .card-details .check-box.materialCheckBox.is-checked { - border-bottom: 2px solid #fff; - border-right: 2px solid #fff; - border-top: 0; - border-left: 0; -} -.board-color-moderndark .card-details .js-add-checklist-item { - margin-top: 4px; -} -.board-color-moderndark .checklist-items .add-checklist-item { - margin-top: 0.7em; -} -.board-color-moderndark .card-details .activities .activity .activity-desc .activity-comment { - background-color: #ccc; - color: #222; -} -.board-color-moderndark .sidebar { - background-color: #222; - box-shadow: -10px 0 5px -10px #444; - border-left: 1px solid #333; - color: #ccc; -} -.board-color-moderndark .activities .activity .activity-desc .activity-comment { - background-color: #ccc; - color: #222; -} -.board-color-moderndark .activities .activity .activity-desc .activity-checklist { - background-color: #ccc; - color: #222; -} -.board-color-moderndark .attachments-gallery .attachment-item { - color: #222; -} -.board-color-moderndark .minicard-description { - color: #222; -} -.pop-over.board-color-moderndark { - background-color: #454545; - color: #ccc; - border: 1px solid #111; - box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19); -} -.pop-over.board-color-moderndark .header { - background-color: #333; -} -.pop-over.board-color-moderndark .header-title { - /* font-family: Poppins; */ - font-size: 16px; - color: #ccc; -} -.pop-over.board-color-moderndark .pop-over-list li > a:hover { - background-color: rgba(255,255,255,0.2); -} - -/* Transparent moderndark scrollbar - moderndark*/ -.board-color-moderndark .board-canvas { - scrollbar-width: thin; - scrollbar-color: #343434f2 #999999f2; -} -/* Apply scrollbar to sidebar content*/ -.board-color-moderndark .sidebar .sidebar-content { - scrollbar-width: thin; - scrollbar-color: #343434f2 #999999f2; -} + .board-color-moderndark .card-details::-webkit-scrollbar-track { + background: #343434; + } -/* Remove margins in between columns/fix spacing */ + .board-color-moderndark .card-details::-webkit-scrollbar-thumb { + background-color: #999; + border-radius: 6px; + border: 4px solid #343434; + } -.board-color-moderndark .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-moderndark .card-details .card-details-header { + background: #333; + color: #ccc; + border-bottom: 2px solid #2d2d2d; + } -.board-color-moderndark .list-body { - margin-top: 8px; -} + .board-color-moderndark .card-details hr { + background: #2d2d2d; + } -/* === END ModernDark THEME === */ + .board-color-moderndark .card-details .card-details-item-title { + color: #fff; + } + + .board-color-moderndark .card-details .new-description textarea, + .board-color-moderndark .card-details .new-comment textarea { + background-color: #ddd; + color: #111; + } + + .board-color-moderndark .card-details .checklist { + background-color: transparent; + } + + .board-color-moderndark .card-details .checklist-item { + background-color: rgba(255, 255, 255, 0.1); + border-radius: 2px; + + } + + .board-color-moderndark .card-details .checklist-item:hover { + background-color: rgba(255, 255, 255, 0.2); + } + + .board-color-moderndark .card-details .checklist-item .item-title .viewer p { + max-width: auto; + } + + .board-color-moderndark .card-details .check-box.materialCheckBox { + border-color: #fff; + } + + .board-color-moderndark .card-details .check-box.materialCheckBox.is-checked { + border-bottom: 2px solid #fff; + border-right: 2px solid #fff; + border-top: 0; + border-left: 0; + } + + .board-color-moderndark .card-details .activities .activity .activity-desc .activity-comment { + background-color: #ccc; + color: #222; + } + + .board-color-moderndark .sidebar { + background-color: #222; + box-shadow: -10px 0 5px -10px #444; + border-left: 1px solid #333; + color: #ccc; + } + + .board-color-moderndark .activities .activity .activity-desc .activity-comment { + background-color: #ccc; + color: #222; + } + + .board-color-moderndark .activities .activity .activity-desc .activity-checklist { + background-color: #ccc; + color: #222; + } + + .board-color-moderndark .attachments-gallery .attachment-item { + color: #222; + } + + .board-color-moderndark .minicard-description { + color: #222; + } + + .pop-over.board-color-moderndark { + background-color: #454545; + color: #ccc; + border: 1px solid #111; + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); + } + + .pop-over.board-color-moderndark .header { + background-color: #333; + } + + .pop-over.board-color-moderndark .header-title { + /* font-family: Poppins; */ + + color: #ccc; + } + + .pop-over.board-color-moderndark .pop-over-list li > a:hover { + background-color: rgba(255, 255, 255, 0.2); + } + + /* Transparent moderndark scrollbar - moderndark*/ + .board-color-moderndark .board-canvas { + scrollbar-width: thin; + scrollbar-color: #343434f2 #999999f2; + } -/* =============== + /* Apply scrollbar to sidebar content*/ + .board-color-moderndark .sidebar .sidebar-content { + scrollbar-width: thin; + scrollbar-color: #343434f2 #999999f2; + } + + /* Remove margins in between columns/fix spacing */ + + .board-color-moderndark .list { + border-left: none; + } + + + + /* === END ModernDark THEME === */ + + + /* =============== THEME - Exodark =================*/ -.board-color-exodark#header, -.board-color-exodark.sk-spinner div, -.board-backgrounds-list .board-color-exodark.background-box, -.board-list .board-color-exodark a { - background-color: #222; -} -.board-color-exodark .is-selected .minicard { - border-left: 3px solid #222; -} -.board-color-exodark .minicard { - border-radius: 7px; - padding: 10px 10px 4px 10px; - box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15); -} -.board-color-exodark button[type=submit].primary, -.board-color-exodark input[type=submit].primary, -.board-color-exodark .sidebar .sidebar-content .sidebar-btn { - background-color: #1b1b1b; - border-radius: 7px; -} -.board-color-exodark.pop-over .pop-over-list li a:not(.disabled):hover, -.board-color-exodark .sidebar .sidebar-content .sidebar-btn:hover, -.board-color-exodark .sidebar-list li a:hover { - background-color: #383838; -} -.board-color-exodark#header ul li.current, -.board-color-exodark#header-quick-access ul li.current { - border-bottom: 2px solid #383838; -} -.board-color-exodark#header-quick-access { - background: #1f1f1f; - color: #fff; -} -.board-color-exodark#header #header-main-bar .board-header-btn.emphasis { - background: #222; -} -.board-color-exodark#header #header-main-bar .board-header-btn.emphasis:hover, -.board-color-exodark#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { - background: #1f1f1f; -} -.board-color-exodark#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { - background: #1b1b1b; -} -.board-color-exodark .materialCheckBox.is-checked { - border-bottom: 2px solid #dbdbdb!important;/*Fix contrast of checkbox*/ - border-right: 2px solid #dbdbdb!important; -} + .board-color-exodark#header, + .board-color-exodark.sk-spinner div, + .board-backgrounds-list .board-color-exodark.background-box, + .board-list .board-color-exodark a { + background-color: #222; + } + + .board-color-exodark .is-selected .minicard { + border-left: 3px solid #222; + } + + .board-color-exodark .minicard { + border-radius: 0.6ch; + box-shadow: 2px 2px 4px 0px rgba(0, 0, 0, 0.15); + } + + .board-color-exodark button[type=submit].primary, + .board-color-exodark input[type=submit].primary, + .board-color-exodark .sidebar .sidebar-content .sidebar-btn { + background-color: #1b1b1b; + border-radius: 0.6ch; + } + + .board-color-exodark.pop-over .pop-over-list li a:not(.disabled):hover, + .board-color-exodark .sidebar .sidebar-content .sidebar-btn:hover, + .board-color-exodark .sidebar-list li a:hover { + background-color: #383838; + } + + .board-color-exodark#header ul li.current, + .board-color-exodark#header-quick-access ul li.current { + border-bottom: 2px solid #383838; + } + + .board-color-exodark#header-quick-access { + background: #1f1f1f; + color: #fff; + } + + .board-color-exodark#header #header-main-bar .board-header-btn.emphasis { + background: #222; + } + + .board-color-exodark#header #header-main-bar .board-header-btn.emphasis:hover, + .board-color-exodark#header #header-main-bar .board-header-btn.emphasis .board-header-btn-close { + background: #1f1f1f; + } + + .board-color-exodark#header #header-main-bar .board-header-btn.emphasis:hover .board-header-btn-close { + background: #1b1b1b; + } + + .board-color-exodark .materialCheckBox.is-checked { + border-bottom: 2px solid #dbdbdb !important; + /*Fix contrast of checkbox*/ + border-right: 2px solid #dbdbdb !important; + } .board-color-exodark .checklist-progress-bar { background-color: #cccccc !important; } .board-color-exodark .checklist-progress-bar .checklist-progress { background-color: #222 !important; } -.board-color-exodark .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { - background: #e9e9e9; -} -.board-color-exodark .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { - background: #f8f8f8; -} -.board-color-exodark .toggle-label:after { - background-color: #1b1b1b; -} -.board-color-exodark .toggle-switch:checked ~ .toggle-label { - background-color: #4e4e4e; -} -.board-color-exodark .toggle-switch:checked ~ .toggle-label:after { - background-color: #1b1b1b; -} -@media screen and (max-width: 800px) { - .board-color-exodark.pop-over .header { - background: #222; - color: #fff; + + .board-color-exodark .is-multiselection-active .multi-selection-checkbox.is-checked + .minicard { + background: #e9e9e9; } -} -.board-color-exodark#header ul li.current, -.board-color-exodark#header-quick-access ul li.current { - border-bottom: 4px solid #4e4e4e; -} -.board-color-exodark body { - background: #222; -} -/* Uncomment to fix change color selected checkmark not visible + + .board-color-exodark .is-multiselection-active .multi-selection-checkbox:not(.is-checked) + .minicard:hover:not(.minicard-composer) { + background: #f8f8f8; + } + + .board-color-exodark .toggle-label:after { + background-color: #1b1b1b; + } + + .board-color-exodark .toggle-switch:checked ~ .toggle-label { + background-color: #4e4e4e; + } + + .board-color-exodark .toggle-switch:checked ~ .toggle-label:after { + background-color: #1b1b1b; + } + + @media screen and (max-width: 800px) { + .board-color-exodark.pop-over .header { + background: #222; + color: #fff; + } + } + + .board-color-exodark#header ul li.current, + .board-color-exodark#header-quick-access ul li.current { + border-bottom: 4px solid #4e4e4e; + } + + .board-color-exodark body { + background: #222; + } + + /* Uncomment to fix change color selected checkmark not visible .board-color-exodark i { color: #fff !important; } */ -.board-color-exodark.board-wrapper { - background: #222; - /* font-family: Poppins; */ -} -.board-color-exodark .swimlane { - background: #222; -} -.board-color-exodark .list { - margin: 10px 0; - color: #fff; - border-radius: 15px; - background-color: #1c1c1c; - border: none; -} -.board-color-exodark .swimlane .list:first-child { - min-width: 20px; - margin-left: 10px; /*Added 10px margin to prevent butting up against edge of screen */ - border-left: none; -} -.board-color-exodark .swimlane .list:nth-child { - flex: 0 0 265px; -} -.board-color-exodark .list.list-composer.js-list-composer { - transition: all 0.3s ease; - min-width: 0; -} -.board-color-exodark .list-header { - border-top-right-radius: 15px; - border-top-left-radius: 15px; - background: #222; - box-shadow: inset 15px 15px 37px #1c1c1c, inset -15px -15px 37px #282828; -} -.board-color-exodark .list-header-menu a { - color: #00897b !important; -} -.board-color-exodark .is-selected .minicard { - color: #fff; - background: #2b2b2b; - border: 1px solid #00897b; -} -.board-color-exodark .minicard { - color: #fff; - background: #2b2b2b; -} -.board-color-exodark .list-body .open-minicard-composer:hover { - background: #2b2b2b; - border: 1px solid #00897b; - border-radius: 10px; -} -.board-color-exodark .badges { - color: #fff; -} -.board-color-exodark .minicard textarea { - color: #fff; -} -.board-color-exodark .minicard .minicard-description { - background: #2b2b2b; - border: 1px solid #00897b; -} -.board-color-exodark .minicard:hover:not(.minicard-composer) { - border: 1px solid #00897b; - background: #2b2b2b; - padding: 9px 9px 3px 9px; /*because of the 1px border we need to reduce padding by 1px*/ -} -.board-color-exodark .card-details { - background: #2b2b2b !important; - color: #fff; -} -.board-color-exodark .card-details .comment-text { - color:#2b2b2b -} /*Fixes issue with comment text colour blending into background*/ -.board-color-exodark .card-details .card-details-header { - background: #2b2b2b; - color: #fff; -} -.board-color-exodark .sidebar-content { - background: #2b2b2b; - color: #fff; -} -.board-color-exodark .card-details, -.board-color-exodark .sidebar-content { - box-shadow: 0 0 7px 0 #00897b; -} -.board-color-exodark .attachments-gallery .attachment-item { - background: #2b2b2b; -} -.board-color-exodark .attachments-gallery .attachment-item:hover { - border: 1px solid #00897b; - background: #2b2b2b; -} -.board-color-exodark .checklist { - background: #2b2b2b; -} -.board-color-exodark .checklist .checklist-item { - background: #2b2b2b; -} -.board-color-exodark .checklist .checklist-item:hover { - background: #2b2b2b; -} -.board-color-exodark .add-checklist-item.js-open-inlined-form:hover { - background: #2b2b2b; - border: 1px solid #00897b; -} -.board-color-exodark .add-checklist.js-open-inlined-form:hover { - background: #2b2b2b; - border: 1px solid #00897b; -} -.board-color-exodark .card-details > h1, -.board-color-exodark h2, -.board-color-exodark h3, -.board-color-exodark h4, -.board-color-exodark h5, -.board-color-exodark h6, -/* Below added .card-details > to p/a/span to fix white swimlane text not visible + .board-color-exodark.board-wrapper { + background: #222; + /* font-family: Poppins; */ + } + + .board-color-exodark .swimlane { + background: #222; + } + + .board-color-exodark .list { + color: #fff; + border-radius: 15px; + background-color: #1c1c1c; + border: none; + } + + .board-color-exodark .swimlane .list:first-child { + border-left: none; + } + + + .board-color-exodark .list.list-composer.js-list-composer { + transition: all 0.3s ease; + min-width: 0; + } + + .board-color-exodark .list-header { + border-top-right-radius: 15px; + border-top-left-radius: 15px; + background: #222; + box-shadow: inset 15px 15px 37px #1c1c1c, inset -15px -15px 37px #282828; + } + + .board-color-exodark .list-header-menu a { + color: #00897b !important; + } + + .board-color-exodark .is-selected .minicard { + color: #fff; + background: #2b2b2b; + border: 1px solid #00897b; + } + + .board-color-exodark .minicard { + color: #fff; + background: #2b2b2b; + } + + .board-color-exodark .list-body .open-minicard-composer:hover { + background: #2b2b2b; + border: 1px solid #00897b; + border-radius: 10px; + } + + .board-color-exodark .badges { + color: #fff; + } + + .board-color-exodark .minicard textarea { + color: #fff; + } + + .board-color-exodark .minicard .minicard-description { + background: #2b2b2b; + border: 1px solid #00897b; + } + + .board-color-exodark .minicard:hover:not(.minicard-composer) { + border: 1px solid #00897b; + background: #2b2b2b; + } + + .board-color-exodark .card-details { + background: #2b2b2b !important; + color: #fff; + } + + .board-color-exodark .card-details .comment-text { + color:#2b2b2b + } + + /*Fixes issue with comment text colour blending into background*/ + .board-color-exodark .card-details .card-details-header { + background: #2b2b2b; + color: #fff; + } + + .board-color-exodark .sidebar-content { + background: #2b2b2b; + color: #fff; + } + + .board-color-exodark .card-details, + .board-color-exodark .sidebar-content { + box-shadow: 0 0 7px 0 #00897b; + } + + .board-color-exodark .attachments-gallery .attachment-item { + background: #2b2b2b; + } + + .board-color-exodark .attachments-gallery .attachment-item:hover { + border: 1px solid #00897b; + background: #2b2b2b; + } + + .board-color-exodark .checklist { + background: #2b2b2b; + } + + .board-color-exodark .checklist .checklist-item { + background: #2b2b2b; + } + + .board-color-exodark .checklist .checklist-item:hover { + background: #2b2b2b; + } + + .board-color-exodark .add-checklist-item.js-open-inlined-form:hover { + background: #2b2b2b; + border: 1px solid #00897b; + } + + .board-color-exodark .add-checklist.js-open-inlined-form:hover { + background: #2b2b2b; + border: 1px solid #00897b; + } + + .board-color-exodark .card-details > h1, + .board-color-exodark h2, + .board-color-exodark h3, + .board-color-exodark h4, + .board-color-exodark h5, + .board-color-exodark h6, + /* Below added .card-details > to p/a/span to fix white swimlane text not visible https://github.com/wekan/wekan/issues/4451 */ -.board-color-exodark .card-details > p, -.board-color-exodark .card-details > a, -.board-color-exodark .card-details > span { - color: #fff !important; -} -.board-color-exodark .activity-desc { - background-color: #2b2b2b !important; -} -.board-color-exodark .activity-checklist { - background: #2b2b2b !important; - border: 1px solid #00897b; -} -.board-color-exodark .activity-comment { - background: #2b2b2b !important; - border: 1px solid #00897b; -} -.board-color-exodark .toggle-switch:checked ~ .toggle-label { - background-color: #fff !important; -} -.pop-over.board-color-exodark { - background: #2b2b2b; - color: #fff; -} -.pop-over.board-color-exodark .header { - background: #2b2b2b; - color: #fff; -} + .board-color-exodark .card-details > p, + .board-color-exodark .card-details > a, + .board-color-exodark .card-details > span { + color: #fff !important; + } -/* Transparent modern scrollbar - Exodark*/ -.board-color-exodark .list-body { - scrollbar-color: #e4e4e4d4 #202020ba; -} + .board-color-exodark .activity-desc { + background-color: #2b2b2b !important; + } -.board-color-exodark .list { - overflow: hidden; -} + .board-color-exodark .activity-checklist { + background: #2b2b2b !important; + border: 1px solid #00897b; + } -.board-color-exodark .board-canvas { - scrollbar-color: #e4e4e4d4 #202020ba; -} + .board-color-exodark .activity-comment { + background: #2b2b2b !important; + border: 1px solid #00897b; + } -/* Apply scrollbar to sidebar content*/ -.board-color-exodark .sidebar .sidebar-content { - scrollbar-color: #e4e4e4d4 #202020ba; -} + .board-color-exodark .toggle-switch:checked ~ .toggle-label { + background-color: #fff !important; + } -/* === END Exodark THEME === */ + .pop-over.board-color-exodark { + background: #2b2b2b; + color: #fff; + } -/* =============== + .pop-over.board-color-exodark .header { + background: #2b2b2b; + color: #fff; + } + + /* Transparent modern scrollbar - Exodark*/ + .board-color-exodark .list-body { + scrollbar-color: #e4e4e4d4 #202020ba; + } + + .board-color-exodark .list { + overflow: hidden; + } + + .board-color-exodark .board-canvas { + scrollbar-color: #e4e4e4d4 #202020ba; + } + + /* Apply scrollbar to sidebar content*/ + .board-color-exodark .sidebar .sidebar-content { + scrollbar-color: #e4e4e4d4 #202020ba; + } + + /* === END Exodark THEME === */ + + /* =============== THEME - Clean Dark =================*/ -.board-color-cleandark#header ul li, -.board-color-cleandark#header-quick-access ul li { - color: rgba(255, 255, 255, 50%); - font-size: 16px; - font-weight: 400; - line-height: 24px; -} - -.board-color-cleandark#header-main-bar h1 { - font-size: 16px; - font-weight: 500; - line-height: 24px !important; - color: rgba(255, 255, 255, 1); -} - -.board-color-cleandark#header ul li.current, -.board-color-cleandark#header-quick-access ul li.current { - color: rgba(255, 255, 255, 85%); -} - -.board-color-cleandark .swimlane-header { - font-size: 16px; - font-weight: 500; - line-height: 24px; - color: rgba(255, 255, 255, 1); -} - -.board-color-cleandark.board-wrapper { - background: #0A0A14; -} - -.board-color-cleandark .sidebar { - background: rgba(35, 35, 43, 1) !important; - box-shadow: none; -} - -.board-color-cleandark .sidebar hr { - background:rgba(255, 255, 255, 0.05); -} - -.board-color-cleandark .sidebar .tab-item { - border-radius: 16px; - padding: 4px 12px 4px 12px; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.85); - background: rgba(57, 57, 71, 1); -} - -.board-color-cleandark .sidebar .tab-item.active { - background: rgba(255, 255, 255, 1); - color: rgba(10, 10, 20, 1); - border: none; - padding: 4px 12px 4px 12px !important; -} - -.board-color-cleandark .sidebar .tabs-content-container { - border: none; -} - -.board-color-cleandark .card-details { - background: #23232B; - scrollbar-color: #ffffff #2e2e39; - border-radius: 20px; - box-shadow: none; -} - -.board-color-cleandark .card-details-item a { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.5); -} - -.board-color-cleandark .add-assignee { - box-shadow: none !important; -} - -.board-color-cleandark .add-assignee:hover { - background: #444455; - border-radius: 8px; -} - -.board-color-cleandark .add-checklist-top { - display: none !important; -} - -.board-color-cleandark .add-checklist { - padding: 8px; - width: min-content !important; -} - -.board-color-cleandark .add-checklist:hover { - background: #444455 !important; - border-radius: 12px !important; -} - -.board-color-cleandark .add-checklist:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .add-assignee:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .card-time.card-label-green { - background: #009B64; - width: min-content; - color: #FFFFFF; - padding-left: 8px; - padding-right: 8px; - border-radius: 8px; - margin-left: 4px; -} - -.board-color-cleandark .card-details hr { - background: rgba(255, 255, 255, 0.05); -} - -.board-color-cleandark .card-details-canvas { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.85); -} - -.board-color-cleandark.pop-over { - border-radius: 12px; - border: none; - background: rgba(46, 46, 57, 1); -} - -.board-color-cleandark.pop-over .pop-over-list, -.board-color-cleandark.pop-over .content { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 1); -} - -.board-color-cleandark.pop-over .pop-over-list a:hover { - background: #393947 !important; -} - -.board-color-cleandark .member { - box-shadow: none !important; -} - -.board-color-cleandark .add-member:hover { - background: #444455; - border-radius: 8px; -} - -.board-color-cleandark .add-member:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .add-label { - box-shadow: none !important; -} - -.board-color-cleandark .add-label:hover { - background: #444455; - border-radius: 8px; -} - -.board-color-cleandark .add-label:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark.pop-over .content kbd { - background: rgba(46, 46, 57, 1); -} - -.board-color-cleandark .full-name { - font-size: 16px; - font-weight: 500; - line-height: 24px; - - color: rgba(255, 255, 255, 0.85); -} - -.board-color-cleandark .username { - font-size: 16px; - font-weight: 400; - line-height: 24px; - - color: rgba(255, 255, 255, 0.7); -} - -.board-color-cleandark .attachment-item:hover { - background: rgba(46, 46, 57, 1); -} - -.board-color-cleandark .checklist { - background: none; - color: #FFFFFF; -} - -.board-color-cleandark .checklist-item { - background: none; -} - -.board-color-cleandark .checklist-item:hover { - background: rgba(46, 46, 57, 1) !important; -} - -.board-color-cleandark .add-checklist-item { - width: min-content !important; - padding: 8px; -} - -.board-color-cleandark .add-checklist-item:hover { - background: #444455 !important; - border-radius: 12px !important; -} - -.board-color-cleandark .add-checklist-item:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .add-attachment { - border-radius: 12px; -} - -.board-color-cleandark .add-attachment:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .attachment-actions i, -.board-color-cleandark .attachment-actions a { - font-size: 1em !important; -} - -.board-color-cleandark .activity-desc { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.5); -} - -.board-color-cleandark .activity-desc .activity-member { - color: rgba(255, 255, 255, 0.85); -} - -.board-color-cleandark .comments .comment .comment-desc .comment-text { - background: transparent; -} - -.board-color-cleandark .activity-checklist, -.board-color-cleandark .activity-comment { - background: none !important; - color: #FFFFFF; - border: 1px solid rgba(0, 155, 100, 1); - border-radius: 12px !important; -} - -.board-color-cleandark button[type=submit].primary, -.board-color-cleandark input[type=submit].primary { - font-size: 16px; - font-weight: 400; - line-height: 24px; - border-radius: 12px; - padding: 6px 12px 6px 12px; - background: #FFFFFF; - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleandark textarea { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 1); - background: rgba(57, 57, 71, 1) !important; - border: none !important; - border-radius: 12px !important; -} - -.board-color-cleandark textarea::placeholder { - color: rgba(255, 255, 255, 0.85) !important; -} - -.board-color-cleandark input { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.85) !important; - background: rgba(57, 57, 71, 1) !important; - border-radius: 12px !important; - border: none !important; -} - -.board-color-cleandark input::placeholder { - color: rgba(255, 255, 255, 1) !important; -} - -.board-color-cleandark select { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.85); - background: rgba(57, 57, 71, 1); - border-radius: 12px; - border: none; -} - -.board-color-cleandark button.primary { - padding: 6px 12px 6px 12px; - border-radius: 12px; - border: none; - background: #FFFFFF; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleandark button.primary:hover { - background: rgba(255, 255, 255, 0.85); -} - -.board-color-cleandark button.negate { - padding: 6px 12px 6px 12px; - border-radius: 12px; - border: none; - background: #cc003a; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: #FFFFFF; -} - -.board-color-cleandark button.negate:hover { - background: rgba(204, 0, 58, 0.77); -} - -.board-color-cleandark .card-details .checklist-item { - display: flex; - align-items: center; - gap: 4px; -} - -.board-color-cleandark .card-details .check-box.materialCheckBox { - border-radius: 4px; - border: none; - background: #393947; - height: 24px; - width: 24px; -} - -.board-color-cleandark .card-details .check-box.materialCheckBox.is-checked { - border-bottom: 2px solid #FFFFFF; - border-right: 2px solid #FFFFFF; - width: 11px; - height: 19px; - border-radius: 0; - background: none; -} - -.board-color-cleandark .sidebar .sidebar-content h3, -.board-color-cleandark .sidebar .sidebar-content h2, -.board-color-cleandark .sidebar .sidebar-content h1 { - color: #FFFFFF; -} - -.board-color-cleandark #cards span { - color: #FFFFFF; -} - -.board-color-cleandark #cards .materialCheckBox { - border-radius: 4px; - border: none; - background: #393947; - height: 18px; - width: 18px; -} - -.board-color-cleandark .sidebar-list-item-description { - color: #FFFFFF; -} - -.board-color-cleandark #cards .materialCheckBox.is-checked { - border-bottom: 2px solid #FFFFFF; - border-right: 2px solid #FFFFFF; - width: 5px; - height: 13px; - border-radius: 0; - background: none; - margin-left: 3px; - margin-top: 3px; -} + .board-color-cleandark#header ul li, + .board-color-cleandark#header-quick-access ul li { + color: rgba(255, 255, 255, 50%); + + font-weight: 400; + } + + .board-color-cleandark#header-main-bar h1 { + font-weight: 500; + color: rgba(255, 255, 255, 1); + } + + .board-color-cleandark#header ul li.current, + .board-color-cleandark#header-quick-access ul li.current { + color: rgba(255, 255, 255, 85%); + } + + .board-color-cleandark .swimlane-header { + font-weight: 500; + color: rgba(255, 255, 255, 1); + } + + .board-color-cleandark.board-wrapper { + background: #0A0A14; + } + + .board-color-cleandark .sidebar { + background: rgba(35, 35, 43, 1) !important; + box-shadow: none; + } + + .board-color-cleandark .sidebar hr { + background:rgba(255, 255, 255, 0.05); + } + + .board-color-cleandark .sidebar .tab-item { + border-radius: 16px; + + font-weight: 400; + color: rgba(255, 255, 255, 0.85); + background: rgba(57, 57, 71, 1); + } + + .board-color-cleandark .sidebar .tab-item.active { + background: rgba(255, 255, 255, 1); + color: rgba(10, 10, 20, 1); + border: none; + } + + .board-color-cleandark .sidebar .tabs-content-container { + border: none; + } + + .board-color-cleandark .card-details { + background: #23232B; + scrollbar-color: #ffffff #2e2e39; + border-radius: 20px; + box-shadow: none; + } + + .board-color-cleandark .card-details-item a { + font-weight: 400; + color: rgba(255, 255, 255, 0.5); + } + + .board-color-cleandark .add-assignee { + box-shadow: none !important; + } + + .board-color-cleandark .add-assignee:hover { + background: #444455; + border-radius: 0.8ch; + } + + .board-color-cleandark .add-checklist-top { + display: none !important; + } + + .board-color-cleandark .add-checklist { + width: min-content !important; + } + + .board-color-cleandark .add-checklist:hover { + background: #444455 !important; + border-radius: 12px !important; + } + + .board-color-cleandark .add-checklist:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark .add-assignee:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark .card-time.card-label-green { + background: #009B64; + width: min-content; + color: #FFFFFF; + border-radius: 0.8ch; + } + + .board-color-cleandark .card-details hr { + background: rgba(255, 255, 255, 0.05); + } + + .board-color-cleandark .card-details-canvas { + font-weight: 400; + color: rgba(255, 255, 255, 0.85); + } + + .board-color-cleandark.pop-over { + border-radius: 12px; + border: none; + background: rgba(46, 46, 57, 1); + } + + .board-color-cleandark.pop-over .pop-over-list, + .board-color-cleandark.pop-over .content { + + font-weight: 400; + color: rgba(255, 255, 255, 1); + } + + .board-color-cleandark.pop-over .pop-over-list a:hover { + background: #393947 !important; + } + + .board-color-cleandark .member { + box-shadow: none !important; + } + + .board-color-cleandark .add-member:hover { + background: #444455; + border-radius: 0.8ch; + } + + .board-color-cleandark .add-member:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark .add-label { + box-shadow: none !important; + } + + .board-color-cleandark .add-label:hover { + background: #444455; + border-radius: 0.8ch; + } + + .board-color-cleandark .add-label:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark.pop-over .content kbd { + background: rgba(46, 46, 57, 1); + } + + .board-color-cleandark .full-name { + + font-weight: 500; + + color: rgba(255, 255, 255, 0.85); + } + + .board-color-cleandark .username { + + font-weight: 400; + + color: rgba(255, 255, 255, 0.7); + } + + .board-color-cleandark .attachment-item:hover { + background: rgba(46, 46, 57, 1); + } + + .board-color-cleandark .checklist { + background: none; + color: #FFFFFF; + } + + .board-color-cleandark .checklist-item { + background: none; + } + + .board-color-cleandark .checklist-item:hover { + background: rgba(46, 46, 57, 1) !important; + } + + .board-color-cleandark .add-checklist-item { + width: min-content !important; + } + + .board-color-cleandark .add-checklist-item:hover { + background: #444455 !important; + border-radius: 12px !important; + } + + .board-color-cleandark .add-checklist-item:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark .add-attachment { + border-radius: 12px; + } + + .board-color-cleandark .add-attachment:hover i { + color: #FFFFFF !important; + } + + + .board-color-cleandark .activity-desc { + font-weight: 400; + color: rgba(255, 255, 255, 0.5); + } + + .board-color-cleandark .activity-desc .activity-member { + color: rgba(255, 255, 255, 0.85); + } + + .board-color-cleandark .comments .comment .comment-desc .comment-text { + background: transparent; + } + + .board-color-cleandark .activity-checklist, + .board-color-cleandark .activity-comment { + background: none !important; + color: #FFFFFF; + border: 1px solid rgba(0, 155, 100, 1); + border-radius: 12px !important; + } + + .board-color-cleandark button[type=submit].primary, + .board-color-cleandark input[type=submit].primary { + + font-weight: 400; + border-radius: 12px; + background: #FFFFFF; + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleandark textarea { + font-weight: 400; + color: rgba(255, 255, 255, 1); + background: rgba(57, 57, 71, 1) !important; + border: none !important; + border-radius: 12px !important; + } + + .board-color-cleandark textarea::placeholder { + color: rgba(255, 255, 255, 0.85) !important; + } + + .board-color-cleandark input { + font-weight: 400; + color: rgba(255, 255, 255, 0.85) !important; + background: rgba(57, 57, 71, 1) !important; + border-radius: 12px !important; + border: none !important; + } + + .board-color-cleandark input::placeholder { + color: rgba(255, 255, 255, 1) !important; + } + + .board-color-cleandark select { + font-weight: 400; + color: rgba(255, 255, 255, 0.85); + background: rgba(57, 57, 71, 1); + border-radius: 12px; + border: none; + } + + .board-color-cleandark button.primary { + border-radius: 12px; + border: none; + background: #FFFFFF; + + font-weight: 400; + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleandark button.primary:hover { + background: rgba(255, 255, 255, 0.85); + } + + .board-color-cleandark button.negate { + border-radius: 12px; + border: none; + background: #cc003a; + + font-weight: 400; + color: #FFFFFF; + } + + .board-color-cleandark button.negate:hover { + background: rgba(204, 0, 58, 0.77); + } + + .board-color-cleandark .card-details .checklist-item { + display: flex; + align-items: center; + } + + .board-color-cleandark .card-details .check-box.materialCheckBox { + border-radius: 0.4ch; + border: none; + background: #393947; + } + + .board-color-cleandark .card-details .check-box.materialCheckBox.is-checked { + border-bottom: 2px solid #FFFFFF; + border-right: 2px solid #FFFFFF; + border-radius: 0; + background: none; + } + + .board-color-cleandark .sidebar .sidebar-content h3, + .board-color-cleandark .sidebar .sidebar-content h2, + .board-color-cleandark .sidebar .sidebar-content h1 { + color: #FFFFFF; + } + + .board-color-cleandark #cards span { + color: #FFFFFF; + } + + .board-color-cleandark #cards .materialCheckBox { + border-radius: 0.4ch; + border: none; + background: #393947; + } + + .board-color-cleandark .sidebar-list-item-description { + color: #FFFFFF; + } + + .board-color-cleandark #cards .materialCheckBox.is-checked { + border-bottom: 2px solid #FFFFFF; + border-right: 2px solid #FFFFFF; + border-radius: 0; + background: none; + } .board-color-cleandark .checklist-progress-bar { background-color: #6b6b78 !important; } @@ -3249,757 +3370,668 @@ THEME - Clean Dark background-color: #23232B !important; } -.board-color-cleandark .allBoards { - white-space: nowrap; -} + .board-color-cleandark .allBoards { + white-space: nowrap; + } -.board-color-cleandark#header-quick-access ul.header-quick-access-list li { - display: inline-flex; - align-items: center; - padding-bottom: 4px; - padding-top: 4px; - margin-right: 10px; -} + .board-color-cleandark#header-quick-access ul.header-quick-access-list li { + display: inline-flex; + align-items: center; + } -.board-color-cleandark#header-quick-access ul.header-quick-access-list { - display: flex; - align-items: center; -} + .board-color-cleandark#header-quick-access ul.header-quick-access-list { + display: flex; + align-items: center; + } -/* Transparent modern scrollbar - cleandark*/ -.board-color-cleandark .board-canvas { - scrollbar-color: #23232be6 #e4e4e400; -} + /* Transparent modern scrollbar - cleandark*/ + .board-color-cleandark .board-canvas { + scrollbar-color: #23232be6 #e4e4e400; + } -/* Apply scrollbar to sidebar content*/ -.board-color-cleandark .sidebar .sidebar-content { - scrollbar-color: #ff6d00 #e4e4e400; -} + /* Apply scrollbar to sidebar content*/ + .board-color-cleandark .sidebar .sidebar-content { + scrollbar-color: #ff6d00 #e4e4e400; + } -/* Remove margins in between columns/fix spacing */ + /* Remove margins in between columns/fix spacing */ -.board-color-cleandark .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-cleandark .list { + border-left: none; + } -.board-color-cleandark .list-body { - margin-top: 8px; -} -.board-color-cleandark.background-box { - background-color:#23232B; -} /*Fixes contrast issues with background box in theme selection list*/ -/* =============== + + .board-color-cleandark.background-box { + background-color:#23232B; + } + + /*Fixes contrast issues with background box in theme selection list*/ + /* =============== THEME - Clean Light =================*/ -/* Please note Clean Light theme elements also contain references to some cleandark theme elements so if unable to find code you're looking for under CleanDark it might be here. This should probably be cleaned up*/ -.board-color-cleanlight.background-box { - background-color:#e0e0e0; - color:#010101!important; -} /*Fixes issues with text colour/background box being similar no contrast */ + /* Please note Clean Light theme elements also contain references to some cleandark theme elements so if unable to find code you're looking for under CleanDark it might be here. This should probably be cleaned up*/ + .board-color-cleanlight.background-box { + background-color:#e0e0e0; + color:#010101 !important; + } -.board-color-cleanlight { - background: #E0E0E0; -} + /*Fixes issues with text colour/background box being similar no contrast */ -.board-color-cleanlight .board-header-btn { - color: rgba(10, 10, 20, 0.85) !important; -} + .board-color-cleanlight { + background: #E0E0E0; + } -.board-color-cleanlight .board-header-btn i { - color: rgba(10, 10, 20, 0.85) !important; -} + .board-color-cleanlight .board-header-btn { + color: rgba(10, 10, 20, 0.85) !important; + } -.board-color-cleanlight .board-header-btns a { - color: rgba(10, 10, 20, 0.85) !important; -} + .board-color-cleanlight .board-header-btn i { + color: rgba(10, 10, 20, 0.85) !important; + } -.board-color-cleanlight .header-user-bar-name { - color: rgba(10, 10, 20, 0.85) !important; -} + .board-color-cleanlight .board-header-btns a { + color: rgba(10, 10, 20, 0.85) !important; + } -.board-color-cleanlight#header ul li, -.board-color-cleanlight#header-quick-access ul li { - color: rgba(10, 10, 20, 0.5) !important; - font-size: 16px; - font-weight: 400; - line-height: 24px; -} + .board-color-cleanlight .header-user-bar-name { + color: rgba(10, 10, 20, 0.85) !important; + } -.board-color-cleanlight#header ul li:hover, -.board-color-cleanlight#header-quick-access ul li:hover { - background: rgba(190, 190, 190, 1) !important; - border-radius: 8px; - color: rgba(10, 10, 20, 0.5) !important; -} + .board-color-cleanlight#header ul li, + .board-color-cleanlight#header-quick-access ul li { + color: rgba(10, 10, 20, 0.5) !important; -.board-color-cleanlight #header-main-bar h1 { - font-size: 16px; - font-weight: 500; - line-height: 24px !important; - color: rgba(10, 10, 20, 1) !important; -} + font-weight: 400; + } -.board-color-cleanlight#header ul li.current, -.board-color-cleanlight#header-quick-access ul li.current { - color: rgba(10, 10, 20, 0.85) !important; -} + .board-color-cleanlight#header ul li:hover, + .board-color-cleanlight#header-quick-access ul li:hover { + background: rgba(190, 190, 190, 1) !important; + border-radius: 0.8ch; + color: rgba(10, 10, 20, 0.5) !important; + } -.board-color-cleanlight .swimlane-header { - font-size: 16px; - font-weight: 500; - line-height: 24px; - color: rgba(10, 10, 20, 1); -} + .board-color-cleanlight #header-main-bar h1 { + font-weight: 500; + color: rgba(10, 10, 20, 1) !important; + } -.board-color-cleanlight.board-wrapper { - background: #FFFFFF; -} + .board-color-cleanlight#header ul li.current, + .board-color-cleanlight#header-quick-access ul li.current { + color: rgba(10, 10, 20, 0.85) !important; + } -.board-color-cleanlight .fa { - color: rgba(10, 10, 20, 1); -} + .board-color-cleanlight .swimlane-header { + font-weight: 500; + color: rgba(10, 10, 20, 1); + } -.board-color-cleandark .fa { - color: #FFFFFF; -} + .board-color-cleanlight.board-wrapper { + background: #FFFFFF; + } -/*fdsfdsfdsfdsfsdddddddddd */ + .board-color-cleanlight .fa { + color: rgba(10, 10, 20, 1); + } -.board-color-cleanlight .list, -.board-color-cleandark .list { - background: none; - border-left: none; -} + .board-color-cleandark .fa { + color: #FFFFFF; + } -.board-color-cleanlight .list .list-header, -.board-color-cleandark .list .list-header { - border-bottom: none; - display: flex; - justify-content: space-between; - align-items: center; - font-size: 16px; - background: none; -} + /*fdsfdsfdsfdsfsdddddddddd */ -.board-color-cleanlight .list .list-header div:has(.list-header-name), -.board-color-cleandark .list .list-header div:has(.list-header-name) { - display: contents; -} + .board-color-cleanlight .list, + .board-color-cleandark .list { + background: none; + border-left: none; + } -.board-color-cleanlight .list .list-header-name { - color: rgba(10, 10, 20, 1); -} + .board-color-cleanlight .list .list-header, + .board-color-cleandark .list .list-header { + border-bottom: none; + display: flex; + justify-content: space-between; + align-items: center; -.board-color-cleandark .list .list-header-name { - color: #FFFFFF; -} + background: none; + } -.board-color-cleanlight .list .list-header .list-header-menu, -.board-color-cleandark .list .list-header .list-header-menu { - display: flex; - gap: 8px; - align-items: center; -} + .board-color-cleanlight .list .list-header div:has(.list-header-name), + .board-color-cleandark .list .list-header div:has(.list-header-name) { + display: contents; + } -.board-color-cleanlight .list .list-header .list-header-menu .js-open-list-menu , -.board-color-cleandark .list .list-header .list-header-menu .js-open-list-menu { - font-size: 16px !important; -} + .board-color-cleanlight .list .list-header-name { + color: rgba(10, 10, 20, 1); + } -.board-color-cleanlight .list .list-header .list-header-menu a, -.board-color-cleandark .list .list-header .list-header-menu a { - margin: 0 !important; -} + .board-color-cleandark .list .list-header-name { + color: #FFFFFF; + } -.board-color-cleanlight .list .list-header .list-header-menu .list-header-plus-top, -.board-color-cleandark .list .list-header .list-header-menu .list-header-plus-top { - color: #FFFFFF; - background: #FF6D00; - padding: 8px; - border-radius: 12px; - font-size: 16px !important; -} + .board-color-cleanlight .list .list-header .list-header-menu, + .board-color-cleandark .list .list-header .list-header-menu { + display: flex; + align-items: center; + } -.board-color-cleanlight .list .list-header .list-header-menu .list-header-plus-top:hover, -.board-color-cleandark .list .list-header .list-header-menu .list-header-plus-top:hover { - background: #d25b02; -} -.board-color-cleanlight .list .list-header .list-header-menu .js-collapse, -.board-color-cleandark .list .list-header .list-header-menu .js-collapse { - /* Make collapse button visible in Clean Light / Clean Dark themes. + .board-color-cleanlight .list .list-header .list-header-menu a, + .board-color-cleandark .list .list-header .list-header-menu a { + margin: 0 !important; + } + + .board-color-cleanlight .list .list-header .list-header-menu .list-header-plus-top, + .board-color-cleandark .list .list-header .list-header-menu .list-header-plus-top { + color: #FFFFFF; + background: #FF6D00; + border-radius: 12px; + + } + + .board-color-cleanlight .list .list-header .list-header-menu .list-header-plus-top:hover, + .board-color-cleandark .list .list-header .list-header-menu .list-header-plus-top:hover { + background: #d25b02; + } + + .board-color-cleanlight .list .list-header .list-header-menu .js-collapse, + .board-color-cleandark .list .list-header .list-header-menu .js-collapse { + /* Make collapse button visible in Clean Light / Clean Dark themes. Previously this was hidden which caused the missing Collapse button when using these themes. Use inline-block so it lines up with other header controls. */ - display: inline-block; - vertical-align: middle; - color: inherit; -} - -.board-color-cleanlight .list-header-add, -.board-color-cleandark .list-header-add { - border-radius: 12px; - margin-top: 18px; - padding: 8px; - margin-right: 8px; - display: flex; - align-items: center; - justify-content: center; - margin-left: 10px; -} - -.board-color-cleanlight .list-header-add:hover { - background: rgba(227, 227, 230, 1); - color: rgba(10, 10, 20, 1); - border-radius: 8px; - cursor: pointer; -} - -.board-color-cleandark .list-header-add:hover { - background: rgba(255, 255, 255, 0.1); - color: #FFFFFF; - border-radius: 8px; - cursor: pointer; -} - -.board-color-cleanlight .list-header-add a:hover i { - color: #FFFFFF !important; -} - -.board-color-cleandark .list-header-add { - background: #23232B !important; - color: #FFFFFF !important; -} - -.board-color-cleanlight .card-label, -.board-color-cleandark .card-label { - border-radius: 18px; - margin-top: 6px; - margin-right: 8px; - border: none; - padding: 4px 12px; -} - -.board-color-cleanlight .swimlane, -.board-color-cleandark .swimlane { - background: none; -} - -.board-color-cleanlight .swimlane-height-apply, -.board-color-cleandark .swimlane-height-apply { - border-radius: 12px !important; -} - -.board-color-cleandark .swimlane-height-apply { - background: #FFFFFF !important; - color: #0A0A14 !important; -} - -.board-color-cleanlight .swimlane-height-apply { - background: rgba(23, 23, 28, 1) !important; - color: rgba(255, 255, 255, 0.85) !important; -} - -.board-color-cleandark .swimlane-height-apply:hover { - background: rgba(255, 255, 255, 0.85) !important; -} - -.board-color-cleanlight .swimlane-height-apply:hover { - background: rgba(227, 227, 230, 1) !important; -} - -.board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header, -.board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header, -.board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header-menu .fa, -.board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header-menu .fa { - font-size: 16px !important; -} - -.board-color-cleanlight .swimlane .swimlane-header-wrap { - background-color: #F1F1F3; -} - -.board-color-cleandark .swimlane .swimlane-header-wrap { - background-color: #2E2E39; -} - -.board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header-plus-icon, -.board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header-plus-icon { - margin-left: 14px; -} - -.board-color-cleanlight .swimlane .swimlane-header-wrap .list-composer, -.board-color-cleandark .swimlane .swimlane-header-wrap .list-composer { - display: flex; - gap: 12px; - margin-left: 20px; -} - -.board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header .viewer p, -.board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header .viewer p { - margin-bottom: 0; -} - -.board-color-cleanlight .js-toggle-desktop-drag-handles, -.board-color-cleandark .js-toggle-desktop-drag-handles { - display: none; -} - -.board-color-cleanlight .sidebar { - background: rgba(248, 248, 249, 1) !important; - box-shadow: none; -} - -.board-color-cleanlight .sidebar hr { - background: rgba(23, 23, 28, 0.05); -} - -.board-color-cleanlight .sidebar .tab-item { - border-radius: 16px; - padding: 4px 12px 4px 12px; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.85); - background: rgba(234, 234, 237, 1); -} - -.board-color-cleanlight .sidebar .tab-item.active { - background: rgba(23, 23, 28, 1); - color: rgba(255, 255, 255, 1); - border: none; - padding: 4px 12px 4px 12px !important; -} - -.board-color-cleanlight .sidebar .tabs-content-container { - border: none; -} - -.board-color-cleanlight .card-details { - background: rgba(248, 248, 249, 1); - border-radius: 20px; - box-shadow: none; -} - -.board-color-cleanlight .card-details-item a { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.5); -} - -.board-color-cleanlight .card-details-header, -.board-color-cleandark .card-details-header { - font-size: 24px !important; - font-weight: 600; - line-height: 28px; - border-bottom: none !important; - padding: 12px 20px !important; -} - -.board-color-cleanlight .card-details-header { - background: rgba(241, 241, 243, 1); - color: rgba(10, 10, 20, 1); -} - -.board-color-cleandark .card-details-header { - background: #2E2E39 !important; - color: #FFF !important; -} - -.board-color-cleanlight .card-details-header .card-details-title, -.board-color-cleandark .card-details-header .card-details-title { - font-size: 24px !important; -} - -.board-color-cleanlight .card-details .card-details-item-title, -.board-color-cleandark .card-details .card-details-item-title { - display: flex; - gap: 8px; - align-items: center; - - font-size: 16px; - font-weight: 500; - line-height: 24px; -} - -.board-color-cleanlight .card-details .card-details-item-title { - color: rgba(10, 10, 20, 1); -} - -.board-color-cleandark .card-details .card-details-item-title { - color: rgba(255, 255, 255, 1); -} - -.board-color-cleanlight .add-assignee { - box-shadow: none !important; -} - -.board-color-cleanlight .add-assignee:hover { - background: rgba(227, 227, 230, 1); - border-radius: 8px; -} - -.board-color-cleanlight .add-assignee:hover i { - color: #000000 !important; -} - -.board-color-cleanlight .add-checklist-top { - display: none !important; -} - -.board-color-cleanlight .add-checklist { - padding: 8px; - width: min-content !important; -} - -.board-color-cleanlight .add-checklist:hover { - background: rgba(227, 227, 230, 1) !important; - border-radius: 12px !important; -} - -.board-color-cleanlight .add-checklist:hover i { - color: #000000 !important; -} - -.board-color-cleanlight .card-time.card-label-green { - background: #009B64; - width: min-content; - color: #FFFFFF; - padding-left: 8px; - padding-right: 8px; - border-radius: 8px; - margin-left: 4px; -} - -.board-color-cleanlight .card-details hr { - background: rgba(23, 23, 28, 0.05); -} - -.board-color-cleanlight .card-details-canvas { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.5); -} - -.board-color-cleanlight.pop-over { - border-radius: 12px; - border: none; - background: rgba(241, 241, 243, 1); -} - -.board-color-cleanlight.pop-over .header, -.board-color-cleandark.pop-over .header { - border-radius: 12px 12px 0 0; - border-bottom: none; - background: inherit; - - font-size: 16px; - font-weight: 500; - line-height: 24px; -} - -.board-color-cleanlight.pop-over .header { - color: rgba(10, 10, 20, 1); -} - - -.board-color-cleandark.pop-over .header { - color: rgba(255, 255, 255, 1);; -} - -.board-color-cleanlight.pop-over .pop-over-list, -.board-color-cleanlight.pop-over .content { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.8); -} - -.board-color-cleanlight.pop-over .pop-over-list a:hover { - background: #393947 !important; -} - -.board-color-cleanlight .member { - box-shadow: none !important; -} - -.board-color-cleanlight .add-member:hover { - background: rgba(227, 227, 230, 1); - border-radius: 8px; -} - -.board-color-cleanlight .add-member:hover i { - color: #000000 !important; -} - -.board-color-cleanlight .add-label { - box-shadow: none !important; -} - -.board-color-cleanlight .add-label:hover { - background: rgba(227, 227, 230, 1); - border-radius: 8px; -} - -.board-color-cleanlight .add-label:hover i { - color: #000000 !important; -} - -.board-color-cleanlight.pop-over .content kbd { - background: rgba(180, 180, 180, 1); - border-radius: 8px; -} - -.board-color-cleanlight .full-name { - font-size: 16px; - font-weight: 500; - line-height: 24px; - - color: rgba(10, 10, 20, 0.85) !important; -} - -.board-color-cleanlight .username { - font-size: 16px; - font-weight: 400; - line-height: 24px; - - color: rgba(10, 10, 20, 0.5) !important; -} - -.board-color-cleanlight .attachment-item:hover { - background: rgba(227, 227, 230, 1); -} - -.board-color-cleanlight .checklist { - background: none; - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight .checklist-item { - background: none; -} - -.board-color-cleanlight .checklist-item:hover { - background: rgba(227, 227, 230, 1) !important; -} - -.board-color-cleanlight .add-checklist-item { - width: min-content !important; - padding: 8px; -} - -.board-color-cleanlight .add-checklist-item:hover { - background: rgba(227, 227, 230, 1) !important; - border-radius: 12px !important; -} - -.board-color-cleanlight .add-checklist-item:hover i { - color: #000000 !important; -} - -.board-color-cleanlight .add-attachment { - background: rgba(248, 248, 249, 1) !important; - border-radius: 12px; - border-color: rgba(197, 197, 200, 1); -} - -.board-color-cleanlight .add-attachment:hover { - background: rgba(227, 227, 230, 1) !important; -} - -.board-color-cleanlight .add-attachment:hover i { - color: #000000 !important; -} - -.board-color-cleanlight .attachment-actions i, -.board-color-cleanlight .attachment-actions a { - font-size: 1em !important; -} - -.board-color-cleanlight .activity-desc { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.5); -} - -.board-color-cleanlight .activity-desc .activity-member { - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight .activity-checklist, -.board-color-cleanlight .activity-comment { - background: none !important; - color: rgba(10, 10, 20, 0.85); - border: 1px solid rgba(0, 155, 100, 1); - border-radius: 12px !important; -} - -.board-color-cleanlight button[type=submit].primary, -.board-color-cleanlight input[type=submit].primary { - font-size: 16px; - font-weight: 400; - line-height: 24px; - border-radius: 12px; - padding: 6px 12px 6px 12px; - background: rgba(23, 23, 28, 1); - color: rgba(255, 255, 255, 0.85); -} - -.board-color-cleanlight input.primary { - font-size: 16px; - font-weight: 400; - line-height: 24px; - border-radius: 12px; - padding: 6px 12px 6px 12px; - background: rgba(23, 23, 28, 1) !important; - color: rgba(255, 255, 255, 0.85) !important; -} - -.board-color-cleanlight input.primary:hover { - background: #444455 !important; -} - -.board-color-cleanlight textarea { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.85); - background: rgba(234, 234, 237, 1); - border: none !important; - border-radius: 12px !important; -} - -.board-color-cleanlight textarea::placeholder { - color: rgba(10, 10, 20, 0.5) !important; -} - -.board-color-cleanlight textarea:focus, -.board-color-cleandark textarea:focus { - border: none !important; - box-shadow: none; -} - -.board-color-cleanlight input { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.85) !important; - background: rgba(234, 234, 237, 1) !important; - border-radius: 12px !important; - border: none !important; -} - -.board-color-cleanlight input::placeholder { - color: rgba(10, 10, 20, 0.5) !important; -} - -.board-color-cleanlight input:focus, -.board-color-cleandark input:focus { - border: none !important; - box-shadow: none !important; -} - -.board-color-cleanlight select { - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(10, 10, 20, 0.85); - background: rgba(234, 234, 237, 1); - border-radius: 12px; - border: none; -} - -.board-color-cleanlight button.primary { - padding: 6px 12px 6px 12px; - border-radius: 12px; - border: none; - background: rgba(23, 23, 28, 1); - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 0.85); -} - -.board-color-cleanlight button.primary:hover { - background: #444455; -} - -.board-color-cleanlight button.negate { - padding: 6px 12px 6px 12px; - border-radius: 12px; - border: none; - background: #cc003a; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: #FFFFFF; -} - -.board-color-cleanlight button.negate:hover { - background: rgba(204, 0, 58, 0.77); -} - -.board-color-cleanlight .card-details .checklist-item { - display: flex; - align-items: center; - gap: 4px; -} - -.board-color-cleanlight .card-details .check-box.materialCheckBox { - border-radius: 4px; - border: none; - background: rgba(234, 234, 237, 1); - height: 24px; - width: 24px; -} - -.board-color-cleanlight .card-details .check-box.materialCheckBox.is-checked { - border-bottom: 2px solid #000000; - border-right: 2px solid #000000; - width: 11px; - height: 19px; - border-radius: 0; - background: none; -} - -.board-color-cleanlight .sidebar-list-item-description { - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight .sidebar .sidebar-content h3, -.board-color-cleanlight .sidebar .sidebar-content h2, -.board-color-cleanlight .sidebar .sidebar-content h1 { - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight #cards span { - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight #cards .materialCheckBox { - border-radius: 4px; - border: none; - background: rgba(234, 234, 237, 1); - height: 18px; - width: 18px; -} - -.board-color-cleanlight #cards .materialCheckBox.is-checked { - border-bottom: 2px solid #000000; - border-right: 2px solid #000000; - width: 5px; - height: 13px; - border-radius: 0; - background: none; - margin-left: 3px; - margin-top: 3px; -} + display: inline-block; + vertical-align: middle; + color: inherit; + } + + .board-color-cleanlight .list-header-add, + .board-color-cleandark .list-header-add { + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + } + + .board-color-cleanlight .list-header-add:hover { + background: rgba(227, 227, 230, 1); + color: rgba(10, 10, 20, 1); + border-radius: 0.8ch; + cursor: pointer; + } + + .board-color-cleandark .list-header-add:hover { + background: rgba(255, 255, 255, 0.1); + color: #FFFFFF; + border-radius: 0.8ch; + cursor: pointer; + } + + .board-color-cleanlight .list-header-add a:hover i { + color: #FFFFFF !important; + } + + .board-color-cleandark .list-header-add { + background: #23232B !important; + color: #FFFFFF !important; + } + + .board-color-cleanlight .card-label, + .board-color-cleandark .card-label { + border-radius: 18px; + border: none; + } + + .board-color-cleanlight .swimlane, + .board-color-cleandark .swimlane { + background: none; + } + + .board-color-cleanlight .swimlane-height-apply, + .board-color-cleandark .swimlane-height-apply { + border-radius: 12px !important; + } + + .board-color-cleandark .swimlane-height-apply { + background: #FFFFFF !important; + color: #0A0A14 !important; + } + + .board-color-cleanlight .swimlane-height-apply { + background: rgba(23, 23, 28, 1) !important; + color: rgba(255, 255, 255, 0.85) !important; + } + + .board-color-cleandark .swimlane-height-apply:hover { + background: rgba(255, 255, 255, 0.85) !important; + } + + .board-color-cleanlight .swimlane-height-apply:hover { + background: rgba(227, 227, 230, 1) !important; + } + + + .board-color-cleanlight .swimlane .swimlane-header-wrap { + background-color: #F1F1F3; + } + + .board-color-cleandark .swimlane .swimlane-header-wrap { + background-color: #2E2E39; + } + + + .board-color-cleanlight .swimlane .swimlane-header-wrap .list-composer, + .board-color-cleandark .swimlane .swimlane-header-wrap .list-composer { + display: flex; + } + + .board-color-cleanlight .swimlane .swimlane-header-wrap .swimlane-header .viewer p, + .board-color-cleandark .swimlane .swimlane-header-wrap .swimlane-header .viewer p { + margin-bottom: 0; + } + + .board-color-cleanlight .js-toggle-desktop-drag-handles, + .board-color-cleandark .js-toggle-desktop-drag-handles { + display: none; + } + + .board-color-cleanlight .sidebar { + background: rgba(248, 248, 249, 1) !important; + box-shadow: none; + } + + .board-color-cleanlight .sidebar hr { + background: rgba(23, 23, 28, 0.05); + } + + .board-color-cleanlight .sidebar .tab-item { + border-radius: 16px; + + font-weight: 400; + color: rgba(10, 10, 20, 0.85); + background: rgba(234, 234, 237, 1); + } + + .board-color-cleanlight .sidebar .tab-item.active { + background: rgba(23, 23, 28, 1); + color: rgba(255, 255, 255, 1); + border: none; + } + + .board-color-cleanlight .sidebar .tabs-content-container { + border: none; + } + + .board-color-cleanlight .card-details { + background: rgba(248, 248, 249, 1); + border-radius: 20px; + box-shadow: none; + } + + .board-color-cleanlight .card-details-item a { + font-weight: 400; + color: rgba(10, 10, 20, 0.5); + } + + .board-color-cleanlight .card-details-header, + .board-color-cleandark .card-details-header { + + font-weight: 600; + border-bottom: none !important; + } + + .board-color-cleanlight .card-details-header { + background: rgba(241, 241, 243, 1); + color: rgba(10, 10, 20, 1); + } + + .board-color-cleandark .card-details-header { + background: #2E2E39 !important; + color: #FFF !important; + } + + + .board-color-cleanlight .card-details .card-details-item-title, + .board-color-cleandark .card-details .card-details-item-title { + display: flex; + align-items: center; + + font-weight: 500; + } + + .board-color-cleanlight .card-details .card-details-item-title { + color: rgba(10, 10, 20, 1); + } + + .board-color-cleandark .card-details .card-details-item-title { + color: rgba(255, 255, 255, 1); + } + + .board-color-cleanlight .add-assignee { + box-shadow: none !important; + } + + .board-color-cleanlight .add-assignee:hover { + background: rgba(227, 227, 230, 1); + border-radius: 0.8ch; + } + + .board-color-cleanlight .add-assignee:hover i { + color: #000000 !important; + } + + .board-color-cleanlight .add-checklist-top { + display: none !important; + } + + .board-color-cleanlight .add-checklist { + width: min-content !important; + } + + .board-color-cleanlight .add-checklist:hover { + background: rgba(227, 227, 230, 1) !important; + border-radius: 12px !important; + } + + .board-color-cleanlight .add-checklist:hover i { + color: #000000 !important; + } + + .board-color-cleanlight .card-time.card-label-green { + background: #009B64; + width: min-content; + color: #FFFFFF; + border-radius: 0.8ch; + } + + .board-color-cleanlight .card-details hr { + background: rgba(23, 23, 28, 0.05); + } + + .board-color-cleanlight .card-details-canvas { + font-weight: 400; + color: rgba(10, 10, 20, 0.5); + } + + .board-color-cleanlight.pop-over { + border-radius: 12px; + border: none; + background: rgba(241, 241, 243, 1); + } + + .board-color-cleanlight.pop-over .header, + .board-color-cleandark.pop-over .header { + border-radius: 12px 12px 0 0; + border-bottom: none; + background: inherit; + + font-weight: 500; + } + + .board-color-cleanlight.pop-over .header { + color: rgba(10, 10, 20, 1); + } + + + .board-color-cleandark.pop-over .header { + color: rgba(255, 255, 255, 1); ; + } + + .board-color-cleanlight.pop-over .pop-over-list, + .board-color-cleanlight.pop-over .content { + + font-weight: 400; + color: rgba(10, 10, 20, 0.8); + } + + .board-color-cleanlight.pop-over .pop-over-list a:hover { + background: #393947 !important; + } + + .board-color-cleanlight .member { + box-shadow: none !important; + } + + .board-color-cleanlight .add-member:hover { + background: rgba(227, 227, 230, 1); + border-radius: 0.8ch; + } + + .board-color-cleanlight .add-member:hover i { + color: #000000 !important; + } + + .board-color-cleanlight .add-label { + box-shadow: none !important; + } + + .board-color-cleanlight .add-label:hover { + background: rgba(227, 227, 230, 1); + border-radius: 0.8ch; + } + + .board-color-cleanlight .add-label:hover i { + color: #000000 !important; + } + + .board-color-cleanlight.pop-over .content kbd { + background: rgba(180, 180, 180, 1); + border-radius: 0.8ch; + } + + .board-color-cleanlight .full-name { + + font-weight: 500; + + color: rgba(10, 10, 20, 0.85) !important; + } + + .board-color-cleanlight .username { + + font-weight: 400; + + color: rgba(10, 10, 20, 0.5) !important; + } + + .board-color-cleanlight .attachment-item:hover { + background: rgba(227, 227, 230, 1); + } + + .board-color-cleanlight .checklist { + background: none; + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleanlight .checklist-item { + background: none; + } + + .board-color-cleanlight .checklist-item:hover { + background: rgba(227, 227, 230, 1) !important; + } + + .board-color-cleanlight .add-checklist-item { + width: min-content !important; + } + + .board-color-cleanlight .add-checklist-item:hover { + background: rgba(227, 227, 230, 1) !important; + border-radius: 12px !important; + } + + .board-color-cleanlight .add-checklist-item:hover i { + color: #000000 !important; + } + + .board-color-cleanlight .add-attachment { + background: rgba(248, 248, 249, 1) !important; + border-radius: 12px; + border-color: rgba(197, 197, 200, 1); + } + + .board-color-cleanlight .add-attachment:hover { + background: rgba(227, 227, 230, 1) !important; + } + + .board-color-cleanlight .add-attachment:hover i { + color: #000000 !important; + } + + + .board-color-cleanlight .activity-desc { + font-weight: 400; + color: rgba(10, 10, 20, 0.5); + } + + .board-color-cleanlight .activity-desc .activity-member { + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleanlight .activity-checklist, + .board-color-cleanlight .activity-comment { + background: none !important; + color: rgba(10, 10, 20, 0.85); + border: 1px solid rgba(0, 155, 100, 1); + border-radius: 12px !important; + } + + .board-color-cleanlight button[type=submit].primary, + .board-color-cleanlight input[type=submit].primary { + + font-weight: 400; + border-radius: 12px; + background: rgba(23, 23, 28, 1); + color: rgba(255, 255, 255, 0.85); + } + + .board-color-cleanlight input.primary { + + font-weight: 400; + border-radius: 12px; + background: rgba(23, 23, 28, 1) !important; + color: rgba(255, 255, 255, 0.85) !important; + } + + .board-color-cleanlight input.primary:hover { + background: #444455 !important; + } + + .board-color-cleanlight textarea { + font-weight: 400; + color: rgba(10, 10, 20, 0.85); + background: rgba(234, 234, 237, 1); + border: none !important; + border-radius: 12px !important; + } + + .board-color-cleanlight textarea::placeholder { + color: rgba(10, 10, 20, 0.5) !important; + } + + .board-color-cleanlight textarea:focus, + .board-color-cleandark textarea:focus { + border: none !important; + box-shadow: none; + } + + .board-color-cleanlight input { + font-weight: 400; + color: rgba(10, 10, 20, 0.85) !important; + background: rgba(234, 234, 237, 1) !important; + border-radius: 12px !important; + border: none !important; + } + + .board-color-cleanlight input::placeholder { + color: rgba(10, 10, 20, 0.5) !important; + } + + .board-color-cleanlight input:focus, + .board-color-cleandark input:focus { + border: none !important; + box-shadow: none !important; + } + + .board-color-cleanlight select { + font-weight: 400; + color: rgba(10, 10, 20, 0.85); + background: rgba(234, 234, 237, 1); + border-radius: 12px; + border: none; + } + + .board-color-cleanlight button.primary { + border-radius: 12px; + border: none; + background: rgba(23, 23, 28, 1); + + font-weight: 400; + color: rgba(255, 255, 255, 0.85); + } + + .board-color-cleanlight button.primary:hover { + background: #444455; + } + + .board-color-cleanlight button.negate { + border-radius: 12px; + border: none; + background: #cc003a; + + font-weight: 400; + color: #FFFFFF; + } + + .board-color-cleanlight button.negate:hover { + background: rgba(204, 0, 58, 0.77); + } + + .board-color-cleanlight .card-details .checklist-item { + display: flex; + align-items: center; + } + + .board-color-cleanlight .card-details .check-box.materialCheckBox { + border-radius: 0.4ch; + border: none; + background: rgba(234, 234, 237, 1); + } + + .board-color-cleanlight .card-details .check-box.materialCheckBox.is-checked { + border-bottom: 2px solid #000000; + border-right: 2px solid #000000; + border-radius: 0; + background: none; + } + + .board-color-cleanlight .sidebar-list-item-description { + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleanlight .sidebar .sidebar-content h3, + .board-color-cleanlight .sidebar .sidebar-content h2, + .board-color-cleanlight .sidebar .sidebar-content h1 { + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleanlight #cards span { + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleanlight #cards .materialCheckBox { + border-radius: 0.4ch; + border: none; + background: rgba(234, 234, 237, 1); + } + + .board-color-cleanlight #cards .materialCheckBox.is-checked { + border-bottom: 2px solid #000000; + border-right: 2px solid #000000; + border-radius: 0; + background: none; + } .board-color-cleanlight .checklist-progress-bar { background-color: #f5f5f5 !important; } @@ -4008,311 +4040,273 @@ THEME - Clean Light color: #010101 !important; } -.board-color-cleanlight .allBoards { - white-space: nowrap; -} - -.board-color-cleanlight#header-quick-access, -.board-color-cleandark#header-quick-access { - padding: 10px 20px; - padding-top: 12px !important; - gap: 20px; -} - -.board-color-cleandark#header-quick-access { - background: #2E2E39 !important; -} - -.board-color-cleanlight#header-quick-access { - background: #F1F1F3 !important; - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleanlight#header-quick-access ul.header-quick-access-list li a .viewer, -.board-color-cleandark#header-quick-access ul.header-quick-access-list li a .viewer { - max-width: 400px; - text-overflow: ellipsis; - overflow: hidden; - display: inline-flex; - align-items: center; -} - -.board-color-cleanlight#header-quick-access ul.header-quick-access-list li a .viewer p, -.board-color-cleandark#header-quick-access ul.header-quick-access-list li a .viewer p { - margin-bottom: 0; - overflow: hidden; - text-overflow: ellipsis; -} - -.board-color-cleanlight#header-quick-access ul.header-quick-access-list li { - display: inline-flex; - align-items: center; - padding-bottom: 4px; - padding-top: 4px; - margin-right: 10px; -} - -.board-color-cleanlight#header-quick-access ul.header-quick-access-list { - display: flex; - align-items: center; -} - -.board-color-cleanlight #header-main-bar, -.board-color-cleanlight#header { - background: #F1F1F3 !important; - color: rgba(10, 10, 20, 0.85) !important; -} - -.board-color-cleandark #header-main-bar, -.board-color-cleandark#header { - background: #2E2E39 !important; - color: #FFFFFF; -} - -.board-color-cleanlight .list-body .open-minicard-composer, -.board-color-cleandark .list-body .open-minicard-composer { - display: none !important; -} - -.board-color-cleanlight .minicard, -.board-color-cleandark .minicard { - border-radius: 12px; - font-size: 16px; - font-weight: 400; - line-height: 24px; - padding: 12px; -} - -.board-color-cleanlight .minicard { - background: rgba(248, 248, 249, 1); - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleandark .minicard { - color: #FFFFFF; - background: #23232B; -} - -.board-color-cleanlight .minicard .minicard-details-menu, -.board-color-cleandark .minicard .minicard-details-menu { - font-size: 16px !important; -} - -.board-color-cleanlight .minicard .date, -.board-color-cleandark .minicard .date, -.board-color-cleanlight .minicard .end-date, -.board-color-cleandark .minicard .end-date { - font-size: 16px; - font-weight: 400; - line-height: 24px; - margin-bottom: 10px; -} - -.board-color-cleanlight .minicard .date a, -.board-color-cleandark .minicard .date a, -.board-color-cleanlight .minicard .end-date, -.board-color-cleandark .minicard .end-date, -.board-color-cleanlight .card-details .card-date, -.board-color-cleandark .card-details .card-date { - padding: 4px 8px 4px 8px; - font-size: 16px; - font-weight: 400; - line-height: 24px; - color: rgba(255, 255, 255, 1); -} - -.board-color-cleanlight .minicard .end-date, -.board-color-cleandark .minicard .end-date, -.board-color-cleanlight .minicard .due-date, -.board-color-cleandark .minicard .due-date, -.board-color-cleanlight .card-details .card-date, -.board-color-cleandark .card-details .card-date { - border-radius: 8px; -} - -.board-color-cleanlight .minicard .end-date, -.board-color-cleanlight .minicard .due-date, -.board-color-cleanlight .card-details .card-date { - background: rgba(227, 227, 230, 1); - color: rgba(10, 10, 20, 1) !important; -} - -.board-color-cleandark .minicard .end-date, -.board-color-cleandark .minicard .due-date, -.board-color-cleandark .card-details .card-date { - background: #444455; -} - -.board-color-cleandark .minicard .end-date:hover, -.board-color-cleandark .minicard .due-date:hover, -.board-color-cleandark .card-details .card-date:hover { - background: rgba(68, 68, 85, 0.73); -} - -.board-color-cleanlight .minicard .end-date:hover, -.board-color-cleanlight .minicard .due-date:hover, -.board-color-cleanlight .card-details .card-date:hover { - background: rgba(207, 207, 210, 1); -} - -.board-color-cleanlight .minicard .date .current, -.board-color-cleandark .minicard .date .current, -.board-color-cleanlight .minicard .current, -.board-color-cleandark .minicard .current, -.board-color-cleanlight .card-details .current, -.board-color-cleandark .card-details .current { - background: #009B64; - border-radius: 8px; - color: rgba(255, 255, 255, 1) !important; -} - -.board-color-cleandark .minicard .date .current:hover, -.board-color-cleanlight .minicard .date .current:hover, -.board-color-cleandark .minicard .current:hover, -.board-color-cleanlight .minicard .current:hover, -.board-color-cleandark .card-details .current:hover, -.board-color-cleanlight .card-details .current:hover { - background: rgba(0, 155, 100, 0.73); - color: rgba(255, 255, 255, 1) !important; -} - -.board-color-cleanlight .minicard .date .due, -.board-color-cleandark .minicard .date .due, -.board-color-cleanlight .minicard .due, -.board-color-cleandark .minicard .due, -.board-color-cleanlight .card-details .due, -.board-color-cleandark .card-details .due { - background: #CC003A; - border-radius: 8px; - color: rgba(255, 255, 255, 1) !important; -} - -.board-color-cleanlight .card-details .due:hover, -.board-color-cleanlight .minicard .date .due:hover, -.board-color-cleanlight .minicard .due:hover, -.board-color-cleandark .minicard .due:hover, -.board-color-cleandark .minicard .date .due:hover, -.board-color-cleandark .card-details .due:hover { - background: rgba(204, 0, 58, 0.73); - color: rgba(255, 255, 255, 1) !important; -} - -.board-color-cleanlight .minicard-assignees, -.board-color-cleandark .minicard-assignees { - border-bottom: none !important; -} - -.board-color-cleanlight .minicard-composer-textarea { - background: #f8f8f9 !important; -} - -.board-color-cleandark .minicard-composer-textarea { - background: #23232B !important; -} - -.board-color-cleanlight .minicard-composer:hover { - background: #f8f8f9 !important; -} - -.board-color-cleandark .minicard-composer:hover { - background: #23232B !important; -} - -.board-color-cleanlight .minicard .badges .badge.is-finished, -.board-color-cleandark .minicard .badges .badge.is-finished { - background: #009B64 !important; - border-radius: 8px; -} - -.board-color-cleanlight .minicard .badges .badge.is-finished .badge-icon { - color: #FFFFFF; -} - -.board-color-cleanlight .card-details-item-customfield:has(.checklist-item), -.board-color-cleandark .card-details-item-customfield:has(.checklist-item) { - display: flex !important; - align-items: center; - gap: 8px; -} - -.board-color-cleanlight .card-details-item-customfield:has(.checklist-item) div, -.board-color-cleandark .card-details-item-customfield:has(.checklist-item) div { - padding-right: 0 !important; -} - -.board-color-cleanlight .card-details .card-details-items .card-details-item.custom-fields, -.board-color-cleanlight .card-details .card-details-items .card-details-item.custom-fields { - margin-left: auto; - flex-grow: 0; - border-radius: 12px; -} - -.board-color-cleanlight .card-details-item-customfield:has(.checklist-item) h3, -.board-color-cleandark .card-details-item-customfield:has(.checklist-item) h3 { - width: min-content !important; - display: flex; - align-items: center; - gap: 8px; - margin: 0 !important; -} - -.board-color-cleanlight .new-description .fa, -.board-color-cleandark .new-description .fa { - display: none; -} - -.board-color-cleanlight .card-details-left .viewer p { - color: rgba(10, 10, 20, 0.85); -} - -.board-color-cleandark .card-details-left .viewer p { - color: #FFFFFF; -} - -.board-color-cleanlight .new-comment .fa, -.board-color-cleandark .new-comment .fa { - display: none; -} - -.board-color-cleanlight .pop-over-list li > a, -.board-color-cleandark .pop-over-list li > a { - font-weight: 500; -} - -.board-color-cleanlight .pop-over-list li > a i, -.board-color-cleandark .pop-over-list li > a i { - margin-right: 6px !important; -} - -.board-color-cleanlight .pop-over .quiet { - margin-left: 100px !important; -} - -.board-color-cleandark .minicard:hover:not(.minicard-composer), -.board-color-cleandark .is-selected .minicard, .draggable-hover-card .minicard { - background: #23232B; -} - -/* Transparent modern scrollbar - cleanlight*/ -.board-color-cleanlight .board-canvas { - scrollbar-color: #0a0a14d1 #e4e4e400; -} + .board-color-cleanlight .allBoards { + white-space: nowrap; + } -/* Apply scrollbar to sidebar content*/ -.board-color-cleanlight .sidebar .sidebar-content { - scrollbar-color: #0a0a14d1 #e4e4e400; -} + .board-color-cleandark#header-quick-access { + background: #2E2E39 !important; + } -/* Remove margins in between columns/fix spacing */ + .board-color-cleanlight#header-quick-access { + background: #F1F1F3 !important; + color: rgba(10, 10, 20, 0.85); + } -.board-color-cleanlight .list { - border-left: none; - padding-bottom: 8px; -} + .board-color-cleanlight#header-quick-access ul.header-quick-access-list li a .viewer, + .board-color-cleandark#header-quick-access ul.header-quick-access-list li a .viewer { + text-overflow: ellipsis; + overflow: hidden; + display: inline-flex; + align-items: center; + } -.board-color-cleanlight .list-body { - margin-top: 8px; -} + .board-color-cleanlight#header-quick-access ul.header-quick-access-list li a .viewer p, + .board-color-cleandark#header-quick-access ul.header-quick-access-list li a .viewer p { + margin-bottom: 0; + overflow: hidden; + text-overflow: ellipsis; + } -/* === END CleanDark/Light THEME === */ + .board-color-cleanlight#header-quick-access ul.header-quick-access-list li { + display: inline-flex; + align-items: center; + } + + .board-color-cleanlight#header-quick-access ul.header-quick-access-list { + display: flex; + align-items: center; + } + + .board-color-cleanlight #header-main-bar, + .board-color-cleanlight#header { + background: #F1F1F3 !important; + color: rgba(10, 10, 20, 0.85) !important; + } + + .board-color-cleandark #header-main-bar, + .board-color-cleandark#header { + background: #2E2E39 !important; + color: #FFFFFF; + } + + .board-color-cleanlight .list-body .open-minicard-composer, + .board-color-cleandark .list-body .open-minicard-composer { + display: none !important; + } + + .board-color-cleanlight .minicard, + .board-color-cleandark .minicard { + border-radius: 12px; + + font-weight: 400; + } + + .board-color-cleanlight .minicard { + background: rgba(248, 248, 249, 1); + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleandark .minicard { + color: #FFFFFF; + background: #23232B; + } + + + .board-color-cleanlight .minicard .date, + .board-color-cleandark .minicard .date, + .board-color-cleanlight .minicard .end-date, + .board-color-cleandark .minicard .end-date { + + font-weight: 400; + } + + .board-color-cleanlight .minicard .date a, + .board-color-cleandark .minicard .date a, + .board-color-cleanlight .minicard .end-date, + .board-color-cleandark .minicard .end-date, + .board-color-cleanlight .card-details .card-date, + .board-color-cleandark .card-details .card-date { + + font-weight: 400; + color: rgba(255, 255, 255, 1); + } + + .board-color-cleanlight .minicard .end-date, + .board-color-cleandark .minicard .end-date, + .board-color-cleanlight .minicard .due-date, + .board-color-cleandark .minicard .due-date, + .board-color-cleanlight .card-details .card-date, + .board-color-cleandark .card-details .card-date { + border-radius: 0.8ch; + } + + .board-color-cleanlight .minicard .end-date, + .board-color-cleanlight .minicard .due-date, + .board-color-cleanlight .card-details .card-date { + background: rgba(227, 227, 230, 1); + color: rgba(10, 10, 20, 1) !important; + } + + .board-color-cleandark .minicard .end-date, + .board-color-cleandark .minicard .due-date, + .board-color-cleandark .card-details .card-date { + background: #444455; + } + + .board-color-cleandark .minicard .end-date:hover, + .board-color-cleandark .minicard .due-date:hover, + .board-color-cleandark .card-details .card-date:hover { + background: rgba(68, 68, 85, 0.73); + } + + .board-color-cleanlight .minicard .end-date:hover, + .board-color-cleanlight .minicard .due-date:hover, + .board-color-cleanlight .card-details .card-date:hover { + background: rgba(207, 207, 210, 1); + } + + .board-color-cleanlight .minicard .date .current, + .board-color-cleandark .minicard .date .current, + .board-color-cleanlight .minicard .current, + .board-color-cleandark .minicard .current, + .board-color-cleanlight .card-details .current, + .board-color-cleandark .card-details .current { + background: #009B64; + border-radius: 0.8ch; + color: rgba(255, 255, 255, 1) !important; + } + + .board-color-cleandark .minicard .date .current:hover, + .board-color-cleanlight .minicard .date .current:hover, + .board-color-cleandark .minicard .current:hover, + .board-color-cleanlight .minicard .current:hover, + .board-color-cleandark .card-details .current:hover, + .board-color-cleanlight .card-details .current:hover { + background: rgba(0, 155, 100, 0.73); + color: rgba(255, 255, 255, 1) !important; + } + + .board-color-cleanlight .minicard .date .due, + .board-color-cleandark .minicard .date .due, + .board-color-cleanlight .minicard .due, + .board-color-cleandark .minicard .due, + .board-color-cleanlight .card-details .due, + .board-color-cleandark .card-details .due { + background: #CC003A; + border-radius: 0.8ch; + color: rgba(255, 255, 255, 1) !important; + } + + .board-color-cleanlight .card-details .due:hover, + .board-color-cleanlight .minicard .date .due:hover, + .board-color-cleanlight .minicard .due:hover, + .board-color-cleandark .minicard .due:hover, + .board-color-cleandark .minicard .date .due:hover, + .board-color-cleandark .card-details .due:hover { + background: rgba(204, 0, 58, 0.73); + color: rgba(255, 255, 255, 1) !important; + } + + .board-color-cleanlight .minicard-assignees, + .board-color-cleandark .minicard-assignees { + border-bottom: none !important; + } + + .board-color-cleanlight .minicard-composer-textarea { + background: #f8f8f9 !important; + } + + .board-color-cleandark .minicard-composer-textarea { + background: #23232B !important; + } + + .board-color-cleanlight .minicard-composer:hover { + background: #f8f8f9 !important; + } + + .board-color-cleandark .minicard-composer:hover { + background: #23232B !important; + } + + .board-color-cleanlight .minicard .badges .badge.is-finished, + .board-color-cleandark .minicard .badges .badge.is-finished { + background: #009B64 !important; + border-radius: 0.8ch; + } + + .board-color-cleanlight .minicard .badges .badge.is-finished .badge-icon { + color: #FFFFFF; + } + + .board-color-cleanlight .card-details-item-customfield:has(.checklist-item), + .board-color-cleandark .card-details-item-customfield:has(.checklist-item) { + display: flex !important; + align-items: center; + } + + .board-color-cleanlight .card-details .card-details-items .card-details-item.custom-fields, + .board-color-cleanlight .card-details .card-details-items .card-details-item.custom-fields { + margin-left: auto; + flex-grow: 0; + border-radius: 12px; + } + + .board-color-cleanlight .card-details-item-customfield:has(.checklist-item) h3, + .board-color-cleandark .card-details-item-customfield:has(.checklist-item) h3 { + width: min-content !important; + display: flex; + align-items: center; + margin: 0 !important; + } + + .board-color-cleanlight .new-description .fa, + .board-color-cleandark .new-description .fa { + display: none; + } + + .board-color-cleanlight .card-details-left .viewer p { + color: rgba(10, 10, 20, 0.85); + } + + .board-color-cleandark .card-details-left .viewer p { + color: #FFFFFF; + } + + .board-color-cleanlight .new-comment .fa, + .board-color-cleandark .new-comment .fa { + display: none; + } + + .board-color-cleanlight .pop-over-list li > a, + .board-color-cleandark .pop-over-list li > a { + font-weight: 500; + } + + + .board-color-cleandark .minicard:hover:not(.minicard-composer), + .board-color-cleandark .is-selected .minicard, .draggable-hover-card .minicard { + background: #23232B; + } + + /* Transparent modern scrollbar - cleanlight*/ + .board-color-cleanlight .board-canvas { + scrollbar-color: #0a0a14d1 #e4e4e400; + } + + + /* Apply scrollbar to sidebar content*/ + .board-color-cleanlight .sidebar .sidebar-content { + scrollbar-color: #0a0a14d1 #e4e4e400; + } + + /* Remove margins in between columns/fix spacing */ + + .board-color-cleanlight .list { + border-left: none; + } + + + + /* === END CleanDark/Light THEME === */ \ No newline at end of file diff --git a/client/components/boards/boardHeader.css b/client/components/boards/boardHeader.css index faf20e2f5..58445493d 100644 --- a/client/components/boards/boardHeader.css +++ b/client/components/boards/boardHeader.css @@ -22,918 +22,90 @@ padding: 0.7vh 0.7vw; } -/* Zoom and Mobile Mode Controls */ -.board-header-btns.center { +.board-header { + display: grid; + flex: 1; + gap: 0.3lh; +} + +body { + &.mobile-mode { + .board-header { + flex-wrap: wrap; + } + } + &:not(.mobile-mode) { + .header-board-menu { + flex: 1; + } + .board-header { + justify-content: space-between; + grid-auto-flow: column; + } + .board-header-btns-left { + flex: 1; + justify-content: center; + } + .board-header-btns-right { + flex-grow: 0; + justify-content: end; + } + & .board-header-btns-right, + & .board-header-btns-left, + & .header-board-menu { + align-self: center; + align-items: center; + display: flex; + gap: 1.5ch; + overflow-wrap: normal; + } + } +} + +/* Make some space on intermediate layouts */ +@media screen and (max-width: 1200px) { + .board-header-btns-right span { + display: none !important; + } +} +.header-board-menu, .board-header-btns { display: flex; + align-self: center; align-items: center; justify-content: center; - flex: 1; + gap: 1ch; + & p { + margin: 0; + } } -.zoom-controls { +.board-header-btns-right > a { + flex-wrap: no-wrap; +} +body.mobile-mode { + header-board-menu h1 { + font-size: 2em; + } + .board-header-btn { + /* avoid wrapping if possible, at the cost of little icons */ + font-size: 0.5em; + /* no much choice because the way FA icons are inserted */ + padding-top: 0.1lh; + min-height: 0.8lh; + } + .board-header-btns-right { + display: grid; + grid-auto-flow: column; + grid-template-columns: repeat(auto-fit, 1fr); + flex: 1; + gap: 1ch; + justify-content: start; + align-items: center; + } +} +.board-header-btns-left { 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: 7px !important; - font-size: clamp(16px, 3vw, 20px) !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: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !important; - overflow-x: hidden !important; - overflow-y: auto !important; -} - - .mobile-mode .swimlane { - display: block !important; - width: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !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: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !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: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !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: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !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: 100vw !important; - max-width: 100vw !important; - min-width: 100vw !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; + flex: 1; + gap: 2ch; + padding: 0 0.5ch; } diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade index 76fd8a25a..441f821ef 100644 --- a/client/components/boards/boardHeader.jade +++ b/client/components/boards/boardHeader.jade @@ -1,26 +1,67 @@ template(name="boardHeaderBar") - h1.header-board-menu - with currentBoard - if $eq title 'Templates' - | {{_ 'templates'}} - else - +viewer - = title + .board-header + .header-board-menu + with currentBoard + if $eq title 'Templates' + | {{_ 'templates'}} + else + +viewer + = title + if currentBoard + if currentUser + with currentBoard + if currentUser.isBoardAdmin + a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}" title="{{_ 'edit'}}" value=title) + i.fa.fa-pencil-square-o + unless isMiniScreen + .board-header-btns-left + if currentBoard + if currentUser + with currentBoard + a.board-header-btn( + class="{{#if currentUser.isBoardAdmin}}js-change-visibility{{else}}is-disabled{{/if}}" + title="{{_ currentBoard.permission}}") + i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") + span {{_ currentBoard.permission}} - .board-header-btns.left - unless isMiniScreen + a.board-header-btn.js-watch-board( + title="{{_ watchLevel }}") + if $eq watchLevel "watching" + i.fa.fa-eye + if $eq watchLevel "tracking" + i.fa.fa-bell + if $eq watchLevel "muted" + i.fa.fa-bell-slash + span {{_ watchLevel}} + a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}" title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}") + i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") + if showStarCounter + span.board-star-counter {{currentBoard.stars}} + a.board-header-btn(title="{{_ 'sort-cards'}}" class="{{#if isSortActive }}emphasis{{else}} js-sort-cards {{/if}}") + i.fa.fa-sort + span {{#if isSortActive }}{{_ 'sort-is-on'}}{{else}}{{_ 'sort-cards'}}{{/if}} + if isSortActive + a.board-header-btn-close.js-sort-reset(title="{{_ 'remove-sort'}}") + i.fa.fa-times-thin + + else + a.board-header-btn.js-log-in( + title="{{_ 'log-in'}}") + i.fa.fa-sign-in + span {{_ 'log-in'}} + + .board-header-btns-right + .separator if currentBoard - if currentUser - with currentBoard - if currentUser.isBoardAdmin + if isMiniScreen + if currentUser + with currentBoard a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}" title="{{_ 'edit'}}" value=title) i.fa.fa-pencil-square-o - - a.board-header-btn( - class="{{#if currentUser.isBoardAdmin}}js-change-visibility{{else}}is-disabled{{/if}}" - title="{{_ currentBoard.permission}}") - i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") - span {{_ currentBoard.permission}} + a.board-header-btn( + class="{{#if currentUser.isBoardAdmin}}js-change-visibility{{else}}is-disabled{{/if}}" + title="{{_ currentBoard.permission}}") + i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") a.board-header-btn.js-watch-board( title="{{_ watchLevel }}") @@ -29,86 +70,43 @@ template(name="boardHeaderBar") if $eq watchLevel "tracking" i.fa.fa-bell if $eq watchLevel "muted" - i.fa.fa-bell-slash - span {{_ watchLevel}} - a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}" - title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}") - i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") - if showStarCounter - span.board-star-counter {{currentBoard.stars}} - a.board-header-btn(title="{{_ 'sort-cards'}}" class="{{#if isSortActive }}emphasis{{else}} js-sort-cards {{/if}}") - i.fa.fa-sort - span {{#if isSortActive }}{{_ 'sort-is-on'}}{{else}}{{_ 'sort-cards'}}{{/if}} - if isSortActive - a.board-header-btn-close.js-sort-reset(title="{{_ 'remove-sort'}}") - i.fa.fa-times-thin - - else - a.board-header-btn.js-log-in( - title="{{_ 'log-in'}}") - i.fa.fa-sign-in - span {{_ 'log-in'}} - - .board-header-btns.center - - .board-header-btns.right - if currentBoard - if isMiniScreen - if currentUser - with currentBoard - a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}" title="{{_ 'edit'}}" value=title) - i.fa.fa-pencil-square-o - - a.board-header-btn( - class="{{#if currentUser.isBoardAdmin}}js-change-visibility{{else}}is-disabled{{/if}}" - title="{{_ currentBoard.permission}}") - i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") - - a.board-header-btn.js-watch-board( - title="{{_ watchLevel }}") - if $eq watchLevel "watching" - i.fa.fa-eye - if $eq watchLevel "tracking" i.fa.fa-bell - if $eq watchLevel "muted" - i.fa.fa-bell-slash a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}" title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}") i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") a.board-header-btn(title="{{_ 'sort-cards'}}" class="{{#if isSortActive }}emphasis{{else}} js-sort-cards {{/if}}") i.fa.fa-sort - span {{#if isSortActive }}{{_ 'sort-is-on'}}{{else}}{{_ 'sort-cards'}}{{/if}} if isSortActive a.board-header-btn-close.js-sort-reset(title="{{_ 'remove-sort'}}") i.fa.fa-times-thin - else - a.board-header-btn.js-log-in( - title="{{_ 'log-in'}}") - i.fa.fa-sign-in + else + a.board-header-btn.js-log-in( + title="{{_ 'log-in'}}") + i.fa.fa-sign-in - if isSandstorm - if currentUser - a.board-header-btn.js-open-archived-board - i.fa.fa-archive + if isSandstorm + if currentUser + a.js-open-archived-board + i.fa.fa-archive - //if showSort - // a.board-header-btn.js-open-sort-view(title="{{_ 'sort-desc'}}") - // i.fa(class="{{directionClass}}") - // span {{_ 'sort'}}{{_ listSortShortDesc}} + //if showSort + // a.board-header-btn.js-open-sort-view(title="{{_ 'sort-desc'}}") + // i.fa(class="{{directionClass}}") + // span {{_ 'sort'}}{{_ listSortShortDesc}} - a.board-header-btn.js-open-filter-view( - title="{{#if Filter.isActive}}{{_ 'filter-on-desc'}}{{else}}{{_ 'filter'}}{{/if}}" - class="{{#if Filter.isActive}}js-filter-active{{/if}}") - i.fa.fa-filter - span {{#if Filter.isActive}}{{_ 'filter-on-desc'}}{{else}}{{_ 'filter'}}{{/if}} - if Filter.isActive - a.board-header-btn-close.js-filter-reset(title="{{_ 'filter-clear'}}") - i.fa.fa-times-thin + a.board-header-btn.js-open-filter-view( + title="{{#if Filter.isActive}}{{_ 'filter-on-desc'}}{{else}}{{_ 'filter'}}{{/if}}" + class="{{#if Filter.isActive}}js-filter-active{{/if}}") + i.fa.fa-filter + span {{#if Filter.isActive}}{{_ 'filter-on-desc'}}{{else}}{{_ 'filter'}}{{/if}} + if Filter.isActive + a.board-header-btn-close.js-filter-reset(title="{{_ 'filter-clear'}}") + i.fa.fa-times-thin - a.board-header-btn.js-open-search-view(title="{{_ 'search'}}") - i.fa.fa-search - span {{_ 'search'}} + a.board-header-btn.js-open-search-view(title="{{_ 'search'}}") + i.fa.fa-search + span {{_ 'search'}} unless currentBoard.isTemplatesBoard a.board-header-btn.js-toggle-board-view @@ -140,9 +138,9 @@ template(name="boardHeaderBar") a.board-header-btn-close.js-multiselection-reset(title="{{_ 'filter-clear'}}") i.fa.fa-times-thin - .separator - a.board-header-btn.js-toggle-sidebar(title="{{_ 'sidebar-open'}} {{_ 'or'}} {{_ 'sidebar-close'}}") - i.fa.fa-bars + .separator + a.board-header-btn.js-toggle-sidebar(title="{{_ 'sidebar-open'}} {{_ 'or'}} {{_ 'sidebar-close'}}") + i.fa.fa-bars template(name="boardVisibilityList") ul.pop-over-list @@ -172,26 +170,29 @@ template(name="boardChangeWatchPopup") li with "watching" a.js-select-watch - i.fa.fa-eye - | {{_ 'watching'}} - if watchCheck - i.fa.fa-check + span + i.fa.fa-eye + | {{_ 'watching'}} + if watchCheck + i.fa.fa-check span.sub-name {{_ 'watching-info'}} li with "tracking" a.js-select-watch - i.fa.fa-bell - | {{_ 'tracking'}} - if watchCheck - i.fa.fa-check + span + i.fa.fa-bell + | {{_ 'tracking'}} + if watchCheck + i.fa.fa-check span.sub-name {{_ 'tracking-info'}} li with "muted" a.js-select-watch - i.fa.fa-bell-slash - | {{_ 'muted'}} - if watchCheck - i.fa.fa-check + span + i.fa.fa-bell-slash + | {{_ 'muted'}} + if watchCheck + i.fa.fa-check span.sub-name {{_ 'muted-info'}} template(name="boardChangeViewPopup") @@ -247,12 +248,13 @@ template(name="createBoard") .materialCheckBox#add-template-container span {{_ 'add-template-container'}} input.primary.wide(type="submit" value="{{_ 'create'}}") - span.quiet - | {{_ 'or'}} - a.js-import-board {{_ 'import'}} - span.quiet - | / - a.js-board-template {{_ 'template'}} + .create-element-foooter + span.quiet + | {{_ 'or'}} + a.js-import-board {{_ 'import'}} + span.quiet + | / + a.js-board-template {{_ 'template'}} template(name="createBoardPopup") form @@ -276,12 +278,13 @@ template(name="createBoardPopup") .materialCheckBox#add-template-container span {{_ 'add-template-container'}} input.primary.wide(type="submit" value="{{_ 'create'}}") - span.quiet - | {{_ 'or'}} - a.js-import-board {{_ 'import'}} - span.quiet - | / - a.js-board-template {{_ 'template'}} + .create-element-foooter + span.quiet + | {{_ 'or'}} + a.js-import-board {{_ 'import'}} + span.quiet + | / + a.js-board-template {{_ 'template'}} // New popup for Template Container creation; shares the same form content template(name="createTemplateContainerPopup") @@ -305,13 +308,14 @@ template(name="createTemplateContainerPopup") a.flex.js-toggle-add-template-container .materialCheckBox#add-template-container span {{_ 'add-template-container'}} - input.primary.wide(type="submit" value="{{_ 'create'}}") - span.quiet - | {{_ 'or'}} - a.js-import-board {{_ 'import'}} - span.quiet - | / - a.js-board-template {{_ 'template'}} + .create-element-foooter + input.primary.wide(type="submit" value="{{_ 'create'}}") + span.quiet + | {{_ 'or'}} + a.js-import-board {{_ 'import'}} + span.quiet + | / + a.js-board-template {{_ 'template'}} //template(name="listsortPopup") // h2 @@ -362,4 +366,3 @@ template(name="cardsSortPopup") a.js-sort-created-asc i.fa.fa-arrow-up | {{_ 'created-at-oldest-first'}} - diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js index 7317a7501..4fef70ef3 100644 --- a/client/components/boards/boardHeader.js +++ b/client/components/boards/boardHeader.js @@ -33,9 +33,6 @@ BlazeComponent.extendComponent({ const currentBoard = Utils.getCurrentBoard(); return currentBoard && currentBoard.getWatchLevel(Meteor.userId()); }, - - - isStarred() { const boardId = Session.get('currentBoard'); const user = ReactiveCache.getCurrentUser(); @@ -182,7 +179,7 @@ Template.boardHeaderBar.helpers({ if (!sortBy) { return '🃏'; // Card icon when nothing is selected } - + // Determine which sort option is active based on sortBy object if (sortBy.dueAt) { return '📅'; // Due date icon @@ -191,7 +188,7 @@ Template.boardHeaderBar.helpers({ } else if (sortBy.createdAt) { return sortBy.createdAt === 1 ? '⬆️' : '⬇️'; // Up/down arrow based on direction } - + return '🃏'; // Default card icon }, }); diff --git a/client/components/boards/boardsList.css b/client/components/boards/boardsList.css index 9ba4ee1c7..66c17404a 100644 --- a/client/components/boards/boardsList.css +++ b/client/components/boards/boardsList.css @@ -1,7 +1,7 @@ @import url("../../../css/reset.css") print, screen; -/* Board List Header with Zoom Controls */ -.board-list-header { +/* Board List Header */ +.board-list-header:not(:empty) { display: flex; justify-content: center; margin: 1vh 0 2vh 0; @@ -11,42 +11,57 @@ /* Two-column layout for All Boards */ .boards-layout { display: grid; - grid-template-columns: 260px 1fr; - gap: 16px; + gap: 1ch; + /* menu takes the space it needs, boards has the rest */ + grid-template-columns: minmax(max-content, 250px) 1fr; + justify-content: stretch; + align-items: stretch; +} + +body:not(.mobile-mode) .boards-layout { + padding: 1vmax; +} + +body.mobile-mode .boards-layout { + grid-auto-flow: row; + grid-template-rows: 1fr auto; + grid-template-columns: minmax(auto, 100vw); } .boards-left-menu { + display: flex; + flex-direction: column; + align-items: stretch; border-right: 1px solid #e0e0e0; - padding-right: 12px; + overflow: visible; + align-self: stretch; + min-width: max-content; + flex: 1; } -.boards-left-menu ul.menu { - list-style: none; - padding: 0; - margin: 0 0 12px 0; -} - -.boards-left-menu .menu-item { - margin: 4px 0; -} .boards-left-menu .menu-item a { display: flex; justify-content: space-between; align-items: center; - padding: 8px 10px; - border-radius: 4px; + border-radius: 0.4ch; cursor: pointer; } .boards-left-menu .menu-item .menu-label { flex: 1; + padding: 0.3lh; } .boards-left-menu .menu-item .menu-count { + display: flex; + align-items: center; + justify-content: center; background: #ddd; - padding: 2px 8px; - border-radius: 12px; - font-size: 12px; + margin-right: 0.4ch; + aspect-ratio: 1 / 1; + border-radius: 50%; + padding: 0.2em; + font-size: 0.8em; + min-width: 3ch; font-weight: bold; - margin-left: 8px; } .boards-left-menu .menu-item.active a, .boards-left-menu .menu-item a:hover { @@ -62,19 +77,29 @@ border: 2px dashed #2196F3; } +.boards-right-grid { + display: flex; + flex-direction: column; + gap: 1vmax; + /* hackish way to make the item grow only when wrapping, i.e. with no + other competing item on the cross axis */ + flex: 10 1 0; +} + .workspaces-header { display: flex; align-items: center; justify-content: space-between; font-weight: bold; - margin-top: 12px; + padding: 0.3lh 0.8ch; + gap: 0.3lh; } .workspaces-header .js-add-space { text-decoration: none; font-weight: bold; border: 1px solid #ccc; padding: 2px 8px; - border-radius: 4px; + border-radius: 0.4ch; } .workspace-tree { @@ -90,9 +115,11 @@ .workspace-node-content { display: flex; align-items: center; - gap: 4px; - padding: 4px; - border-radius: 4px; + gap: 2ch; + justify-content: end; + flex: 1; + padding: 0.3lh 1ch 0 2ch; + border-radius: 0.4ch; transition: background-color 0.2s; } @@ -109,7 +136,6 @@ .workspace-drag-handle { cursor: grab; color: #999; - font-size: 14px; padding: 0 4px; user-select: none; } @@ -123,14 +149,13 @@ align-items: center; gap: 6px; padding: 4px 8px; - border-radius: 4px; + border-radius: 0.4ch; cursor: pointer; flex: 1; text-decoration: none; } .workspace-node .workspace-icon { - font-size: 16px; line-height: 1; } @@ -142,7 +167,6 @@ background: #ddd; padding: 2px 6px; border-radius: 10px; - font-size: 11px; font-weight: bold; min-width: 20px; text-align: center; @@ -154,7 +178,6 @@ border-radius: 3px; cursor: pointer; text-decoration: none; - font-size: 14px; opacity: 0.6; transition: opacity 0.2s; } @@ -174,71 +197,89 @@ background: #bbb; } -.boards-right-grid { - min-height: 200px; +.boards-left-menu .menu { + display: flex; + flex-direction: column; + gap: 0.3lh; + padding-bottom: 0.3lh; } - .boards-path-header { display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - padding: 12px 16px; - margin-bottom: 16px; + flex-direction: column; background: #f5f5f5; border-radius: 6px; - font-size: 16px; font-weight: 500; + min-height: 2lh; + justify-content: center; + + .path-left { + display: flex; + align-items: center; + gap: 1ch; + flex: 1; + } + .path-top { + display: flex; + flex: 1; + justify-content: center; + gap: 1ch; + } + .path-bottom { + display: flex; + align-items: stretch; + justify-content: space-between; + gap: 1ch; + padding: 0 0.5ch; + } } -.boards-path-header .path-left { - display: flex; - align-items: center; - gap: 8px; - flex: 1; -} - -.boards-path-header .multiselection-hint { +.multiselection-hint { background: #FFF3CD; color: #856404; - padding: 4px 12px; - border-radius: 4px; - font-size: 13px; + border-radius: 0.4ch; + padding: 0.2lh 0.5ch; font-weight: normal; border: 1px solid #FFE69C; animation: pulse 2s ease-in-out infinite; + display: flex; + flex: 1; + font-size: 0.8em; + >span { + flex: 1; + align-self: center; + } } @keyframes pulse { 0%, 100% { opacity: 1; } - 50% { opacity: 0.7; } + 50% { opacity: 0; } } .boards-path-header .path-right { display: flex; align-items: center; - gap: 8px; + gap: 0.5lh; + +} + +.boards-path-header .path-right button { + margin: 0; } .boards-path-header .path-icon { - font-size: 18px; -} + } .boards-path-header .path-text { color: #333; } .boards-path-header .board-header-btn { - padding: 6px 12px; - background: #fff; - border: 1px solid #ddd; - border-radius: 4px; - cursor: pointer; + min-width: 4ch; + min-height: 4ch; display: flex; + justify-content: center; + align-self: center; align-items: center; - gap: 6px; - font-size: 14px; - transition: all 0.2s; } .boards-path-header .board-header-btn:hover { @@ -246,13 +287,22 @@ border-color: #bbb; } -.boards-path-header .board-header-btn.emphasis { - background: #2196F3; - color: #fff; - border-color: #2196F3; +.boards-path-header .board-header-btn.js-multiselection-activate { + &.emphasis { + background: #2196F3; + color: #fff; + border-color: #2196F3; + box-shadow: 0 2px 8px rgba(33, 150, 243, 0.5); + } font-weight: bold; - box-shadow: 0 2px 8px rgba(33, 150, 243, 0.5); - transform: scale(1.05); + align-self: stretch; + align-items: center; + display: flex; + justify-content: center; + flex: 1; + min-width: 4ch; + font-size: 1em; + border-radius: 0.6ch; } .boards-path-header .board-header-btn.emphasis:hover { @@ -261,101 +311,42 @@ } .boards-path-header .board-header-btn-close { - padding: 4px 10px; + align-self: stretch; + align-items: center; + display: flex; + justify-content: center; + flex: 1; + border-radius: 0.6ch; + min-width: 4ch; background: #f44336; color: #000; border: none; - border-radius: 4px; cursor: pointer; - font-size: 16px; - margin-left: 10px; /* Extra space between MultiSelection toggle and Remove Filter */ + font-size: 1em; } .boards-path-header .board-header-btn-close:hover { background: #d32f2f; } -.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; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(30ch, 1fr)); + grid-auto-rows: 7lh; + gap: 0.5lh 0.5lh; + align-items: start; } -.board-list li { - float: left; - width: 20%; - box-sizing: border-box; - position: relative; + +.board-list .details { + height: fit-content; +} + +.board-list .board-list-item-name .viewer { + min-height: 0; +} + +.board-list .board-list-item-name p { + margin: 0; } .board-list li.placeholder:after { content: ''; @@ -380,21 +371,59 @@ .board-list li:hover .is-not-star-active { opacity: 1; } +.board-list { + .js-board, .js-add-board { + display: flex; + overflow: hidden; + background-color: inherit; + min-height: 4lh !important; + min-width: min-content; + height: 100%; + /* Inherit board color from parent li.js-board */ + color: #f6f6f6; + border-radius: 0.5ch; + /* No border-radius - parent .js-board has it */ + font-weight: 700; + position: relative; + text-decoration: none; + overflow-wrap: break-word; + box-sizing: border-box; + justify-content: center; + align-items: stretch; + >a { + display: flex; + align-items: center; + justify-content: stretch; + flex: 1; + } + } + .board-list-item { + display: flex; + text-align: center; + justify-content: center; + align-items: center; + gap: 1ch; + flex: 1; + padding: 0 1ch; + } +} + +.board-list .board-list-item .board-card-header { + display: flex; + justify-content: center; + align-items: center; + gap: 0.3lh; +} + .board-list .board-list-item { - overflow: hidden; - background-color: inherit; /* Inherit board color from parent li.js-board */ - color: #f6f6f6; - min-height: 100px; - font-size: 16px; - line-height: 22px; - border-radius: 0; /* No border-radius - parent .js-board has it */ - display: block; - font-weight: 700; - padding: 36px 8px 32px 8px; /* Top padding for drag handle, bottom for checkbox */ - margin: 0; /* No margin - moved to parent .js-board */ - position: relative; - text-decoration: none; - word-wrap: break-word; + font-size: var(--list-item-size); +} + +.board-list .board-list-item .board-card-footer { + display: flex; + justify-content: center; + box-sizing: border-box; + padding: 0.1ch 0.1lh; } .board-list .board-list-item > .js-open-board { @@ -402,9 +431,6 @@ color: inherit; display: block; } -.board-list .board-list-item.template-container { - border: 4px solid #fff; -} .board-list .board-list-item.tile { background-size: auto; background-repeat: repeat; @@ -412,30 +438,23 @@ .board-list .board-list-item-sub-name { color: rgba(255,255,255,0.5); display: block; - font-size: 14px; font-weight: 400; line-height: 22px; } .board-list .board-list-item-desc { color: #fff; display: block; - font-size: 14px; font-weight: 400; line-height: 18px; } -.board-list .js-add-board { - text-align: center; -} .board-list .js-add-board .label { font-weight: normal; - line-height: 56px; - min-height: 100px; display: flex; align-items: center; + font-size: var(--list-item-size); + font-weight: bold; justify-content: center; background-color: #999; /* Darker background for better text contrast */ - border-radius: 3px; - padding: 36px 8px 32px 8px; color: #fff; /* White text */ } .board-list .js-add-board .label i { @@ -449,23 +468,12 @@ } .board-list .is-star-active, .board-list .is-not-star-active { - top: 0; - font-size: 14px; - height: 18px; - line-height: 18px; opacity: 0; - padding: 9px 9px; - position: absolute; - right: 0; transition-duration: 0.15s; transition-property: color, font-size, background; } .board-list .fa-circle { bottom: 0; - font-size: 10px; - height: 10px; - line-height: 10px; - padding: 9px 9px; position: absolute; right: 0; transition-duration: 0.15s; @@ -481,26 +489,13 @@ color: #fff; } .board-list .fa-clone { - position: absolute; - bottom: 0; - font-size: 14px; - height: 18px; line-height: 18px; - opacity: 0; - right: 0; - padding: 9px 9px; transition-duration: 0.15s; transition-property: color, font-size, background; } .board-list .fa-archive { position: absolute; - bottom: 0; - font-size: 14px; - height: 18px; - line-height: 18px; opacity: 0; - left: 0; - padding: 9px 9px; transition-duration: 0.15s; transition-property: color, font-size, background; } @@ -521,7 +516,6 @@ .board-list li:hover a .fa-clone:hover, .board-list li:hover a .fa-archive:hover, .board-list li:hover a .is-not-star-active:hover { - font-size: 18px; opacity: 1; } .board-list li:hover a .is-star-active, @@ -533,15 +527,9 @@ /* Board drag handle - always visible and positioned at top */ .board-list .board-handle { - position: absolute; - padding: 4px 6px; - top: 4px; - left: 50%; - transform: translateX(-50%); - font-size: 14px; color: #fff; background: rgba(0,0,0,0.4); - border-radius: 4px; + border-radius: 0.4ch; display: flex; align-items: center; justify-content: center; @@ -561,53 +549,75 @@ color: #000; } -/* Multiselection checkbox on board items */ -.board-list .board-list-item .multi-selection-checkbox { - position: absolute !important; - bottom: 4px !important; - left: 4px !important; - top: auto !important; - width: 24px; - height: 24px; - border: 3px solid #fff; - background: rgba(0,0,0,0.5); - border-radius: 4px; - cursor: pointer; - z-index: 11; - display: flex; - align-items: center; - justify-content: center; - transition: all 0.2s; - box-shadow: 0 2px 4px rgba(0,0,0,0.3); - transform: none !important; - margin: 0 !important; +/* used to animate checkbox when added +without messing with the event/activation system */ +@keyframes revealCheckBox { + from { opacity: 0; } + to { opacity: 1; } } -.board-list .board-list-item .multi-selection-checkbox:hover { - background: rgba(0,0,0,0.7); - transform: scale(1.15) !important; - box-shadow: 0 3px 6px rgba(0,0,0,0.5); +.board-list .board-list-item .multi-selection-checkbox{ + display: flex; + align-self: center; + width: 2ch; + height: 2ch; } .board-list .board-list-item .multi-selection-checkbox.is-checked { background: #3cb500; border-color: #3cb500; box-shadow: 0 2px 8px rgba(60, 181, 0, 0.6); - width: 24px !important; - height: 24px !important; + width: 2ch !important; + height: 2ch !important; top: auto !important; - left: 4px !important; transform: none !important; - border-radius: 4px !important; + border-radius: 0.4ch !important; } .board-list .board-list-item .multi-selection-checkbox.is-checked::after { content: '✓'; color: #fff; - font-size: 16px; font-weight: bold; + position: absolute; + left: 0.4ch; + top: -0.2ch; } +/* Multiselection checkbox on board items */ +.board-list .board-list-item .multi-selection-checkbox:where(.active) { + border: none; + box-shadow: 0 0 0 3px #fff; + /* get back margin from box-shadow */ + background: rgba(0,0,0,0.5); + outline-color: transparent; + border-radius: 0.4ch; + cursor: pointer; + z-index: 11; + align-items: center; + justify-content: center; + animation: 0.2s ease-out 0s 1 revealCheckBox; + + + &:hover { + background: rgba(0, 0, 0, 0.7); + transform: scale(1.15) !important; + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.5); + } + + &.is-checked { + background: #3cb500; + border-color: #3cb500; + box-shadow: 0 3px 6px #3cb500; + + &::after {content: '✅'; + color: #fff; + font-size: 1em; + font-weight: bold; + } + } +} + + /* Grey checkboxes when grey icons setting is enabled */ body.grey-icons-enabled .board-list .board-list-item .multi-selection-checkbox.is-checked { background: #7a7a7a; @@ -622,48 +632,41 @@ body.grey-icons-enabled .board-list.is-multiselection-active .js-board.is-checke .board-list.is-multiselection-active .js-board.is-checked { outline: 4px solid #3cb500; - outline-offset: -4px; + outline-offset: -2px; box-shadow: 0 4px 12px rgba(60, 181, 0, 0.4); } /* Visual hint when multiselection is active */ .board-list.is-multiselection-active .board-list-item { - border: 2px dashed rgba(33, 150, 243, 0.3); + outline: 2px dashed rgba(33, 150, 243, 0.3); +} + +.board-backgrounds-list { + display: grid; + grid-template-columns: 1fr 1fr; + grid-auto-rows: 3lh; + justify-items: stretch; + gap: 1ch; } .board-backgrounds-list .board-background-select { box-sizing: border-box; - display: block; - float: left; - width: 50%; - padding-top: 12px; + display: flex; position: relative; z-index: 1; } -.board-backgrounds-list .board-background-select:nth-child(-n + 2) { - padding-top: 0; -} -.board-backgrounds-list .board-background-select:nth-child(2n) { - padding-left: 6px; -} -.board-backgrounds-list .board-background-select:nth-child(2n+1) { - padding-right: 6px; -} .board-backgrounds-list .board-background-select .background-box { color: #fff; - border-radius: 3px; - background-size: cover; - display: block; - height: 74px; - position: relative; - width: 100%; - cursor: pointer; display: flex; + border-radius: 0.4ch; + flex: 1; align-items: center; justify-content: center; + gap: 1ch; + font-size: 1.1em; + cursor: pointer; } .board-backgrounds-list .board-background-select .background-box i.fa-check { - font-size: 25px; color: #3cb500; } /* Grey check icons when grey icons setting is enabled */ @@ -679,56 +682,20 @@ body.grey-icons-enabled .checkmark-no-grey { /* Mobile view styles - applied when isMiniScreen is true (iPhone, etc.) */ .board-list.mobile-view { - 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: 100%; - float: none; - display: block; - margin-bottom: 1rem; - padding-right: 50px; /* Space for drag handle */ -} -.board-list.mobile-view .board-list-item { - overflow: visible; - height: 8rem; - width: 100%; - margin: 0; - padding-right: 50px; /* Ensure content doesn't overlap with drag handle */ + display: flex; + flex-direction: column; + align-items: stretch; + margin: 0 0.5ch; + gap: 0.3lh; } -.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; - top: -100px; - left: -100px; -} -.board-list.mobile-view .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; - z-index: 10; - transition: background-color 0.2s ease; + position: relative;; } .board-list.mobile-view .board-handle:hover { @@ -760,11 +727,6 @@ body.grey-icons-enabled .checkmark-no-grey { 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 */ -} - /* Hide archive and clone board buttons in mobile view */ .board-list.mobile-view .js-archive-board, .board-list.mobile-view .js-clone-board { @@ -777,368 +739,11 @@ body.grey-icons-enabled .checkmark-no-grey { font-family: inherit !important; } -.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), - screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - .board-list { - height: 100%; - overflow-y: auto; - overflow-x: hidden; - padding: 0 1rem; - margin: 0; - } - .board-list li { - width: 100%; - float: none; - display: block; - margin-bottom: 1rem; - padding-right: 50px; /* Space for drag handle */ - } - .board-list .board-list-item { - 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; - top: -100px; - left: -100px; - } - .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; - z-index: 10; - transition: background-color 0.2s ease; - } - - .board-list .board-handle:hover { - background: rgba(255, 255, 0, 0.8) !important; /* Yellow hover */ - } -} -/* 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), - screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - .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 { list-style-type: none; overflow: hidden; } -.AllBoardTeams, -.AllBoardOrgs, -.AllBoardBtns { - float: left; -} -.js-AllBoardOrgs { - margin-left: 16px; -} -.AllBoardTeams { - margin-left: 16px; -} -.AllBoardButtonsContainer { - margin: 16px; -} #filterBtn, #resetBtn { display: inline; @@ -1148,10 +753,8 @@ body.grey-icons-enabled .checkmark-no-grey { background: #f44336; color: #000; border: none; - border-radius: 4px; - padding: 6px 12px; + border-radius: 0.4ch; cursor: pointer; - font-size: 14px; display: inline-flex; align-items: center; gap: 6px; @@ -1163,21 +766,17 @@ body.grey-icons-enabled .checkmark-no-grey { } #resetBtn.filter-reset-btn .reset-icon { - font-size: 14px; -} + } .js-board { - display: block; background-color: #999; /* Default gray background if no color class is applied */ border-radius: 3px; /* Rounded corners for board items */ overflow: hidden; /* Ensure children respect rounded corners */ - margin: 8px; /* Space between board items */ } /* Reset background for add-board button */ .js-add-board { background-color: transparent !important; - margin: 8px !important; /* Keep margin for add-board */ } /* Apply board colors to li.js-board parent instead of just the link */ @@ -1200,13 +799,10 @@ body.grey-icons-enabled .checkmark-no-grey { .board-list .board-color-exodark { background-color: #222; } .minicard-members { - padding: 6px 0 6px 8px; - width: 100%; - margin-bottom: 2px; - margin-left: -4px; - display: inline-block; + display: flex; + justify-content: stretch; } -.minicard-lists { +.minicard-lists:has(*) { margin: 0 auto; max-width: 95%; height: 100%; @@ -1232,7 +828,6 @@ body.grey-icons-enabled .checkmark-no-grey { screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { .wrapper { overflow: hidden; - height: 100vh; } .board-list { @@ -1241,7 +836,6 @@ body.grey-icons-enabled .checkmark-no-grey { -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 */ @@ -1278,14 +872,6 @@ body.grey-icons-enabled .checkmark-no-grey { .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 */ @@ -1295,6 +881,8 @@ body.grey-icons-enabled .checkmark-no-grey { #content { overflow: hidden; + display: flex; + flex: 1; } /* Hide archive and clone board buttons in mobile view */ @@ -1309,4 +897,3 @@ body.grey-icons-enabled .checkmark-no-grey { font-family: inherit !important; } } - diff --git a/client/components/boards/boardsList.jade b/client/components/boards/boardsList.jade index aea3c2d8a..f9f57edf2 100644 --- a/client/components/boards/boardsList.jade +++ b/client/components/boards/boardsList.jade @@ -67,81 +67,71 @@ template(name="boardList") // Right boards grid .boards-right-grid .boards-path-header - .path-left - span.path-icon.emoji-icon {{currentMenuPath.icon}} - span.path-text {{currentMenuPath.text}} - if BoardMultiSelection.isActive - span.multiselection-hint - span.emoji-icon - i.fa.fa-thumb-tack - | {{_ 'multi-selection-active'}} - .path-right - if canModifyBoards - if hasBoardsSelected - button.js-archive-selected-boards.board-header-btn + .path-bottom + .path-left + span.path-icon.emoji-icon {{currentMenuPath.icon}} + span.path-text {{currentMenuPath.text}} + .path-right + unless isMiniScreen + +headerMultiSelection + if canModifyBoards + a.board-header-btn.js-multiselection-activate( + title="{{#if BoardMultiSelection.isActive}}{{_ 'multi-selection-on'}}{{else}}{{_ 'multi-selection'}}{{/if}}" + class="{{#if BoardMultiSelection.isActive}}emphasis{{/if}}") span.emoji-icon - i.fa.fa-archive - span {{_ 'archive-board'}} - button.js-duplicate-selected-boards.board-header-btn - span.emoji-icon - i.fa.fa-clipboard - span {{_ 'duplicate-board'}} - a.board-header-btn.js-multiselection-activate( - title="{{#if BoardMultiSelection.isActive}}{{_ 'multi-selection-on'}}{{else}}{{_ 'multi-selection'}}{{/if}}" - class="{{#if BoardMultiSelection.isActive}}emphasis{{/if}}") - span.emoji-icon - i.fa.fa-check-square-o - if BoardMultiSelection.isActive - a.board-header-btn-close.js-multiselection-reset(title="{{_ 'filter-clear'}}") - span.emoji-icon - i.fa.fa-times + i.fa.fa-check-square-o + if BoardMultiSelection.isActive + a.board-header-btn-close.js-multiselection-reset(title="{{_ 'filter-clear'}}") + span.emoji-icon + i.fa.fa-times ul.board-list.clearfix.js-boards(class="{{#if isMiniScreen}}mobile-view{{/if}} {{#if BoardMultiSelection.isActive}}is-multiselection-active{{/if}}") li.js-add-board if isSelectedMenu 'templates' a.board-list-item.label(title="{{_ 'add-template-container'}}") span.emoji-icon i.fa.fa-plus - | {{_ 'add-template-container'}} + | {{_ 'add-template-container'}} else a.board-list-item.label(title="{{_ 'add-board'}}") span.emoji-icon i.fa.fa-plus - | {{_ 'add-board'}} + | {{_ 'add-board'}} each boards li.js-board(class="{{_id}} {{#if isStarred}}starred{{/if}} {{colorClass}} {{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}", draggable="true") if isInvited .board-list-item - if BoardMultiSelection.isActive - .materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection( - class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}") - span.details - span.board-list-item-name= title + .board-card-header span.js-star-board( class="{{#if isStarred}}is-star-active{{else}}is-not-star-active{{/if}}" title="{{_ 'star-board-title'}}") span.emoji-icon - | {{#if isStarred}}⭐{{else}}☆{{/if}} + i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") + .board-card-body + span.details + span.board-list-item-name= title p.board-list-item-desc {{_ 'just-invited'}} button.js-accept-invite.primary {{_ 'accept'}} button.js-decline-invite {{_ 'decline'}} + .board-card-footer + .materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection( + class="{{#if BoardMultiSelection.isActive }}active{{/if}} {{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}") else if $eq type "template-container" - .template-container.board-list-item - if BoardMultiSelection.isActive - .materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection( - class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}") - span.board-handle(title="{{_ 'drag-board'}}") - span.emoji-icon - i.fa.fa-arrows - - a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}") + a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}") + .template-container.board-list-item + if BoardMultiSelection.isActive + .materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection( + class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}") + + span.details span.board-list-item-name(title="{{_ 'template-container'}}") +viewer = title - p.board-list-item-desc - +viewer - = description + //- #FIXME: is this obsolete ? + //- p.board-list-item-desc + //- +viewer + //- = description if hasSpentTimeCards span.js-has-spenttime-cards( class="{{#if hasOvertimeCards}}has-overtime-card-active{{else}}no-overtime-card-active{{/if}}" @@ -154,19 +144,20 @@ template(name="boardList") span.emoji-icon i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") else - .board-list-item - if BoardMultiSelection.isActive - .materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection( - class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}") - span.board-handle(title="{{_ 'drag-board'}}") - span.emoji-icon - i.fa.fa-arrows - - a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}") + a.js-open-board(href="{{pathFor 'board' id=_id slug=slug}}") + .board-list-item + if BoardMultiSelection.isActive + .materialCheckBox.multi-selection-checkbox.js-toggle-board-multi-selection( + class="{{#if BoardMultiSelection.isSelected _id}}is-checked{{/if}}") + + span.details span.board-list-item-name(title="{{_ 'board-drag-drop-reorder-or-click-open'}}") +viewer = title + //- p.board-list-item-desc + //- +viewer + //- = description unless currentSetting.hideBoardMemberList if allowsBoardMemberList .minicard-members @@ -175,34 +166,24 @@ template(name="boardList") +userAvatar(userId=member noRemove=true) unless currentSetting.hideCardCounterList if allowsCardCounterList - .minicard-lists.flex.flex-wrap + .minicard-lists each list in boardLists _id .item | {{ list }} - p.board-list-item-desc - +viewer - = description if hasSpentTimeCards span.js-has-spenttime-cards( class="{{#if hasOvertimeCards}}has-overtime-card-active{{else}}no-overtime-card-active{{/if}}" title="{{#if hasOvertimeCards}}{{_ 'has-overtime-cards'}}{{else}}{{_ 'has-spenttime-cards'}}{{/if}}") span.emoji-icon i.fa.fa-clock-o - a.js-star-board( - class="{{#if isStarred}}is-star-active{{else}}is-not-star-active{{/if}}" - title="{{_ 'star-board-title'}}") - span.emoji-icon - i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") + a.js-star-board( + class="{{#if isStarred}}is-star-active{{else}}is-not-star-active{{/if}}" + title="{{_ 'star-board-title'}}") + span.emoji-icon + i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}") template(name="boardListHeaderBar") h1 {{_ title }} - //.board-header-btns.right - // a.board-header-btn.js-open-archived-board - // i.fa.fa-archive - // span {{_ 'archives'}} - // a.board-header-btn(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}") - // i.fa.fa-clone - // span {{_ 'templates'}} // Recursive template for workspaces tree template(name="workspaceTree") @@ -214,7 +195,7 @@ template(name="workspaceTree") span.workspace-drag-handle span.emoji-icon i.fa.fa-arrows - + a.js-select-workspace(data-id="{{id}}") span.workspace-icon if icon @@ -231,3 +212,16 @@ template(name="workspaceTree") a.js-add-subworkspace(data-id="{{id}}" title="{{_ 'allboards.add-subworkspace'}}") + if children +workspaceTree(nodes=children selectedWorkspaceId=selectedWorkspaceId) + +template(name="headerMultiSelection") + if BoardMultiSelection.isActive + if canModifyBoards + if hasBoardsSelected + button.negate.js-archive-selected-boards.board-header-btn + span.emoji-icon + i.fa.fa-archive + span {{_ 'archive-board'}} + button.negate.js-duplicate-selected-boards.board-header-btn + span.emoji-icon + i.fa.fa-clipboard + span {{_ 'duplicate-board'}} \ No newline at end of file diff --git a/client/components/boards/boardsList.js b/client/components/boards/boardsList.js index fcb2461e6..26c6b532d 100644 --- a/client/components/boards/boardsList.js +++ b/client/components/boards/boardsList.js @@ -108,10 +108,7 @@ BlazeComponent.extendComponent({ const newTree = EJSON.clone(tree); // Remove the dragged space - const { tree: treeAfterRemoval, removed } = removeSpace( - newTree, - draggedSpaceId, - ); + const { tree: treeAfterRemoval, removed } = removeSpace(newTree, draggedSpaceId); if (removed) { // Insert after target @@ -127,46 +124,39 @@ BlazeComponent.extendComponent({ onRendered() { // jQuery sortable is disabled in favor of HTML5 drag-and-drop for space management // The old sortable code has been removed to prevent conflicts - /* OLD SORTABLE CODE - DISABLED - const itemsSelector = '.js-board:not(.placeholder)'; - const $boards = this.$('.js-boards'); - $boards.sortable({ - connectWith: '.js-boards', - tolerance: 'pointer', - appendTo: '.board-list', - helper: 'clone', - distance: 7, - items: itemsSelector, - placeholder: 'board-wrapper placeholder', - start(evt, ui) { - ui.helper.css('z-index', 1000); - ui.placeholder.height(ui.helper.height()); - EscapeActions.executeUpTo('popup-close'); - }, - async stop(evt, ui) { - const prevBoardDom = ui.item.prev('.js-board').get(0); - const nextBoardDom = ui.item.next('.js-board').get(0); - const sortIndex = Utils.calculateIndex(prevBoardDom, nextBoardDom, 1); + // #FIXME OLD SORTABLE CODE - WILL BE DISABLED + // + // const itemsSelector = '.js-board'; - const boardDomElement = ui.item.get(0); - const board = Blaze.getData(boardDomElement); - $boards.sortable('cancel'); - const currentUser = ReactiveCache.getCurrentUser(); - if (currentUser && typeof currentUser.setBoardSortIndex === 'function') { - await currentUser.setBoardSortIndex(board._id, sortIndex.base); - } - }, - }); + // const $boards = this.$('.js-boards'); + // $boards.sortable({ + // connectWith: '.js-boards', + // tolerance: 'pointer', + // appendTo: '.board-list', + // helper: 'clone', + // distance: 7, + // items: itemsSelector, + // placeholder: 'board-wrapper placeholder', + // start(evt, ui) { + // ui.helper.css('z-index', 1000); + // ui.placeholder.height(ui.helper.height()); + // EscapeActions.executeUpTo('popup-close'); + // }, + // async stop(evt, ui) { + // const prevBoardDom = ui.item.prev('.js-board').get(0); + // const nextBoardDom = ui.item.next('.js-board').get(0); + // const sortIndex = Utils.calculateIndex(prevBoardDom, nextBoardDom, 1); - this.autorun(() => { - if (Utils.isTouchScreenOrShowDesktopDragHandles()) { - $boards.sortable({ - handle: '.board-handle', - }); - } - }); - */ + // const boardDomElement = ui.item.get(0); + // const board = Blaze.getData(boardDomElement); + // $boards.sortable('cancel'); + // const currentUser = ReactiveCache.getCurrentUser(); + // if (currentUser && typeof currentUser.setBoardSortIndex === 'function') { + // await currentUser.setBoardSortIndex(board._id, sortIndex.base); + // } + // }, + // }); }, userHasTeams() { if (ReactiveCache.getCurrentUser()?.teams?.length > 0) return true; @@ -357,7 +347,7 @@ BlazeComponent.extendComponent({ const lists = ReactiveCache.getLists({ 'boardId': boardId, 'archived': false },{sort: ['sort','asc']}); const ret = lists.map(list => { let cardCount = ReactiveCache.getCards({ 'boardId': boardId, 'listId': list._id }).length; - return `${list.title}: ${cardCount}`; + return `${list.title}: ${cardCountcardCount}`; }); return ret; */ @@ -535,6 +525,7 @@ BlazeComponent.extendComponent({ 'click .js-multiselection-reset'(evt) { evt.preventDefault(); BoardMultiSelection.disable(); + Popup.close(); }, 'click .js-toggle-board-multi-selection'(evt) { evt.preventDefault(); @@ -708,6 +699,7 @@ BlazeComponent.extendComponent({ icon: newIcon || '📁', }); + Meteor.call('setWorkspacesTree', updatedTree, (err) => { if (err) console.error(err); }); @@ -808,6 +800,7 @@ BlazeComponent.extendComponent({ // Get the workspace ID directly from the dropped workspace-node's data-workspace-id attribute const workspaceId = targetEl.getAttribute('data-workspace-id'); + if (workspaceId) { if (isMultiBoard) { // Multi-board drag @@ -830,6 +823,7 @@ BlazeComponent.extendComponent({ evt.preventDefault(); evt.stopPropagation(); + const menuType = evt.currentTarget.getAttribute('data-type'); // Only allow drop on "remaining" menu to unassign boards from spaces if (menuType === 'remaining') { @@ -844,9 +838,11 @@ BlazeComponent.extendComponent({ evt.preventDefault(); evt.stopPropagation(); + const menuType = evt.currentTarget.getAttribute('data-type'); evt.currentTarget.classList.remove('drag-over'); + // Only handle drops on "remaining" menu if (menuType !== 'remaining') return; @@ -908,6 +904,7 @@ BlazeComponent.extendComponent({ }; const allBoards = ReactiveCache.getBoards(query, {}); + if (type === 'starred') { return allBoards.filter( (b) => currentUser && currentUser.hasStarred(b._id), diff --git a/client/components/boards/originalPositionsView.css b/client/components/boards/originalPositionsView.css index ec3abd4c5..920b3068f 100644 --- a/client/components/boards/originalPositionsView.css +++ b/client/components/boards/originalPositionsView.css @@ -23,7 +23,7 @@ .original-positions-content { background-color: white; border: 1px solid #dee2e6; - border-radius: 4px; + border-radius: 0.4ch; padding: 15px; } @@ -65,7 +65,7 @@ .original-position-item { background-color: #f8f9fa; border: 1px solid #e9ecef; - border-radius: 4px; + border-radius: 0.4ch; margin-bottom: 10px; padding: 12px; transition: all 0.2s ease; @@ -100,7 +100,7 @@ color: white; padding: 2px 6px; border-radius: 3px; - font-size: 11px; + font-weight: 500; text-transform: uppercase; } @@ -112,7 +112,7 @@ .entity-id { color: #6c757d; - font-size: 11px; + font-family: monospace; } @@ -123,12 +123,12 @@ .original-position-description { color: #495057; margin-bottom: 6px; - font-size: 13px; + } .original-title { color: #6c757d; - font-size: 12px; + margin-bottom: 6px; padding: 4px 6px; background-color: #e9ecef; @@ -141,7 +141,7 @@ .original-position-date { color: #6c757d; - font-size: 11px; + } .no-original-positions { @@ -152,7 +152,7 @@ } .no-original-positions i { - font-size: 24px; + margin-bottom: 10px; display: block; color: #adb5bd; @@ -164,32 +164,32 @@ margin: 5px 0; padding: 10px; } - + .original-positions-header { flex-direction: column; align-items: stretch; gap: 8px; } - + .original-positions-header .btn { justify-content: center; } - + .original-positions-filters .btn-group { justify-content: center; } - + .original-position-item-header { flex-wrap: wrap; gap: 6px; } - + .entity-name { flex: 1; min-width: 0; word-break: break-word; } - + .original-position-item-details { margin-left: 0; margin-top: 8px; @@ -203,60 +203,60 @@ border-color: #4a5568; color: #e2e8f0; } - + .original-positions-content { background-color: #1a202c; border-color: #4a5568; } - + .original-position-item { background-color: #2d3748; border-color: #4a5568; color: #e2e8f0; } - + .original-position-item:hover { background-color: #4a5568; border-color: #718096; } - + .original-position-item-header { color: #e2e8f0; } - + .original-position-item-header i { color: #a0aec0; } - + .entity-name { color: #e2e8f0; } - + .entity-id { color: #a0aec0; } - + .original-position-description { color: #e2e8f0; } - + .original-title { background-color: #4a5568; color: #a0aec0; } - + .original-title strong { color: #e2e8f0; } - + .original-position-date { color: #a0aec0; } - + .no-original-positions { color: #a0aec0; } - + .no-original-positions i { color: #718096; } diff --git a/client/components/cards/attachments.css b/client/components/cards/attachments.css index 97039dfe3..31f6747a9 100644 --- a/client/components/cards/attachments.css +++ b/client/components/cards/attachments.css @@ -6,75 +6,80 @@ font-weight: bold; } .attachment-gallery { - display: flex; - flex-direction: column; + display: grid; + grid-auto-flow: row; } .attachment-item { - display: flex; - flex-direction: row; + display: grid; + grid-template-columns: 10ch auto; align-items: center; - margin-top: 16px; + grid-template-rows: repeat(auto-fit, minmax(1.5lh, auto)); + justify-content: stretch; + gap: 2ch; + padding: 2ch; + border-radius: 0.6ch; } + .attachment-item:hover { background: #e0e0e0; } -.attachment-thumbnail-container { - display: block; - width: 150px; - min-width: 150px; - max-height: 150px; - padding-right: 16px; + +.attachment-details-container { + display: flex; + flex: 1; } + +.attachment-thumbnail-container { + display: flex; + flex: 1; + position: relative; +} + .attachment-thumbnail { - max-width: 150px; - max-height: 150px; - min-height: 2em; + /* more deterministic outcome */ + aspect-ratio: 1/1; + object-fit: cover; + max-width: 100%; cursor: pointer; + border-radius: 0.4ch; } .attachment-thumbnail-text { - min-height: 2em; - display: flex; - align-items: center; - justify-content: center; - font-size: 2em; - cursor: pointer; + flex: 1; + text-align: center; + border-radius: 2px; border: 1px solid #ccc; - border-radius: 5px; -} -.attachment-details-container { - display: block; - flex-grow: 1; } .attachment-details { display: flex; - justify-content: space-between; - margin-right: 25px; /* Make sure the icons are not to far to the right */ + flex: 1; + gap: 0.5ch; + align-items: center; } .attachment-actions { display: flex; flex-direction: row; align-items: center; + gap: 1.5ch; } -.attachment-actions a { - margin-left: 16px; -} -.attachment-actions a:first-child { - margin-left: 0; + +body.mobile-mode .attachment-actions { + flex-direction: column; + gap: 0; } + .add-attachment { + border: 1px dashed #555; + border-radius: .5ch; + cursor: pointer; + aspect-ratio: 1/1; + height: 1.5lh; display: flex; align-items: center; justify-content: center; - border: 1px dashed #555; - border-radius: 5px; - padding: 10px; - cursor: pointer; - margin-top: 16px; } .icon { font-size: 1.5em; cursor: pointer; - margin-left: 10px; } .icon:hover { color: #666; @@ -95,26 +100,25 @@ height: 100%; } #viewer-top-bar { - display: flex; - flex-direction: row; - justify-content: space-between; - width: 100%; - padding: 16px; + display: grid; + grid-template-columns: 1fr auto; + justify-content: center; + justify-items: center; + font-size: 2rem; + padding: 0.3lh 0.5ch; } #attachment-name { color: white; - font-size: 1.5em; - max-width: calc( - 100% - 50px - ); /* Make sure the name does not overlap the close button */ + text-overflow: ellipsis; + overflow: hidden; } #viewer-close { color: white; cursor: pointer; - font-size: 4em; position: absolute; right: 50px; top: 16px; + font-size: 2em; } /* Upload progress indicators for drag-and-drop uploads */ @@ -122,30 +126,24 @@ .card-details-upload-progress { background: #f8f9fa; border: 1px solid #e9ecef; - border-radius: 4px; - padding: 12px; - margin: 8px 0; - font-size: 14px; + border-radius: 0.4ch; + } .upload-progress-header { display: flex; align-items: center; - margin-bottom: 8px; font-weight: bold; color: #495057; } .upload-progress-header i { - margin-right: 8px; color: #007bff; } .upload-progress-item { display: flex; flex-direction: column; - margin-bottom: 8px; - padding: 8px; background: white; border-radius: 3px; border: 1px solid #dee2e6; @@ -158,22 +156,17 @@ .upload-progress-filename { font-weight: 500; - margin-bottom: 4px; color: #495057; word-break: break-all; } .upload-progress-bar { - width: 100%; - height: 6px; background: #e9ecef; border-radius: 3px; overflow: hidden; - margin-bottom: 4px; } .upload-progress-fill { - height: 100%; background: linear-gradient(90deg, #007bff, #0056b3); transition: width 0.3s ease; border-radius: 3px; @@ -187,7 +180,6 @@ .upload-progress-success { display: flex; align-items: center; - font-size: 12px; font-weight: 500; } @@ -199,47 +191,6 @@ color: #28a745; } -.upload-progress-error i, -.upload-progress-success i { - margin-right: 4px; -} - -/* Minicard specific styles */ -.minicard-upload-progress { - margin: 4px 0; - padding: 8px; - font-size: 12px; -} - -.minicard-upload-progress .upload-progress-item { - padding: 6px; - margin-bottom: 6px; -} - -.minicard-upload-progress .upload-progress-filename { - font-size: 11px; -} - -/* Card details specific styles */ -.card-details-upload-progress { - margin: 12px 0; - padding: 16px; -} - -.card-details-upload-progress .upload-progress-header { - font-size: 16px; - margin-bottom: 12px; -} - -.card-details-upload-progress .upload-progress-item { - padding: 12px; - margin-bottom: 10px; -} - -.card-details-upload-progress .upload-progress-filename { - font-size: 14px; -} - /* Drag over state for minicards */ .minicard.is-dragging-over { border: 2px dashed #007bff !important; @@ -256,7 +207,6 @@ color: white; cursor: pointer; align-self: center; - margin: 0 20px; } #prev-attachment { font-size: 4em; @@ -322,7 +272,6 @@ position: absolute; bottom: 2.2em; font-size: 1.6em; - padding: 16px; } #prev-attachment { left: 0; @@ -356,19 +305,10 @@ margin-top: 20%; width: 100%; } - .attachment-thumbnail-container { - width: 100px; - min-width: 100px; - } - .attachment-thumbnail { - max-width: 100px; - } .attachment-details { flex-direction: column; - margin-right: 0px; } .attachment-actions { flex-direction: row; - margin-top: 10px; } } diff --git a/client/components/cards/attachments.jade b/client/components/cards/attachments.jade index 054c547d9..d63e9e485 100644 --- a/client/components/cards/attachments.jade +++ b/client/components/cards/attachments.jade @@ -49,15 +49,11 @@ template(name="attachmentViewer") i.fa.fa-caret-right#next-attachment template(name="attachmentGallery") - + if canModifyCard + a.add-attachment.js-add-attachment + i.fa.fa-plus .attachment-gallery - - if canModifyCard - a.attachment-item.add-attachment.js-add-attachment - i.fa.fa-plus - each attachments - .attachment-item(class="{{#if isAttachmentMigrating _id}}migrating{{/if}}") .attachment-thumbnail-container.open-preview(data-attachment-id="{{_id}}" data-card-id="{{ meta.cardId }}") if link diff --git a/client/components/cards/cardDate.css b/client/components/cards/cardDate.css index 4a873e485..09a33aaad 100644 --- a/client/components/cards/cardDate.css +++ b/client/components/cards/cardDate.css @@ -1,6 +1,5 @@ .card-date { display: block; - border-radius: 4px; padding: 1px 3px; background-color: #dbdbdb; } @@ -106,6 +105,10 @@ background-color: #e6c200; } +.date a:has(time) { + text-decoration: none; +} + .card-date.end-date { background-color: #ffb3b3; /* Light red for end */ color: #000; /* Black text for end */ @@ -139,6 +142,6 @@ } .customfield-date { display: block; - border-radius: 4px; + border-radius: 0.4ch; padding: 1px 3px; } diff --git a/client/components/cards/cardDate.js b/client/components/cards/cardDate.js index 5863e8f48..386c78467 100644 --- a/client/components/cards/cardDate.js +++ b/client/components/cards/cardDate.js @@ -1,24 +1,24 @@ import { TAPi18n } from '/imports/i18n'; import { DatePicker } from '/client/lib/datepicker'; -import { - formatDateTime, - formatDate, +import { + formatDateTime, + formatDate, formatDateByUserPreference, - formatTime, - getISOWeek, - isValidDate, - isBefore, - isAfter, - isSame, - add, - subtract, - startOf, - endOf, - format, - parseDate, - now, - createDate, - fromNow, + formatTime, + getISOWeek, + isValidDate, + isBefore, + isAfter, + isSame, + add, + subtract, + startOf, + endOf, + format, + parseDate, + now, + createDate, + fromNow, calendar, diff } from '/imports/lib/dateUtils'; @@ -143,7 +143,7 @@ class CardReceivedDate extends CardDate { const startAt = this.data().getStart(); const theDate = this.date.get(); const now = this.now.get(); - + // Received date logic: if received date is after start, due, or end dates, it's overdue if ( (startAt && isAfter(theDate, startAt)) || @@ -187,7 +187,7 @@ class CardStartDate extends CardDate { const endAt = this.data().getEnd(); const theDate = this.date.get(); const now = this.now.get(); - + // Start date logic: if start date is after due or end dates, it's overdue if ((endAt && isAfter(theDate, endAt)) || (dueAt && isAfter(theDate, dueAt))) { classes += 'overdue'; @@ -230,7 +230,7 @@ class CardDueDate extends CardDate { const endAt = this.data().getEnd(); const theDate = this.date.get(); const now = this.now.get(); - + // If there's an end date and it's before the due date, task is completed early if (endAt && isBefore(endAt, theDate)) { classes += 'completed-early'; @@ -242,7 +242,7 @@ class CardDueDate extends CardDate { // Due date logic based on current time else { const daysDiff = diff(theDate, now, 'days'); - + if (daysDiff < 0) { // Due date is in the past - overdue classes += 'overdue'; @@ -254,7 +254,7 @@ class CardDueDate extends CardDate { classes += 'not-due'; } } - + return classes; } @@ -286,7 +286,7 @@ class CardEndDate extends CardDate { let classes = 'end-date '; const dueAt = this.data().getDue(); const theDate = this.date.get(); - + if (!dueAt) { // No due date set - just show as completed classes += 'completed'; @@ -371,7 +371,7 @@ CardCustomFieldDate.register('cardCustomFieldDate'); template() { return 'minicardReceivedDate'; } - + showDate() { const currentUser = ReactiveCache.getCurrentUser(); const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD'; @@ -383,7 +383,7 @@ CardCustomFieldDate.register('cardCustomFieldDate'); template() { return 'minicardStartDate'; } - + showDate() { const currentUser = ReactiveCache.getCurrentUser(); const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD'; @@ -395,7 +395,7 @@ CardCustomFieldDate.register('cardCustomFieldDate'); template() { return 'minicardDueDate'; } - + showDate() { const currentUser = ReactiveCache.getCurrentUser(); const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD'; @@ -407,7 +407,7 @@ CardCustomFieldDate.register('cardCustomFieldDate'); template() { return 'minicardEndDate'; } - + showDate() { const currentUser = ReactiveCache.getCurrentUser(); const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD'; @@ -419,7 +419,7 @@ CardCustomFieldDate.register('cardCustomFieldDate'); template() { return 'minicardCustomFieldDate'; } - + showDate() { const currentUser = ReactiveCache.getCurrentUser(); const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD'; diff --git a/client/components/cards/cardDescription.css b/client/components/cards/cardDescription.css index b65e6b65a..55d75fe76 100644 --- a/client/components/cards/cardDescription.css +++ b/client/components/cards/cardDescription.css @@ -1,16 +1,12 @@ .new-description { - position: relative; - margin: 0 0 20px 0; + flex: 1; } -.new-description.is-open .helper { - display: inline-block; -} -.new-description.is-open textarea { - min-height: 100px; +.new-description textarea { + min-height: 1lh; color: #4d4d4d; cursor: auto; overflow: hidden; - word-wrap: break-word; + overflow-wrap: break-word; } .new-description .too-long { margin-top: 8px; @@ -19,9 +15,6 @@ background-color: #fff; border: 0; box-shadow: 0 1px 2px rgba(0,0,0,0.23); - height: 36px; - margin: 4px 4px 6px 0; - padding: 9px 11px; width: 100%; } .new-description textarea:hover, @@ -39,16 +32,12 @@ border: 0; box-shadow: 0 1px 2px rgba(0,0,0,0.23); color: #8c8c8c; - height: 36px; - margin: 4px 4px 6px 0; - width: 92%; } .description-item:hover { background: #e0e0e0; } .description-item.add-description { display: flex; - margin: 5px; } .description-item.add-description a { display: block; diff --git a/client/components/cards/cardDetails.css b/client/components/cards/cardDetails.css index 42821d284..96abf7ff0 100644 --- a/client/components/cards/cardDetails.css +++ b/client/components/cards/cardDetails.css @@ -1,25 +1,18 @@ -/* Date Format Selector */ -.card-details-item-date-format { - margin-bottom: 12px; -} - .card-details-item-date-format .card-details-item-title { - font-size: 15px; font-weight: bold; - margin-bottom: 6px; color: #333; letter-spacing: 0.03em; } .card-details-item-date-format .js-date-format-selector { - width: 100%; - padding: 9px 10px; border: 1px solid #ddd; border-radius: 5px; background-color: #fff; - font-size: 15px; - cursor: pointer; transition: border-color 0.15s, box-shadow 0.15s; + cursor: pointer; + width: 100%; + display: flex; + flex: 1; } .card-details-item-date-format .js-date-format-selector:focus { @@ -28,44 +21,80 @@ box-shadow: 0 0 0 2px rgba(0, 124, 186, 0.2); } -.assignee { - display: block; - position: relative; - float: left; - height: clamp(24px, 3.5vw, 36px); - width: clamp(24px, 3.5vw, 36px); - margin: 0.3vh; - cursor: pointer; - user-select: none; - z-index: 1; - text-decoration: none; - border-radius: 50%; - box-shadow: 0 1px 2px 0 rgba(0,0,0,0.04); +.card-details h3 { + font-size: 1.1em; } -.assignee .avatar { - overflow: hidden; - border-radius: 50%; -} -.assignee .avatar.avatar-assignee-initials { - height: 70%; - width: 70%; - padding: 15%; - background-color: #dbdbdb; - color: #444; - position: absolute; - text-align: center; + +.card-checklists { display: flex; + flex-direction: column; +} + +.card-body { + display: flex; + flex-direction: column; + flex: 1; + padding: 2ch; + align-items: stretch; + gap: 0.5lh; + /* for popups */ + overflow-y: auto; + + &.is-maximized { + display: grid; + /* divide available space; 3/4 for main content, 1/4 for activity feed */ + /* better use a grid, otherwise flexbox will not expand left pane if fullscreen + > max-content, but some users may want to expend elements anyways */ + grid-template-columns: 3fr 1fr; + .card-details-left { + border-right: solid 2px #dbdbdb; + padding-right: 2ch; + } + } +} + +.card-header-content { + display: grid; + margin: 0 1ch; + grid-auto-columns: auto 1fr auto; + grid-auto-flow: column; + justify-content: stretch; align-items: center; + min-height: 2lh; + gap: 1ch; +} + +body.mobile-mode { + .card-header-content { + padding-inline: 0.5ch; + } + .card-header-middle { + padding-inline: 0; + background: unset; + font-size: 1.1em; + } +} + +.card-header-middle { + display: flex; + min-height: 1.5lh; + font-size: 1.3em; justify-content: center; - font-weight: bold; + align-items: center; + background: #dfdfdf; + border-radius: 1ch; + padding-inline: 1ch; + justify-self: stretch; + cursor: grab !important; } -.assignee .avatar.avatar-image { - object-fit: cover; - object-position: center; - height: 100%; - width: 100%; - display: block; +.assignee.add-assignee:hover, +.assignee.add-assignee.is-active { + box-shadow: 0 0 0 2px #666 inset; } +.assignee { + box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.04); +} + .assignee .assignee-presence-status { background-color: #b3b3b3; border: 1px solid #fff; @@ -77,6 +106,7 @@ bottom: -1px; z-index: 15; } + .assignee .assignee-presence-status.active { background: #64c464; border-color: #daf1da; @@ -96,164 +126,153 @@ .assignee.add-assignee { display: flex; align-items: center; - justify-content: center; - box-shadow: 0 0 0 2px #bfbfbf inset; transition: box-shadow 0.12s; } -.assignee.add-assignee:hover, -.assignee.add-assignee.is-active { - box-shadow: 0 0 0 2px #666 inset; + +.card-header-controls-grid { + display: grid; + grid-template-columns: repeat(auto-fill, 2ch); + gap: 0.5ch; + grid-auto-flow: column; + flex-direction: column; + align-items: center; + justify-items: center; } .copied-tooltip { - display: none; - padding: 0 1.3vw; + position: absolute; background-color: rgba(0,0,0,0.875); color: #fff; border-radius: 0.7vw; font-size: 0.98em; } +.copied-tooltip-visible { + visibility: visible; + opacity: 1; + transition: opacity 0.1s linear; +} + +.copied-tooltip-hidden { + visibility: hidden; + opacity: 0; + transition: visibility 0s 0.1s, opacity 0.1s linear; +} .card-details { padding: 0; - flex-shrink: 0; - flex-basis: min(600px, 80vw); - will-change: flex-basis; + display: flex; + flex: 1; overflow-y: auto; overflow-x: hidden; background: #f7f7f7; border-radius: 0 0 0.4vw 0.4vw; - z-index: 30; + z-index: 100; animation: flexGrowIn 0.1s; box-shadow: 0 0 0.9vh 0 #b3b3b3; transition: flex-basis 0.1s, box-shadow 0.15s; box-sizing: border-box; + &:not(.collapsed) { + min-height: 20lh; + /* at this point, popup can still be resized but stops + to shrink content, so the later stays visible */ + min-width: 30vw; + } } -/* Desktop mode: position card below board header */ -body.desktop-mode .card-details:not(.card-details-popup) { - position: fixed; - width: auto; - max-width: 800px; - flex-basis: auto; - border-radius: 8px; - z-index: 100; +.edit-vote-question { + display: flex; + flex-direction: column; + & > .fields { + display: flex; + flex-direction: column; + gap: 0.2lh; + margin: 0.2lh 0; + } } - -/* Default position for first card or when dragged */ -body.desktop-mode .card-details:not(.card-details-popup):not([style*="left"]):not([style*="top"]) { - top: 50px; - left: 20px; - right: 20px; - bottom: 20px; +.card-details .card-details-canvas { + display: grid; + background: #ededed; + border-bottom: 1px solid #dbdbdb; + flex: 1; + grid-template-rows: auto auto; + grid-auto-flow: row; + grid-template-columns: auto; + align-items: stretch; + align-content: center; } - -/* Stagger positions for multiple cards using nth-of-type */ -body.desktop-mode .card-details:not(.card-details-popup):nth-of-type(1) { - top: 50px; - left: 20px; -} -body.desktop-mode .card-details:not(.card-details-popup):nth-of-type(2) { - top: 80px; - left: 50px; -} -body.desktop-mode .card-details:not(.card-details-popup):nth-of-type(3) { - top: 110px; - left: 80px; -} -body.desktop-mode .card-details:not(.card-details-popup):nth-of-type(4) { - top: 140px; - left: 110px; -} -body.desktop-mode .card-details:not(.card-details-popup):nth-of-type(5) { - top: 170px; - left: 140px; -} - -/* For expanded cards, set dimensions */ -body.desktop-mode .card-details:not(.card-details-popup):not(.card-details-collapsed) { - right: 20px; - bottom: 20px; -} - /* Collapsed card state - hide content and set height to title row only */ -.card-details.card-details-collapsed .card-details-canvas > *:not(.card-details-header) { +.card-details.card-details.collapsed .card-details-canvas > *:not(.card-details-header) { display: none !important; } -.card-details.card-details-collapsed { - height: auto !important; - bottom: auto !important; - overflow: visible; -} -body.desktop-mode .card-details.card-details-collapsed { - bottom: auto !important; -} .card-details .mCustomScrollBox { padding-left: 0; } -.card-details .card-details-canvas { - width: auto; - padding: 0 2.5vw; -} -.card-details .card-details-header { - margin: 0 -20px 5px; - padding: 8px 20px; - background: #ededed; - border-bottom: 1px solid #dbdbdb; - position: sticky; - top: 0px; - z-index: 500; - display: flow-root; - min-height: 44px; -} .card-details .card-details-header .card-number { color: #b3b3b3; display: inline-block; - margin-right: 6px; } /* Collapse toggle triangle */ .card-details .card-details-header .card-collapse-toggle { - float: left; - font-size: 20px; - padding: 7px 10px; - margin-left: -10px; - margin-right: 5px; cursor: pointer; user-select: none; color: #000; - vertical-align: middle; - line-height: 1.2; +} + +/* Bring to front / Send to back buttons */ +/* #FIXME see .jade */ +/* .card-details .card-details-header .card-bring-to-front, +.card-details .card-details-header .card-send-to-back { + float: right; + font-size: 18px; + padding: 7px 8px; + margin-right: 5px; + cursor: pointer; + user-select: none; + color: #333; +} */ + +.card-details .card-details-header .card-bring-to-front:hover, +.card-details .card-details-header .card-send-to-back:hover { + color: #000; + background: rgba(0,0,0,0.05); + border-radius: 3px; } .card-details .card-details-header .card-drag-handle { - font-size: 20px; - padding: 8px 10px; - margin-right: 10px; cursor: move; user-select: none; - display: inline-block; - float: right; - vertical-align: middle; - line-height: 1.2; } -.card-details .card-details-header .close-card-details, -.card-details .card-details-header .maximize-card-details, -.card-details .card-details-header .minimize-card-details, -.card-details .card-details-header .card-details-menu, -.card-details .card-details-header .card-copy-button, -.card-details .card-details-header .card-copy-mobile-button, -.card-details .card-details-header .close-card-details-mobile-web, -.card-details .card-details-header .card-details-menu-mobile-web, -.card-details .card-details-header .copied-tooltip { - float: right; -} +.card-details .js-card-details-title { + /* override inlined forms defauts: take all width available + and just what's needed to edit card title */ + width: 100%; + display: flex; + .js-edit-card-title { + height: fit-content; + margin: 0; + } + .edit-controls { + flex: 1; + align-items: center; + button { + margin: 0; + display: flex; + max-width: 20ch; + justify-content: center; + align-items: center; + } + } + .js-submit-edit-card-title-form { + margin: 0.3lh 0; + flex: 1; + display: flex; + } +} + .card-details .card-details-header .close-card-details, .card-details .card-details-header .maximize-card-details, .card-details .card-details-header .minimize-card-details { - font-size: 24px; - padding: 5px 10px 5px 10px; - margin-right: -8px; cursor: pointer; user-select: none; vertical-align: middle; @@ -262,78 +281,155 @@ body.desktop-mode .card-details.card-details-collapsed { } .card-details .card-details-header .close-card-details-mobile-web, .card-details .card-details-header .card-mobile-desktop-toggle { - font-size: 24px; - padding: 5px; - margin-right: 5px; cursor: pointer; user-select: none; } -.card-details .card-details-header .card-copy-button { - font-size: 17px; - padding: 10px; - margin-right: 10px; -} -.card-details .card-details-header .card-copy-mobile-button { - font-size: 17px; - padding: 10px; - margin-right: 10px; -} -.card-details .card-details-header .card-details-menu { - font-size: 17px; - padding: 10px; - vertical-align: middle; - line-height: 1.2; -} -.card-details .card-details-header .card-details-menu-mobile-web { - font-size: 17px; - padding: 10px; - margin-right: 30px; -} -.card-details .card-details-header .card-mobile-desktop-toggle, -.card-details .card-details-header .card-zoom-in, -.card-details .card-details-header .card-zoom-out { - font-size: 24px; - padding: 5px 10px 5px 10px; - margin-right: 5px; +.card-details .card-details-header .card-mobile-desktop-toggle { cursor: pointer; user-select: none; float: right; } +body:not(.mobile-mode) { + + .card-details-date-container, + .card-details-user-container, + .card-details-misc-container, + card-details-description { + grid-template-columns: repeat(3, 1fr) !important; + gap: 1ch; + } +} + /* Unify all card text to match title size */ .card-details { font-size: 1em; } -.card-details p, -.card-details span, -.card-details div, -.card-details a, -.card-details label, -.card-details input, -.card-details textarea, -.card-details select, -.card-details button, -.card-details .card-details-item-title, -.card-details .card-label, -.card-details .viewer { - font-size: inherit; - line-height: 1.5; + +.card-details .card-details-header .card-details-watch { + color: #a6a6a6; +} + +.card-details .card-details-header { + & .card-details-title { + display: inline-block; + font-weight: bold; + font-size: 1.33em; + margin: 0; + --overflow-lines: 3; + & p { + margin: 0; + } + } +} + + +.card-add-label, .card-details .js-date-format-selector { + padding: 0.2lh 0.5ch; +} +.card-details-main { + display: flex; + gap: 0.3lh; + flex-direction: column; + hr { + margin: 0; + } + &>div { + display: flex; + gap: 0.2lh; + flex: 1; + } + &>div:empty { + /* to avoid gaps */ + display: none; + } + .card-details-misc-container { + display: flex; + flex-direction: column; + gap: 0.3lh; + } + .card-details-date-container, .card-details-user-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1ch; + align-items: end; + h3 { + + *:not(:has(.member), :is(:hover)) { + background-color: #f7f7f7; + } + + *:not(:is(form)) { + display: flex; + align-items: center; + overflow: hidden; + font-size: 0.8em; + + &:not(.member, :has(.member)) { + border-radius: 5px; + justify-content: start; + height: 1.8lh; + padding: 0.3lh 1ch; + } + + &:has(select) { + padding-inline: 0 !important; + >select { + align-self: stretch; + } + } + + time { + color: black; + } + +form { + height: 3lh; + overflow: visible; + margin: 0.5lh 0; + + > { + width: 100%; + } + } + } + } + } + .card-details-items { + gap: 0.5lh; + } + .card-details-comments { + flex-direction: column; + gap: 0.5lh; + } +} + +.card-details-description { + display: flex; + flex-direction: column; + flex: 1; +} +.card-details-comments { + flex-direction: column; + gap: 0.5lh; } .card-details .card-details-header .card-details-watch { - font-size: 17px; - padding-left: 7px; color: #a6a6a6; } .card-details .card-details-header .card-details-title { font-weight: bold; font-size: 1.35em; - margin: 7px 0 0; padding: 0; display: inline-block; vertical-align: middle; line-height: 1.3; letter-spacing: 0.01em; } + +body.mobile-mode { + .card-details .card-details-header .card-details-title { + --overflow-lines: 2; + font-size: 0.8em; + } +} + .card-details .card-details-header .linked-card-location { font-style: italic; font-size: 1em; @@ -342,283 +438,70 @@ body.desktop-mode .card-details.card-details-collapsed { .card-details .card-details-header .linked-card-location p { margin-bottom: 0; } -.card-details .card-details-header form.inlined-form { - margin-top: 5px; - margin-bottom: 10px; -} -.card-details .card-details-header form.inlined-form .copied-tooltip { - padding: 0 10px; -} -.card-details .card-details-header .card-details-list { - font-size: 0.9em; - margin-bottom: 3px; -} -.card-details .card-details-header .card-details-list a.card-details-list-title { - font-weight: bold; -} -.card-details .card-details-header .card-details-list a.card-details-list-title.is-editable { - display: inline-block; - background: #e6e6e6; - border-radius: 3px; - padding: 0 5px; -} -.card-details .card-details-header .copied-tooltip { - margin-right: 10px; - padding: 10px; -} .card-details .card-description i.fa.fa-pencil-square-o { float: right; } .card-details .card-description textarea { - min-height: 100px; resize: vertical; + min-height: 2lh; } -.card-details .card-details-items { +.card-details { + .card-details-items, .card-details-item { + display: flex; + flex-direction: column; + gap: 0.3lh; + } + .card-details-item { + justify-content: end; + align-self: stretch; + } + .card-details-avatar-container { + display: flex; + justify-content: start; + gap: 0.5ch; + } +} +.card-details-item-labels-container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(12ch, auto)); + grid-auto-rows: 1.5lh; + align-items: stretch; + justify-content: start; + gap: 1ch; +} + +.card-details .subtask-container { display: flex; - flex-wrap: wrap; - margin: 15px 0; - gap: 0.5em; -} -.card-details .card-details-items .card-details-item { - margin-right: 0.5em; - flex-grow: 1; -} -.card-details .card-details-items .card-details-item:last-child { - margin-right: 0; -} -.card-details .card-details-items .card-details-item.card-details-item-labels { - display: block; - word-wrap: break-word; - max-width: 95%; -} -.card-details .card-details-items .card-details-item.card-details-item-members, -.card-details .card-details-items .card-details-item.card-details-item-assignees, -.card-details .card-details-items .card-details-item.card-details-item-customfield, -.card-details .card-details-items .card-details-item.card-details-item-name { - display: block; - word-wrap: break-word; - max-width: 36%; -} -.card-details .card-details-items .card-details-item.card-details-item-creator, -.card-details .card-details-items .card-details-item.card-details-item-received, -.card-details .card-details-items .card-details-item.card-details-item-start, -.card-details .card-details-items .card-details-item.card-details-item-due, -.card-details .card-details-items .card-details-item.card-details-item-end { - display: block; - word-wrap: break-word; - max-width: 28%; -} -.card-details .card-details-items .card-details-item.custom-fields { - padding-left: 10px; + flex: 1; + flex-wrap: nowrap; + align-items: center; + gap: 1ch; + h2 { + margin: 0; + } + .subtask { + min-height: 1.5lh; + } } .card-details .card-details-item-title { - font-size: 16px; font-weight: bold; color: #4d4d4d; + display: flex; + align-items: center; + gap: 0.8ch; +} + +.card-details .edit-card-details-description { + display: flex; + align-items: center; + gap: .5ch; } .card-details .activities { padding-top: 10px; } -@media screen and (min-width: 801px) { - .card-details { - top: 97px; - left: calc(50% - (600px / 2)); - width: 600px; - bottom: 0; - position: fixed; - resize: both; - } - - /* Override for mobile mode even on larger screens */ - body.mobile-mode .card-details { - width: 100vw !important; - top: 0 !important; - left: 0 !important; - right: 0 !important; - bottom: 0 !important; - height: 100vh !important; - max-height: 100vh !important; - resize: none !important; - } - - .card-details-maximized { - padding: 0; - flex-shrink: 0; - flex-basis: calc(100% - 20px); - will-change: flex-basis; - overflow-y: auto; - overflow-x: auto; - background: #f7f7f7; - border-radius: 0 0 3px 3px; - z-index: 100; - animation: flexGrowIn 0.1s; - box-shadow: 0 0 7px 0 #b3b3b3; - transition: flex-basis 0.1s; - box-sizing: border-box; - top: 97px; - left: 0px; - height: calc(100% - 100px); - width: calc(100% - 20px); - float: left; - } - .card-details-maximized .card-details-left { - float: left; - top: 60px; - left: 20px; - width: 47%; - border-right: solid 2px #dbdbdb; - padding-right: 10px; - } - .card-details-maximized .card-details-right { - position: absolute; - float: right; - left: 50%; - margin: 15px 0; - } - .card-details-maximized .card-details-header { - width: 100%; - } -} -input[type="text"].attachment-add-link-input { - float: left; - margin: 0 0 8px; - width: 80%; -} -input[type="submit"].attachment-add-link-submit { - float: left; - margin: 0 0 8px 4px; - padding: 6px 12px; - width: 18%; -} -@media screen and (max-width: 800px) { - .card-details { - width: 100% !important; - padding: 0 !important; - margin: 0 !important; - transition: none; - overflow-y: auto; - overflow-x: hidden; - -webkit-overflow-scrolling: touch; - position: fixed !important; - top: 0 !important; - left: 0 !important; - right: 0 !important; - bottom: 0 !important; - z-index: 100 !important; - height: 100vh !important; - max-height: 100vh !important; - border-radius: 0 !important; - box-shadow: none !important; - } - - /* Ensure card details are above everything on mobile */ - body.mobile-mode .card-details { - z-index: 100 !important; - width: 100vw !important; - left: 0 !important; - right: 0 !important; - } - .card-details .card-details-canvas { - width: 100%; - padding-left: 0px; - padding: 0 15px; - } - .card-details .card-details-header .close-card-details { - margin-right: 0px; - display: block !important; - } - .card-details .card-details-header .close-card-details-mobile-web { - display: block !important; - margin-right: 5px !important; - } - .card-details .card-details-header .card-mobile-desktop-toggle { - display: block !important; - margin-right: 5px !important; - } - .card-details .card-details-header .card-mobile-desktop-toggle { - display: block !important; - margin-right: 5px !important; - } - .card-details .card-details-header .card-details-menu { - margin-right: 40px; - } - .card-details .card-details-header .maximize-card-details { - margin-right: 40px; - } - .card-details .card-details-header .minimize-card-details { - margin-right: 40px; - } - .card-details-popup { - padding: 0px 10px; - } - .pop-over > .content-wrapper > .popup-container-depth-0 { - width: 100%; - } - .pop-over > .content-wrapper > .popup-container-depth-0 > .content { - width: calc(100% - 10px); - } - .pop-over > .content-wrapper > .popup-container-depth-0 > .content > .card-details-popup hr { - margin: 15px 0px; - } - .pop-over > .content-wrapper > .popup-container-depth-0 .card-details-header { - margin: 0; - } - /* iPhone mobile: enlarge header buttons and increase spacing */ - body.mobile-mode.iphone-device .card-details .card-details-header { - padding-right: 16px; - } - body.mobile-mode.iphone-device .card-details .card-details-header .close-card-details, - body.mobile-mode.iphone-device .card-details .card-details-header .maximize-card-details, - body.mobile-mode.iphone-device .card-details .card-details-header .minimize-card-details, - body.mobile-mode.iphone-device .card-details .card-details-header .card-details-menu-mobile-web, - body.mobile-mode.iphone-device .card-details .card-details-header .card-copy-mobile-button, - body.mobile-mode.iphone-device .card-details .card-details-header .card-mobile-desktop-toggle, - body.mobile-mode.iphone-device .card-details .card-details-header .card-zoom-in, - body.mobile-mode.iphone-device .card-details .card-details-header .card-zoom-out { - font-size: 2em !important; /* 2x bigger */ - padding: 0.3em !important; - margin-right: 0.75em !important; /* 2x space compared to default */ - margin-left: 0 !important; - } - /* Avoid clipping of the close button on the right edge */ - body.mobile-mode.iphone-device .card-details .card-details-header .close-card-details { - margin-right: 0.75em !important; - } - /* Enlarge the header title too */ - body.mobile-mode.iphone-device .card-details .card-details-header .card-details-title { - font-size: 1.2em !important; - font-weight: bold; - } -} - -/* Mobile mode styles - apply when body has mobile-mode class regardless of screen size */ -body.mobile-mode .card-details { - width: 100vw !important; - padding: 0px !important; - margin: 0px !important; - position: fixed !important; - top: 0 !important; - left: 0 !important; - right: 0 !important; - bottom: 0 !important; - z-index: 100 !important; - height: 100vh !important; - max-height: 100vh !important; - border-radius: 0 !important; - box-shadow: none !important; - overflow-y: auto !important; - overflow-x: hidden !important; - -webkit-overflow-scrolling: touch; -} body.mobile-mode .card-details .card-details-canvas { - width: 100% !important; - padding: 0 15px !important; -} - -body.mobile-mode .card-details .card-details-header .close-card-details, -body.mobile-mode .card-details .card-details-header .close-card-details-mobile-web { - display: block !important; + padding: 0 !important; } .card-details-white { background: #fff !important; @@ -727,16 +610,21 @@ body.mobile-mode .card-details .card-details-header .close-card-details-mobile-w .vote-title { display: flex; justify-content: space-between; + & + .viewer { + font-size: 1.1em; + font-weight: bold; + } align-items: center; } .vote-title .js-edit-date { align-self: flex-start; - margin-left: 6px; } .vote-result { display: flex; - gap: 6px; -} + gap: 0.5ch; + .card-label { + min-width: 5ch; + } .js-show-positive-votes { cursor: pointer; } @@ -750,7 +638,6 @@ body.mobile-mode .card-details .card-details-header .close-card-details-mobile-w } .poker-title .js-edit-date { align-self: flex-start; - margin-left: 6px; } .poker-result { display: flex; @@ -837,24 +724,9 @@ body.mobile-mode .card-details .card-details-header .close-card-details-mobile-w .estimation-add { display: block; overflow: auto; - margin-top: 15px; - margin-bottom: 5px; -} -.estimation-add input { - display: inline-block; - float: right; - margin: auto; - margin-right: 10px; - width: 100px; - border-radius: 2px; - padding: 3px 6px; } .estimation-add button { display: inline-block; - float: right; - margin: auto; - border-radius: 2px; - padding: 3px 10px; } .poker-card { width: 48px; @@ -866,7 +738,6 @@ body.mobile-mode .card-details .card-details-header .close-card-details-mobile-w box-sizing: border-box; padding: 5px; margin: 3px; - font-size: 20px; font-weight: bold; text-shadow: #2d2d2d 1px 1px 0; box-shadow: 0 0 5px #aaa; @@ -890,3 +761,13 @@ body.mobile-mode .card-details .card-details-header .close-card-details-mobile-w transform: scale(1.01); transition: all 0.2s ease; } + +.cardMorePopup { + display: flex; + flex-direction: column; + gap: 0.1lh; + .card-add-date { + display: flex; + gap: 0.5ch; + } +} \ No newline at end of file diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index 7adaca873..94f82868d 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -1,87 +1,73 @@ + template(name="cardDetailsPopup") - +cardDetails(popupCard) + //- just a proxy so the caller code is almost the same + //- when using popups or inlined element; + with popupArgs + +popup(this) template(name="cardDetails") - +attachmentViewer - - section.card-details.js-card-details.nodragscroll(class='{{#if cardMaximized}}card-details-maximized{{/if}}' class='{{#if isPopup}}card-details-popup{{/if}}' class='{{#unless isVerticalScrollbars}}no-scrollbars{{/unless}}' class='{{#if cardCollapsed}}card-details-collapsed{{/if}}'): .card-details-canvas + section.card-details.js-card-details.nodragscroll(class='{{#if isPopup}}card-details-popup{{/if}}' class='{{#unless isVerticalScrollbars}}no-scrollbars{{/unless}}' class='{{#if cardCollapsed}}collapsed{{/if}}'): .card-details-canvas .card-details-header(class='{{#if colorClass}}card-details-{{colorClass}}{{/if}}') +inlinedForm(classNames="js-card-details-title") +editCardTitleForm else - unless isMiniScreen - unless isPopup + .card-header-content + .card-header-left + //- resizing with the CSS property can achieve the same + //- on desktop; keep this button for mobile where we don't + //- have CSS resize. span.card-collapse-toggle.js-card-collapse-toggle(title="{{_ 'collapse-card'}}") if cardCollapsed i.fa.fa-caret-right else i.fa.fa-caret-down - a.close-card-details.js-close-card-details(title="{{_ 'close-card'}}") - i.fa.fa-times-thin - if cardMaximized - a.fa.fa-window-minimize.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}") - else - a.fa.fa-window-maximize.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}") - a.card-details-menu.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") - i.fa.fa-bars - a.card-copy-button.js-copy-link( - id="cardURL_copy" - title="{{_ 'copy-card-link-to-clipboard'}}" - href="{{ originRelativeUrl }}" - ) - span.emoji-icon - i.fa.fa-link - if canModifyCard - span.card-drag-handle.js-card-drag-handle(title="Drag card") - i.fa.fa-arrows - span.copied-tooltip {{_ 'copied'}} - else - a.close-card-details.js-close-card-details(title="{{_ 'close-card'}}") - i.fa.fa-times-thin - a.card-zoom-out.js-card-zoom-out(title="{{_ 'zoom-out'}}") - i.fa.fa-search-minus - a.card-zoom-in.js-card-zoom-in(title="{{_ 'zoom-in'}}") - i.fa.fa-search-plus - a.card-mobile-desktop-toggle.js-card-mobile-desktop-toggle(title="{{_ 'mobile-desktop-toggle'}}") - if mobileMode - i.fa.fa-desktop - else - i.fa.fa-mobile - if cardMaximized - a.fa.fa-window-minimize.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}") - else - a.fa.fa-window-maximize.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}") - a.card-details-menu-mobile-web.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") - i.fa.fa-bars - a.card-copy-mobile-button.js-copy-link( - id="cardURL_copy" - title="{{_ 'copy-card-link-to-clipboard'}}" - href="{{ originRelativeUrl }}" - ) - span.emoji-icon - i.fa.fa-link - span.copied-tooltip {{_ 'copied'}} - h2.card-details-title.js-card-title( - class="{{#if canModifyCard}}js-open-inlined-form is-editable{{else}}js-card-title-drag-handle{{/if}}") - +viewer - if currentBoard.allowsCardNumber - span.card-number - | ##{getCardNumber} - = getTitle if isWatching i.card-details-watch i.fa.fa-eye - .card-details-path - each parentList - | > - a.js-parent-card(href=linkForCard) {{title}} - // else - {{_ 'top-level-card'}} - if isLinkedCard - a.linked-card-location.js-go-to-linked-card - +viewer - | {{getBoardTitle}} > {{getTitle}} + .card-header-middle + h2.card-details-title.js-card-title( + class="{{#if canModifyCard}}js-open-inlined-form is-editable{{/if}}") + +viewer + if currentBoard.allowsCardNumber + span.card-number + | ##{getCardNumber} - + = getTitle + + .card-details-path + each parentList + | > + a.js-parent-card(href=linkForCard) {{title}} + // else + {{_ 'top-level-card'}} + + .card-header-controls-grid + if canModifyCard + unless isMiniScreen + if cardMaximized + a.fa.fa-window-minimize.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}") + else + a.fa.fa-window-maximize.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}") + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} + a.card-copy-button.js-copy-link.emoji-icon( + id="cardURL_copy" + title="{{_ 'copy-card-link-to-clipboard'}}" + href="{{ originRelativeUrl }}" + ) + i.fa.fa-link + a.card-details-menu.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") + i.fa.fa-bars + a.close-card-details.js-close-card-details.js-close-pop-over(title="{{_ 'close-card'}}") + i.fa.fa-times-thin + //- #FIXME removed in upstream? should we make it reactive to the popupcomponent stack for example? + //- a.card-send-to-back.js-card-send-to-back(title="Send to back") + //- | ⏬ + //- a.card-bring-to-front.js-card-bring-to-front(title="Bring to front") + //- | ⏫ + if isLinkedCard + a.linked-card-location.js-go-to-linked-card + +viewer + | {{getBoardTitle}} > {{getTitle}} if getArchived if isLinkedBoard @@ -108,550 +94,547 @@ template(name="cardDetails") .upload-progress-success i.fa.fa-check span {{_ 'upload-completed'}} - - .card-details-left - - .card-details-items - if currentBoard.allowsLabels - .card-details-item.card-details-item-labels - h3.card-details-item-title - i.fa.fa-tags - | {{_ 'labels'}} - a(class="{{#if canModifyCard}}js-add-labels{{else}}is-disabled{{/if}}" title="{{_ 'card-labels-title'}}") - each labels - span.card-label(class="card-label-{{color}}" title=name) - +viewer - = name - if canModifyCard - unless currentUser.isWorker - a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}") - i.fa.fa-plus - - if currentBoard.hasAnyAllowsDate - hr - - .card-details-item.card-details-item-date-format - h3.card-details-item-title - i.fa.fa-calendar - | {{_ 'date-format'}} - .card-details-item-content - select.js-date-format-selector - option(value="YYYY-MM-DD" selected="{{#if isDateFormat 'YYYY-MM-DD'}}selected{{/if}}") {{_ 'date-format-yyyy-mm-dd'}} - option(value="DD-MM-YYYY" selected="{{#if isDateFormat 'DD-MM-YYYY'}}selected{{/if}}") {{_ 'date-format-dd-mm-yyyy'}} - option(value="MM-DD-YYYY" selected="{{#if isDateFormat 'MM-DD-YYYY'}}selected{{/if}}") {{_ 'date-format-mm-dd-yyyy'}} - - if currentBoard.allowsReceivedDate - .card-details-item.card-details-item-received - h3.card-details-item-title - i.fa.fa-sign-out - | {{_ 'card-received'}} - if getReceived - +cardReceivedDate - else - if canModifyCard - unless currentUser.isWorker - a.card-label.add-label.js-received-date - i.fa.fa-plus - - if currentBoard.allowsStartDate - .card-details-item.card-details-item-start - h3.card-details-item-title - i.fa.fa-hourglass-start - | {{_ 'card-start'}} - if getStart - +cardStartDate - else - if canModifyCard - unless currentUser.isWorker - a.card-label.add-label.js-start-date - i.fa.fa-plus - - if currentBoard.allowsDueDate - .card-details-item.card-details-item-due - h3.card-details-item-title - i.fa.fa-clock-o - | {{_ 'card-due'}} - if getDue - +cardDueDate - else - if canModifyCard - unless currentUser.isWorker - a.card-label.add-label.js-due-date - i.fa.fa-plus - - if currentBoard.allowsEndDate - .card-details-item.card-details-item-end - h3.card-details-item-title - i.fa.fa-hourglass-end - | {{_ 'card-end'}} - if getEnd - +cardEndDate - else - if canModifyCard - unless currentUser.isWorker - a.card-label.add-label.js-end-date - i.fa.fa-plus - - if currentBoard.hasAnyAllowsUser - hr - - if currentBoard.allowsCreator - .card-details-item.card-details-item-creator - h3.card-details-item-title - i.fa.fa-user - | {{_ 'creator'}} - - +userAvatar(userId=userId noRemove=true) - | {{! XXX Hack to hide syntaxic coloration /// }} - - //.card-details-items - if currentBoard.allowsMembers - .card-details-item.card-details-item-members - h3.card-details-item-title - i.fa.fa-users - | {{_ 'members'}} - each userId in getMembers - +userAvatar(userId=userId cardId=_id) - | {{! XXX Hack to hide syntaxic coloration /// }} - if canModifyCard - unless currentUser.isWorker - a.member.add-member.card-details-item-add-button.js-add-members(title="{{_ 'card-members-title'}}") - i.fa.fa-plus - - //if assigneeSelected - if currentBoard.allowsAssignee - .card-details-item.card-details-item-assignees - h3.card-details-item-title - i.fa.fa-user - | {{_ 'assignee'}} - each userId in getAssignees - +userAvatar(userId=userId cardId=_id assignee=true) - | {{! XXX Hack to hide syntaxic coloration /// }} - if canModifyCard - a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}") - i.fa.fa-plus - if currentUser.isWorker - unless assigneeSelected - a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}") - i.fa.fa-plus - - //.card-details-items - if currentBoard.allowsRequestedBy - .card-details-item.card-details-item-name - h3.card-details-item-title - i.fa.fa-shopping-cart - | {{_ 'requested-by'}} - if canModifyCard - unless currentUser.isWorker - +inlinedForm(classNames="js-card-details-requester") - +editCardRequesterForm - else - a.js-open-inlined-form - if getRequestedBy + .card-body(class="{{#if cardMaximized}}is-maximized{{/if}}") + .card-details-left + .card-details-main + .card-details-items + if currentBoard.allowsLabels + .card-details-item-labels + h3.card-details-item-title + i.fa.fa-tags + | {{_ 'labels'}} + if canModifyCard + unless currentUser.isWorker + a.card-add-label.js-add-labels(title="{{_ 'card-labels-title'}}") + i.fa.fa-plus + a.card-details-item-labels-container(class="{{#if canModifyCard}}js-add-labels{{else}}is-disabled{{/if}}" title="{{_ 'card-labels-title'}}") + each labels + span.card-label(class="card-label-{{color}}" title=name) +viewer - = getRequestedBy - else - | {{_ 'add'}} - else if getRequestedBy - +viewer - = getRequestedBy + = name + hr + .card-details-date-container + if currentBoard.allowsReceivedDate + .card-details-item.card-details-item-received + h3.card-details-item-title + i.fa.fa-sign-out + | {{_ 'card-received'}} + if getReceived + +cardReceivedDate + else + if canModifyCard + unless currentUser.isWorker + a.card-add-label.js-received-date + i.fa.fa-plus - if currentBoard.allowsAssignedBy - .card-details-item.card-details-item-name - h3.card-details-item-title - i.fa.fa-user-plus - | {{_ 'assigned-by'}} - if canModifyCard - unless currentUser.isWorker - +inlinedForm(classNames="js-card-details-assigner") - +editCardAssignerForm - else - a.js-open-inlined-form - if getAssignedBy + if currentBoard.allowsStartDate + .card-details-item.card-details-item-start + h3.card-details-item-title + i.fa.fa-hourglass-start + | {{_ 'card-start'}} + if getStart + +cardStartDate + else + if canModifyCard + unless currentUser.isWorker + a.card-add-label.js-start-date + i.fa.fa-plus + + if currentBoard.allowsDueDate + .card-details-item.card-details-item-due + h3.card-details-item-title + i.fa.fa-clock-o + | {{_ 'card-due'}} + if getDue + +cardDueDate + else + if canModifyCard + unless currentUser.isWorker + a.card-add-label.js-due-date + i.fa.fa-plus + + if currentBoard.allowsEndDate + .card-details-item.card-details-item-end + h3.card-details-item-title + i.fa.fa-hourglass-end + | {{_ 'card-end'}} + if getEnd + +cardEndDate + else + if canModifyCard + unless currentUser.isWorker + a.card-add-label.js-end-date + i.fa.fa-plus + if currentBoard.hasAnyAllowsDate + .card-details-item.card-details-item-date-format + h3.card-details-item-title + i.fa.fa-calendar + | {{_ 'date-format'}} + .card-details-item-content + select.js-date-format-selector + option(value="YYYY-MM-DD" selected="{{#if isDateFormat 'YYYY-MM-DD'}}selected{{/if}}") {{_ 'date-format-yyyy-mm-dd'}} + option(value="DD-MM-YYYY" selected="{{#if isDateFormat 'DD-MM-YYYY'}}selected{{/if}}") {{_ 'date-format-dd-mm-yyyy'}} + option(value="MM-DD-YYYY" selected="{{#if isDateFormat 'MM-DD-YYYY'}}selected{{/if}}") {{_ 'date-format-mm-dd-yyyy'}} + if currentBoard.hasAnyAllowsUser + hr + .card-details-user-container + if currentBoard.allowsCreator + .card-details-item.card-details-item-creator + h3.card-details-item-title + i.fa.fa-user + | {{_ 'creator'}} + + +userAvatar(userId=userId noRemove=true) + | {{! XXX Hack to hide syntaxic coloration /// }} + + //.card-details-items + if currentBoard.allowsMembers + .card-details-item.card-details-item-members + h3.card-details-item-title + i.fa.fa-users + | {{_ 'members'}} + .card-details-avatar-container + each userId in getMembers + +userAvatar(userId=userId cardId=_id) + | {{! XXX Hack to hide syntaxic coloration /// }} + if canModifyCard + unless currentUser.isWorker + a.member.add-member.card-details-item-add-button.js-add-members(title="{{_ 'card-members-title'}}") + i.fa.fa-plus + + //if assigneeSelected + if currentBoard.allowsAssignee + .card-details-item.card-details-item-assignees + h3.card-details-item-title + i.fa.fa-user + | {{_ 'assignee'}} + .card-details-avatar-container + each userId in getAssignees + +userAvatar(userId=userId cardId=_id assignee=true) + | {{! XXX Hack to hide syntaxic coloration /// }} + if canModifyCard + a.member.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}") + i.fa.fa-plus + if currentUser.isWorker + unless assigneeSelected + a.member.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}") + i.fa.fa-plus + + //.card-details-items + if currentBoard.allowsRequestedBy + .card-details-item.card-details-item-name + h3.card-details-item-title + i.fa.fa-shopping-cart + | {{_ 'requested-by'}} + if canModifyCard + unless currentUser.isWorker + +inlinedForm(classNames="js-card-details-requester") + +editCardRequesterForm + else + a.js-open-inlined-form + if getRequestedBy + +viewer + = getRequestedBy + else + | {{_ 'add'}} + else if getRequestedBy + +viewer + = getRequestedBy + + if currentBoard.allowsAssignedBy + .card-details-item.card-details-item-name + h3.card-details-item-title + i.fa.fa-user-plus + | {{_ 'assigned-by'}} + if canModifyCard + unless currentUser.isWorker + +inlinedForm(classNames="js-card-details-assigner") + +editCardAssignerForm + else + a.js-open-inlined-form + if getAssignedBy + +viewer + = getAssignedBy + else + | {{_ 'add'}} + else if getRequestedBy +viewer = getAssignedBy - else - | {{_ 'add'}} - else if getRequestedBy - +viewer - = getAssignedBy - if $or currentBoard.allowsCardSortingByNumber getSpentTime - hr - - if currentBoard.allowsCardSortingByNumber - .card-details-item.card-details-sort-order - h3.card-details-item-title - i.fa.fa-sort-numeric-asc - | {{_ 'sort'}} - if canModifyCard - +inlinedForm(classNames="js-card-details-sort") - +editCardSortOrderForm - else - a.js-open-inlined-form - +viewer - = sort - - if currentBoard.allowsShowLists - .card-details-item.card-details-show-lists - h3.card-details-item-title - i.fa.fa-list - | {{_ 'list'}} - select.js-select-card-details-lists(disabled="{{#unless canModifyCard}}disabled{{/unless}}") - each currentBoard.lists - option(value="{{_id}}" selected="{{#if isCurrentListId _id}}selected{{/if}}") {{title}} - - //.card-details-items - if getSpentTime - .card-details-item.card-details-item-spent - if getIsOvertime - h3.card-details-item-title - | {{_ 'overtime-hours'}} - else - h3.card-details-item-title - | {{_ 'spent-time-hours'}} - +cardSpentTime - - //.card-details-items - if customFieldsWD - unless customFieldsGrid + if $or currentBoard.allowsCardSortingByNumber getSpentTime hr - each customFieldsWD - if customFieldsGrid - hr - .card-details-item.card-details-item-customfield + + if currentBoard.allowsCardSortingByNumber + .card-details-item.card-details-sort-order + h3.card-details-item-title + i.fa.fa-sort-numeric-asc + | {{_ 'sort'}} + if canModifyCard + +inlinedForm(classNames="js-card-details-sort") + +editCardSortOrderForm + else + a.js-open-inlined-form + +viewer + = sort + + if currentBoard.allowsShowLists + .card-details-item.card-details-show-lists h3.card-details-item-title i.fa.fa-list - = definition.name - +cardCustomField + | {{_ 'list'}} + select.js-select-card-details-lists(disabled="{{#unless canModifyCard}}disabled{{/unless}}") + each currentBoard.lists + option(value="{{_id}}" selected="{{#if isCurrentListId _id}}selected{{/if}}") {{title}} - if $gt customFieldsWD.length 1 - .material-toggle-switch(title="{{_ 'change'}} {{_ 'custom-fields'}} {{_ 'layout'}}") - if customFieldsGrid - input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton" checked="checked") + //.card-details-items + if getSpentTime + .card-details-item.card-details-item-spent + if getIsOvertime + h3.card-details-item-title + | {{_ 'overtime-hours'}} else - input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton") - label.toggle-label(for="toggleCustomFieldsGridButton") - a.js-custom-fields.card-details-item.custom-fields(title="{{_ 'custom-fields'}}") + h3.card-details-item-title + | {{_ 'spent-time-hours'}} + +cardSpentTime - if getVoteQuestion - hr - .vote-title - div.flex - h3 - i.fa.fa-thumbs-up - | {{_ 'vote-question'}} - if getVoteEnd - +voteEndDate - .vote-result - if votePublic - a.card-label.card-label-green.js-show-positive-votes {{ voteCountPositive }} - a.card-label.card-label-red.js-show-negative-votes {{ voteCountNegative }} - else - .card-label.card-label-green {{ voteCountPositive }} - .card-label.card-label-red {{ voteCountNegative }} - unless ($and currentBoard.isPublic voteAllowNonBoardMembers ) - .card-label.card-label-gray {{ voteCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }} - +viewer - = getVoteQuestion - if showVotingButtons - button.card-details-green.js-vote.js-vote-positive(class="{{#if voteState}}voted{{/if}}") - if voteState - i.fa.fa-thumbs-up - | {{_ 'vote-for-it'}} - button.card-details-red.js-vote.js-vote-negative(class="{{#if $eq voteState false}}voted{{/if}}") - if $eq voteState false - | 👎 - | {{_ 'vote-against'}} + //.card-details-items + if customFieldsWD + unless customFieldsGrid + hr + each customFieldsWD + if customFieldsGrid + hr + .card-details-item.card-details-item-customfield + h3.card-details-item-title + i.fa.fa-list + = definition.name + +cardCustomField - if getPokerQuestion - hr - .poker-title - div.flex - h3 - i.fa.fa-thumbs-up - | {{_ 'poker-question'}} - if getPokerEnd - +pokerEndDate - div.flex + if $gt customFieldsWD.length 1 + .material-toggle-switch(title="{{_ 'change'}} {{_ 'custom-fields'}} {{_ 'layout'}}") + if customFieldsGrid + input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton" checked="checked") + else + input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton") + label.toggle-label(for="toggleCustomFieldsGridButton") + a.js-custom-fields.card-details-item.custom-fields(title="{{_ 'custom-fields'}}") + + if getVoteQuestion + hr + .vote-title + div.flex + h3 + i.fa.fa-thumbs-up + | {{_ 'vote-question'}} + if getVoteEnd + +voteEndDate + .vote-result + if votePublic + a.card-label.card-label-green.js-show-positive-votes {{ voteCountPositive }} + a.card-label.card-label-red.js-show-negative-votes {{ voteCountNegative }} + else + .card-label.card-label-green {{ voteCountPositive }} + .card-label.card-label-red {{ voteCountNegative }} + unless ($and currentBoard.isPublic voteAllowNonBoardMembers ) + .card-label.card-label-gray {{ voteCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }} + +viewer + = getVoteQuestion + if showVotingButtons + button.card-details-green.js-vote.js-vote-positive(class="{{#if voteState}}voted{{/if}}") + if voteState + i.fa.fa-thumbs-up + | {{_ 'vote-for-it'}} + button.card-details-red.js-vote.js-vote-negative(class="{{#if $eq voteState false}}voted{{/if}}") + if $eq voteState false + i.fa.fa-thumbs-down + | {{_ 'vote-against'}} + + if getPokerQuestion + hr + .poker-title + div.flex + h3 + i.fa.fa-thumbs-up + | {{_ 'poker-question'}} + if getPokerEnd + +pokerEndDate + div.flex + .poker-result + if expiredPoker + unless ($and currentBoard.isPublic pokerAllowNonBoardMembers ) + .card-label.card-label-gray {{ pokerCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }} + if showPlanningPokerButtons .poker-result + .poker-deck + .poker-card + span.inner.js-poker.js-poker-vote-one(class="{{#if $eq pokerState 'one'}}poker-voted{{/if}}") {{_ 'poker-one'}} + if $eq pokerState "one" + i.fa.fa-check + .poker-deck + .poker-card + span.inner.js-poker.js-poker-vote-two(class="{{#if $eq pokerState 'two'}}poker-voted{{/if}}") {{_ 'poker-two'}} + if $eq pokerState "two" + i.fa.fa-check + .poker-deck + .poker-card + span.inner.js-poker.js-poker-vote-three(class="{{#if $eq pokerState 'three'}}poker-voted{{/if}}") {{_ 'poker-three'}} + if $eq pokerState "three" + i.fa.fa-check + .poker-deck + .poker-card + span.inner.js-poker.js-poker-vote-five(class="{{#if $eq pokerState 'five'}}poker-voted{{/if}}") {{_ 'poker-five'}} + if $eq pokerState "five" + i.fa.fa-check + .poker-deck + .poker-card + span.inner.js-poker.js-poker-vote-eight(class="{{#if $eq pokerState 'eight'}}poker-voted{{/if}}") {{_ 'poker-eight'}} + if $eq pokerState "eight" + i.fa.fa-check + .poker-deck + .poker-card + span.inner.js-poker.js-poker-vote-thirteen(class="{{#if $eq pokerState 'thirteen'}}poker-voted{{/if}}") {{_ 'poker-thirteen'}} + if $eq pokerState "thirteen" + i.fa.fa-check + .poker-deck + .poker-card + span.inner.js-poker.js-poker-vote-twenty(class="{{#if $eq pokerState 'twenty'}}poker-voted{{/if}}") {{_ 'poker-twenty'}} + if $eq pokerState "twenty" + i.fa.fa-check + .poker-deck + .poker-card + span.inner.js-poker.js-poker-vote-forty(class="{{#if $eq pokerState 'forty'}}poker-voted{{/if}}") {{_ 'poker-forty'}} + if $eq pokerState "forty" + i.fa.fa-check + .poker-deck + .poker-card + span.inner.js-poker.js-poker-vote-one-hundred(class="{{#if $eq pokerState 'oneHundred'}}poker-voted{{/if}}") {{_ 'poker-oneHundred'}} + if $eq pokerState "oneHundred" + i.fa.fa-check + .poker-deck + .poker-card + span.inner.js-poker.js-poker-vote-unsure(class="{{#if $eq pokerState 'unsure'}}poker-voted{{/if}}") {{_ 'poker-unsure'}} + if $eq pokerState "unsure" + i.fa.fa-check + + if currentUser.isBoardAdmin + button.card-details-blue.js-poker-finish(class="{{#if $eq voteState false}}poker-voted{{/if}}") {{_ 'poker-finish'}} + if expiredPoker - unless ($and currentBoard.isPublic pokerAllowNonBoardMembers ) - .card-label.card-label-gray {{ pokerCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }} - if showPlanningPokerButtons - .poker-result - .poker-deck - .poker-card - span.inner.js-poker.js-poker-vote-one(class="{{#if $eq pokerState 'one'}}poker-voted{{/if}}") {{_ 'poker-one'}} - if $eq pokerState "one" - i.fa.fa-check - .poker-deck - .poker-card - span.inner.js-poker.js-poker-vote-two(class="{{#if $eq pokerState 'two'}}poker-voted{{/if}}") {{_ 'poker-two'}} - if $eq pokerState "two" - i.fa.fa-check - .poker-deck - .poker-card - span.inner.js-poker.js-poker-vote-three(class="{{#if $eq pokerState 'three'}}poker-voted{{/if}}") {{_ 'poker-three'}} - if $eq pokerState "three" - i.fa.fa-check - .poker-deck - .poker-card - span.inner.js-poker.js-poker-vote-five(class="{{#if $eq pokerState 'five'}}poker-voted{{/if}}") {{_ 'poker-five'}} - if $eq pokerState "five" - i.fa.fa-check - .poker-deck - .poker-card - span.inner.js-poker.js-poker-vote-eight(class="{{#if $eq pokerState 'eight'}}poker-voted{{/if}}") {{_ 'poker-eight'}} - if $eq pokerState "eight" - i.fa.fa-check - .poker-deck - .poker-card - span.inner.js-poker.js-poker-vote-thirteen(class="{{#if $eq pokerState 'thirteen'}}poker-voted{{/if}}") {{_ 'poker-thirteen'}} - if $eq pokerState "thirteen" - i.fa.fa-check - .poker-deck - .poker-card - span.inner.js-poker.js-poker-vote-twenty(class="{{#if $eq pokerState 'twenty'}}poker-voted{{/if}}") {{_ 'poker-twenty'}} - if $eq pokerState "twenty" - i.fa.fa-check - .poker-deck - .poker-card - span.inner.js-poker.js-poker-vote-forty(class="{{#if $eq pokerState 'forty'}}poker-voted{{/if}}") {{_ 'poker-forty'}} - if $eq pokerState "forty" - i.fa.fa-check - .poker-deck - .poker-card - span.inner.js-poker.js-poker-vote-one-hundred(class="{{#if $eq pokerState 'oneHundred'}}poker-voted{{/if}}") {{_ 'poker-oneHundred'}} - if $eq pokerState "oneHundred" - i.fa.fa-check - .poker-deck - .poker-card - span.inner.js-poker.js-poker-vote-unsure(class="{{#if $eq pokerState 'unsure'}}poker-voted{{/if}}") {{_ 'poker-unsure'}} - if $eq pokerState "unsure" - i.fa.fa-check + .poker-table + .poker-table-side-left + .poker-table-heading-left + .poker-table-row + .poker-table-cell + .poker-table-cell + | {{_ 'poker-result-votes' }} + .poker-table-cell.poker-table-cell-who + | {{_ 'poker-result-who' }} + .poker-table-body + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 1}}winner{{else}}loser{{/if}}") {{_ 'poker-one'}} + .poker-table-cell {{ pokerCountOne }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberOne + a.name + +userAvatar(userId=m._id noRemove=true) - if currentUser.isBoardAdmin - button.card-details-blue.js-poker-finish(class="{{#if $eq voteState false}}poker-voted{{/if}}") {{_ 'poker-finish'}} + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 2}}winner{{else}}loser{{/if}}") {{_ 'poker-two'}} + .poker-table-cell {{ pokerCountTwo }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberTwo + a.name + +userAvatar(userId=m._id noRemove=true) - if expiredPoker - .poker-table - .poker-table-side-left - .poker-table-heading-left - .poker-table-row - .poker-table-cell - .poker-table-cell - | {{_ 'poker-result-votes' }} - .poker-table-cell.poker-table-cell-who - | {{_ 'poker-result-who' }} - .poker-table-body - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 1}}winner{{else}}loser{{/if}}") {{_ 'poker-one'}} - .poker-table-cell {{ pokerCountOne }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberOne - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 3}}winner{{else}}loser{{/if}}") {{_ 'poker-three'}} + .poker-table-cell {{ pokerCountThree }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberThree + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 2}}winner{{else}}loser{{/if}}") {{_ 'poker-two'}} - .poker-table-cell {{ pokerCountTwo }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberTwo - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 5}}winner{{else}}loser{{/if}}") {{_ 'poker-five'}} + .poker-table-cell {{ pokerCountFive }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberFive + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 3}}winner{{else}}loser{{/if}}") {{_ 'poker-three'}} - .poker-table-cell {{ pokerCountThree }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberThree - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 8}}winner{{else}}loser{{/if}}") {{_ 'poker-eight'}} + .poker-table-cell {{ pokerCountEight }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberEight + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 5}}winner{{else}}loser{{/if}}") {{_ 'poker-five'}} - .poker-table-cell {{ pokerCountFive }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberFive - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-side-right + .poker-table-heading-right + .poker-table-row + .poker-table-cell + .poker-table-cell + | {{_ 'poker-result-votes' }} + .poker-table-cell.poker-table-cell-who + | {{_ 'poker-result-who' }} + .poker-table-body + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 13}}winner{{else}}loser{{/if}}") {{_ 'poker-thirteen'}} + .poker-table-cell {{ pokerCountThirteen }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberThirteen + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 8}}winner{{else}}loser{{/if}}") {{_ 'poker-eight'}} - .poker-table-cell {{ pokerCountEight }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberEight - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 20}}winner{{else}}loser{{/if}}") {{_ 'poker-twenty'}} + .poker-table-cell {{ pokerCountTwenty }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberTwenty + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-side-right - .poker-table-heading-right - .poker-table-row - .poker-table-cell - .poker-table-cell - | {{_ 'poker-result-votes' }} - .poker-table-cell.poker-table-cell-who - | {{_ 'poker-result-who' }} - .poker-table-body - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 13}}winner{{else}}loser{{/if}}") {{_ 'poker-thirteen'}} - .poker-table-cell {{ pokerCountThirteen }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberThirteen - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 40}}winner{{else}}loser{{/if}}") {{_ 'poker-forty'}} + .poker-table-cell {{ pokerCountForty }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberForty + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 20}}winner{{else}}loser{{/if}}") {{_ 'poker-twenty'}} - .poker-table-cell {{ pokerCountTwenty }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberTwenty - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 100}}winner{{else}}loser{{/if}}") {{_ 'poker-oneHundred'}} + .poker-table-cell {{ pokerCountOneHundred }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberOneHundred + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 40}}winner{{else}}loser{{/if}}") {{_ 'poker-forty'}} - .poker-table-cell {{ pokerCountForty }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberForty - a.name - +userAvatar(userId=m._id noRemove=true) + .poker-table-row + .poker-table-cell + button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 'unsure'}}winner{{else}}loser{{/if}}") {{_ 'poker-unsure'}} + .poker-table-cell {{ pokerCountUnsure }} + .poker-table-cell.poker-table-cell-who + .poker-result + each m in pokerMemberUnsure + a.name + +userAvatar(userId=m._id noRemove=true) - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 100}}winner{{else}}loser{{/if}}") {{_ 'poker-oneHundred'}} - .poker-table-cell {{ pokerCountOneHundred }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberOneHundred - a.name - +userAvatar(userId=m._id noRemove=true) + if currentUser.isBoardAdmin + div.estimation-add + button.card-details-red.js-poker-replay(class="{{#if $eq voteState false}}voted{{/if}}") {{_ 'poker-replay'}} + div.estimation-add + button.js-poker-estimation + i.fa.fa-plus + | {{_ 'set-estimation'}} + input(type=text,autofocus value=getPokerEstimation,id="pokerEstimation") - .poker-table-row - .poker-table-cell - button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 'unsure'}}winner{{else}}loser{{/if}}") {{_ 'poker-unsure'}} - .poker-table-cell {{ pokerCountUnsure }} - .poker-table-cell.poker-table-cell-who - .poker-result - each m in pokerMemberUnsure - a.name - +userAvatar(userId=m._id noRemove=true) - - if currentUser.isBoardAdmin - div.estimation-add - button.card-details-red.js-poker-replay(class="{{#if $eq voteState false}}voted{{/if}}") {{_ 'poker-replay'}} - div.estimation-add - button.js-poker-estimation - i.fa.fa-plus - | {{_ 'set-estimation'}} - input(type=text,autofocus value=getPokerEstimation,id="pokerEstimation") - - //- XXX We should use "editable" to avoid repetiting ourselves - if canModifyCard - unless currentUser.isWorker + //- XXX We should use "editable" to avoid repetiting ourselves + if canModifyCard + unless currentUser.isWorker + if currentBoard.allowsDescriptionTitle + hr + h3.card-details-item-title + i.fa.fa-file-text-o + | {{_ 'description'}} + if currentBoard.allowsDescriptionText + +inlinedCardDescription(classNames="card-description js-card-description") + +descriptionForm + .edit-controls.clearfix + button.primary(type="submit") {{_ 'save'}} + a.js-close-inlined-form + else + if currentBoard.allowsDescriptionText + .edit-card-details-description + a.js-open-inlined-form(title="{{_ 'edit'}}" value=title) + i.fa.fa-pencil-square-o + a.js-open-inlined-form(title="{{_ 'edit'}}" value=title) + if getDescription + +viewer + = getDescription + if (hasUnsavedValue 'cardDescription' _id) + p.quiet + | {{_ 'unsaved-description'}} + a.js-open-inlined-form {{_ 'view-it'}} + = ' - ' + a.js-close-inlined-form {{_ 'discard'}} + else if getDescription if currentBoard.allowsDescriptionTitle hr - h3.card-details-item-title - i.fa.fa-file-text-o - | {{_ 'description'}} + h3.card-details-item-title {{_ 'description'}} if currentBoard.allowsDescriptionText - +inlinedCardDescription(classNames="card-description js-card-description") - +descriptionForm - .edit-controls.clearfix - button.primary(type="submit") {{_ 'save'}} - a.js-close-inlined-form - else - if currentBoard.allowsDescriptionText - a.js-open-inlined-form(title="{{_ 'edit'}}" value=title) - i.fa.fa-pencil-square-o - a.js-open-inlined-form(title="{{_ 'edit'}}" value=title) - if getDescription - +viewer - = getDescription - if (hasUnsavedValue 'cardDescription' _id) - p.quiet - | {{_ 'unsaved-description'}} - a.js-open-inlined-form {{_ 'view-it'}} - = ' - ' - a.js-close-inlined-form {{_ 'discard'}} - else if getDescription - if currentBoard.allowsDescriptionTitle - hr - h3.card-details-item-title {{_ 'description'}} - if currentBoard.allowsDescriptionText - +viewer - = getDescription + +viewer + = getDescription - .card-checklist-attachmentGalleries - .card-checklist-attachmentGallery.card-checklists - if currentBoard.allowsChecklists + .card-checklist-attachmentGalleries + .card-checklist-attachmentGallery.card-checklists + if currentBoard.allowsChecklists + hr + +checklists(cardId = _id card = this) + if currentBoard.allowsSubtasks + hr + +subtasks(cardId = _id) + if currentBoard.allowsAttachments hr - +checklists(cardId = _id card = this) - if currentBoard.allowsSubtasks - hr - +subtasks(cardId = _id) - if currentBoard.allowsAttachments - hr - h3.card-details-item-title - i.fa.fa-paperclip - | {{_ 'attachments'}} - if Meteor.settings.public.attachmentsUploadMaxSize - | {{_ 'max-upload-filesize'}} {{Meteor.settings.public.attachmentsUploadMaxSize}} - br - if Meteor.settings.public.attachmentsUploadMimeTypes - | {{_ 'allowed-upload-filetypes'}} {{Meteor.settings.public.attachmentsUploadMimeTypes}} - br - | {{_ 'invalid-file'}} - .card-checklist-attachmentGallery.card-attachmentGallery - +attachmentGallery - hr + h3.card-details-item-title + i.fa.fa-paperclip + | {{_ 'attachments'}} + if Meteor.settings.public.attachmentsUploadMaxSize + | {{_ 'max-upload-filesize'}} {{Meteor.settings.public.attachmentsUploadMaxSize}} + br + if Meteor.settings.public.attachmentsUploadMimeTypes + | {{_ 'allowed-upload-filetypes'}} {{Meteor.settings.public.attachmentsUploadMimeTypes}} + br + | {{_ 'invalid-file'}} + .card-checklist-attachmentGallery.card-attachmentGallery + +attachmentGallery + hr - unless currentUser.isNoComments - .comment-title - h3.card-details-item-title - i.fa.fa-comment-o - | {{_ 'comments'}} + unless currentUser.isNoComments + .comment-title + h3.card-details-item-title + i.fa.fa-comment-o + | {{_ 'comments'}} - if currentBoard.allowsComments - if currentUser.isBoardMember - unless currentUser.isNoComments - unless currentUser.isReadOnly - unless currentUser.isReadAssignedOnly - +commentForm - +comments - hr + if currentBoard.allowsComments + if currentUser.isBoardMember + unless currentUser.isNoComments + +commentForm + +comments + hr - .card-details-right - - if currentUser.isBoardAdmin - .activity-title - h3.card-details-item-title - i.fa.fa-history - | {{ _ 'activities'}} - if currentUser.isBoardMember - .material-toggle-switch(title="{{_ 'show-activities'}}") - if showActivities - input.toggle-switch(type="checkbox" id="toggleShowActivitiesCard" checked="checked") - else - input.toggle-switch(type="checkbox" id="toggleShowActivitiesCard") - label.toggle-label(for="toggleShowActivitiesCard") + .card-details-right + unless currentUser.isNoComments + .activity-title + h3.card-details-item-title + i.fa.fa-history + | {{ _ 'activities'}} + if currentUser.isBoardMember + .material-toggle-switch(title="{{_ 'show-activities'}}") + if showActivities + input.toggle-switch(type="checkbox" id="toggleShowActivitiesCard" checked="checked") + else + input.toggle-switch(type="checkbox" id="toggleShowActivitiesCard") + label.toggle-label(for="toggleShowActivitiesCard") if currentUser.isBoardAdmin if isLoaded.get @@ -662,32 +645,36 @@ template(name="cardDetails") else +activities(card=this mode="card") + template(name="editCardTitleForm") a(title="{{_ 'copy-text-to-clipboard'}}") - span.copied-tooltip {{_ 'copied'}} - textarea.js-edit-card-title(rows='1' autofocus dir="auto") + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} + textarea.js-edit-card-title(rows='1' dir="auto") = getTitle .edit-controls.clearfix + button.negate.js-back-view(type="submit") {{_ 'cancel'}} button.primary.confirm.js-submit-edit-card-title-form(type="submit") {{_ 'save'}} - a.js-close-inlined-form template(name="editCardRequesterForm") - input.js-edit-card-requester(type='text' autofocus value=getRequestedBy dir="auto") + input.js-edit-card-requester(type='text' value=getRequestedBy dir="auto") .edit-controls.clearfix button.primary.confirm.js-submit-edit-card-requester-form(type="submit") {{_ 'save'}} a.js-close-inlined-form + i.fa.fa-times-thin template(name="editCardAssignerForm") - input.js-edit-card-assigner(type='text' autofocus value=getAssignedBy dir="auto") + input.js-edit-card-assigner(type='text' value=getAssignedBy dir="auto") .edit-controls.clearfix button.primary.confirm.js-submit-edit-card-assigner-form(type="submit") {{_ 'save'}} a.js-close-inlined-form + i.fa.fa-times-thin template(name="editCardSortOrderForm") - input.js-edit-card-sort(type='text' autofocus value=sort dir="auto") + input.js-edit-card-sort(type='text' value=sort dir="auto") .edit-controls.clearfix button.primary.confirm.js-submit-edit-card-sort-form(type="submit") {{_ 'save'}} a.js-close-inlined-form + i.fa.fa-times-thin template(name="cardDetailsActionsPopup") ul.pop-over-list @@ -880,7 +867,7 @@ template(name="moveCardPopup") template(name="copyCardPopup") label(for='copy-card-title') {{_ 'title'}}: - textarea#copy-card-title.minicard-composer-textarea.js-card-title(autofocus) + textarea#copy-card-title.minicard-composer-textarea.js-card-title = getTitle unless currentUser.isWorker label {{_ 'boards'}}: @@ -915,7 +902,7 @@ template(name="copyCardPopup") template(name="copyManyCardsPopup") label(for='copy-checklist-cards-title') {{_ 'copyManyCardsPopup-instructions'}}: - textarea#copy-card-title.minicard-composer-textarea.js-card-title(autofocus) + textarea#copy-card-title.minicard-composer-textarea.js-card-title | {{_ 'copyManyCardsPopup-format'}} unless currentUser.isWorker label {{_ 'boards'}}: @@ -950,11 +937,11 @@ template(name="copyManyCardsPopup") template(name="convertChecklistItemToCardPopup") label(for='convert-checklist-item-to-card-title') {{_ 'title'}}: - textarea#copy-card-title.minicard-composer-textarea.js-card-title(autofocus) + textarea#copy-card-title.minicard-composer-textarea.js-card-title = item.title unless currentUser.isWorker label {{_ 'boards'}}: - select.js-select-boards(autofocus) + select.js-select-boards each boards option(value="{{_id}}" selected="{{#if isDialogOptionBoardId _id}}selected{{/if}}") {{add @index 1}}. {{title}} @@ -1039,14 +1026,14 @@ template(name="cardAssigneePopup") li: a.js-edit-profile {{_ 'edit-profile'}} template(name="cardMorePopup") - p.quiet + p.quiet.cardMorePopup span.clearfix span {{_ 'link-card'}} = ' ' i.fa(class="{{#if currentBoard.isPublic}}fa-globe{{else}}fa-lock{{/if}}") - input.inline-input(type="text" id="cardURL" readonly value="{{ originRelativeUrl }}" autofocus="autofocus") + input.inline-input(type="text" id="cardURL" readonly value="{{ originRelativeUrl }}" ) button.js-copy-card-link-to-clipboard(class="btn" id="clipboard") {{_ 'copy-card-link-to-clipboard'}} - .copied-tooltip {{_ 'copied'}} + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} span.clearfix br h2 {{_ 'change-card-parent'}} @@ -1073,22 +1060,22 @@ template(name="cardMorePopup") option(value="{{_id}}" selected) {{title}} else option(value="{{_id}}") {{title}} - br - | {{_ 'added'}} - span.date(title=card.createdAt) {{ moment createdAt 'LLL' }} - if currentUser.isBoardAdmin - a.js-delete(title="{{_ 'card-delete-notice'}}") {{_ 'delete'}} + .card-add-date + | {{_ 'added'}} + span.date(title=card.createdAt) {{ moment createdAt 'LLL' }} + if currentUser.isBoardAdmin + a.js-delete(title="{{_ 'card-delete-notice'}}") {{_ 'delete'}} template(name="setCardColorPopup") form.edit-label - .palette-colors - each colors - unless $eq color 'white' - span.card-label.palette-color.js-palette-color(class="card-details-{{color}}") - if(isSelected color) - i.fa.fa-check - button.primary.confirm.js-submit {{_ 'save'}} - button.js-remove-color.negate.wide.right {{_ 'unset-color'}} + .palette-colors: each colors + unless $eq color 'white' + span.card-label.palette-color.js-palette-color(class="card-details-{{color}}") + if(isSelected color) + i.fa.fa-check + .form-buttons + button.primary.confirm.js-submit {{_ 'save'}} + button.js-remove-color.negate.wide.right {{_ 'unset-color'}} template(name="cardDeletePopup") p {{_ "card-delete-pop"}} @@ -1110,7 +1097,7 @@ template(name="cardStartVotingPopup") form.edit-vote-question .fields label(for="vote") {{_ 'vote-question'}} - input.js-vote-field#vote(type="text" name="vote" value="{{getVoteQuestion}}" autofocus disabled="{{#if getVoteQuestion}}disabled{{/if}}") + input.js-vote-field#vote(type="text" name="vote" value="{{getVoteQuestion}}" disabled="{{#if getVoteQuestion}}disabled{{/if}}") .check-div a.flex(class="{{#if getVoteQuestion}}is-disabled{{else}}js-toggle-vote-allow-non-members{{/if}}") .materialCheckBox#vote-allow-non-members(name="vote-allow-non-members" class="{{#if voteAllowNonBoardMembers}}is-checked{{/if}}") @@ -1178,4 +1165,4 @@ template(name="cardStartPlanningPokerPopup") button.primary.js-submit {{_ 'save'}} if getPokerQuestion if currentUser.isBoardAdmin - button.js-remove-poker.negate.wide.right {{_ 'delete'}} + button.js-remove-poker.negate.wide.right {{_ 'delete'}} \ No newline at end of file diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 5f69d4bd8..2a7a3b480 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -2,25 +2,25 @@ import { ReactiveCache } from '/imports/reactiveCache'; import { TAPi18n } from '/imports/i18n'; import { FlowRouter } from 'meteor/ostrio:flow-router-extra'; import { DatePicker } from '/client/lib/datepicker'; -import { - formatDateTime, - formatDate, - formatTime, - getISOWeek, - isValidDate, - isBefore, - isAfter, - isSame, - add, - subtract, - startOf, - endOf, - format, - parseDate, - now, - createDate, - fromNow, - calendar +import { + formatDateTime, + formatDate, + formatTime, + getISOWeek, + isValidDate, + isBefore, + isAfter, + isSame, + add, + subtract, + startOf, + endOf, + format, + parseDate, + now, + createDate, + fromNow, + calendar } from '/imports/lib/dateUtils'; import Cards from '/models/cards'; import Boards from '/models/boards'; @@ -35,6 +35,7 @@ import { DialogWithBoardSwimlaneList } from '/client/lib/dialogWithBoardSwimlane import { DialogWithBoardSwimlaneListCard } from '/client/lib/dialogWithBoardSwimlaneListCard'; import { handleFileUpload } from './attachments'; import uploadProgressManager from '../../lib/uploadProgressManager'; +import PopupComponent from '../main/popup'; const subManager = new SubsManager(); const { calculateIndexData } = Utils; @@ -60,19 +61,8 @@ BlazeComponent.extendComponent({ onCreated() { this.currentBoard = Utils.getCurrentBoard(); this.isLoaded = new ReactiveVar(false); + this.dep = new Tracker.Dependency(); - if (this.parentComponent() && this.parentComponent().parentComponent()) { - const boardBody = this.parentComponent().parentComponent(); - //in Miniview parent is Board, not BoardBody. - if (boardBody !== null) { - // Only show overlay in mobile mode, not in desktop mode - const isMobile = Utils.getMobileMode(); - if (isMobile) { - boardBody.showOverlay.set(true); - } - boardBody.mouseHasEnterCardDetails = false; - } - } this.calculateNextPeak(); Meteor.subscribe('unsaved-edits'); @@ -85,6 +75,18 @@ BlazeComponent.extendComponent({ // }); }, + onRendered() { + const boardOverlay = document.getElementsByClassName('board-overlay')?.[0]; + this.boardBody = BlazeComponent.getComponentForElement(boardOverlay); + if (this.boardBody) { + this.boardBody.mouseHasEnterCardDetails = false; + } + const isMobile = Utils.getMobileMode(); + if (isMobile && Session.get('currentCard')) { + //this.boardBody?.showOverlay.set(true); + } + }, + isWatching() { const card = this.currentData(); if (!card || typeof card.findWatcher !== 'function') return false; @@ -95,8 +97,8 @@ BlazeComponent.extendComponent({ return ReactiveCache.getCurrentUser().hasCustomFieldsGrid(); }, - cardMaximized() { + this.dep.depend(); return !Utils.getPopupCardId() && ReactiveCache.getCurrentUser().hasCardMaximized(); }, @@ -175,6 +177,11 @@ BlazeComponent.extendComponent({ }, onRendered() { + // #FIXME hackish; if accepted tweak static funcs + if (this.cardMaximized()) { + PopupComponent.maximize({target: this.firstNode()}); + } + if (Meteor.settings.public.CARD_OPENED_WEBHOOK_ENABLED) { // Send Webhook but not create Activities records --- const card = this.currentData(); @@ -209,11 +216,11 @@ BlazeComponent.extendComponent({ } const $checklistsDom = this.$('.card-checklist-items'); - + const sortableSelector = Utils.isMiniScreen() ? '.checklist-handle' : '.checklist-title'; $checklistsDom.sortable({ tolerance: 'pointer', helper: 'clone', - handle: '.checklist-title', + handle: sortableSelector, items: '.js-checklist', placeholder: 'checklist placeholder', distance: 7, @@ -282,6 +289,8 @@ BlazeComponent.extendComponent({ return ReactiveCache.getCurrentUser()?.isBoardMember(); } + + // Disable sorting if the current user is not a board member this.autorun(() => { const disabled = !userIsMember(); @@ -289,10 +298,7 @@ BlazeComponent.extendComponent({ $checklistsDom.data('uiSortable') || $checklistsDom.data('sortable') ) { - $checklistsDom.sortable('option', 'disabled', disabled); - if (Utils.isTouchScreenOrShowDesktopDragHandles()) { - $checklistsDom.sortable({ handle: '.checklist-handle' }); - } + $checklistsDom.sortable('option', 'handle', sortableSelector); } if ($subtasksDom.data('uiSortable') || $subtasksDom.data('sortable')) { $subtasksDom.sortable('option', 'disabled', disabled); @@ -301,11 +307,7 @@ BlazeComponent.extendComponent({ }, onDestroyed() { - if (this.parentComponent() === null) return; - const parentComponent = this.parentComponent().parentComponent(); - //on mobile view parent is Board, not board body. - if (parentComponent === null) return; - parentComponent.showOverlay.set(false); + this.boardBody?.showOverlay.set(false); }, events() { @@ -332,59 +334,11 @@ BlazeComponent.extendComponent({ }, 'mousedown .js-card-drag-handle'(event) { event.preventDefault(); - const $card = $(event.target).closest('.card-details'); - const startX = event.clientX; - const startY = event.clientY; - const startLeft = $card.offset().left; - const startTop = $card.offset().top; - - const onMouseMove = (e) => { - const deltaX = e.clientX - startX; - const deltaY = e.clientY - startY; - $card.css({ - left: startLeft + deltaX + 'px', - top: startTop + deltaY + 'px' - }); - }; - - const onMouseUp = () => { - $(document).off('mousemove', onMouseMove); - $(document).off('mouseup', onMouseUp); - }; - - $(document).on('mousemove', onMouseMove); - $(document).on('mouseup', onMouseUp); + PopupComponent.toFront(event); }, - 'mousedown .js-card-title-drag-handle'(event) { - // Allow dragging from title for ReadOnly users - // Don't interfere with text selection - if (event.target.tagName === 'A' || $(event.target).closest('a').length > 0) { - return; // Don't drag if clicking on links - } - + 'click .js-card-send-to-back'(event) { event.preventDefault(); - const $card = $(event.target).closest('.card-details'); - const startX = event.clientX; - const startY = event.clientY; - const startLeft = $card.offset().left; - const startTop = $card.offset().top; - - const onMouseMove = (e) => { - const deltaX = e.clientX - startX; - const deltaY = e.clientY - startY; - $card.css({ - left: startLeft + deltaX + 'px', - top: startTop + deltaY + 'px' - }); - }; - - const onMouseUp = () => { - $(document).off('mousemove', onMouseMove); - $(document).off('mouseup', onMouseUp); - }; - - $(document).on('mousemove', onMouseMove); - $(document).on('mouseup', onMouseUp); + PopupComponent.toBack(event); }, 'click .js-close-card-details'() { // Get board ID from either the card data or current board in session @@ -392,26 +346,21 @@ BlazeComponent.extendComponent({ const boardId = (card && card.boardId) || Utils.getCurrentBoard()._id; const cardId = card && card._id; - if (boardId) { - // In desktop mode, remove from openCards array - const isMobile = Utils.getMobileMode(); - if (!isMobile && cardId) { - const openCards = Session.get('openCards') || []; - const filtered = openCards.filter(id => id !== cardId); - Session.set('openCards', filtered); - - // If this was the current card, clear it - if (Session.get('currentCard') === cardId) { - Session.set('currentCard', null); - } - // Don't navigate away in desktop mode - just close the card - return; + if (boardId && cardId) { + const openCards = Session.get('openCards') || []; + const filtered = openCards.filter(id => id !== cardId); + // If this was the current card, clear it + if (openCards.length === filtered.length) { + Session.set('currentCard', null); } + else { + Session.set('currentCard', filtered[0]); + } + Session.set('openCards', filtered); - // Mobile mode: Clear the current card session to close the card - Session.set('currentCard', null); - - // Navigate back to board without card + // Navigate back to board without card: must be done at the time of writing + // otherwise the route for the card is disabled until another + // card is opened const board = ReactiveCache.getBoard(boardId); if (board) { FlowRouter.go('board', { @@ -434,34 +383,6 @@ BlazeComponent.extendComponent({ Meteor.call('changeDateFormat', dateFormat); }, 'click .js-open-card-details-menu': Popup.open('cardDetailsActions'), - // Mobile: switch to desktop popup view (maximize) - 'click .js-mobile-switch-to-desktop'(event) { - event.preventDefault(); - // Switch global mode to desktop so the card appears as desktop popup - Utils.setMobileMode(false); - }, - 'click .js-card-zoom-in'(event) { - event.preventDefault(); - const current = Utils.getCardZoom(); - const newZoom = Math.min(3.0, current + 0.1); - Utils.setCardZoom(newZoom); - }, - 'click .js-card-zoom-out'(event) { - event.preventDefault(); - const current = Utils.getCardZoom(); - const newZoom = Math.max(0.5, current - 0.1); - Utils.setCardZoom(newZoom); - }, - 'click .js-card-mobile-desktop-toggle'(event) { - event.preventDefault(); - const currentMode = Utils.getMobileMode(); - Utils.setMobileMode(!currentMode); - }, - 'click .js-card-mobile-desktop-toggle'(event) { - event.preventDefault(); - const currentMode = Utils.getMobileMode(); - Utils.setMobileMode(!currentMode); - }, async 'submit .js-card-description'(event) { event.preventDefault(); const description = this.currentComponent().getValue(); @@ -525,7 +446,7 @@ BlazeComponent.extendComponent({ 'click .js-add-members': Popup.open('cardMembers'), 'click .js-assignee': Popup.open('cardAssignee'), 'click .js-add-assignees': Popup.open('cardAssignees'), - 'click .js-add-labels': Popup.open('cardLabels'), + 'click .js-add-labels'(event) {Popup.open('cardLabels')(event, { dataContextIfCurrentDataIsUndefined: this.currentData() })}, 'click .js-received-date': Popup.open('editCardReceivedDate'), 'click .js-start-date': Popup.open('editCardStartDate'), 'click .js-due-date': Popup.open('editCardDueDate'), @@ -534,12 +455,10 @@ BlazeComponent.extendComponent({ 'click .js-show-negative-votes': Popup.open('negativeVoteMembers'), 'click .js-custom-fields': Popup.open('cardCustomFields'), 'mouseenter .js-card-details'() { - if (this.parentComponent() === null) return; - const parentComponent = this.parentComponent().parentComponent(); - //on mobile view parent is Board, not BoardBody. - if (parentComponent === null) return; - parentComponent.showOverlay.set(true); - parentComponent.mouseHasEnterCardDetails = true; + if (this.boardBody) { + this.boardBody.showOverlay.set(true); + this.boardBody.mouseHasEnterCardDetails = true; + } }, 'mousedown .js-card-details'() { Session.set('cardDetailsIsDragging', false); @@ -560,13 +479,13 @@ BlazeComponent.extendComponent({ 'click #toggleCustomFieldsGridButton'() { Meteor.call('toggleCustomFieldsGrid'); }, - 'click .js-maximize-card-details'() { + 'click .js-maximize-card-details'(e) { + PopupComponent.maximize(e); Meteor.call('toggleCardMaximized'); - autosize($('.card-details')); }, - 'click .js-minimize-card-details'() { + 'click .js-minimize-card-details'(e) { + PopupComponent.minimize(e); Meteor.call('toggleCardMaximized'); - autosize($('.card-details')); }, 'click .js-vote'(e) { const forIt = $(e.target).hasClass('js-vote-positive'); @@ -737,16 +656,6 @@ Template.cardDetails.helpers({ return uploadProgressManager.getUploadCountForCard(this._id); } }); -Template.cardDetailsPopup.onDestroyed(() => { - Session.delete('popupCardId'); - Session.delete('popupCardBoardId'); -}); -Template.cardDetailsPopup.helpers({ - popupCard() { - const ret = Utils.getPopupCard(); - return ret; - }, -}); BlazeComponent.extendComponent({ template() { @@ -883,9 +792,7 @@ Template.cardDetailsActionsPopup.events({ 'click .js-toggle-watch-card'() { const currentCard = this; const level = currentCard.findWatcher(Meteor.userId()) ? null : 'watching'; - Meteor.call('watch', 'card', currentCard._id, level, (err, ret) => { - if (!err && ret) Popup.close(); - }); + Meteor.call('watch', 'card', currentCard._id, level) }, 'click .js-toggle-show-list-on-minicard'() { const currentCard = this; @@ -896,9 +803,6 @@ Template.cardDetailsActionsPopup.events({ }); BlazeComponent.extendComponent({ - onRendered() { - autosize(this.$('textarea.js-edit-card-title')); - }, events() { return [ { @@ -979,10 +883,6 @@ const filterMembers = (filterTerm) => { return members; } -Template.editCardRequesterForm.onRendered(function () { - autosize(this.$('.js-edit-card-requester')); -}); - Template.editCardRequesterForm.events({ 'keydown .js-edit-card-requester'(event) { // If enter key was pressed, submit the data @@ -992,10 +892,6 @@ Template.editCardRequesterForm.events({ }, }); -Template.editCardAssignerForm.onRendered(function () { - autosize(this.$('.js-edit-card-assigner')); -}); - Template.editCardAssignerForm.events({ 'keydown .js-edit-card-assigner'(event) { // If enter key was pressed, submit the data @@ -1469,13 +1365,13 @@ BlazeComponent.extendComponent({ 'DD/MM/YYYY HH:mm', 'DD-MM-YYYY HH:mm' ]; - + let parsedDate = null; for (const format of formats) { parsedDate = parseDate(dateString, [format], true); if (parsedDate) break; } - + // Fallback to native Date parsing if (!parsedDate) { parsedDate = new Date(dateString); @@ -1721,13 +1617,13 @@ BlazeComponent.extendComponent({ 'DD/MM/YYYY HH:mm', 'DD-MM-YYYY HH:mm' ]; - + let parsedDate = null; for (const format of formats) { parsedDate = parseDate(dateString, [format], true); if (parsedDate) break; } - + // Fallback to native Date parsing if (!parsedDate) { parsedDate = new Date(dateString); @@ -1905,9 +1801,6 @@ EscapeActions.register( () => { return !Session.equals('currentCard', null); }, - { - noClickEscapeOn: '.js-card-details,.board-sidebar,#header', - }, ); Template.cardAssigneesPopup.onCreated(function () { @@ -1985,3 +1878,16 @@ Template.cardAssigneePopup.events({ }, 'click .js-edit-profile': Popup.open('editProfile'), }); + +Template.cardDetailsPopup.helpers({ + popupArgs() { + return { + name: "cardDetails", + showHeader: false, + closeDOMs: ["click .js-close-card-details"], + followDOM: ".card-details", + handleDOM: ".card-header-middle", + closeVar: "currentCard" + } + }, +}); \ No newline at end of file diff --git a/client/components/cards/cardTime.css b/client/components/cards/cardTime.css index ab8f2fae1..77586ac86 100644 --- a/client/components/cards/cardTime.css +++ b/client/components/cards/cardTime.css @@ -1,6 +1,6 @@ .card-time { display: block; - border-radius: 4px; + border-radius: 0.4ch; padding: 1px 3px; color: #fff; background-color: #dbdbdb; diff --git a/client/components/cards/checklists.css b/client/components/cards/checklists.css index 073e7ec79..83dabf68b 100644 --- a/client/components/cards/checklists.css +++ b/client/components/cards/checklists.css @@ -4,7 +4,7 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item { overflow: hidden; - word-wrap: break-word; + overflow-wrap: break-word; resize: none; height: 34px; } @@ -13,7 +13,7 @@ textarea.js-edit-checklist-item { .js-convert-checklist-item-to-card { color: #8c8c8c; text-decoration: underline; - word-wrap: break-word; + overflow-wrap: break-word; float: right; padding-top: 6px; } @@ -25,6 +25,7 @@ textarea.js-edit-checklist-item { .checklists-title { display: flex; justify-content: space-between; + align-items: center; } .checklist-progress-bar-container { display: flex; @@ -35,7 +36,7 @@ textarea.js-edit-checklist-item { margin-right: 10px; } .checklist-progress-bar-container .checklist-progress-bar { - width: 80%; + flex: 1; height: 10px; background-color: #e0e0e0; border-radius: 16px; @@ -47,19 +48,29 @@ textarea.js-edit-checklist-item { border-radius: 16px; height: 100%; } -.checklist-title { - padding: 10px; + +.checklist-controls { + display: flex; + gap: 0.25lh; } + +.checklist-title { + display: flex; + align-items: center; + justify-content: space-between; +} + .checklist-title .checkbox { float: left; width: 30px; height: 30px; - font-size: 18px; + line-height: 30px; } -.checklist-title .title { - font-size: 18px; - line-height: 25px; +.checklist-title p, .title { + font-size: 1em; + line-height: 1; + margin: 0; } .checklist-title .checklist-stat { margin: 0 0.5em; @@ -79,29 +90,31 @@ textarea.js-edit-checklist-item { bottom: -600px; right: 0; } + .checklist { - background: #f7f7f7; + padding: 0.5lh; + margin: 0.5lh 0; + background-color: #f7f7f7; } + + .checklist.placeholder { background: #ccc; border-radius: 2px; } .checklist.ui-sortable-helper { box-shadow: -2px 2px 8px rgba(0,0,0,0.3), 0 0 1px rgba(0,0,0,0.5); - transform: rotate(4deg); cursor: grabbing; } .checklist-item { - margin: 0 0 0 0.1em; - line-height: 18px; - font-size: 1.1em; - margin-top: 3px; display: flex; - background: #f7f7f7; + gap: 0.25lh; opacity: 1; transition: height 0ms 400ms, opacity 400ms 0ms; - height: auto; overflow: hidden; + align-items: center; + min-height: 1.5lh; + padding: 0 1ch; } .checklist-item.is-checked.invisible { opacity: 0; @@ -114,26 +127,21 @@ textarea.js-edit-checklist-item { background: #ccc; border-radius: 2px; } -.checklist-item.ui-sortable-helper { - box-shadow: -2px 2px 8px rgba(0,0,0,0.3), 0 0 1px rgba(0,0,0,0.5); - transform: rotate(4deg); - cursor: grabbing; -} .checklist-item:hover { background-color: #ebebeb; } -.checklist-item .check-box-container { - padding-right: 10px; -} .checklist-item .check-box { margin: 0.1em 0 0 0; } .checklist-item .check-box.is-checked { - border-bottom: 2px solid #3cb500; - border-right: 2px solid #3cb500; + border-bottom: 0.2ch solid #3cb500; + border-right: 0.2ch solid #3cb500; } .checklist-item .item-title { + display: flex; + justify-content: start; flex: 1; + cursor: grab; } .checklist-item .item-title.is-checked { color: #8c8c8c; @@ -141,27 +149,18 @@ textarea.js-edit-checklist-item { text-decoration: line-through; } .checklist-item .item-title .viewer p { - margin-bottom: 2px; - display: block; - word-wrap: break-word; + display: flex; + overflow-wrap: break-word; max-width: 420px; } -.checklist-item span.fa.checklistitem-handle { - padding-top: 2px; - padding-right: 10px; -} .js-delete-checklist-item, .js-convert-checklist-item-to-card { margin: 0 0 0.5em 1.33em; padding: 12px 0 0 0; } -.add-checklist-item { - margin: 0.2em 0 0.5em 1.33em; -} .add-checklist-item.js-open-inlined-form, .add-checklist.js-open-inlined-form { - display: block; - width: 50%; + display: inline-block; } .add-checklist-item.js-open-inlined-form:hover, .add-checklist.js-open-inlined-form:hover { @@ -169,25 +168,13 @@ textarea.js-edit-checklist-item { color: #222; box-shadow: 0 1px 2px rgba(0,0,0,0.2); } -.add-checklist-top { - /* more space to checklists title */ - padding-left: 20px; - /* + is easier clickable */ - padding-right: 20px; -} + .add-checklist-top.js-open-inlined-form:hover { background: #dbdbdb; color: #222; box-shadow: 0 1px 2px rgba(0,0,0,.2); } -.card-details-item-title { - /* max width for adding checklist at top */ - width: 100%; -} -.checklist-details-menu { - float: right; - padding: 6px 10px 6px 10px; -} + .edit-controls label.toggle-label { margin-left: 2px; } diff --git a/client/components/cards/checklists.jade b/client/components/cards/checklists.jade index e943e338f..c9bbf9f66 100644 --- a/client/components/cards/checklists.jade +++ b/client/components/cards/checklists.jade @@ -36,26 +36,31 @@ template(name="checklistDetail") +editChecklistItemForm(checklist = checklist) else .checklist-title - span - if canModifyCard - a.fa.fa-navicon.checklist-details-menu.js-open-checklist-details-menu(title="{{_ 'checklistActionsPopup-title'}}") - - if canModifyCard - h4.title.js-open-inlined-form.is-editable - if isTouchScreenOrShowDesktopDragHandles - span.fa.checklist-handle(class="fa-arrows" title="{{_ 'dragChecklist'}}") + h4.title + if canModifyCard + a.js-open-inlined-form.is-editable(title="{{_ 'moveChecklistPopup-title'}}") + +viewer + = checklist.title + else +viewer = checklist.title - else - h4.title - +viewer + .checklist-controls + if canModifyCard + a.fa.fa-navicon.checklist-details-menu.js-open-checklist-details-menu(title="{{_ 'checklistActionsPopup-title'}}") + if isMiniScreen + span.fa.checklist-handle(class="fa-arrows" title="{{_ 'dragChecklist'}}") + +viewer = checklist.title - if $gt finishedPercent 0 - .checklist-progress-bar-container - .checklist-progress-text {{finishedPercent}}% - .checklist-progress-bar + //- jumps where checking the first item is not comfortable; + //- so try to show it anytime. also, it helps to separate the checklists. + .checklist-progress-bar-container + .checklist-progress-text {{finishedPercent}}% + .checklist-progress-bar + if $gt finishedPercent 0 .checklist-progress(style="width:{{finishedPercent}}%") + else + .checklist-progress(style="visibility:hidden") +checklistItems(checklist = checklist card = card) template(name="checklistDeletePopup") @@ -64,7 +69,7 @@ template(name="checklistDeletePopup") template(name="addChecklistItemForm") a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}") - span.copied-tooltip {{_ 'copied'}} + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} textarea.js-add-checklist-item(rows='1' autofocus) .edit-controls.clearfix button.primary.confirm.js-submit-add-checklist-item-form(type="submit") {{_ 'save'}} @@ -73,16 +78,12 @@ template(name="addChecklistItemForm") .material-toggle-switch(title="{{_ 'newlineBecomesNewChecklistItem'}}") input.toggle-switch(type="checkbox" id="toggleNewlineBecomesNewChecklistItem") label.toggle-label(for="toggleNewlineBecomesNewChecklistItem") + span.toggle-switch-desc | {{_ 'newLineNewItem'}} - if $eq position 'top' - .material-toggle-switch(title="{{_ 'newlineBecomesNewChecklistItemOriginOrder'}}") - input.toggle-switch(type="checkbox" id="toggleNewlineBecomesNewChecklistItemOriginOrder") - label.toggle-label(for="toggleNewlineBecomesNewChecklistItemOriginOrder") - | {{_ 'originOrder'}} template(name="editChecklistItemForm") a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}") - span.copied-tooltip {{_ 'copied'}} + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} textarea.js-edit-checklist-item(rows='1' autofocus dir="auto") if $eq type 'item' = item.title @@ -99,13 +100,6 @@ template(name="editChecklistItemForm") | {{_ 'convertChecklistItemToCardPopup-title'}} template(name="checklistItems") - if checklist.items.length - if canModifyCard - +inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist position="top") - +addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=true position="top") - else - a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}") - i.fa.fa-plus .checklist-items.js-checklist-items each item in checklist.items +inlinedForm(classNames="js-edit-checklist-item" item = item checklist = checklist) @@ -118,14 +112,15 @@ template(name="checklistItems") else a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}") i.fa.fa-plus + +inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist) + +addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=true position="top") template(name='checklistItemDetail') - .js-checklist-item.checklist-item(class="{{#if item.isFinished }}is-checked{{#if checklist.hideCheckedChecklistItems}} invisible{{/if}}{{/if}}{{#if checklist.hideAllChecklistItems}} is-checked invisible{{/if}}" - role="checkbox" aria-checked="{{#if item.isFinished }}true{{else}}false{{/if}}" tabindex="0") + .js-checklist-item.checklist-item(class="{{#if item.isFinished }}is-checked{{#if checklist.hideCheckedChecklistItems}} invisible{{/if}}{{/if}}{{#if checklist.hideAllChecklistItems}} is-checked invisible{{/if}}" role="checkbox" aria-checked="{{#if item.isFinished }}true{{else}}false{{/if}}" tabindex="0") if canModifyCard .check-box-container .check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}") - if isTouchScreenOrShowDesktopDragHandles + if isMiniScreen span.fa.checklistitem-handle(class="fa-arrows" title="{{_ 'dragChecklistItem'}}") .item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}") +viewer @@ -141,16 +136,16 @@ template(name="checklistActionsPopup") li a.js-delete-checklist.delete-checklist i.fa.fa-trash - | {{_ "delete"}} ... + | {{_ "delete"}} a.js-move-checklist.move-checklist i.fa.fa-arrow-right - | {{_ "moveChecklist"}} ... + | {{_ "moveChecklist"}} a.js-copy-checklist.copy-checklist i.fa.fa-copy - | {{_ "copyChecklist"}} ... + | {{_ "copyChecklist"}} a.js-hide-checked-checklist-items i.fa.fa-eye-slash - | {{_ "hideCheckedChecklistItems"}} ... + | {{_ "hideCheckedChecklistItems"}} .material-toggle-switch(title="{{_ 'hide-checked-items'}}") if checklist.hideCheckedChecklistItems input.toggle-switch(type="checkbox" id="toggleHideCheckedChecklistItems_{{checklist._id}}" checked="checked") @@ -158,7 +153,7 @@ template(name="checklistActionsPopup") input.toggle-switch(type="checkbox" id="toggleHideCheckedChecklistItems_{{checklist._id}}") label.toggle-label(for="toggleHideCheckedChecklistItems_{{checklist._id}}") a.js-hide-all-checklist-items - i.fa.fa-ban + | 🚫 | {{_ "hideAllChecklistItems"}} ... .material-toggle-switch(title="{{_ 'hideAllChecklistItems'}}") if checklist.hideAllChecklistItems diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js index 16fd74402..c016f9902 100644 --- a/client/components/cards/checklists.js +++ b/client/components/cards/checklists.js @@ -7,7 +7,7 @@ import { DialogWithBoardSwimlaneListCard } from '/client/lib/dialogWithBoardSwim const subManager = new SubsManager(); const { calculateIndexData, capitalize } = Utils; -function initSorting(items) { +function initSorting(items, handleSelector) { items.sortable({ tolerance: 'pointer', helper: 'clone', @@ -16,6 +16,7 @@ function initSorting(items) { appendTo: 'parent', distance: 7, placeholder: 'checklist-item placeholder', + handle: handleSelector, scroll: true, start(evt, ui) { ui.placeholder.height(ui.helper.height()); @@ -48,8 +49,9 @@ function initSorting(items) { BlazeComponent.extendComponent({ onRendered() { const self = this; + this.handleSelector = Utils.isMiniScreen() ? 'span.fa.checklistitem-handle' : '.item-title'; self.itemsDom = this.$('.js-checklist-items'); - initSorting(self.itemsDom); + initSorting(self.itemsDom, this.handleSelector); self.itemsDom.mousedown(function (evt) { evt.stopPropagation(); }); @@ -63,11 +65,9 @@ BlazeComponent.extendComponent({ const $itemsDom = $(self.itemsDom); if ($itemsDom.data('uiSortable') || $itemsDom.data('sortable')) { $(self.itemsDom).sortable('option', 'disabled', !userIsMember()); - if (Utils.isTouchScreenOrShowDesktopDragHandles()) { - $(self.itemsDom).sortable({ - handle: 'span.fa.checklistitem-handle', - }); - } + $(self.itemsDom).sortable({ + handle: this.handleSelector, + }); } }); }, diff --git a/client/components/cards/labels.css b/client/components/cards/labels.css index 19a8746a8..03f6fc4c7 100644 --- a/client/components/cards/labels.css +++ b/client/components/cards/labels.css @@ -1,20 +1,20 @@ .card-label { - border: 1px solid #000; - border-radius: 4px; + border-radius: 0.4ch; color: #fff; display: inline-block; font-weight: 700; - font-size: 13px; - margin-right: 4px; - margin-bottom: 5px; - padding: 3px 8px; - max-width: 210px; - min-width: 8px; - word-wrap: break-word; - min-height: 18px; - vertical-align: middle; - white-space: initial; - overflow: initial; + font-size: 0.9em; + display: flex; + /* prefer not using padding/margin but let outer grids + position/size labels (see e.g. minicards), otherwise we get + inconsistencies */ + align-self: stretch; + justify-content: center; + align-items: center; + text-align: center; + padding: 0 0.5ch; + height: var(--label-height); + min-width: 8ch; } .card-label:hover { color: #fff; @@ -34,6 +34,7 @@ } .card-label p { margin: 0px; + --overflow-lines: 1; } .palette-colors { display: flex; @@ -138,37 +139,22 @@ .card-label-indigo { background-color: #4b0082; } -.edit-label .card-label, -.create-label .card-label { - float: left; - height: 25px; - margin: 0px 3% 7px 0px; - width: 10.5%; - max-width: 10.5%; - cursor: pointer; -} -.edit-labels input[type="text"] { - margin: 4px 0 6px 38px; - width: 243px; -} -.edit-labels .card-label { - height: 30px; - left: 0; - padding: 1px 5px; - position: absolute; - top: 0; - width: 24px; -} -.edit-labels .labels-static .card-label { - line-height: 30px; - margin-bottom: 4px; - position: relative; - top: auto; - left: 0; - width: 260px; -} .edit-labels-pop-over { - margin-bottom: 8px; + display: grid; + /* so that inner elements, align nicely */ + grid-template-columns: 1fr; + gap: 0.1lh; + >li { + display: flex; + flex-direction: row-reverse; + gap: 1ch; + align-items: center; + } + .card-label-selectable { + flex: 1; + display: flex; + gap: 1ch; + } } .edit-labels-pop-over .card-label .viewer p { margin: 0; @@ -176,34 +162,6 @@ .edit-labels-pop-over .shortcut { display: inline-block; } -.card-label-selectable { - border-radius: 3px; - cursor: pointer; - margin: 0; - margin-bottom: 3px; - width: 190px; - min-height: 18px; - padding: 8px; - position: relative; - transition: margin-right 0.1s; -} -.card-label-selectable .card-label-selectable-icon { - position: absolute; - top: 8px; - right: -20px; -} -.card-label-selectable.active:hover, -.card-label-selectable.active, -.card-label-selectable.active.selected:hover, -.card-label-selectable.active.selected { - padding-right: 32px; -} -.card-label-selectable.active:hover .card-label-selectable-icon, -.card-label-selectable.active .card-label-selectable-icon, -.card-label-selectable.active.selected:hover .card-label-selectable-icon, -.card-label-selectable.active.selected .card-label-selectable-icon { - right: 6px; -} .card-label-selectable.selected, .card-label-selectable:hover { opacity: 0.8; @@ -212,24 +170,6 @@ .active .card-label-selectable:hover { margin-right: 0; } -.active .card-label-selectable .card-label-selectable-icon { - right: 8px; -} -.card-label-edit-button { - border-radius: 3px; - float: right; - padding: 8px; -} .card-label-edit-button:hover { background: #dbdbdb; -} -ul.edit-labels-pop-over span.label-handle { - padding-right: 10px; - display: inline-block; - width: 1.2em; - text-align: center; - color: #999; -} -ul.edit-labels-pop-over span.label-handle + .card-label { - max-width: 180px; -} +} \ No newline at end of file diff --git a/client/components/cards/minicard.css b/client/components/cards/minicard.css index 32dea839d..80facfb8e 100644 --- a/client/components/cards/minicard.css +++ b/client/components/cards/minicard.css @@ -1,10 +1,32 @@ +.minicard-body { + display: flex; + flex-direction: column; + padding: 0 1ch 0.2lh 1ch; + gap: 0.2lh; +} + .minicard-wrapper { cursor: pointer; position: relative; display: flex; align-items: center; - margin-bottom: 1.2vh; + height: min-content; } +.minicard-header { + display: flex; + align-items: center; + padding: 0 1ch; + gap: 1ch; +} + +.minicard > hr { + margin: 0; +} + +.minicard-add-form { + width: auto; +} + .minicard-wrapper.placeholder { background: #ccc; border-radius: 1.2vw; @@ -28,32 +50,25 @@ .minicard-wrapper .multi-selection-checkbox + .minicard { margin-left: 1vw; } -@media only screen { - .minicard { - padding: 0.8vh 1vw 0.3vh; - position: relative; - flex: 1; - flex-wrap: wrap; - background-color: #fff; - min-height: 2.5vh; - box-shadow: 0 0.2vh 0.3vh rgba(0,0,0,0.15); - border-radius: 0.3vw; - color: #4d4d4d; - overflow: hidden; - transition: transform 0.2s, border-radius 0.2s; - } +.minicard { + display: grid; + grid-auto-flow: row; + grid-template-rows: min-content 1fr auto auto; + gap: 0.4lh; + background-color: #fff; + box-shadow: 0 0.2vh 0.3vh rgba(0,0,0,0.15); + border-radius: 0.3vw; + color: #4d4d4d; + overflow: hidden; + transition: transform 0.2s, border-radius 0.2s; + flex: 1; } -.minicard-details-menu-with-handle { - float: right; - padding-left: 0.7vw; - font-size: clamp(14px, 3vw, 18px); - padding: 0; - z-index: 1; -} -.minicard-details-menu { - float: right; - font-size: clamp(14px, 3vw, 18px); - padding-left: 0.7vw; + +.minicard-actions-right { + justify-content: end; + display: flex; + align-items: end; + gap: .5lh; } @media print { .minicard-details-menu, @@ -76,7 +91,6 @@ transform: translateX(1.5vw); border-bottom-right-radius: 0; border-top-right-radius: 0; - z-index: 25; box-shadow: -0.3vw 0.2vh 0.3vh rgba(0,0,0,0.2); } .minicard:hover:not(.minicard-composer), @@ -96,20 +110,30 @@ margin: 0.8vh -1vw 0.8vh -1vw; border-radius: top 0.3vw; } -.minicard .minicard-labels { - float: none; - margin-right: 6vw; -} -.minicard .minicard-labels .minicard-label { - width: clamp(12px, 1.5vw, 16px); - height: clamp(12px, 1.5vw, 16px); - border-radius: 0.3vw; - margin-right: 0.4vw; - margin-bottom: 0.4vh; -} -.minicard .minicard-labels-no-text { - display: flex; - flex-wrap: wrap; +.minicard { + .minicard-labels, .dates { + display: grid; + grid-auto-rows: min-content; + justify-content: stretch; + font-size: 0.8em; + grid-auto-rows: minmax(1.3lh, auto); + } + .minicard-labels { + grid-template-columns: repeat(auto-fill, minmax(12ch, auto)); + gap: 0.2lh 0.5ch; + } + .minicard-labels-no-text { + grid-template-columns: repeat(auto-fill, 4ch); + grid-template-rows: 4ch; + font-size: 0.4em; + .minicard-label { + border-radius: 1ch; + } + } + .dates { + height: min-content; + grid-template-columns: repeat(auto-fit, minmax(15ch, auto)); + } } .minicard .minicard-custom-fields { display: block; @@ -121,26 +145,22 @@ .minicard .minicard-custom-field-item { flex-grow: 1; display: block; - word-wrap: break-word; + overflow-wrap: break-word; max-width: 13vw; margin-right: 0.5vw; } .minicard .minicard-custom-field-item-fullwidth { flex-grow: 1; display: block; - word-wrap: break-word; + overflow-wrap: break-word; max-width: 100%; margin-right: 0.5vw; } .minicard .handle { - width: clamp(20px, 2.5vw, 28px); - height: clamp(20px, 2.5vw, 28px); - position: absolute; - right: 0vw; - top: 4vh; display: none; z-index: 1; } + @media only screen { .minicard .handle { display: block; @@ -154,58 +174,34 @@ text-align: center; } .minicard .minicard-title { - margin-right: 1.5vw; + display: flex; + max-width: 100%; + flex: 1; + cursor: grab; + .viewer { + --overflow-lines: 2; + } + } .minicard .minicard-title .card-number { color: #b3b3b3; display: inline-block; margin-right: 0.7vw; } -@media only screen { - .minicard .minicard-title p:last-child { - margin-bottom: 0; - } - .minicard .minicard-title .viewer { - display: block; - word-wrap: break-word; - } -} -.minicard .dates { - display: flex; - flex-direction: row; - flex-wrap: wrap; - position: relative; - z-index: 5; - margin-right: 6vw; - clear: both; -} .minicard .date { - margin-right: 0.4vw; + display: flex; + &>a { + display: flex; + justify-content: center; + flex: 1; + align-items: center; + text-align: center; + align-self: stretch; + } } - -/* Unicode icons for minicard dates - matching cardDate.css */ -.minicard .card-date.end-date time::before { - content: "🏁"; /* Finish flag - represents end/completion */ -} -.minicard .card-date.due-date time::before { - content: "⏰"; /* Alarm clock - represents due/deadline */ -} -.minicard .card-date.start-date time::before { - content: "🚀"; /* Rocket - represents start/launch */ -} -.minicard .card-date.received-date time::before { - content: "📥"; /* Inbox tray - represents received/incoming */ -} - -.minicard .card-date time::before { - font-size: inherit; - margin-right: 0.3em; - display: inline-block; -} - /* Date type specific colors for minicards - matching cardDate.css */ .minicard .card-date.received-date { - background-color: #dbdbdb; /* Grey for received - same as base card-date */ + background-color: #d3d3d3; /* Grey for received - a bit darker than base card-date */ } .minicard .card-date.received-date:hover, @@ -311,102 +307,134 @@ background-color: #1976d2 !important; } +.minicard .minicard-badges-and-creator { + display: flex; + flex-direction: row-reverse; + justify-content: end; + gap: 0 0.5ch;; +} + +.minicard-people-grid { + display: grid; + grid-template-columns: 1fr auto; + grid-auto-rows: auto; +} + +.minicard-people-wrapper { + display: flex; + justify-content: end; + gap: 0.1lh; +} .minicard .badges { - float: left; - margin-top: 1vh; + display: flex; + align-items: center; + gap: 1.5ch; color: #808080; + /* this avoid padding-ish at the bottom of the card */ + font-size: 0.8rem; } -.minicard .badges:empty { - display: none; -} -.minicard .badges .badge { - float: left; - margin-right: 1.5vw; - margin-bottom: 0.4vh; - font-size: 0.9em; -} + .minicard .badges .badge.is-finished { background: #3cb500; - padding: 0 0.4vw; + padding: 0.3lh 0.8ch; border-radius: 0.4vw; - color: #fff; + &, .fa { + color: #fff; + } } .minicard .badges .badge:last-of-type { margin-right: 0; } -.minicard .badges .badge .badge-icon, -.minicard .badges .badge .badge-text { - vertical-align: middle; -} -.minicard .badges .badge .badge-icon.badge-comment, -.minicard .badges .badge .badge-text.badge-comment { - margin-bottom: 0.1rem; -} -.minicard .badges .badge .badge-text { - font-size: 0.9em; - padding-left: 0.3vw; - line-height: 1.2; -} -.minicard .badges .badge .check-list-text { - padding-left: 0px; - line-height: 1.1; -} -.minicard .minicard-members, -.minicard .minicard-assignees, -.minicard .minicard-creator { - float: right; - margin-left: 0.7vw; - margin-bottom: 0.5vh; -} .minicard .minicard-members .member, .minicard .minicard-assignees .member, .minicard .minicard-creator .member { - float: right; + display: flex; border-radius: 50%; - height: clamp(24px, 3.5vw, 32px); - width: clamp(24px, 3.5vw, 32px); - margin-bottom: 0.5vh; + font-size: 0.8em; + margin-bottom: 0.2lh; } -.minicard .minicard-members .assignee, -.minicard .minicard-assignees .assignee, -.minicard .minicard-creator .assignee { - float: right; - border-radius: 50%; - height: clamp(24px, 3.5vw, 32px); - width: clamp(24px, 3.5vw, 32px); + +.minicard .minicard-assignees .member { + border: 2px solid rgb(180, 87, 87); } -.minicard .minicard-members + .badges, -.minicard .minicard-assignees + .badges, -.minicard .minicard-creator + .badges { - margin-top: 0.7vh; + +.minicard .minicard-creator .member { + border: 2px solid #7fd67f; +} + +.minicard .minicard-members .member { + border: 2px solid #5a5ac6; } .minicard .minicard-assignees { - border-bottom: 1px solid #f00; -} -.minicard .minicard-creator { - border-bottom: 1px solid #008000; + display: flex; } + .minicard .minicard-members:empty, .minicard .minicard-assignees:empty { display: none; } .minicard .minicard-description { - padding: 0.8vh 0 0 1vw; color: #000; background-color: #eee; - width: 100%; - margin-bottom: 0.3vh; - margin-left: -0.5vw; - border-radius: 0.4vw; - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; + padding: 0.5lh 1ch; + --overflow-lines: 2; + .viewer { + font-size: 0.9em; + ul { + padding-bottom: 0; + } + } } + +.minicard .minicard-description p { + margin: 0; +} + +.minicard-composer { + display: flex; + flex-direction: column; + + .minicard-composer-icons { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.2lh; + } + + .minicard-bottom { + display: flex; + justify-content: end; + align-items: center; + gap: 1ch; + + .minicard-composer-icons { + display: flex; + flex: 1; + flex-wrap: wrap; + flex-direction: row-reverse; + } + + .add-controls { + display: flex; + align-self: start; + } + + textarea { + display: flex; + flex: 1; + } + } +} + .minicard.minicard-composer { - margin-bottom: 1.3vh; + flex-wrap: wrap; + flex: 1; + align-self: stretch; + gap: 0.3lh; + padding: 0.5lh 1ch; + position: relative; } + .minicard.minicard-composer textarea.minicard-composer-textarea, .minicard.minicard-composer textarea.minicard-composer-textarea:focus { resize: none; @@ -415,11 +443,11 @@ box-shadow: none; height: auto; margin: 0; - padding: 0; - max-height: 22vh; - min-height: 5vh; - margin-bottom: 2.5vh; + padding: 1ch; + min-height: 5lh; overflow-y: auto; + flex: 1; + width: 100%; } .parent-prefix { color: #b3b3b3; @@ -734,30 +762,12 @@ /* List name display on minicard */ .minicard-list-name { - font-size: 0.75em; + font-size: inherit; color: #8c8c8c; - margin-top: 0.2vh; display: flex; - align-items: center; - gap: 0.3vw; -} - -/* Checklist display on minicard */ -.minicard-checklist { - width: 100%; - margin-top: 0.5vh; - margin-bottom: 0.5vh; - padding: 0.3vh 0.5vw; - background-color: rgba(255, 255, 255, 0.8); - border-radius: 0.3vw; - border: 1px solid #e0e0e0; -} - -.minicard-checklist .checklist-header { + padding: 0 0.5ch; display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 0.3vh; + gap: 0.5ch; } .minicard-checklist .checklist-title { diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index 2a1d4162d..c00974b0b 100644 --- a/client/components/cards/minicard.jade +++ b/client/components/cards/minicard.jade @@ -1,226 +1,236 @@ template(name="minicard") + if isSelected + +cardDetailsPopup(this) .minicard.nodragscroll( class="{{#if isLinkedCard}}linked-card{{/if}}" class="{{#if isLinkedBoard}}linked-board{{/if}}" class="{{#if colorClass}}minicard-{{colorClass}}{{/if}}") - if canMoveCard - if isTouchScreenOrShowDesktopDragHandles - .handle - i.fa.fa-arrows - if canModifyCard - a.minicard-details-menu-with-handle.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") - i.fa.fa-bars .dates - if getReceived - .date - +minicardReceivedDate - if getStart - .date - +minicardStartDate - if getDue - .date - +minicardDueDate - if getEnd - +minicardEndDate + if allowsReceivedDate + if getReceived + .date.viewer + +minicardReceivedDate + if allowsStartDate + if getStart + .date.viewer + +minicardStartDate + if allowsDueDate + if getDue + .date.viewer + +minicardDueDate + if allowsEndDate + if getEnd + .date.viewer + +minicardEndDate if getSpentTime - .date + .date.viewer +cardSpentTime - if cover - if currentBoard.allowsCoverAttachmentOnMinicard - .minicard-cover(style="background-image: url('{{cover.link 'original'}}?dummyReloadAfterSessionEstablished={{sess}}');") + .minicard-header + .minicard-title + if $eq 'prefix-with-full-path' currentBoard.presentParentTask + .parent-prefix + | {{ parentString ' > ' }} + if $eq 'prefix-with-parent' currentBoard.presentParentTask + .parent-prefix + | {{ parentCardName }} + if isLinkedBoard + a.js-linked-link + span.linked-icon + i.fa.fa-folder + else if isLinkedCard + a.js-linked-link + span.linked-icon + i.fa.fa-id-card + if getArchived + span.linked-icon.linked-archived + i.fa.fa-archive + +viewer + if allowsCardNumber + span.card-number + | ##{getCardNumber} + = getTitle + div.minicard-actions-right + if canModifyCard + a.minicard-details-menu-with-handle.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}") + i.fa.fa-bars + if isMiniScreen + if canMoveCard + .handle + i.fa.fa-arrows + hr + .minicard-body + if cover + if allowsCoverAttachmentOnMinicard + .minicard-cover(style="background-image: url('{{cover.link 'original'}}?dummyReloadAfterSessionEstablished={{sess}}');") - // Upload progress indicator for drag-and-drop uploads - if hasActiveUploads - .minicard-upload-progress - .upload-progress-header - i.fa.fa-upload - span {{_ 'uploading-files'}} ({{uploadCount}}) - each uploads - .upload-progress-item(class="{{#if $eq status 'error'}}upload-error{{/if}}") - .upload-progress-filename {{file.name}} - .upload-progress-bar - .upload-progress-fill(style="width: {{progress}}%") - if $eq status 'error' - .upload-progress-error - i.fa.fa-warning - span {{_ 'upload-failed'}} - else if $eq status 'completed' - .upload-progress-success - i.fa.fa-check - span {{_ 'upload-completed'}} + //- Upload progress indicator for drag-and-drop uploads + if hasActiveUploads + .minicard-upload-progress + .upload-progress-header + i.fa.fa-upload + span {{_ 'uploading-files'}} ({{uploadCount}}) + each uploads + .upload-progress-item(class="{{#if $eq status 'error'}}upload-error{{/if}}") + .upload-progress-filename {{file.name}} + .upload-progress-bar + .upload-progress-fill(style="width: {{progress}}%") + if $eq status 'error' + .upload-progress-error + i.fa.fa-warning + span {{_ 'upload-failed'}} + else if $eq status 'completed' + .upload-progress-success + i.fa.fa-check + span {{_ 'upload-completed'}} - .minicard-title - if $eq 'prefix-with-full-path' currentBoard.presentParentTask - .parent-prefix - | {{ parentString ' > ' }} - if $eq 'prefix-with-parent' currentBoard.presentParentTask - .parent-prefix - | {{ parentCardName }} - if isLinkedBoard - a.js-linked-link - span.linked-icon - i.fa.fa-folder - else if isLinkedCard - a.js-linked-link - span.linked-icon - i.fa.fa-id-card - if getArchived - span.linked-icon.linked-archived - i.fa.fa-archive - +viewer - if currentBoard.allowsCardNumber - span.card-number - | ##{getCardNumber} - = getTitle - if labels - .minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}") - each labels - unless hiddenMinicardLabelText - span.js-card-label.card-label(class="card-label-{{color}}" title=name) - +viewer - = name - if hiddenMinicardLabelText - .minicard-label(class="card-label-{{color}}" title="{{name}}") + if labels + .minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}") + each labels + unless hiddenMinicardLabelText + span.js-card-label.card-label(class="card-label-{{color}}" title=name) + +viewer + = name + if hiddenMinicardLabelText + .minicard-label(class="card-label-{{color}}" title="{{name}}") - .minicard-custom-fields - each customFieldsWD - if definition.showOnCard - if trueValue - .minicard-custom-field - // If there is custom field label, show label at left, - // and value at right - if definition.showLabelOnMiniCard - .minicard-custom-field-item - +viewer - = definition.name - .minicard-custom-field-item - if $eq definition.type "currency" + .minicard-custom-fields + each customFieldsWD + if definition.showOnCard + if trueValue + .minicard-custom-field + // If there is custom field label, show label at left, + // and value at right + if definition.showLabelOnMiniCard + .minicard-custom-field-item +viewer - = formattedCurrencyCustomFieldValue(definition) - else if $eq definition.type "date" - .date - +minicardCustomFieldDate - else if $eq definition.type "checkbox" - .materialCheckBox(class="{{#if value }}is-checked{{/if}}") - else if $eq definition.type "stringtemplate" - +viewer - = formattedStringtemplateCustomFieldValue(definition) - else - +viewer - = trueValue - else - // If there is no custom field label, - // show value full width - .minicard-custom-field-item-fullwidth - if $eq definition.type "currency" - +viewer - = formattedCurrencyCustomFieldValue(definition) - else if $eq definition.type "date" - .date - +minicardCustomFieldDate - else if $eq definition.type "checkbox" - .materialCheckBox(class="{{#if value }}is-checked{{/if}}") - else if $eq definition.type "stringtemplate" - +viewer - = formattedStringtemplateCustomFieldValue(definition) - else - +viewer - = trueValue + = definition.name + .minicard-custom-field-item + if $eq definition.type "currency" + +viewer + = formattedCurrencyCustomFieldValue(definition) + else if $eq definition.type "date" + .date + +minicardCustomFieldDate + else if $eq definition.type "checkbox" + .materialCheckBox(class="{{#if value }}is-checked{{/if}}") + else if $eq definition.type "stringtemplate" + +viewer + = formattedStringtemplateCustomFieldValue(definition) + else + +viewer + = trueValue + else + // If there is no custom field label, + // show value full width + .minicard-custom-field-item-fullwidth + if $eq definition.type "currency" + +viewer + = formattedCurrencyCustomFieldValue(definition) + else if $eq definition.type "date" + .date + +minicardCustomFieldDate + else if $eq definition.type "checkbox" + .materialCheckBox(class="{{#if value }}is-checked{{/if}}") + else if $eq definition.type "stringtemplate" + +viewer + = formattedStringtemplateCustomFieldValue(definition) + else + +viewer + = trueValue + .minicard-people-grid + if allowsAssignee + if getAssignees + .minicard-people-wrapper + .minicard-assignees.js-minicard-assignees + each getAssignees + +userAvatar(userId=this) - if showAssignee - if getAssignees - .minicard-assignees.js-minicard-assignees - each getAssignees - +userAvatar(userId=this) + if allowsMembers + if getMembers + .minicard-people-wrapper + .minicard-members.js-minicard-members + each getMembers + +userAvatar(userId=this) - if showMembers - if getMembers - .minicard-members.js-minicard-members - each getMembers - +userAvatar(userId=this) + .minicard-badges-and-creator + if allowsCreatorOnMinicard + .minicard-creator + +userAvatar(userId=this.userId noRemove=true) - if showCreatorOnMinicard - .minicard-creator - +userAvatar(userId=this.userId noRemove=true) - - .badges - if canModifyCard - if comments.length - .badge(title="{{_ 'card-comments-title' comments.length }}") - span.badge-icon.badge-comment.badge-text - i.fa.fa-comment-o - = ' ' - = comments.length - //span.badge-comment.badge-text - //| {{_ 'comment'}} - if getDescription - unless currentBoard.allowsDescriptionTextOnMinicard - .badge.badge-state-image-only(title=getDescription) - span.badge-icon - i.fa.fa-file-text-o - if getVoteQuestion - .badge.badge-state-image-only(title=getVoteQuestion) - span.badge-icon(class="{{#if voteState}}text-green{{/if}}") - i.fa.fa-thumbs-up - span.badge-text {{ voteCountPositive }} - span.badge-icon(class="{{#if $eq voteState false}}text-red{{/if}}") - i.fa.fa-thumbs-down - span.badge-text {{ voteCountNegative }} - if getPokerQuestion - .badge.badge-state-image-only(title=getPokerQuestion) - span.badge-icon(class="{{#if pokerState}}text-green{{/if}}") - i.fa.fa-check-square - if expiredPoker - span.badge-text {{ getPokerEstimation }} - if attachments.length - if currentBoard.allowsBadgeAttachmentOnMinicard - .badge - span.badge-icon - i.fa.fa-paperclip - span.badge-text= attachments.length - if allSubtasks.count - .badge - span.badge-icon - i.fa.fa-globe - span.badge-text.check-list-text {{subtasksFinishedCount}}/{{allSubtasksCount}} - //{{subtasksFinishedCount}}/{{subtasksCount}} does not work because when a subtaks is archived, the count goes down - if currentBoard.allowsCardSortingByNumber - if currentBoard.allowsCardSortingByNumberOnMinicard - .badge - span.badge-icon - i.fa.fa-sort-numeric-asc - span.badge-text.check-list-sort {{ sort }} - if shouldShowChecklistAtMinicard - each shouldShowChecklistAtMinicard - +minicardChecklist(checklist=. card=..) - if currentBoard.allowsDescriptionTextOnMinicard + .badges + if canModifyCard + if allowsComments + if comments.length + .badge(title="{{_ 'card-comments-title' comments.length }}") + span.badge-icon.badge-comment.badge-text + i.fa.fa-comment-o + = ' ' + = comments.length + //span.badge-comment.badge-text + //| {{_ 'comment'}} + if getDescription + unless allowsDescriptionTextOnMinicard + .badge.badge-state-image-only(title=getDescription) + span.badge-icon + i.fa.fa-file-text-o + if getVoteQuestion + .badge.badge-state-image-only(title=getVoteQuestion) + span.badge-icon(class="{{#if voteState}}text-green{{/if}}") + i.fa.fa-thumbs-up + span.badge-text {{ voteCountPositive }} + span.badge-icon(class="{{#if $eq voteState false}}text-red{{/if}}") + i.fa.fa-thumbs-down + span.badge-text {{ voteCountNegative }} + if getPokerQuestion + .badge.badge-state-image-only(title=getPokerQuestion) + span.badge-icon(class="{{#if pokerState}}text-green{{/if}}") + i.fa.fa-check-square + if expiredPoker + span.badge-text {{ getPokerEstimation }} + if attachments.length + if allowsBadgeAttachmentOnMinicard + .badge + span.badge-icon + i.fa.fa-paperclip + span.badge-text= attachments.length + if checklists.length + if allowsChecklists + .badge(class="{{#if checklistFinished}}is-finished{{/if}}") + span.badge-icon + i.fa.fa-check + span.badge-text.check-list-text {{checklistFinishedCount}}/{{checklistItemCount}} + if allSubtasks.count + if allowsSubtasks + .badge + span.badge-icon + i.fa.fa-globe + span.badge-text.check-list-text {{subtasksFinishedCount}}/{{allSubtasksCount}} + //{{subtasksFinishedCount}}/{{subtasksCount}} does not work because when a subtaks is archived, the count goes down + if allowsCardSortingByNumber + if allowsCardSortingByNumberOnMinicard + .badge + span.badge-icon + i.fa.fa-sort-numeric-asc + span.badge-text.check-list-sort {{ sort }} + if shouldShowListOnMinicard + .minicard-list-name + span + i.fa.fa-list + span + | {{ listName }} + if $eq 'subtext-with-full-path' presentParentTask + .parent-subtext + | {{ parentString ' > ' }} + if $eq 'subtext-with-parent' presentParentTask + .parent-subtext + | {{ parentCardName }} + if allowsDescriptionTextOnMinicard if getDescription .minicard-description +viewer | {{ getDescription }} - if shouldShowListOnMinicard - .minicard-list-name - i.fa.fa-list - | {{ listName }} - if $eq 'subtext-with-full-path' currentBoard.presentParentTask - .parent-subtext - | {{ parentString ' > ' }} - if $eq 'subtext-with-parent' currentBoard.presentParentTask - .parent-subtext - | {{ parentCardName }} template(name="editCardSortOrderPopup") - input.js-edit-card-sort-popup(type='text' autofocus value=sort dir="auto") + input.js-edit-card-sort-popup(type='text' value=sort dir="auto") .edit-controls.clearfix - button.primary.confirm.js-submit-edit-card-sort-popup(type="submit") {{_ 'save'}} - -template(name="minicardChecklist") - .minicard-checklist - .checklist-header - .checklist-title= checklist.title - if canModifyCard - a.checklist-menu.js-open-checklist-menu(title="{{_ 'checklistActionsPopup-title'}}") - i.fa.fa-bars - each visibleItems - +checklistItemDetail(item = . checklist = checklist card = card) - + button.primary.confirm.js-submit-edit-card-sort-popup(type="submit") {{_ 'save'}} \ No newline at end of file diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js index 8be2ed4be..75b7858e3 100644 --- a/client/components/cards/minicard.js +++ b/client/components/cards/minicard.js @@ -13,6 +13,24 @@ BlazeComponent.extendComponent({ return 'minicard'; }, + onRendered() { + // cannot be done with CSS because newlines + // rendered by the JADE engine count as non empty + // and some "empty" divs are nested + // this is not very robust and could probably be + // done with a helper, but it could be in fact worse + // because we would need to to if (allowsX() && X() && ...) + const body = $(this.find('.minicard-body')); + if (!body) {return} + let emptyChildren; + do { + emptyChildren = body.find('*').filter((_, e) => !e.classList.contains('fa') && $(e).html().trim().length === 0).remove(); + } while (emptyChildren.length > 0) + if (body.html().trim().length === 0) { + body.parent().find('hr:has(+ .minicard-body)').remove(); + } + }, + formattedCurrencyCustomFieldValue(definition) { const customField = this.data() .customFieldsWD() @@ -39,46 +57,14 @@ BlazeComponent.extendComponent({ return ret; }, - showCreatorOnMinicard() { - // cache "board" to reduce the mini-mongodb access - const board = this.data().board(); - let ret = false; - if (board) { - ret = board.allowsCreatorOnMinicard ?? false; - } - return ret; - }, isWatching() { const card = this.currentData(); return card.findWatcher(Meteor.userId()); }, - showMembers() { - // cache "board" to reduce the mini-mongodb access - const board = this.data().board(); - let ret = false; - if (board) { - ret = - board.allowsMembers === null || - board.allowsMembers === undefined || - board.allowsMembers - ; - } - return ret; - }, - - showAssignee() { - // cache "board" to reduce the mini-mongodb access - const board = this.data().board(); - let ret = false; - if (board) { - ret = - board.allowsAssignee === null || - board.allowsAssignee === undefined || - board.allowsAssignee - ; - } - return ret; + isSelected() { + const card = this.currentData(); + return Session.get('currentCard') === card._id; }, /** opens the card label popup only if clicked onto a label @@ -87,6 +73,8 @@ BlazeComponent.extendComponent({ */ cardLabelsPopup(event) { if (this.find('.js-card-label:hover')) { + event.preventDefault(); + event.stopPropagation(); Popup.open("cardLabels")(event, {dataContextIfCurrentDataIsUndefined: this.currentData()}); } }, @@ -203,7 +191,7 @@ BlazeComponent.extendComponent({ visibleItems() { const checklist = this.currentData().checklist || this.currentData(); const items = checklist.items(); - + return items.filter(item => { // Hide finished items if hideCheckedChecklistItems is true if (item.isFinished && checklist.hideCheckedChecklistItems) { @@ -254,33 +242,8 @@ Template.minicard.helpers({ }, shouldShowListOnMinicard() { - // Show list name if either: - // 1. Board-wide setting is enabled, OR - // 2. This specific card has the setting enabled - const currentBoard = this.board(); - if (!currentBoard) return false; - return currentBoard.allowsShowListsOnMinicard || this.showListOnMinicard; + return Utils.allowsShowLists(); }, - - shouldShowChecklistAtMinicard() { - // Return checklists that should be shown on minicard - const currentBoard = this.board(); - if (!currentBoard) return []; - - const checklists = this.checklists(); - const visibleChecklists = []; - - checklists.forEach(checklist => { - // Show checklist if either: - // 1. Board-wide setting is enabled, OR - // 2. This specific checklist has the setting enabled - if (currentBoard.allowsChecklistAtMinicard || checklist.showChecklistAtMinicard) { - visibleChecklists.push(checklist); - } - }); - - return visibleChecklists; - } }); BlazeComponent.extendComponent({ diff --git a/client/components/cards/resultCard.css b/client/components/cards/resultCard.css index e47e929c7..0b5e0e9ee 100644 --- a/client/components/cards/resultCard.css +++ b/client/components/cards/resultCard.css @@ -18,7 +18,8 @@ font-weight: bold; } .result-card-context-list { - margin-bottom: 0.7rem; + display: flex; + gap: 0.2ch; } .result-card-block-wrapper { display: inline-block; diff --git a/client/components/cards/resultCard.js b/client/components/cards/resultCard.js index 8e04f1654..ad9a249a2 100644 --- a/client/components/cards/resultCard.js +++ b/client/components/cards/resultCard.js @@ -14,17 +14,10 @@ BlazeComponent.extendComponent({ onReady() { Session.set('popupCardId', cardId); Session.set('popupCardBoardId', boardId); - this_.cardDetailsPopup(evt); }, }); }, - cardDetailsPopup(event) { - if (!Popup.isOpen()) { - Popup.open("cardDetails")(event); - } - }, - events() { return [ { diff --git a/client/components/cards/subtasks.css b/client/components/cards/subtasks.css index ba89ad2b0..2d9a7fcf4 100644 --- a/client/components/cards/subtasks.css +++ b/client/components/cards/subtasks.css @@ -4,19 +4,14 @@ textarea.js-add-subtask-item, textarea.js-edit-subtask-item { overflow: hidden; - word-wrap: break-word; + overflow-wrap: break-word; resize: none; - height: 34px; } .delete-text, .subtask-title .js-delete-subtask, .subtask-title .js-view-subtask, .js-delete-subtask-item { color: #8c8c8c; - text-decoration: underline; - word-wrap: break-word; - float: right; - padding-top: 6px; } .delete-text:hover, .subtask-title .js-delete-subtask:hover, @@ -28,11 +23,11 @@ textarea.js-edit-subtask-item { float: left; width: 30px; height: 30px; - font-size: 18px; + line-height: 30px; } .subtask-title .title { - font-size: 18px; + line-height: 25px; } .subtask-title .subtasks-stat { @@ -133,7 +128,7 @@ textarea.js-edit-subtask-item { margin: 0.1em 0 0 0; } .subtasks-item .check-box.is-checked { - border-bottom: 2px solid #3cb500; + border-bottom: 0.2ch solid #3cb500; border-right: 2px solid #3cb500; } /* Unicode checkbox icons styling */ @@ -165,16 +160,4 @@ body.grey-icons-enabled .subtasks-item .check-box-unicode { } .subtasks-item .item-title .viewer p { margin-bottom: 2px; -} -.js-delete-subtask-item { - margin: 0 0 0.5em 1.33em; - padding: 12px 0 0 0; -} -.add-subtask-item { - margin: 0.2em 0 0.5em 1.33em; - display: inline-block; -} -.subtask-details-menu { - float: right; - padding: 6px 10px 6px 10px; -} +} \ No newline at end of file diff --git a/client/components/cards/subtasks.jade b/client/components/cards/subtasks.jade index 3ea5ec5e3..2210c94b1 100644 --- a/client/components/cards/subtasks.jade +++ b/client/components/cards/subtasks.jade @@ -4,12 +4,20 @@ template(name="subtasks") | {{_ 'subtasks'}} if currentUser.isBoardAdmin if toggleDeleteDialog.get - .board-overlay#card-details-overlay +subtaskDeleteDialog(subtask = subtaskToDelete) - .card-subtasks-items - each subtask in currentCard.subtasks - +subtaskDetail(subtask = subtask) + if currentCard.subtasks + .card-subtasks-items + each subtask in currentCard.subtasks + .subtask-container + +subtaskDetail(subtask = subtask) + if canModifyCard + a.subtask-details-menu.js-open-subtask-details-menu(title="{{_ 'subtaskActionsPopup-title'}}") + | ☰ + if currentUser.isBoardAdmin + a.js-delete-subtask-item + | ❌ + if canModifyCard +inlinedForm(autoclose=false classNames="js-add-subtask" cardId = cardId) @@ -24,9 +32,6 @@ template(name="subtaskDetail") +editSubtaskItemForm(subtask = subtask) else .subtask-title - span - if canModifyCard - a.subtask-details-menu.js-open-subtask-details-menu(title="{{_ 'subtaskActionsPopup-title'}}") if canModifyCard h2.title.js-open-inlined-form.is-editable +viewer @@ -37,13 +42,13 @@ template(name="subtaskDetail") = subtask.title template(name="addSubtaskItemForm") - textarea.js-add-subtask-item(rows='1' autofocus dir="auto") + textarea.js-add-subtask-item(rows='1' dir="auto") .edit-controls.clearfix button.primary.confirm.js-submit-add-subtask-item-form(type="submit") {{_ 'save'}} a.js-close-inlined-form template(name="editSubtaskItemForm") - textarea.js-edit-subtask-item(rows='1' autofocus dir="auto") + textarea.js-edit-subtask-item(rows='1' dir="auto") if $eq type 'item' = item.title else @@ -52,9 +57,6 @@ template(name="editSubtaskItemForm") button.primary.confirm.js-submit-edit-subtask-item-form(type="submit") {{_ 'save'}} a.js-close-inlined-form span(title=createdAt) {{ moment createdAt }} - if canModifyCard - if currentUser.isBoardAdmin - a.js-delete-subtask-item {{_ "delete"}}... template(name="subtasksItems") .subtasks-items.js-subtasks-items @@ -100,4 +102,3 @@ template(name="subtaskActionsPopup") a.js-delete-subtask.delete-subtask i.fa.fa-trash | {{_ "delete"}} ... - diff --git a/client/components/common/originalPosition.css b/client/components/common/originalPosition.css index 1c31c4860..9825716ca 100644 --- a/client/components/common/originalPosition.css +++ b/client/components/common/originalPosition.css @@ -2,8 +2,8 @@ .original-position-info { margin: 5px 0; padding: 8px; - border-radius: 4px; - font-size: 12px; + border-radius: 0.4ch; + line-height: 1.4; } @@ -57,7 +57,7 @@ .original-title { color: #6c757d; - font-size: 11px; + margin-top: 4px; padding-top: 4px; border-top: 1px solid #e9ecef; @@ -78,14 +78,14 @@ /* Responsive adjustments */ @media (max-width: 768px) { .original-position-info { - font-size: 11px; + padding: 6px; } - + .original-position-details { padding: 4px 6px; } - + .original-position-moved, .original-position-unchanged { padding: 3px 5px; @@ -99,24 +99,24 @@ border-color: #4a5568; color: #e2e8f0; } - + .original-position-moved { background-color: #744210; border-color: #b7791f; color: #fbd38d; } - + .original-position-unchanged { background-color: #22543d; border-color: #38a169; color: #9ae6b4; } - + .original-title { color: #a0aec0; border-color: #4a5568; } - + .original-title strong { color: #e2e8f0; } diff --git a/client/components/forms/datepicker.css b/client/components/forms/datepicker.css index f0adcab6c..0be169357 100644 --- a/client/components/forms/datepicker.css +++ b/client/components/forms/datepicker.css @@ -1,22 +1,18 @@ -.datepicker-container .fields .left { - width: 56%; -} -.datepicker-container .fields .right { - width: 38%; -} -.datepicker-container .datepicker { - width: 100%; -} -.datepicker-container .datepicker table { - width: 100%; - border: none; - border-spacing: 0; - border-collapse: collapse; -} -.datepicker-container .datepicker table thead { - background: none; -} -.datepicker-container .datepicker table td, -.datepicker-container .datepicker table th { - box-sizing: border-box; -} +.datepicker-container { + form { + display: flex; + gap: 0.3lh; + padding: 0.3lh 1ch; + } + .fields { + display: flex; + justify-content: stretch; + gap: 1ch; + .left, .right { + display: flex; + flex: 1; + flex-direction: column; + align-items: stretch; + } + } +} \ No newline at end of file diff --git a/client/components/forms/forms.css b/client/components/forms/forms.css index ed26361bf..e2aaa7d75 100644 --- a/client/components/forms/forms.css +++ b/client/components/forms/forms.css @@ -1,3 +1,16 @@ +select, button, input { + font-size: 1rem !important; +} + +form { + /* 🛑 remove me if it causes a significant issue. + this can be overidden and otherwise allow forms to + scale with their parent. */ + display: flex; + flex-direction: column; + flex: 1; +} + select, textarea, input:not([type=file]), @@ -7,9 +20,8 @@ button { border: 1px solid #ccc; border-radius: 0.4vw; display: block; - margin-bottom: 1.5vh; - min-height: 4.5vh; - padding: 1vh 1vw; + padding: 0.3lh 1ch; + max-width: clamp(30vw, 100%, 800px); } select.full, textarea.full, @@ -42,18 +54,6 @@ input[type="text"], input[type="password"], input[type="email"] { transition: background 85ms ease-in, border-color 85ms ease-in; - width: min(250px, 30vw); -} -input[type="text"].inline-input, -input[type="password"].inline-input, -input[type="email"].inline-input { - background: none; - border: 0; - margin: 0; - padding: 0.3vh; - min-height: 0; - height: 2.5vh; - width: min(200px, 25vw); } input[type="text"].full-line, input[type="password"].full-line, @@ -102,11 +102,6 @@ textarea:disabled { -webkit-user-select: none; user-select: none; } -select { - max-height: 40vh; - width: min(256px, 32vw); - margin-bottom: 1vh; -} select.inline { width: 100%; } @@ -114,14 +109,11 @@ option[disabled] { color: #222; } textarea { - height: 20vh; transition: background 85ms ease-in, border-color 85ms ease-in; resize: vertical; - width: 100%; -} -textarea.editor { - resize: none; - padding-bottom: 3vh; + width: auto; + font-size: 0.9em; + min-height: 3lh; } .button { border-radius: 3px; @@ -137,9 +129,16 @@ button { display: inline-block; font-weight: 700; line-height: 1.3; - padding: 1vh 2.5vw; + /* in flex layouts, padding often disturbs computations. rather rarely have + two lines, so setting relative-unit min-height works better */ + min-height: 1.8lh; + padding: 0 2ch; text-align: center; color: #fff; + z-index: 1; + :not(.password-toggle-btn) { + margin-top: 0.1lh; + } } input[type="submit"] .wide, button .wide { @@ -241,9 +240,9 @@ input[type="hidden"] { } .radio-div, .check-div { - display: block; - margin: 0 0 0.5vh 2.5vw; - min-height: 2.5vh; + display: flex; + align-items: center; + gap: 0.2lh; position: relative; } .radio-div input, @@ -260,9 +259,10 @@ input[type="hidden"] { font-weight: 400; } label { - display: block; + display: flex; + flex-direction: column; + flex: 1; font-weight: 700; - margin-bottom: 0.5vh; } label.form-error { color: #d32f2f; @@ -274,11 +274,32 @@ textarea::-moz-placeholder { color: #333 !important; } .edit-controls, -.add-controls { +.add-controls, +.links-controls { display: flex; align-items: center; - margin-top: 0px; - margin-bottom: 1.5vh; + gap: 1ch; + button { + display: flex; + justify-content: center; + align-items: center; + } +} + +.edit-controls { + grid-area: main-controls; +} + +.add-controls { + grid-area: main-controls; +} + +.links-controls { + grid-area: links-controls +} + +.links-controls span.quiet { + margin: auto; } @media print { .add-controls { @@ -289,14 +310,7 @@ textarea::-moz-placeholder { .add-controls button[type=submit], .edit-controls input[type=button], .add-controls input[type=button] { - float: left; - height: 4.5vh; - margin-bottom: 0px; -} -.edit-controls .fa-times-thin, -.add-controls .fa-times-thin { - font-size: clamp(20px, 4vw, 26px); - margin: 0.5vh 1.5vw; + margin: 0; } [type="checkbox"]:not(:checked), [type="checkbox"]:checked { @@ -306,6 +320,18 @@ textarea::-moz-placeholder { display: none; } .materialCheckBox { + position: relative; + width: 0.5lh; + height: 0.5lh; + z-index: 0; + border: 0.2ch solid #5a5a5a; + border-radius: 1px; + transition: 0.2s; + margin: 0; + margin-left: 0px; + cursor: pointer; +} +.materialCheckBox:is(.active) { position: relative; width: 13px; height: 13px; @@ -317,19 +343,33 @@ textarea::-moz-placeholder { cursor: pointer; } .materialCheckBox.is-checked { - top: -4px; - left: -3px; - width: 7px; - height: 15px; - margin-right: 6px; - border-top: 2px solid transparent; - border-left: 2px solid transparent; - border-bottom: 2px solid #3cb500; - border-right: 2px solid #3cb500; - transform: rotate(40deg); + top: 0.3lh; + left: 0.25lh; + width: 0.25lh; + height: 0.5lh; + margin-right: 0.6lh; + border-top: 0 solid transparent; + border-left: 0 solid transparent; + border-bottom: 0.3ch solid #3cb500; + border-right: 0.3ch solid #3cb500; -webkit-backface-visibility: hidden; backface-visibility: hidden; - transform-origin: 100% 100%; + transform: rotate(50deg); + backface-visibility: hidden; + transform-origin: 0.5lh 0; +} + +form .form-buttons { + display: flex; + flex: 1; + align-self: stretch; + justify-content: stretch; + gap: 0.5ch; + &>button { + display: flex; + flex: 1; + justify-content: center; + } } /* Grey checkmarks when grey icons setting is enabled */ body.grey-icons-enabled .materialCheckBox.is-checked { @@ -362,7 +402,7 @@ body.grey-icons-enabled .materialCheckBox.is-checked { border-radius: 3px; color: #fff; display: none; - font-size: 12px; + font-weight: 700; height: 17px; line-height: 17px; @@ -419,7 +459,7 @@ body.grey-icons-enabled .materialCheckBox.is-checked { .button-link.setting .label { color: #222; display: block; - font-size: 12px; + line-height: 14px; margin-bottom: 0; } @@ -428,7 +468,7 @@ body.grey-icons-enabled .materialCheckBox.is-checked { } .button-link.setting .value { display: block; - font-size: 18px; + line-height: 24px; overflow: hidden; text-overflow: ellipsis; @@ -572,7 +612,7 @@ button.loud-text-button:hover { padding: 11px; position: relative; text-decoration: none; - font-size: 16px; + line-height: 20px; } .big-link .text { @@ -615,7 +655,7 @@ button.loud-text-button:hover { width: 40px; } .big-link.avatar-changer .member .member-initials { - font-size: 16px; + height: 40px; line-height: 40px; max-height: 40px; @@ -655,7 +695,7 @@ button.loud-text-button:hover { left: 0; width: 100%; z-index: 2; - font-size: 23px; + } .uploader .realfile input[type="file"] { cursor: pointer; @@ -666,7 +706,7 @@ button.loud-text-button:hover { padding: 0; width: 100%; z-index: 2; - font-size: 23px; + } .uploader:hover .fakefile { background: #318ec4; @@ -705,13 +745,13 @@ button.loud-text-button:hover { color: #fff; } .material-toggle-switch { - display: flex; + padding: 0.2rlh 1ch; + align-self: center; } .toggle-label { + height: 0.6rlh; + width: 1.3rlh; position: relative; - display: block; - height: 20px; - width: 44px; background-color: #a6a6a6; border-radius: 100px; cursor: pointer; @@ -719,11 +759,13 @@ button.loud-text-button:hover { } .toggle-label:after { position: absolute; - left: -2px; - top: -3px; - display: block; - width: 26px; - height: 26px; + /* ensure vertical centering */ + margin: auto; + top: 0; + bottom: 0; + left: -0.2rlh; + width: .8rlh; + height: .8rlh; border-radius: 100px; background-color: #fff; box-shadow: 0px 3px 3px rgba(0,0,0,0.05); @@ -737,7 +779,7 @@ button.loud-text-button:hover { background-color: #6fbeb5; } .toggle-switch:checked ~ .toggle-label:after { - left: 20px; + left: 1.5ch; background-color: #179588; } .toggle-switch:checked:disabled ~ .toggle-label { diff --git a/client/components/gantt/gantt.css b/client/components/gantt/gantt.css index 81139f07b..f9bf0ad16 100644 --- a/client/components/gantt/gantt.css +++ b/client/components/gantt/gantt.css @@ -52,7 +52,7 @@ min-width: 800px; border: 2px solid #666; font-family: sans-serif; - font-size: 13px; + background-color: #fff; } @@ -81,7 +81,7 @@ padding: 2px 1px; /* half */ text-align: center; background-color: #f5f5f5; - font-size: 11px; + min-width: 15px; /* half of 30px */ font-weight: bold; height: auto; @@ -112,7 +112,7 @@ vertical-align: middle; line-height: 28px; background-color: #ffffff; - font-size: 18px; + font-weight: bold; } @@ -162,7 +162,7 @@ .gantt-container tbody td.ganttview-block { background-color: #4CAF50 !important; color: #fff !important; - font-size: 18px !important; + font-weight: bold !important; padding: 2px !important; border-radius: 2px; @@ -171,7 +171,7 @@ /* Responsive adjustments */ @media (max-width: 768px) { .gantt-container table { - font-size: 11px; + } .gantt-container thead td { @@ -187,7 +187,7 @@ .gantt-container tbody td:first-child { width: 100px; - font-size: 12px; + } } diff --git a/client/components/lists/list.css b/client/components/lists/list.css index 1cfd6ca6f..d2270cc9a 100644 --- a/client/components/lists/list.css +++ b/client/components/lists/list.css @@ -1,50 +1,77 @@ -.list { +.list:not(.mobile-view, .list-composer) { box-sizing: border-box; display: flex; flex-direction: column; + align-self: start; position: relative; background: #dedede; border-left: 1px solid #ccc; padding: 0; - float: left; + /* so we get the computed minimal width, if no setting exist */ + width: var(--list-width, min-content) !important; + min-width: var(--list-min-width, 200) !important; + max-width: var(--list-max-width, auto) !important; + /* Both needs to be set to 0 so that resize works; but implies overflowing without size constraints */ + flex-grow: 0; + flex-shrink: 0; + z-index: 0; + /* So that sortable area is the tallest possible + ⚠️ This will make swimlane resizes less fluid, because height + is re-applied in realtime, rather than the list being hidden + by swimlane. Maybe there is another way.*/ + height: var(--swimlane-height, 100%); +} + +.list.mobile-view { + max-height: 100%; } /* List resize handle */ .list-resize-handle { position: absolute; top: 0; - right: -3px; - width: 6px; - height: 100%; + right: 0; + width: max(0.7ch, 0.3lh); cursor: col-resize; - z-index: 10; - background: transparent; - transition: background-color 0.2s ease; - border-radius: 2px; + z-index: 0; /* Ensure the handle is clickable */ pointer-events: auto; + height: 100%; + transition: all 0.2s ease-out; + box-sizing: border-box; } -.list-resize-handle:hover { - background: rgba(0, 123, 255, 0.4); - box-shadow: 0 0 4px rgba(0, 123, 255, 0.3); -} - -.list-resize-handle:active { - background: rgba(0, 123, 255, 0.6); - box-shadow: 0 0 6px rgba(0, 123, 255, 0.4); +.add-card-wrapper { + display: flex; + flex: 1; + justify-content: center; + align-items: stretch; + min-height: 2lh; + > { + display: flex; + align-items: center; + } } /* Show resize handle only on hover */ -.list:hover .list-resize-handle { - background: rgba(0, 0, 0, 0.1); +.list:hover .list-resize-handle, .list.list-resizing .list-resize-handle { + background: rgba(0, 123, 255, 0.2); + border-left: 1px solid rgba(0, 123, 255, 0.5); } -.list:hover .list-resize-handle:hover { - background: rgba(0, 123, 255, 0.4); - box-shadow: 0 0 4px rgba(0, 123, 255, 0.3); + +.list:not(.cannot-resize) { + &:hover + .list-resize-handle, + .list-resize-handle:hover { + border-left: 1px solid rgba(0, 123, 255, 0.5); + background: rgba(0, 123, 255, 0.2); + border-radius: 0; + } + .list-resize-handle:hover, &.list-resizing .list-resize-handle { + background: rgba(0, 123, 255, 0.3); + } } + /* Add a subtle indicator line */ .list-resize-handle::before { content: ''; @@ -57,10 +84,11 @@ background: rgba(0, 0, 0, 0.2); border-radius: 1px; opacity: 0; - transition: opacity 0.2s ease; + transition: opacity 0.2s ease-out; + } -.list-resize-handle:hover::before { +.list-resize-handle:hover::before, .list.list-resizing + .list-resize-handle:hover::before { opacity: 1; } @@ -75,163 +103,144 @@ display: none; } -/* Visual feedback during resize */ -.list.list-resizing { - transition: none !important; - box-shadow: 0 0 10px rgba(0, 123, 255, 0.3); - /* Ensure the list maintains its new width during resize */ - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - /* Override any conflicting layout properties */ - float: left !important; - display: block !important; - position: relative !important; - /* Force width to be respected */ - width: var(--list-width, auto) !important; - min-width: var(--list-width, auto) !important; - max-width: var(--list-width, auto) !important; - /* Ensure the width is applied immediately */ - overflow: visible !important; +.list.list-resizing.cannot-resize .list-resize-handle { + background: rgba(227, 64, 83, 0.5) !important; + border-left: 1px solid rgba(155, 32, 46, 0.5); } body.list-resizing-active { cursor: col-resize !important; + user-select: none !important; } body.list-resizing-active * { cursor: col-resize !important; + user-select: none !important; } -/* Ensure swimlane container doesn't interfere with list resizing */ -.swimlane .list.list-resizing { - /* Override any swimlane flex properties */ - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - /* Ensure width is respected */ - width: var(--list-width, auto) !important; - min-width: var(--list-width, auto) !important; - max-width: var(--list-width, auto) !important; + +body.mobile-mode { + .list-header:not(.open-list-composer) { + .list-header-name-container { + justify-content: start; + } + } } -/* More aggressive override for any container that might interfere */ -.js-swimlane .list.list-resizing, -.dragscroll .list.list-resizing, -[id^="swimlane-"] .list.list-resizing { - /* Force the width to be applied */ - width: var(--list-width, auto) !important; - min-width: var(--list-width, auto) !important; - max-width: var(--list-width, auto) !important; - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - float: left !important; - display: block !important; +.list-header-add { + display: flex; + justify-content: center; + >.inlined-form { + padding: 1ch; + } +} +.list-header:not(.open-list-composer) { + overflow: hidden !important; + display: flex; + align-items: center; + justify-content: center; + column-gap: 0.5lh; + row-gap: 0.5lh; + flex-shrink: 0; + background-color: #e4e4e4; + padding: 0.5lh; + .list-header-name-container { + display: grid; + /* by default, grid fill row before columns */ + grid-auto-flow: column; + align-items: center; + justify-content: center; + flex: 1; /* so we can see the ellipsis */ + max-width: 90%; + gap: 0.5ch; + flex-shrink: 0; + cursor: grab; + } + .list-header-menu { + width: max-content; + align-items: center; + gap: .5rlh; + } + &:not(:has(.list-rotated), :is(.list-header-name-container)) { + .list-header-name-container { + display: flex; + flex-wrap: wrap; + gap: 1ch; + align-items: center; + } + } + &:has(.list-rotated) { + .list-header-name-container { + /* this time we switch to a vertical layout, justified "top" */ + grid-auto-flow: row; + align-items: start; + align-content: start; + justify-items: center; + flex: 0; + gap: 0.3lh; + } + } + .viewer p { + /* cf https://developer.mozilla.org/fr/docs/Web/CSS/Reference/Properties/text-overflow */ + white-space: nowrap; + overflow: scroll; + text-overflow: ellipsis; + } } -/* Ensure the width persists after resize is complete */ -.js-swimlane .list[style*="--list-width"], -.dragscroll .list[style*="--list-width"], -[id^="swimlane-"] .list[style*="--list-width"] { - /* Maintain the width after resize */ - width: var(--list-width, auto) !important; - min-width: var(--list-width, auto) !important; - max-width: var(--list-width, auto) !important; - flex: none !important; - flex-basis: auto !important; - flex-grow: 0 !important; - flex-shrink: 0 !important; - float: left !important; - display: block !important; -} - -/* Ensure consistent header height for all lists */ -.list-header { - /* Maintain consistent height and padding for all lists */ - min-height: 2.5vh !important; - height: auto !important; - padding: 2.5vh 1.5vw 0.5vh !important; - /* Make sure the background covers the full height */ - background-color: #e4e4e4 !important; - border-bottom: 0.8vh solid #e4e4e4 !important; - /* Use original display for consistent button positioning */ - display: block !important; - position: relative !important; - /* Allow overflow for text wrapping and forms */ - overflow: visible !important; -} - -/* Clearfix for floated buttons */ -.list-header::after { - content: ""; - display: table; - clear: both; +.mini-list { + .list-header { + padding: 0.5lh 2ch; + } + .list-header-name-container { + /* on mobile, put card count below list name for a nice alignement effect */ + grid-auto-flow: row; + gap: 0; + } } /* Ensure title text doesn't cause height changes for all lists */ .list-header .list-header-name { - /* Allow text wrapping to flow below buttons */ - white-space: normal !important; - /* Ensure proper line height */ - line-height: 1.2 !important; - /* Ensure it doesn't overflow horizontally */ - overflow-wrap: break-word !important; - word-wrap: break-word !important; - /* Full width since buttons are now absolutely positioned above */ - width: 100% !important; + font-weight: bold; + /* Ensure it doesn't overflow */ + overflow: hidden !important; } -/* Position elements at top aligned with collapse button */ -.list-header .js-open-list-menu { - position: absolute !important; - top: 5px !important; - right: 10px !important; - z-index: 15 !important; - display: inline-block !important; - padding: 4px !important; +.list-header .list-header-name p { + margin: 0; } -.list-header .list-header-plus-top { - position: absolute !important; - top: 5px !important; - right: 30px !important; - z-index: 15 !important; - display: inline-block !important; - padding: 4px !important; +.list-header .list-header-wrap { + display: flex; } -.list-header .list-header-handle-desktop { - position: absolute !important; - top: 5px !important; - right: 80px !important; - z-index: 15 !important; - display: inline-block !important; +/* Position drag handle at top-right corner for ALL lists */ +.list-header .list-header-handle { + align-self: end; + /* Ensure it's clickable and shows proper cursor */ cursor: move !important; pointer-events: auto !important; - padding: 4px !important; } -/* Anchor header action buttons within header during resize */ -.list .list-header { position: relative; z-index: 5; } -.list .list-header .js-open-list-menu, -.list .list-header .list-header-plus-top, -.list .list-header .list-header-handle-desktop { - position: absolute !important; +.list:not:has(.list-header-add) { + /* so that absolute handle is positionned relative to the list */ + position: relative; + &:last-child { + /* hackisk compensation of the handle "gap" effect; to be done better */ + border-right: 1px solid #bbb; + } + height: 100%; } -[id^="swimlane-"] .list:first-child { - min-width: 2.5vw; + +.list.list-composer { + display: flex; + justify-content: center; + min-width: 4ch; + padding-top: 0.5lh; } .list.list-auto-width { flex: 1; } -.list:first-child { - border-left: none; - flex: none; -} .card-details + .list { border-left: none; } @@ -250,184 +259,53 @@ body.list-resizing-active * { height: 15vh; } .list.list-collapsed { - flex: none; - min-width: 30px; - max-width: 30px; - width: 30px; - min-height: 60vh; - height: 60vh; - overflow: visible; - position: relative; + overflow: hidden !important; + /* strict sizing when collapsed because no resizing + and constant, vertical layout */ + min-width: fit-content !important; + width: fit-content !important; + max-width: fit-content !important; } + .list.list-collapsed .list-header { - padding: 5px 0; - min-height: 100% !important; - height: 100% !important; - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-start; - position: relative; + flex-direction: column !important; overflow: visible !important; - width: 30px; - max-width: 30px; - margin: 0; -} -.list.list-collapsed .list-header .js-collapse { - position: relative !important; - left: -10px !important; - margin: 5px auto; - z-index: 10; - padding: 5px; - font-size: 16px; - white-space: nowrap; - display: block; - width: auto; - left: auto !important; - top: auto !important; -} -.list.list-collapsed .list-header .list-header-handle { - position: static !important; - margin: 5px auto; - z-index: 10; - padding: 5px; - display: block; - width: auto; - top: auto !important; - right: auto !important; -} - -.list.list-collapsed .list-header .list-header-handle-desktop { - position: static !important; - margin: 5px auto; - z-index: 10; - padding: 5px; - display: block; - width: auto; - top: auto !important; - right: auto !important; -} -.list.list-collapsed .list-header .list-rotated { - width: auto !important; - height: auto !important; - margin: 20px 0 0 0 !important; - position: relative !important; - overflow: visible !important; - transform: rotate(90deg); - transform-origin: center center; + gap: 0.2lh !important; + justify-content: flex-start !important; + min-width: 5ch; + /* spans the whole swimlane */ flex: 1; - display: flex; - align-items: center; - justify-content: center; -} -.list.list-collapsed .list-header .list-rotated h2.list-header-name { - text-align: center; - overflow: visible; - white-space: nowrap; - display: block !important; - font-size: 12px; - line-height: 1.2; - color: #333; - padding: 4px 8px; - margin: 0; - width: auto; - height: auto; - position: static; - left: auto; - top: auto; - transform: none; - z-index: 10; - visibility: visible !important; - opacity: 1 !important; - pointer-events: auto; -} - -.list.list-composer, -.list-composer { - display: none; -} - -/* Show list-composer when inside an active inlined form */ -form.inlined-form .list-composer { - display: block; } .list.list-composer .open-list-composer, .list .list-composer .open-list-composer { color: #8c8c8c; + min-width: max-content; } .list.list-composer .list-name-input, .list .list-composer .list-name-input { background: #fff; - margin: -0.4vh 0 1vh; -} -.list-header-add { - flex: 0 0 auto; - padding: 1.5vh 1.5vw; - position: relative; - min-height: 2.5vh; -} -.list-header { - flex: 0 0 auto; - padding: 2.5vh 1.5vw 0.5vh; - position: relative; - min-height: 2.5vh; - background-color: #e4e4e4; - border-bottom: 0.8vh solid #e4e4e4; -} -.list-header.list-header-card-count { - min-height: 4.5vh; - height: auto; -} -.list-header.ui-sortable-handle { - cursor: grab; -} -.list-header .list-header-left-icon { - display: none; -} -.list-header .list-header-name { - display: block; - font-size: clamp(14px, 3vw, 18px); - line-height: 1.2; - margin: 0; - font-weight: bold; - min-height: 1.2vh; - min-width: 4vw; - overflow-wrap: break-word; - word-wrap: break-word; - vertical-align: top; - width: 100%; -} -/* Sum badge shown before list title */ -.list-header .list-sum-badge { - display: inline-block; - margin-right: 8px; - padding: 0; - border-radius: 0; - background: transparent; - color: #8c8c8c; - font-weight: bold; - font-size: 12px; - vertical-align: middle; + display: flex; + flex: 1; + max-height: 2lh; } .list-rotated { - width: 1.3vw; - height: 35vh; - margin-top: -12vh; - margin-left: -14vw; - margin-right: 0; - transform: rotate(90deg); - position: relative; - text-overflow: ellipsis; - white-space: nowrap; + flex: 1; + writing-mode: vertical-rl; } + +body.mobile-mode .list-collapsed:nth-child(2n-1) > .list-header{ + background-color: #f1f1f1; +} + +body.mobile-mode .list-collapsed:nth-child(2n-2) > .list-header { + background-color: #f7f7f7; +} + .list-header .list-header-watch-icon { padding-left: 10px; color: #a6a6a6; } -.list-header .list-header-menu { - float: right; -} @media print { .list-header .list-header-menu, .list-header .list-header-menu-icon { @@ -436,7 +314,6 @@ form.inlined-form .list-composer { } .list-header .list-header-plus-top { color: #a6a6a6; - margin-right: 15px; vertical-align: middle; line-height: 1.2; } @@ -447,39 +324,25 @@ form.inlined-form .list-composer { color: #a6a6a6; margin-right: 15px; } -/* List header collapse button styling - positioned at top left */ +.list-header .list-header-name-container p { + margin: 0; +} + .list-header .js-collapse { position: absolute !important; top: 5px !important; left: 10px !important; color: #a6a6a6; - display: inline-block; - vertical-align: top; - padding: 5px 8px; border: none; border-radius: 0; background-color: transparent; - cursor: pointer; - font-size: 18px; - line-height: 1.2; - min-width: 30px; - text-align: center; text-decoration: none; - margin: 0; - z-index: 15; } .list-header .js-collapse:hover { background-color: transparent; color: #333; } -/* Title text container - full width below buttons */ -.list-header > div { - padding-top: 25px; - width: 100%; - display: block; - clear: both; -} .list.list-collapsed .list-header .js-collapse { display: inline-block !important; visibility: visible !important; @@ -492,214 +355,89 @@ form.inlined-form .list-composer { display: none !important; } -/* Responsive adjustments for collapsed lists */ -@media (min-width: 768px) { - .list.list-collapsed { - min-width: 30px; - max-width: 30px; - width: 30px; - min-height: 60vh; - height: 60vh; - } - .list.list-collapsed .list-header { - width: 30px; - max-width: 30px; - margin: 0; - min-height: 100% !important; - height: 100% !important; - } - .list.list-collapsed .list-header .list-rotated { - width: auto !important; - height: auto !important; - margin: 20px 0 0 0 !important; - position: relative !important; - transform: rotate(90deg); - flex: 1; - } - .list.list-collapsed .list-header .list-rotated h2.list-header-name { - width: auto; - font-size: 12px; - height: auto; - line-height: 1.2; - padding: 4px 8px; - margin: 0; - overflow: visible; - position: static; - left: auto; - top: auto; - transform: none; - text-align: center; - visibility: visible !important; - opacity: 1 !important; - display: block !important; - background-color: transparent; - border: none; - color: #333; - z-index: 10; - } - .list.list-collapsed .list-header .js-collapse { - margin: 5px auto; - } -} - -@media (min-width: 1024px) { - .list.list-collapsed { - min-width: 30px; - max-width: 30px; - width: 30px; - min-height: 60vh; - height: 60vh; - } - .list.list-collapsed .list-header { - width: 30px; - max-width: 30px; - min-height: 100% !important; - height: 100% !important; - } - .list.list-collapsed .list-header .list-rotated { - width: auto !important; - height: auto !important; - margin: 20px 0 0 0 !important; - position: relative !important; - transform: rotate(90deg); - flex: 1; - } - .list.list-collapsed .list-header .list-rotated h2.list-header-name { - width: auto; - font-size: 12px; - height: auto; - line-height: 1.2; - padding: 4px 8px; - margin: 0; - overflow: visible; - position: static; - left: auto; - top: auto; - transform: none; - text-align: center; - visibility: visible !important; - opacity: 1 !important; - display: block !important; - background-color: transparent; - border: none; - color: #333; - z-index: 10; - } - .list.list-collapsed .list-header .js-collapse { - margin: 5px auto; - } -} - -@media (min-width: 1200px) { - .list.list-collapsed { - min-width: 30px; - max-width: 30px; - width: 30px; - min-height: 60vh; - height: 60vh; - } - .list.list-collapsed .list-header { - width: 30px; - max-width: 30px; - min-height: 100% !important; - height: 100% !important; - } - .list.list-collapsed .list-header .list-rotated { - width: auto !important; - height: auto !important; - margin: 20px 0 0 0 !important; - position: relative !important; - transform: rotate(90deg); - flex: 1; - } - .list.list-collapsed .list-header .list-rotated h2.list-header-name { - width: auto; - font-size: 12px; - height: auto; - line-height: 1.2; - padding: 4px 8px; - margin: 0; - overflow: visible; - position: static; - left: auto; - top: auto; - transform: none; - text-align: center; - visibility: visible !important; - opacity: 1 !important; - display: block !important; - background-color: transparent; - border: none; - color: #333; - z-index: 10; - } - .list.list-collapsed .list-header .js-collapse { - margin: 5px auto; - } -} -.list-header .list-header-collapse { - color: #a6a6a6; - margin-right: 15px; -} .list-header .highlight { color: #ce1414; } .list-header .cardCount { color: #8c8c8c; - font-size: 12px; - font-weight: bold; + font-size: 0.9em; + font-weight: normal; + text-wrap: nowrap; } -.list-header .list-header-plus-top, +.list-header, .js-open-list-menu, .list-header-menu a { color: #4d4d4d; - padding-left: 4px; -} -.js-open-list-menu { - font-size: 18px; vertical-align: middle; line-height: 1.2; } .list-body { - flex: 1 1 auto; + /* do not set flex to avoid bad visual effects when resizing swimlanes */ flex-direction: column; display: flex; overflow-y: auto; - padding: 5px 11px; + padding: 0.4lh 1ch; + flex: 1; } +.minilists { + display: flex; + flex-direction: column; + gap: 0.5lh; +} +.minilist-wrapper > .minicard { + padding: 0.3lh 1ch; + .handle { + display: none; + } +} +.mobile-view { + .list-body { + flex: 1 0; + overflow-y: scroll; + } + &.list:not:has(.list-header-add) { + min-height: 50; + display: flex !important; + flex-direction: column; + align-items: stretch; + align-self: stretch; + justify-content: start; + } +} + .list-body .minicards { flex-grow: 1; flex-shrink: 0; + gap: 0.5lh; + display: flex; + flex-direction: column; /** get card drag/drop working for empty swimlanes */ - min-height: 32px; + min-height: 10vh; } .list-body .minicards form { - margin-bottom: 9px; -} -.list-body .minicards .add-controls button { - min-height: 50px; -} -.list-body .open-minicard-composer { - border-radius: 2px; - color: #8c8c8c; - display: block; - padding: 7px 10px; - position: relative; - text-decoration: none; - animation: fadeIn 0.3s; + display: flex; + flex-direction: column; + align-items: center; + flex: 1; } @media print { .list-body .open-minicard-composer { display: none; } } -.list-body .open-minicard-composer i.fa { - margin-right: 7px; + +.list-body .open-minicard-composer { + display: flex; + flex: 1; + border-radius: 0.4ch; + justify-content: center; + align-items: center; + font-size: 1.4em; } -.list-body .open-minicard-composer:hover { +body.mobile-mode .list-body .open-minicard-composer, .list-body .open-minicard-composer:hover { background: #fafafa; color: #222; - box-shadow: 0 1px 2px rgba(0,0,0,0.2); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } #js-wip-limit-edit { padding-top: 2%; @@ -726,280 +464,9 @@ form.inlined-form .list-composer { #js-list-width-edit .list-width-error { display: none; } -/* Mobile view styles - applied when isMiniScreen is true (iPhone, etc.) */ -.mini-list.mobile-view { - flex: 0 0 60px; - height: auto; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; -} -.list.mobile-view { - display: block !important; - flex-basis: auto; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - border-left: 0px !important; - margin: 0 !important; - padding: 0 !important; -} -.list.mobile-view:first-child { - margin-left: 0px; -} -.list.mobile-view.ui-sortable-helper { - flex: 0 0 60px; - height: 60px; - width: 100vw; - max-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; -} -.list.mobile-view.ui-sortable-helper .list-header.ui-sortable-handle { - cursor: grabbing; -} -.list.mobile-view.placeholder { - flex: 0 0 60px; - height: 60px; - width: 100vw; - max-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; -} -.list.mobile-view .list-body { - padding: 15px 19px; - width: 100vw; - max-width: 100vw; - min-width: 100vw; -} -.list.mobile-view .list-header { - /*Updated padding values for mobile devices, this should fix text grouping issue*/ - padding: 20px 0px 20px 0px; - border-bottom: 0px solid #e4e4e4; - min-height: 30px; - margin-top: 10px; - align-items: center; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - /* Force grid layout for iPhone */ - display: grid !important; - grid-template-columns: 30px 1fr auto auto !important; - gap: 10px !important; -} -.list.mobile-view .list-header .list-header-left-icon { - padding: 7px; - padding-right: 27px; - margin-top: 1px; - top: -7px; - left: -7px; -} -.list.mobile-view .list-header .list-header-menu-icon { - padding: 14px; - font-size: 40px !important; - text-align: center; - /* Force positioning for iPhone */ - position: absolute !important; - right: 60px !important; - top: 50% !important; - transform: translateY(-50%) !important; - z-index: 10; -} -.list.mobile-view .list-header .list-header-handle { - padding: 14px; - font-size: 48px !important; - text-align: center; - /* Force positioning for iPhone */ - position: absolute !important; - right: 10px !important; - top: 50% !important; - transform: translateY(-50%) !important; - z-index: 10; -} -.list.mobile-view .list-header .list-header-left-icon { - display: grid; - grid-row: 1/3; - grid-column: 1; -} -.list.mobile-view .list-header .list-header-name { - grid-row: 1; - grid-column: 2; - align-self: end; - font-size: 20px !important; - font-weight: bold; - line-height: 1.2; - padding-bottom: 2px; -} -.list.mobile-view .list-header .cardCount { - grid-row: 2; - grid-column: 2; - align-self: start; - text-align: left; - padding-left: 0; - margin-left: 0; - font-size: 16px !important; - line-height: 1.2; -} -.list.mobile-view .list-header .list-header-menu { - grid-row: 1/3; - grid-column: 3; -} -.list.mobile-view .list-header .list-header-menu-icon { - grid-row: 1/3; - grid-column: 3; -} -.list.mobile-view .list-header .list-header-handle { - grid-row: 1/3; - grid-column: 4; -} -.list.mobile-view .list-header .inlined-form { - grid-row: 1/3; - grid-column: 1/4; -} -.list.mobile-view .list-header .edit-controls { - align-items: initial; -} - -@media screen and (max-width: 800px), - screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - .mini-list { - flex: 0 0 60px; - height: auto; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; - } - .list { - display: block !important; - flex-basis: auto; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - border-left: 0px !important; - margin: 0 !important; - padding: 0 !important; - } - .list:first-child { - margin-left: 0px; - } - .list.ui-sortable-helper { - flex: 0 0 60px; - height: 60px; - width: 100vw; - max-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; - } - .list.ui-sortable-helper .list-header.ui-sortable-handle { - cursor: grabbing; - } - .list.placeholder { - flex: 0 0 60px; - height: 60px; - width: 100vw; - max-width: 100vw; - border-left: 0px !important; - border-bottom: 1px solid #ccc; - display: block !important; - } - .list-body { - padding: 15px 19px; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - } - .list-header { - /*Updated padding values for mobile devices, this should fix text grouping issue*/ - padding: 20px 0px 20px 0px; - border-bottom: 0px solid #e4e4e4; - min-height: 30px; - margin-top: 10px; - align-items: center; - width: 100vw; - max-width: 100vw; - min-width: 100vw; - } - .list-header .list-header-left-icon { - padding: 7px; - padding-right: 27px; - margin-top: 1px; - top: -7px; - left: -7px; - } - .list-header .list-header-menu-icon { - padding: 14px; - font-size: 40px; - text-align: center; - /* iOS Safari fallback positioning */ - position: absolute; - right: 60px; - top: 50%; - transform: translateY(-50%); - } - .list-header .list-header-handle { - padding: 14px; - font-size: 48px; - text-align: center; - /* iOS Safari fallback positioning */ - position: absolute; - right: 10px; - top: 50%; - transform: translateY(-50%); - } - .list-header { - display: grid; - grid-template-columns: 30px 1fr auto auto; - gap: 10px; - } - .list-header .list-header-left-icon { - display: grid; - grid-row: 1/3; - grid-column: 1; - } - .list-header .list-header-name { - grid-row: 1; - grid-column: 2; - align-self: end; - font-size: 20px; - font-weight: bold; - line-height: 1.2; - padding-bottom: 2px; - } - .list-header .cardCount { - grid-row: 2; - grid-column: 2; - align-self: start; - font-size: 16px; - line-height: 1.2; - } - .list-header .list-header-menu { - grid-row: 1/3; - grid-column: 3; - } - .list-header .list-header-menu-icon { - grid-row: 1/3; - grid-column: 3; - } - .list-header .list-header-handle { - grid-row: 1/3; - grid-column: 4; - } - .list-header .inlined-form { - grid-row: 1/3; - grid-column: 1/4; - } - .list-header .edit-controls { - align-items: initial; - } +.js-select-cards { + max-width: 30ch; + text-overflow: ellipsis; } /* iPhone 12 Mini specific - fix icon positioning in stacked lists view */ @@ -1024,7 +491,7 @@ form.inlined-form .list-composer { grid-row: 1/3 !important; grid-column: 3 !important; padding: 14px !important; - font-size: 40px !important; + text-align: center !important; } @@ -1038,7 +505,7 @@ form.inlined-form .list-composer { grid-row: 1/3 !important; grid-column: 4 !important; padding: 14px !important; - font-size: 48px !important; + text-align: center !important; } @@ -1046,7 +513,7 @@ form.inlined-form .list-composer { 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; @@ -1059,14 +526,8 @@ form.inlined-form .list-composer { text-align: left !important; padding-left: 0 !important; margin-left: 0 !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; + line-height: 1.2 !important; } } @@ -1089,7 +550,7 @@ form.inlined-form .list-composer { grid-row: 1/3 !important; grid-column: 3 !important; padding: 14px !important; - font-size: 40px !important; + text-align: center !important; } @@ -1103,7 +564,7 @@ form.inlined-form .list-composer { grid-row: 1/3 !important; grid-column: 4 !important; padding: 14px !important; - font-size: 48px !important; + text-align: center !important; } @@ -1111,7 +572,7 @@ form.inlined-form .list-composer { 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; @@ -1121,7 +582,7 @@ form.inlined-form .list-composer { grid-row: 2 !important; grid-column: 2 !important; align-self: start !important; - font-size: 16px !important; + line-height: 1.2 !important; } @@ -1131,28 +592,42 @@ form.inlined-form .list-composer { grid-column: 1 !important; } -/* Allow long list titles to expand on desktop (non-mobile, non-collapsed) */ -.list:not(.mobile-view):not(.list-collapsed) .list-header { - overflow: visible !important; -} - .list:not(.mobile-view):not(.list-collapsed) .list-header .list-header-name { /* Permit wrapping and full visibility */ - white-space: normal !important; - overflow: visible !important; - text-overflow: clip !important; - display: block !important; - /* Full width since buttons are absolutely positioned */ - width: 100% !important; + /* Break long words to avoid overflow */ - word-break: break-word !important; + white-space: nowrap; + overflow: scroll; + overflow-wrap: break-word !important; + text-overflow: clip; } .link-board-wrapper { display: flex; - align-items: baseline; + flex-direction: column; + padding: 0.3lh 1ch; + >form { + display: flex; + flex-direction: column; + align-items: stretch; + flex: 1; + } } -.link-board-wrapper .js-link-board { - margin-left: 15px; + +.link-board-dropdown { + display: grid; + grid-template-columns: 10ch auto; + gap: 0 1ch; + margin: 0.3lh 0; + grid-auto-columns: auto; + grid-auto-flow: column; + + + .edit-controls { + flex: 1; + justify-content: stretch; + >input { + flex: 1; + } + } } .search-card-results { max-height: 250px; @@ -1260,24 +735,4 @@ form.inlined-form .list-composer { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; -} - -.list.list-collapsed .list-header .js-collapse { - position: relative !important; - left: -10px !important; - color: #333; - background: transparent; - border: none; - border-radius: 0; - width: auto; - height: auto; - min-width: 0; - min-height: 0; - display: block !important; - align-items: initial; - justify-content: initial; - font-size: 16px !important; - box-shadow: none; - margin: 5px auto; - z-index: 10; -} +} \ No newline at end of file diff --git a/client/components/lists/list.jade b/client/components/lists/list.jade index c28dd1a9c..67ab132d1 100644 --- a/client/components/lists/list.jade +++ b/client/components/lists/list.jade @@ -1,12 +1,13 @@ template(name='list') .list.js-list(id="js-list-{{_id}}" - style="{{#unless collapsed}}min-width:{{listWidth}}px;max-width:{{listConstraint}}px;{{/unless}}" class="{{#if collapsed}}list-collapsed{{/if}} {{#if autoWidth}}list-auto-width{{/if}} {{#if isMiniScreen}}mobile-view{{/if}}") +listHeader unless collapsed +listBody - .list-resize-handle.js-list-resize-handle.nodragscroll + .list-resize-handle.js-list-resize-handle.nodragscroll template(name='miniList') a.mini-list.js-select-list.js-list(id="js-list-{{_id}}" class="{{#if isMiniScreen}}mobile-view{{/if}}") +listHeader + if isCurrentList + +listBody \ No newline at end of file diff --git a/client/components/lists/list.js b/client/components/lists/list.js index 0c084a45c..667050def 100644 --- a/client/components/lists/list.js +++ b/client/components/lists/list.js @@ -4,6 +4,8 @@ require('/client/lib/jquery-ui.js') const { calculateIndex } = Utils; +export const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)'; + BlazeComponent.extendComponent({ // Proxy openForm(options) { @@ -12,6 +14,7 @@ BlazeComponent.extendComponent({ onCreated() { this.newCardFormIsVisible = new ReactiveVar(true); + this.collapse = new ReactiveVar(Utils.getListCollapseState(this.data())); }, // The jquery UI sortable library is the best solution I've found so far. I @@ -22,183 +25,37 @@ BlazeComponent.extendComponent({ // callback, we basically solve all issues related to reactive updates. A // comment below provides further details. onRendered() { - const boardComponent = this.parentComponent().parentComponent(); - - // Initialize list resize functionality immediately + this.list = this.firstNode(); + this.resizeHandle = this.find('.js-list-resize-handle'); this.initializeListResize(); - const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)'; - const $cards = this.$('.js-minicards'); - - $cards.sortable({ - connectWith: '.js-minicards:not(.js-list-full)', - tolerance: 'pointer', - appendTo: '.board-canvas', - helper(evt, item) { - const helper = item.clone(); - if (MultiSelection.isActive()) { - const andNOthers = $cards.find('.js-minicard.is-checked').length - 1; - if (andNOthers > 0) { - helper.append( - $( - Blaze.toHTML( - HTML.DIV( - { class: 'and-n-other' }, - TAPi18n.__('and-n-other-card', { count: andNOthers }), - ), - ), - ), - ); - } - } - return helper; - }, - distance: 7, - items: itemsSelector, - placeholder: 'minicard-wrapper placeholder', - scrollSpeed: 10, - start(evt, ui) { - ui.helper.css('z-index', 1000); - ui.placeholder.height(ui.helper.height()); - EscapeActions.executeUpTo('popup-close'); - boardComponent.setIsDragging(true); - }, - stop(evt, ui) { - // To attribute the new index number, we need to get the DOM element - // of the previous and the following card -- if any. - const prevCardDom = ui.item.prev('.js-minicard').get(0); - const nextCardDom = ui.item.next('.js-minicard').get(0); - const nCards = MultiSelection.isActive() ? MultiSelection.count() : 1; - const sortIndex = calculateIndex(prevCardDom, nextCardDom, nCards); - const listId = Blaze.getData(ui.item.parents('.list').get(0))._id; - const currentBoard = Utils.getCurrentBoard(); - const defaultSwimlaneId = currentBoard.getDefaultSwimline()._id; - let targetSwimlaneId = null; - - // only set a new swimelane ID if the swimlanes view is active - if ( - Utils.boardView() === 'board-view-swimlanes' || - currentBoard.isTemplatesBoard() - ) - targetSwimlaneId = Blaze.getData(ui.item.parents('.swimlane').get(0)) - ._id; - - // Normally the jquery-ui sortable library moves the dragged DOM element - // to its new position, which disrupts Blaze reactive updates mechanism - // (especially when we move the last card of a list, or when multiple - // users move some cards at the same time). To prevent these UX glitches - // we ask sortable to gracefully cancel the move, and to put back the - // DOM in its initial state. The card move is then handled reactively by - // Blaze with the below query. - $cards.sortable('cancel'); - - if (MultiSelection.isActive()) { - ReactiveCache.getCards(MultiSelection.getMongoSelector(), { sort: ['sort'] }).forEach((card, i) => { - const newSwimlaneId = targetSwimlaneId - ? targetSwimlaneId - : card.swimlaneId || defaultSwimlaneId; - card.move( - currentBoard._id, - newSwimlaneId, - listId, - sortIndex.base + i * sortIndex.increment, - ); - }); - } else { - const cardDomElement = ui.item.get(0); - const card = Blaze.getData(cardDomElement); - const newSwimlaneId = targetSwimlaneId - ? targetSwimlaneId - : card.swimlaneId || defaultSwimlaneId; - card.move(currentBoard._id, newSwimlaneId, listId, sortIndex.base); - } - boardComponent.setIsDragging(false); - }, - sort(event, ui) { - const $boardCanvas = $('.board-canvas'); - const boardCanvas = $boardCanvas[0]; - - if (event.pageX < 10) { // scroll to the left - boardCanvas.scrollLeft -= 15; - ui.helper[0].offsetLeft -= 15; - } - if ( - event.pageX > boardCanvas.offsetWidth - 10 && - boardCanvas.scrollLeft < $boardCanvas.data('scrollLeftMax') // don't scroll more than possible - ) { // scroll to the right - boardCanvas.scrollLeft += 15; - } - if ( - event.pageY > boardCanvas.offsetHeight - 10 && - event.pageY + boardCanvas.scrollTop < $boardCanvas.data('scrollTopMax') // don't scroll more than possible - ) { // scroll to the bottom - boardCanvas.scrollTop += 15; - } - if (event.pageY < 10) { // scroll to the top - boardCanvas.scrollTop -= 15; - } - }, - activate(event, ui) { - const $boardCanvas = $('.board-canvas'); - const boardCanvas = $boardCanvas[0]; - // scrollTopMax and scrollLeftMax only available at Firefox (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTopMax) - // https://www.it-swarm.com.de/de/javascript/so-erhalten-sie-den-maximalen-dokument-scrolltop-wert/1069126844/ - $boardCanvas.data('scrollTopMax', boardCanvas.scrollHeight - boardCanvas.clientTop); - // https://stackoverflow.com/questions/5138373/how-do-i-get-the-max-value-of-scrollleft/5704386#5704386 - $boardCanvas.data('scrollLeftMax', boardCanvas.scrollWidth - boardCanvas.clientWidth); - }, - }); - - this.autorun(() => { - if ($cards.data('uiSortable') || $cards.data('sortable')) { - if (Utils.isTouchScreenOrShowDesktopDragHandles()) { - $cards.sortable('option', 'handle', '.handle'); - } else { - $cards.sortable('option', 'handle', '.minicard'); - } - - $cards.sortable( - 'option', - 'disabled', - // Disable drag-dropping when user is not member - !Utils.canModifyBoard(), - // Not disable drag-dropping while in multi-selection mode - // MultiSelection.isActive() || !Utils.canModifyBoard(), - ); + const ensureCollapseState = (collapsed) => { + if (this.collapse.get() === collapsed) return; + if (this.autoWidth() || collapsed) { + $(this.resizeHandle).hide(); + } else { + $(this.resizeHandle).show(); } - }); + this.collapse.set(collapsed); + this.initializeListResize(); + } - // We want to re-run this function any time a card is added. + // Reactively update collapse appearance and resize handle visibility when auto-width or collapse changes this.autorun(() => { - const currentBoardId = Tracker.nonreactive(() => { - return Session.get('currentBoard'); - }); - Tracker.afterFlush(() => { - $cards.find(itemsSelector).droppable({ - hoverClass: 'draggable-hover-card', - accept: '.js-member,.js-label', - drop(event, ui) { - const cardId = Blaze.getData(this)._id; - const card = ReactiveCache.getCard(cardId); - - if (ui.draggable.hasClass('js-member')) { - const memberId = Blaze.getData(ui.draggable.get(0)).userId; - card.assignMember(memberId); - } else { - const labelId = Blaze.getData(ui.draggable.get(0))._id; - card.addLabel(labelId); - } - }, - }); - }); + ensureCollapseState(Utils.getListCollapseState(this.data())); }); }, + collapsed() { + return this.collapse.get(); + }, + + listWidth() { const user = ReactiveCache.getCurrentUser(); const list = Template.currentData(); if (!list) return 270; // Return default width if list is not available - + if (user) { // For logged-in users, get from user profile return user.getListWidthFromStorage(list.boardId, list._id); @@ -222,8 +79,8 @@ BlazeComponent.extendComponent({ listConstraint() { const user = ReactiveCache.getCurrentUser(); const list = Template.currentData(); - if (!list) return 550; // Return default constraint if list is not available - + if (!list) return 0; + if (user) { // For logged-in users, get from user profile return user.getListConstraintFromStorage(list.boardId, list._id); @@ -240,7 +97,7 @@ BlazeComponent.extendComponent({ } catch (e) { console.warn('Error reading list constraint from localStorage:', e); } - return 550; // Return default constraint if not found + return 0; } }, @@ -256,18 +113,14 @@ BlazeComponent.extendComponent({ initializeListResize() { // Check if we're still in a valid template context - if (!Template.currentData()) { + if (!this.data()) { console.warn('No current template data available for list resize initialization'); return; } - - const list = Template.currentData(); - const $list = this.$('.js-list'); - const $resizeHandle = this.$('.js-list-resize-handle'); - + // Check if elements exist - if (!$list.length || !$resizeHandle.length) { - console.warn('List or resize handle not found, retrying in 100ms'); + if (!this.list || !this.resizeHandle) { + console.info('List or resize handle not found, retrying in 100ms'); Meteor.setTimeout(() => { if (!this.isDestroyed) { this.initializeListResize(); @@ -275,107 +128,129 @@ BlazeComponent.extendComponent({ }, 100); return; } - - // Reactively show/hide resize handle based on collapse and auto-width state - this.autorun(() => { - const isAutoWidth = this.autoWidth(); - const isCollapsed = Utils.getListCollapseState(list); - if (isCollapsed || isAutoWidth) { - $resizeHandle.hide(); - } else { - $resizeHandle.show(); - } - }); let isResizing = false; - let startX = 0; - let startWidth = 0; - let minWidth = 270; // Minimum width matching system default - let listConstraint = this.listConstraint(); // Store constraint value for use in event handlers - const component = this; // Store reference to component for use in event handlers + let previousLimit = false; + // seems reasonable; better let user shrink too much that too little + const minWidth = 280; + // stored width + const width = this.listWidth(); + // min-width is initially min-content; a good start + let maxWidth = this.listConstraint() || parseInt(this.list.style.getProperty('--list-min-width', `${(minWidth)}px`), 10) || width + 100; + if (!width || width > maxWidth) { + width = (maxWidth + minWidth) / 2; + } + this.list.style.setProperty('--list-min-width', `${Math.round(minWidth)}px`); + // actual size before fitting (usually max-content equivalent) + this.list.style.setProperty('--list-max-width', `${Math.round(maxWidth)}px`); + // avoid jump effect and ensure width stays consistent + this.list.style.setProperty('--list-width', `${Math.round(width)}px`); + + const component = this; + + // wait for click to add other events const startResize = (e) => { - isResizing = true; - startX = e.pageX || e.originalEvent.touches[0].pageX; - startWidth = $list.outerWidth(); - - - // Add visual feedback - $list.addClass('list-resizing'); - $('body').addClass('list-resizing-active'); - - - // Prevent text selection during resize - $('body').css('user-select', 'none'); - + // gain access to modern attributes e.g. isPrimary + e = e.originalEvent; + + if (isResizing || Utils.shouldIgnorePointer(e)) { + return; + } + e.preventDefault(); e.stopPropagation(); + + $(document).on('pointermove', doResize); + // e.g. debugger can cancel event without pointerup being fired + $(document).on('pointercancel', stopResize); + $(document).on('pointerup', stopResize); + + // --list-width can be either a stored size or "auto"; get actual computed size + component.currentWidth = component.list.offsetWidth; + component.list.classList.add('list-resizing'); + document.body.classList.add('list-resizing-active'); + + isResizing = true; }; const doResize = (e) => { - if (!isResizing) { - return; - } - - const currentX = e.pageX || e.originalEvent.touches[0].pageX; - const deltaX = currentX - startX; - const newWidth = Math.max(minWidth, startWidth + deltaX); - - // Apply the new width immediately for real-time feedback - $list[0].style.setProperty('--list-width', `${newWidth}px`); - $list[0].style.setProperty('width', `${newWidth}px`); - $list[0].style.setProperty('min-width', `${newWidth}px`); - $list[0].style.setProperty('max-width', `${newWidth}px`); - $list[0].style.setProperty('flex', 'none'); - $list[0].style.setProperty('flex-basis', 'auto'); - $list[0].style.setProperty('flex-grow', '0'); - $list[0].style.setProperty('flex-shrink', '0'); - - + e = e.originalEvent; + e.preventDefault(); e.stopPropagation(); + + if (!isResizing || !e.isPrimary) { + return; + } + + if (!previousLimit && component.collapsed()) { + previousLimit = true; + component.list.classList.add('cannot-resize'); + return; + } + + // relative to document, always >0 because pointer sticks to the right of list + const deltaX = e.clientX - component.list.getBoundingClientRect().right; + const candidateWidth = component.currentWidth + deltaX; + component.currentWidth = Math.max(minWidth, Math.min(maxWidth, candidateWidth)); + const reachingMax = (maxWidth - component.currentWidth - 20) <= 0 + const reachingMin = (component.currentWidth - 20 - minWidth) <= 0 + // visual indicator to avoid trying too hard; try not to apply each tick + if (!previousLimit && (reachingMax && deltaX > 0 || reachingMin && deltaX < 0)) { + component.list.classList.add('cannot-resize'); + previousLimit = true; + } else if (previousLimit && !reachingMax && !reachingMin) { + component.list.classList.remove('cannot-resize'); + previousLimit = false; + } + // Apply the new width immediately for real-time feedback + component.list.style.setProperty('--list-width', `${component.currentWidth}px`); }; const stopResize = (e) => { - if (!isResizing) return; - + e = e.originalEvent; + + e.preventDefault(); + e.stopPropagation(); + + if (!isResizing || !e.isPrimary) { + return; + } + + // hopefully be gentler on cpu + $(document).off('pointermove', doResize); + $(document).off('pointercancel', stopResize); + $(document).off('pointerup', stopResize); isResizing = false; - - // Calculate final width - const currentX = e.pageX || e.originalEvent.touches[0].pageX; - const deltaX = currentX - startX; - const finalWidth = Math.max(minWidth, startWidth + deltaX); - - // Ensure the final width is applied - $list[0].style.setProperty('--list-width', `${finalWidth}px`); - $list[0].style.setProperty('width', `${finalWidth}px`); - $list[0].style.setProperty('min-width', `${finalWidth}px`); - $list[0].style.setProperty('max-width', `${finalWidth}px`); - $list[0].style.setProperty('flex', 'none'); - $list[0].style.setProperty('flex-basis', 'auto'); - $list[0].style.setProperty('flex-grow', '0'); - $list[0].style.setProperty('flex-shrink', '0'); - - // Remove visual feedback but keep the width - $list.removeClass('list-resizing'); - $('body').removeClass('list-resizing-active'); - $('body').css('user-select', ''); - - // Keep the CSS custom property for persistent width - // The CSS custom property will remain on the element to maintain the width - + + if (previousLimit) { + component.list.classList.remove('cannot-resize'); + } + + const finalWidth = parseInt(component.list.style.getPropertyValue('--list-width'), 10); + + // Remove visual feedback but keep the height + component.list.classList.remove('list-resizing'); + document.body.classList.remove('list-resizing-active'); + + if (component.collapse.get()) { + return; + } + // Save the new width using the existing system + const list = component.data(); const boardId = list.boardId; const listId = list._id; - + // Use the new storage method that handles both logged-in and non-logged-in users if (process.env.DEBUG === 'true') { } - + const currentUser = ReactiveCache.getCurrentUser(); if (currentUser) { // For logged-in users, use server method - Meteor.call('applyListWidthToStorage', boardId, listId, finalWidth, listConstraint, (error, result) => { + Meteor.call('applyListWidthToStorage', boardId, listId, finalWidth, maxWidth, (error, result) => { if (error) { console.error('Error saving list width:', error); } else { @@ -389,61 +264,37 @@ BlazeComponent.extendComponent({ // Save list width const storedWidths = localStorage.getItem('wekan-list-widths'); let widths = storedWidths ? JSON.parse(storedWidths) : {}; - + if (!widths[boardId]) { widths[boardId] = {}; } widths[boardId][listId] = finalWidth; - + localStorage.setItem('wekan-list-widths', JSON.stringify(widths)); - + // Save list constraint const storedConstraints = localStorage.getItem('wekan-list-constraints'); let constraints = storedConstraints ? JSON.parse(storedConstraints) : {}; - + if (!constraints[boardId]) { constraints[boardId] = {}; } constraints[boardId][listId] = listConstraint; - + localStorage.setItem('wekan-list-constraints', JSON.stringify(constraints)); - + if (process.env.DEBUG === 'true') { } } catch (e) { console.warn('Error saving list width/constraint to localStorage:', e); } } - + e.preventDefault(); }; - // Mouse events - $resizeHandle.on('mousedown', startResize); - $(document).on('mousemove', doResize); - $(document).on('mouseup', stopResize); - - // Touch events for mobile - $resizeHandle.on('touchstart', startResize, { passive: false }); - $(document).on('touchmove', doResize, { passive: false }); - $(document).on('touchend', stopResize, { passive: false }); - - - // Prevent dragscroll interference - $resizeHandle.on('mousedown', (e) => { - e.stopPropagation(); - }); - - - // Reactively update resize handle visibility when auto-width or collapse changes - component.autorun(() => { - const collapsed = Utils.getListCollapseState(list); - if (component.autoWidth() || collapsed) { - $resizeHandle.hide(); - } else { - $resizeHandle.show(); - } - }); + // handle both pointer and touch + $(this.resizeHandle).on("pointerdown", startResize); // Clean up on component destruction component.onDestroyed(() => { @@ -455,12 +306,6 @@ BlazeComponent.extendComponent({ }, }).register('list'); -Template.list.helpers({ - collapsed() { - return Utils.getListCollapseState(this); - }, -}); - Template.miniList.events({ 'click .js-select-list'() { const listId = this._id; @@ -468,15 +313,10 @@ Template.miniList.events({ }, }); -// Enable drag-reorder for collapsed lists from .js-collapsed-list-drag area - this.$('.js-collapsed-list-drag').draggable({ - axis: 'x', - helper: 'clone', - revert: 'invalid', - start(evt, ui) { - boardComponent.setIsDragging(true); - }, - stop(evt, ui) { - boardComponent.setIsDragging(false); - } - }); +Template.miniList.helpers({ + isCurrentList() { + const currentList = Utils.getCurrentList(); + const list = Template.currentData(); + return currentList && currentList._id == list._id; + }, +}); \ No newline at end of file diff --git a/client/components/lists/listBody.jade b/client/components/lists/listBody.jade index 3d23a49ce..42914a82c 100644 --- a/client/components/lists/listBody.jade +++ b/client/components/lists/listBody.jade @@ -4,17 +4,18 @@ template(name="listBody") .minicards.clearfix.js-minicards(class="{{#if reachedWipLimit}}js-list-full{{/if}}") +inlinedForm(autoclose=false position="top") +addCardForm(listId=_id position="top") - ul.sidebar-list - each customFieldsSum - li - +viewer - = name - if $eq customFieldsSum.type "number" + if customFieldSum.lenght + ul.sidebar-list + each customFieldsSum + li +viewer - = value - if $eq customFieldsSum.type "currency" - +viewer - = formattedCurrencyCustomFieldValue(value) + = name + if $eq customFieldsSum.type "number" + +viewer + = value + if $eq customFieldsSum.type "currency" + +viewer + = formattedCurrencyCustomFieldValue(value) each (cardsWithLimit (idOrNull ../../_id)) a.minicard-wrapper.js-minicard(href=originRelativeUrl class="{{#if cardIsSelected}}is-selected{{/if}}" @@ -25,15 +26,15 @@ template(name="listBody") +minicard(this) if (showSpinner (idOrNull ../../_id)) +spinnerList + if canSeeAddCard - +inlinedForm(autoclose=false position="bottom") - +addCardForm(listId=_id position="bottom") - else - a.open-minicard-composer.js-card-composer.js-open-inlined-form(title="{{_ 'add-card-to-bottom-of-list'}}") - i.fa.fa-plus - | {{_ 'add-card'}} - +inlinedForm(autoclose=false position="bottom") - +addCardForm(listId=_id position="bottom") + a.minicard-wrapper.minicard-add-form + +inlinedForm(autoclose=false position="bottom") + +addCardForm(listId=_id position="bottom") + else + .add-card-wrapper + a.open-minicard-composer.js-card-composer.js-open-inlined-form(title="{{_ 'add-card-to-bottom-of-list'}}") + i.fa.fa-plus template(name="spinnerList") .sk-spinner.sk-spinner-list( @@ -43,33 +44,30 @@ template(name="spinnerList") template(name="addCardForm") .minicard.minicard-composer.js-composer - if getLabels - .minicard-labels - each getLabels - .minicard-label(class="card-label-{{color}}" title="{{name}}") textarea.minicard-composer-textarea.js-card-title(autofocus dir="auto") - if members.get - .minicard-members.js-minicard-composer-members - each members.get - +userAvatar(userId=this) + .minicard-bottom + .minicard-composer-icons + if getLabels + each getLabels + .minicard-label(class="card-label-{{color}}" title="{{name}}") + if members.get + each members.get + +userAvatar(userId=this) + .add-controls.clearfix + a.js-close-inlined-form + i.fa.fa-times-thin - .add-controls.clearfix - button.primary.confirm(type="submit") {{_ 'add'}} - a.js-close-inlined-form - i.fa.fa-times-thin - .add-controls.clearfix + button.primary.confirm(type="submit") {{_ 'add'}} + + .links-controls.clearfix unless currentBoard.isTemplatesBoard unless currentBoard.isTemplateBoard span.quiet | {{_ 'or'}} a.js-link {{_ 'link'}} span.quiet - | - | / a.js-search {{_ 'search'}} span.quiet - | - | / a.js-card-template {{_ 'template'}} template(name="autocompleteLabelLine") @@ -77,70 +75,73 @@ template(name="autocompleteLabelLine") span(class="{{#if hasNoName}}quiet{{/if}}")= labelName template(name="linkCardPopup") - label {{_ 'boards'}}: .link-board-wrapper - select.js-select-boards - option(value="") - each boards - option(value="{{_id}}") {{isTitleDefault title}} - input.primary.confirm.js-link-board(type="button" value="{{_ 'link'}}") - - label {{_ 'swimlanes'}}: - select.js-select-swimlanes - option(value="") {{_ 'custom-field-dropdown-none'}} - each swimlanes - option(value="{{_id}}") {{isTitleDefault title}} - - label {{_ 'lists'}}: - select.js-select-lists - option(value="") {{_ 'custom-field-dropdown-none'}} - each lists - option(value="{{_id}}") {{isTitleDefault title}} - - label {{_ 'cards'}}: - select.js-select-cards - option(value="") {{_ 'custom-field-dropdown-none'}} - each cards - option(value="{{getRealId}}") {{getTitle}} - - .edit-controls.clearfix - input.primary.confirm.js-done(type="button" value="{{_ 'link'}}") - -template(name="searchElementPopup") - form - label - | {{_ 'title'}} - input.js-element-title(type="text" placeholder="{{_ 'title'}}" autofocus required dir="auto") - unless isTemplateSearch - label {{_ 'boards'}}: - .link-board-wrapper + .link-board-dropdown + label {{_ 'boards'}}: select.js-select-boards option(value="") each boards - option(value="{{_id}}") {{title}} - form.js-search-term-form - label - | {{_ 'template'}} - input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus dir="auto") - .list-body.search-card-results - .minicards.clearfix.js-minicards - if isBoardTemplateSearch - each results - a.minicard-wrapper.js-minicard - +miniboard(this) - if isListTemplateSearch - each results - a.minicard-wrapper.js-minicard - +minilist(this) - if isSwimlaneTemplateSearch - each results - a.minicard-wrapper.js-minicard - +miniswimlane(this) - if isCardTemplateSearch - each results - a.minicard-wrapper.js-minicard - +minicard(this) - unless isTemplateSearch - each results - a.minicard-wrapper.js-minicard - +minicard(this) + option(value="{{_id}}") {{isTitleDefault title}} + input.primary.confirm.js-link-board(type="button" value="{{_ 'link'}}") + + .link-board-dropdown + label {{_ 'swimlanes'}}: + select.js-select-swimlanes + option(value="") {{_ 'custom-field-dropdown-none'}} + each swimlanes + option(value="{{_id}}") {{isTitleDefault title}} + .link-board-dropdown + label {{_ 'lists'}}: + select.js-select-lists + option(value="") {{_ 'custom-field-dropdown-none'}} + each lists + option(value="{{_id}}") {{isTitleDefault title}} + + .link-board-dropdown + label {{_ 'cards'}}: + select.js-select-cards + option(value="") {{_ 'custom-field-dropdown-none'}} + each cards + option(value="{{getRealId}}") {{getTitle}} + + .edit-controls.clearfix + input.primary.confirm.js-done(type="button" value="{{_ 'link'}}") + +template(name="searchElementPopup") + .link-board-wrapper + form + label + | {{_ 'title'}} + input.js-element-title(type="text" placeholder="{{_ 'title'}}" autofocus required dir="auto") + unless isTemplateSearch + label {{_ 'boards'}}: + select.js-select-boards + option(value="") + each (boards) + option(value="{{_id}}") {{title}} + form.js-search-term-form + label + | {{_ 'template'}} + input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus dir="auto") + .list-body.search-card-results + .minicards.clearfix.js-minicards + if isBoardTemplateSearch + each (results) + a.minicard-wrapper.js-minicard + +miniboard(this) + if isListTemplateSearch + each (results) + a.minicard-wrapper.js-minicard + +minilist(this) + if isSwimlaneTemplateSearch + each (results) + a.minicard-wrapper.js-minicard + +miniswimlane(this) + if isCardTemplateSearch + each (results) + a.minicard-wrapper.js-minicard + +minicard(this) + unless isTemplateSearch + each (results) + a.minicard-wrapper.js-minicard + +minicard(this) diff --git a/client/components/lists/listBody.js b/client/components/lists/listBody.js index 3e2612424..12ebc8edb 100644 --- a/client/components/lists/listBody.js +++ b/client/components/lists/listBody.js @@ -3,16 +3,168 @@ import { TAPi18n } from '/imports/i18n'; import { FlowRouter } from 'meteor/ostrio:flow-router-extra'; import { Spinner } from '/client/lib/spinner'; import getSlug from 'limax'; +import { itemsSelector } from './list'; const subManager = new SubsManager(); const InfiniteScrollIter = 10; + +function sortableCards(boardComponent, $cards) { + return { + connectWith: '.js-minicards:not(.js-list-full)', + tolerance: 'pointer', + appendTo: '.board-canvas', + helper(evt, item) { + const helper = item.clone(); + const cardHeight = item.height(); + const cardWidth = item.width(); + helper[0].setAttribute('style', `height: ${cardHeight}px !important; width: ${cardWidth}px !important;`); + + if (MultiSelection.isActive()) { + const andNOthers = $cards.find('.js-minicard.is-checked').length - 1; + if (andNOthers > 0) { + helper.append( + $( + Blaze.toHTML( + HTML.DIV( + { class: 'and-n-other' }, + TAPi18n.__('and-n-other-card', { count: andNOthers }), + ), + ), + ), + ); + } + } + return helper; + }, + distance: 7, + items: itemsSelector, + placeholder: 'minicard-wrapper placeholder', + /* cursor must be tied to smaller objects, position approximately from the button + (can be computed if visually confusing) */ + cursorAt: { right: 20, top: 30 }, + start(evt, ui) { + const cardHeight = ui.helper.height(); + ui.placeholder[0].setAttribute('style', `height: ${cardHeight}px !important;`); + EscapeActions.executeUpTo('popup-close'); + boardComponent.setIsDragging(true); + }, + stop(evt, ui) { + // To attribute the new index number, we need to get the DOM element + // of the previous and the following card -- if any. + const prevCardDom = ui.item.prev('.js-minicard').get(0); + const nextCardDom = ui.item.next('.js-minicard').get(0); + const nCards = MultiSelection.isActive() ? MultiSelection.count() : 1; + const sortIndex = Utils.calculateIndex(prevCardDom, nextCardDom, nCards); + const listId = Blaze.getData(ui.item.parents('.list-body').get(0))._id; + const currentBoard = Utils.getCurrentBoard(); + const defaultSwimlaneId = currentBoard.getDefaultSwimline()._id; + let targetSwimlaneId = null; + + // only set a new swimelane ID if the swimlanes view is active + if ( + Utils.boardView() === 'board-view-swimlanes' || + currentBoard.isTemplatesBoard() + ) + targetSwimlaneId = Blaze.getData(ui.item.parents('.swimlane').get(0)) + ._id; + + // Normally the jquery-ui sortable library moves the dragged DOM element + // to its new position, which disrupts Blaze reactive updates mechanism + // (especially when we move the last card of a list, or when multiple + // users move some cards at the same time). To prevent these UX glitches + // we ask sortable to gracefully cancel the move, and to put back the + // DOM in its initial state. The card move is then handled reactively by + // Blaze with the below query. + $cards.sortable('cancel'); + + if (MultiSelection.isActive()) { + ReactiveCache.getCards(MultiSelection.getMongoSelector(), { sort: ['sort'] }).forEach((card, i) => { + const newSwimlaneId = targetSwimlaneId + ? targetSwimlaneId + : card.swimlaneId || defaultSwimlaneId; + card.move( + currentBoard._id, + newSwimlaneId, + listId, + sortIndex.base + i * sortIndex.increment, + ); + }); + } else { + const cardDomElement = ui.item.get(0); + const card = Blaze.getData(cardDomElement); + const newSwimlaneId = targetSwimlaneId + ? targetSwimlaneId + : card.swimlaneId || defaultSwimlaneId; + card.move(currentBoard._id, newSwimlaneId, listId, sortIndex.base); + } + boardComponent.setIsDragging(false); + }, + sort(event, ui) { + Utils.scrollIfNeeded(event); + }, + }; +}; + BlazeComponent.extendComponent({ onCreated() { // for infinite scrolling this.cardlimit = new ReactiveVar(InfiniteScrollIter); }, + onRendered() { + // Prefer handling drag/sort in listBody rather than list as + // it is shared between mobile and desktop view + const boardComponent = BlazeComponent.getComponentForElement(document.getElementsByClassName('board-canvas')[0]); + const $cards = this.$('.js-minicards'); + $cards.sortable(sortableCards(boardComponent, $cards)); + + this.autorun(() => { + if ($cards.data('uiSortable') || $cards.data('sortable')) { + // Use handle button on mobile, classic move otherwise + if (Utils.isMiniScreen()) { + $cards.sortable('option', 'handle', '.handle'); + } else { + $cards.sortable('option', 'handle', '.minicard'); + } + + $cards.sortable( + 'option', + 'disabled', + // Disable drag-dropping when user is not member + !Utils.canModifyBoard(), + // Not disable drag-dropping while in multi-selection mode + // MultiSelection.isActive() || !Utils.canModifyBoard(), + ); + } + }); + + // We want to re-run this function any time a card is added. + this.autorun(() => { + const currentBoardId = Tracker.nonreactive(() => { + return Session.get('currentBoard'); + }); + Tracker.afterFlush(() => { + $cards.find(itemsSelector).droppable({ + hoverClass: 'draggable-hover-card', + accept: '.js-member,.js-label', + drop(event, ui) { + const cardId = Blaze.getData(this)._id; + const card = ReactiveCache.getCard(cardId); + + if (ui.draggable.hasClass('js-member')) { + const memberId = Blaze.getData(ui.draggable.get(0)).userId; + card.assignMember(memberId); + } else { + const labelId = Blaze.getData(ui.draggable.get(0))._id; + card.addLabel(labelId); + } + }, + }); + }); + }); + }, + mixins() { return []; }, @@ -82,9 +234,10 @@ BlazeComponent.extendComponent({ evt.preventDefault(); const firstCardDom = this.find('.js-minicard:first'); const lastCardDom = this.find('.js-minicard:last'); - const textarea = $(evt.currentTarget).find('textarea'); + // more robust to start from the form + const textarea = $(evt.currentTarget).closest('.inlined-form').find('textarea'); const position = this.currentData().position; - const title = textarea.val().trim(); + const title = $(textarea).val().trim(); let sortIndex; if (position === 'top') { @@ -168,7 +321,6 @@ BlazeComponent.extendComponent({ // We keep the form opened, empty it, and scroll to it. textarea.val('').focus(); - autosize.update(textarea); if (position === 'bottom') { this.scrollToBottom(); } @@ -194,21 +346,19 @@ BlazeComponent.extendComponent({ clickOnMiniCard(evt) { if (MultiSelection.isActive() || evt.shiftKey) { - evt.stopImmediatePropagation(); - evt.preventDefault(); const methodName = evt.shiftKey ? 'toggleRange' : 'toggle'; MultiSelection[methodName](this.currentData()._id); - // If the card is already selected, we want to de-select it. // XXX We should probably modify the minicard href attribute instead of // overwriting the event in case the card is already selected. - } else if (Utils.isMiniScreen()) { - evt.preventDefault(); - Session.set('popupCardId', this.currentData()._id); - this.cardDetailsPopup(evt); } else if (Session.equals('currentCard', this.currentData()._id)) { - evt.stopImmediatePropagation(); - evt.preventDefault(); + // We need to wait a little because router gets called first, + // we probably need a level of indirection + // #FIXME remove if it works with commits we rebased on, + // which change the route declaration order + Meteor.setTimeout(() => { + Session.set('currentCard', null) + }, 50); Utils.goBoardId(Session.get('currentBoard')); } else { // Allow normal href navigation, but if it's the same card URL, @@ -283,12 +433,6 @@ BlazeComponent.extendComponent({ return user && user.isVerticalScrollbars(); }, - cardDetailsPopup(event) { - if (!Popup.isOpen()) { - Popup.open("cardDetails")(event); - } - }, - events() { return [ { @@ -296,6 +440,8 @@ BlazeComponent.extendComponent({ 'click .js-toggle-multi-selection': this.toggleMultiSelection, 'click .open-minicard-composer': this.scrollToBottom, submit: this.addCard, + // #FIXME remove in final MR if it works + 'click .confirm': this.addCard }, ]; }, @@ -401,6 +547,17 @@ BlazeComponent.extendComponent({ 'click .js-link': Popup.open('linkCard'), 'click .js-search': Popup.open('searchElement'), 'click .js-card-template': Popup.open('searchElement'), + submit: this.addCard, + 'click .minicard-label': (event) => { + const clickedData = BlazeComponent.getComponentForElement(event.target).currentData?.() + this.labels.set(this.labels.get().filter(e => e !== clickedData?._id)); + }, + 'click .member': (event) => { + const clickedData = BlazeComponent.getComponentForElement(event.target).currentData?.() + this.members.set(this.members.get().filter(e => e !== clickedData?.userId)); + e.preventDefault(); + e.stopPropagation(); + }, }, ]; }, @@ -409,8 +566,6 @@ BlazeComponent.extendComponent({ const editor = this; const $textarea = this.$('textarea'); - autosize($textarea); - $textarea.escapeableTextComplete( [ // User mentions @@ -421,7 +576,9 @@ BlazeComponent.extendComponent({ callback( $.map(currentBoard.activeMembers(), member => { const user = ReactiveCache.getUser(member.userId); - return user.username.indexOf(term) === 0 ? user : null; + return user.username.indexOf(term) === 0 && + // don't show already selected members + !editor.members.get().find((e) => e === member.userId) ? user : null; }), ); }, @@ -445,8 +602,12 @@ BlazeComponent.extendComponent({ const currentBoard = Utils.getCurrentBoard(); callback( $.map(currentBoard.labels, label => { - if (label.name == undefined) { - label.name = ""; + if ( + label.name == undefined || + // don't show already selected labels + editor.getLabels().find((e) => e._id === label._id) + ) { + return null; } if ( label.name.indexOf(term) > -1 || @@ -503,10 +664,10 @@ BlazeComponent.extendComponent({ subManager.subscribe('board', this.boardId, false); this.board = ReactiveCache.getBoard(this.boardId); // List where to insert card - this.list = $(Popup._getTopStack().openerElement).closest('.js-list'); + this.list = $(PopupComponent.stack[0].openerElement).closest('.js-list'); this.listId = Blaze.getData(this.list[0])._id; // Swimlane where to insert card - const swimlane = $(Popup._getTopStack().openerElement).closest( + const swimlane = $(PopupComponent.stack[0].openerElement).closest( '.js-swimlane', ); this.swimlaneId = ''; @@ -539,10 +700,10 @@ BlazeComponent.extendComponent({ if (!board) { return []; } - + // Ensure default swimlane exists board.getDefaultSwimline(); - + const swimlanes = ReactiveCache.getSwimlanes( { boardId: this.selectedBoardId.get() @@ -559,7 +720,8 @@ BlazeComponent.extendComponent({ } const lists = ReactiveCache.getLists( { - boardId: this.selectedBoardId.get() + boardId: this.selectedBoardId.get(), + swimlaneId: this.selectedSwimlaneId?.get?.() }, { sort: { sort: 1 }, @@ -703,16 +865,16 @@ BlazeComponent.extendComponent({ }, onCreated() { - this.isCardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass( + this.isCardTemplateSearch = $(PopupComponent.stack[0].openerElement).hasClass( 'js-card-template', ); - this.isListTemplateSearch = $(Popup._getTopStack().openerElement).hasClass( + this.isListTemplateSearch = $(PopupComponent.stack[0].openerElement).hasClass( 'js-list-template', ); this.isSwimlaneTemplateSearch = $( - Popup._getTopStack().openerElement, + PopupComponent.stack[0].openerElement, ).hasClass('js-open-add-swimlane-menu'); - this.isBoardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass( + this.isBoardTemplateSearch = $(PopupComponent.stack[0].openerElement).hasClass( 'js-add-board', ); this.isTemplateSearch = @@ -731,20 +893,16 @@ BlazeComponent.extendComponent({ } else { this.board = Utils.getCurrentBoard(); } - if (!this.board) { - Popup.back(); - return; - } - this.boardId = this.board._id; + this.boardId = this.board?._id; // Subscribe to this board subManager.subscribe('board', this.boardId, false); this.selectedBoardId = new ReactiveVar(this.boardId); - this.list = $(Popup._getTopStack().openerElement).closest('.js-list'); if (!this.isBoardTemplateSearch) { + this.list = $(PopupComponent.stack[0].openerElement).closest('.js-list'); this.swimlaneId = ''; // Swimlane where to insert card - const swimlane = $(Popup._getTopStack().openerElement).parents( + const swimlane = $(PopupComponent.stack[0].openerElement).parents( '.js-swimlane', ); if (Utils.boardView() === 'board-view-swimlanes') @@ -783,11 +941,7 @@ BlazeComponent.extendComponent({ } else if (this.isSwimlaneTemplateSearch) { return board.searchSwimlanes(this.term.get()); } else if (this.isBoardTemplateSearch) { - const boards = board.searchBoards(this.term.get()); - boards.forEach(board => { - subManager.subscribe('board', board.linkedId, false); - }); - return boards; + return board.searchBoards(this.term.get()); } else { return []; } diff --git a/client/components/lists/listHeader.jade b/client/components/lists/listHeader.jade index 2dee5749f..3f8dc5c86 100644 --- a/client/components/lists/listHeader.jade +++ b/client/components/lists/listHeader.jade @@ -9,66 +9,68 @@ template(name="listHeader") if currentList a.list-header-left-icon.js-unselect-list i.fa.fa-caret-left - else - if collapsed - if showCardsCountForList cards.length - br - span.cardCount {{cardsCount}} - if isMiniScreen - h2.list-header-name( - title="{{ moment modifiedAt 'LLL' }}" - class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}") - +viewer - = title - if wipLimit.enabled - | ( - span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}} - |/#{wipLimit.value}) - if showCardsCountForList cards.length - span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}} - if hasNumberFieldsSum - | - span.list-sum-badge(title="{{_ 'sum-of-number-fields'}}") ∑ {{numberFieldsSum}} - else - a.list-collapse-indicator.js-collapse(title="{{_ 'collapse'}}") - if collapsed + else + //- start by this on mobile to have cohesion with other views + a.list-header-menu-icon.js-select-list i.fa.fa-caret-right - else - i.fa.fa-caret-down - div(class="{{#if collapsed}}list-rotated{{/if}}") + .list-header-name-container h2.list-header-name( title="{{ moment modifiedAt 'LLL' }}" - class="{{#unless collapsed}}{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}{{/unless}}") + class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}") +viewer = title if wipLimit.enabled - | ( - span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}} - |/#{wipLimit.value}) + | ( + span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}} + |/#{wipLimit.value}) + if showCardsCountForList cards.length + span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}} + if hasNumberFieldsSum + | + span.list-sum-badge(title="{{_ 'sum-of-number-fields'}}") ∑ {{numberFieldsSum}} + else + div.list-header-name-container + unless isMiniScreen + a.list-collapse-indicator.js-collapse(title="{{_ 'collapse'}}") + if collapsed + i.fa.fa-caret-right + else + i.fa.fa-caret-down + div(class="{{#if collapsed}}list-rotated{{/if}}").list-header-wrap + h2.list-header-name( + title="{{ moment modifiedAt 'LLL' }}" + class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}{{#unless currentUser.isWorker}}js-open-inlined-form is-editable{{/unless}}{{/unless}}{{/if}}") + +viewer + = title + if wipLimit.enabled + | ( + span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}} + |/#{wipLimit.value}) unless collapsed if showCardsCountForList cards.length span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}} if hasNumberFieldsSum | span.list-sum-badge(title="{{_ 'sum-of-number-fields'}}") ∑ {{numberFieldsSum}} + div.list-header-menu + unless currentUser.isCommentOnly + unless currentUser.isReadOnly + unless currentUser.isReadAssignedOnly + a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") + i.fa.fa-bars if isMiniScreen if currentList if isWatching - i.list-header-watch-icon i.fa.fa-eye + i.list-header-watch-icon.i.fa.fa-eye div.list-header-menu unless currentUser.isCommentOnly unless currentUser.isReadOnly unless currentUser.isReadAssignedOnly - if canSeeAddCard - a.js-add-card.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}") - i.fa.fa-plus a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") i.fa.fa-bars else - a.list-header-menu-icon.js-select-list - i.fa.fa-caret-right unless currentUser.isWorker - if isTouchScreenOrShowDesktopDragHandles + if isMiniScreen a.list-header-handle.handle.js-list-handle i.fa.fa-arrows else if currentUser.isBoardMember @@ -77,24 +79,13 @@ template(name="listHeader") unless currentUser.isCommentOnly unless currentUser.isReadOnly unless currentUser.isReadAssignedOnly - if isTouchScreenOrShowDesktopDragHandles + if isMiniScreen a.list-header-handle-desktop.handle.js-list-handle(title="{{_ 'drag-list'}}") i.fa.fa-arrows - unless collapsed - div.list-header-menu - unless currentUser.isCommentOnly - unless currentUser.isReadOnly - unless currentUser.isReadAssignedOnly - //if isBoardAdmin - // a.fa.js-list-star.list-header-plus-top(class="fa-star{{#unless starred}}-o{{/unless}}") - if isTouchScreenOrShowDesktopDragHandles - a.list-header-handle-desktop.handle.js-list-handle(title="{{_ 'drag-list'}}") - i.fa.fa-arrows - if canSeeAddCard - a.js-add-card.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}") - i.fa.fa-plus - a.js-open-list-menu(title="{{_ 'listActionPopup-title'}}") - i.fa.fa-bars + unless isMiniScreen + if collapsed + if showCardsCountForList cards.length + span.cardCount {{cardsCount}} template(name="editListTitleForm") .list-composer @@ -224,14 +215,14 @@ template(name="wipLimitErrorPopup") .wip-limit-invalid p {{_ 'wipLimitErrorPopup-dialog-pt1'}} p {{_ 'wipLimitErrorPopup-dialog-pt2'}} - button.full.js-back-view(type="submit") {{_ 'cancel'}} + button.negate.js-back-view(type="submit") {{_ 'cancel'}} template(name="setListWidthPopup") #js-list-width-edit label {{_ 'set-list-width-value'}} p - input.list-width-value(type="number" value="{{ listWidthValue }}" min="270") - input.list-constraint-value(type="number" value="{{ listConstraintValue }}" min="270") + input.list-width-value(type="number" value="{{ listWidthValue }}" min="100") + input.list-constraint-value(type="number" value="{{ listConstraintValue }}" min="100") input.list-width-apply(type="submit" value="{{_ 'apply'}}") input.list-width-error br @@ -242,8 +233,8 @@ template(name="setListWidthPopup") template(name="listWidthErrorPopup") .list-width-invalid - p {{_ 'list-width-error-message'}} '>=270' - button.full.js-back-view(type="submit") {{_ 'cancel'}} + p {{_ 'list-width-error-message'}} '>=100' + button.negate.js-back-view(type="submit") {{_ 'cancel'}} template(name="setListColorPopup") form.edit-label diff --git a/client/components/lists/listHeader.js b/client/components/lists/listHeader.js index 90e5a0b3f..f3319b1e9 100644 --- a/client/components/lists/listHeader.js +++ b/client/components/lists/listHeader.js @@ -9,6 +9,15 @@ Meteor.startup(() => { }); BlazeComponent.extendComponent({ + onRendered() { + /* #FIXME I have no idea why this exact same + event won't fire when in event maps */ + $(this.find('.js-collapse')).on('click', (e) => { + e.preventDefault(); + this.collapsed(!this.collapsed()); + }); + }, + canSeeAddCard() { const list = Template.currentData(); return ( @@ -34,7 +43,7 @@ BlazeComponent.extendComponent({ } }, collapsed(check = undefined) { - const list = Template.currentData(); + const list = this.data(); const status = Utils.getListCollapseState(list); if (check === undefined) { // just check @@ -110,7 +119,11 @@ BlazeComponent.extendComponent({ return TAPi18n.__('cards-count'); } }, - + currentList() { + const currentList = Utils.getCurrentList(); + const list = Template.currentData(); + return currentList && currentList._id == list._id; + }, events() { return [ { @@ -118,10 +131,6 @@ BlazeComponent.extendComponent({ event.preventDefault(); this.starred(!this.starred()); }, - 'click .js-collapse'(event) { - event.preventDefault(); - this.collapsed(!this.collapsed()); - }, 'click .js-open-list-menu': Popup.open('listAction'), 'click .js-add-card.list-header-plus-top'(event) { const listDom = $(event.target).parents( @@ -459,10 +468,10 @@ BlazeComponent.extendComponent({ this.currentBoard = Utils.getCurrentBoard(); this.currentSwimlaneId = new ReactiveVar(null); this.currentListId = new ReactiveVar(null); - + // Get the swimlane context from opener const openerData = Popup.getOpenerComponent()?.data(); - + // If opened from swimlane menu, openerData is the swimlane if (openerData?.type === 'swimlane' || openerData?.type === 'template-swimlane') { this.currentSwimlane = openerData; @@ -554,4 +563,3 @@ BlazeComponent.extendComponent({ ]; }, }).register('addListPopup'); - diff --git a/client/components/main/accessibility.css b/client/components/main/accessibility.css index aa6244a58..dfedd0650 100644 --- a/client/components/main/accessibility.css +++ b/client/components/main/accessibility.css @@ -1,6 +1,6 @@ .my-cards-board-wrapper { border-radius: 0 0 0.5vw 0.5vw; - min-width: min(400px, 52vw); + min-width: min(100%, 400px, 52vw); margin-bottom: 2.5vh; margin-right: auto; margin-left: auto; @@ -33,13 +33,6 @@ text-align: center; margin-bottom: 0.9vh; } -.my-cards-list-wrapper { - margin: 1.3vh 1.3vw; - border-radius: 0.7vw; - display: inline-grid; - min-width: min(250px, 32vw); - max-width: min(350px, 45vw); -} .my-cards-card-wrapper { margin-top: 0; margin-bottom: 1.3vh; @@ -81,7 +74,7 @@ } .accessibility-page h2 { - font-size: 24px; + margin-bottom: 20px; color: #4d4d4d; } diff --git a/client/components/main/editor.css b/client/components/main/editor.css index ac832de59..c9604cece 100644 --- a/client/components/main/editor.css +++ b/client/components/main/editor.css @@ -1,19 +1,18 @@ -.new-comment a.fa.fa-brands.fa-markdown, -.inlined-form a.fa.fa-brands.fa-markdown { - float: right; - position: absolute; - top: -10px; - right: 60px; +.new-comment, .inlined-form { + a.fa.fa-brands.fa-markdown, a.fa.fa-copy { + display: flex; + justify-content: end; + } } -.new-comment a.fa.fa-copy, -.inlined-form a.fa.fa-copy { - float: right; - position: relative; - top: -10px; - right: 5px; -} -.js-inlined-form.viewer.btn-sm { - position: absolute; - top: 20px; - right: 6px; +.editor-controls { + display: flex; + justify-content: end; + grid-area: editor-controls; + align-items: center; + align-self: start; + gap: 1ch; } + +.editor { + grid-area: editor; +} \ No newline at end of file diff --git a/client/components/main/editor.jade b/client/components/main/editor.jade index 4d7117ca3..d45ee2fb4 100644 --- a/client/components/main/editor.jade +++ b/client/components/main/editor.jade @@ -1,12 +1,12 @@ template(name="editor") - a.fa.fa-brands.fa-markdown(title="{{_ 'convert-to-markdown'}}") - a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}") - span.copied-tooltip {{_ 'copied'}} + .editor-controls + a.fa.fa-brands.fa-markdown(title="{{_ 'convert-to-markdown'}}") + a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}") + span.copied-tooltip.copied-tooltip-hidden {{_ 'copied'}} textarea.editor( dir="auto" class="{{class}}" id=id - autofocus=autofocus placeholder="{{_ 'comment-placeholder'}}") +Template.contentBlock diff --git a/client/components/main/editor.js b/client/components/main/editor.js index 8b2c03a03..e27f9bc9f 100644 --- a/client/components/main/editor.js +++ b/client/components/main/editor.js @@ -90,7 +90,6 @@ BlazeComponent.extendComponent({ const enableTextarea = function() { const $textarea = this.$(textareaSelector); - autosize($textarea); $textarea.escapeableTextComplete(mentions); }; if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR === true || Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR === 'true') { diff --git a/client/components/main/globalSearch.css b/client/components/main/globalSearch.css index c5a09060f..c07497dd2 100644 --- a/client/components/main/globalSearch.css +++ b/client/components/main/globalSearch.css @@ -1,6 +1,6 @@ .global-search-board-wrapper { - border-radius: 8px; - min-width: 400px; + border-radius: 0.8ch; + min-width: min(100%, 400px); border-width: 8px; border-color: #808080; border-style: solid; @@ -67,8 +67,6 @@ color: #8b0000; } .global-search-page { - width: 40%; - min-width: 400px; margin-right: auto; margin-left: auto; line-height: 150%; @@ -91,6 +89,13 @@ font-family: Courier; font-style: italic; } + +.lists-wrapper { + display: flex; + flex-wrap: wrap; + gap: 1ch 0.3lh; + +} code { color: #000; background-color: #d3d3d3; diff --git a/client/components/main/header.css b/client/components/main/header.css index 450a72aeb..cff98a907 100644 --- a/client/components/main/header.css +++ b/client/components/main/header.css @@ -1,21 +1,19 @@ #header { + display: flex; + justify-content: stretch; + align-items: center; color: #fff; transition: background-color 0.4s; background: #2980b9; - z-index: 17; } #header #header-main-bar { - height: 40px; - padding: 7px 10px 0; + padding: 0.3lh 0.5ch; + display: flex; + flex: 1; } #header #header-main-bar h1 { - font-size: 20px; - line-height: 1.7em; - padding: 0 10px; margin: 0; - margin-right: 10px; - float: left; - border-radius: 3px; + line-height: unset; } #header #header-main-bar h1 .board-header-watch-icon { padding-left: 7px; @@ -25,7 +23,6 @@ color: #fff; } #header #header-main-bar h1 .back-btn { - font-size: 0.9em; margin-right: 10px; } #header #header-main-bar .wekan-logo { @@ -38,27 +35,14 @@ #header #header-main-bar .wekan-logo:hover { opacity: 0.9; } -#header #header-main-bar .board-header-btns { - display: block; - margin-top: 3px; - width: auto; -} -#header #header-main-bar .board-header-btns.left { - float: left; -} -#header #header-main-bar .board-header-btns.right { - float: right; -} #header #header-main-bar .board-header-btn { - border-radius: 3px; color: #f2f2f2; - padding: 0; - height: 28px; - font-size: 13px; - float: left; + display: flex; + flex-wrap: wrap; + column-gap: 0.5ch; + justify-content: center; overflow: hidden; - line-height: 28px; - margin: 0 12px; + text-align: center; } #header #header-main-bar .board-header-btn i.fa { float: left; @@ -68,8 +52,8 @@ margin: 0 10px; } #header #header-main-bar .board-header-btn i.fa + span { - display: inline-block; - margin-top: 1px; + display: flex; + align-items: center; margin-right: 10px; } #header #header-main-bar .board-header-btn .board-header-btn-close { @@ -99,55 +83,140 @@ background: #0f3a5f; } #header #header-main-bar .separator { - margin: 2px 4px; - border-left: 1px solid rgba(255,255,255,0.3); - height: 24px; - float: left; + border-left: 0.2ch solid rgba(255,255,255,0.3); + display: flex; + align-self: stretch; + flex: 0; } + +/* those are default values, some overriden from mobile below */ #header-quick-access { color: #fff; transition: background-color 0.4s; background: #2573a7; - height: 28px; - font-size: 12px; - display: flex; - z-index: 1000; - padding: 10px 0px; - align-items: center; - flex-wrap: nowrap; /* Prevent wrapping to keep single row */ - min-height: 28px; - overflow: hidden; /* Prevent content from overflowing */ + padding: clamp(2vh, 0.5lh, 2%) 0.8rlh; + font-size: var(--quick-header-scale); + + /* the grid template is different for mobile */ + display: grid; + grid-template-areas: + "logo left right"; + grid-template-columns: 1fr 10fr auto; + justify-content: space-between; + + gap: 2ch; + + + #header-quick-access-left { + display: flex; + flex: 0; + overflow-x: auto; + align-items: center; + justify-content: start; + gap: 10ch; + } + .header-quick-access-list { + display: flex; + padding: 0 1ch; + gap: 2ch; + /* this makes sure the scrollbar is at the bottom of header, + not right below text */ + align-self: stretch; + align-items: center; + + scrollbar-width: thin; + scrollbar-color: rgba(255, 255, 255, 0.3) transparent; + justify-content: start; + transition: opacity 0.2s; + overflow-x: auto; + overflow-y: hidden; + } + + .logo-container { + grid-area: logo; + display: flex; + /* that is, related to the whole grid, not taking account other column's width */ + align-self: stretch; + /* elegant solution to force the row to force the image + to adopt the height of other columns */ + min-height: 100%; + height: 0; + a, img { + display: flex; + align-self: stretch; + width: auto; + } + } + #header-quick-access-right { + grid-area: right; + display: flex; + justify-content: end; + } + + #header-quick-access-icons { + display: flex; + justify-content: start; + align-items: center; + gap: 1ch; + } + + #header-quick-access-left { + grid-area: left; + display: grid; + text-decoration: none; + color: #fff; + border-radius: 0.4ch; + transition: background-color 0.2s ease; + gap: 2ch; + grid-auto-flow: column; + + } +} + +body.mobile-mode { + #header-quick-access { + row-gap: 0.5lh; + grid-template-areas: + "logo icons" + "board board"; + grid-template-columns: 1fr 1fr; + justify-content: center; + align-items: center; + + #header-quick-access-left { + grid-area: board; + justify-self: center; + } + + #header-quick-access-right { + grid-area: icons; + } + } + + .separator { + display: none !important; + } + + .logo-container { + img { + max-height: max(1lh, 5vmax, 3ch); + } + } +} + +#header-quick-access.mobile-view .header-quick-access-list { + display: none; } #header-quick-access .home-icon { display: flex; - align-items: center; - margin-right: 1rem; + /* prevents wrap */ 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; -} #header-quick-access a { text-decoration: none; } @@ -179,8 +248,6 @@ transition: opacity 0.2s; overflow: hidden; white-space: nowrap; - padding: 10px; - margin: -10px; flex: 1; /* Take up available space */ min-width: 0; /* Allow shrinking below content size */ display: flex; /* Use flexbox for better control */ @@ -200,15 +267,9 @@ display: inline-block; /* Keep inline-block for proper spacing */ width: auto; color: #d9d9d9; - padding: 12px 0px; - margin: -10px 0px; flex-shrink: 0; /* Prevent items from shrinking */ white-space: nowrap; /* Prevent text wrapping within items */ } -#header-quick-access ul.header-quick-access-list li a { - padding: 12px 10px; - margin: -10px 0px; -} #header-quick-access ul.header-quick-access-list li a .viewer { display: inline; white-space: nowrap; @@ -241,225 +302,20 @@ #header-quick-access #header-new-board-icon { flex-shrink: 0; } -#header-quick-access #header-user-bar { - margin: 2px 0; -} -#header-quick-access #header-user-bar .header-user-bar-avatar { - float: left; - position: relative; - top: -5px; - margin-right: 5px; -} -#header-quick-access #header-user-bar .header-user-bar-avatar .member, -#header-quick-access #header-help { - width: 24px; - height: 24px; - margin: 0; - margin-top: 1px; -} #header-quick-access #header-user-bar .header-user-bar-name, #header-quick-access #header-help { - 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; + gap: 0.2lh; } -#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 { + font-size: var(--header-scale); + padding: 0.2lh 1ch; } -#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); - box-sizing: border-box; - -webkit-appearance: none; - appearance: none; - flex: 0 0 auto; - } - - /* Make zoom input wider on all mobile screens */ - @media screen and (max-width: 800px), - screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - #header-quick-access .zoom-controls .zoom-input { - min-width: 80px !important; /* Wider on mobile to show 3 digits */ - width: 80px !important; /* Fixed width to show 100 fully */ - font-size: 16px !important; /* Slightly larger text */ - flex: 0 0 80px !important; /* Prevent shrinking in flex */ - } - } - -#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; } @@ -468,697 +324,7 @@ margin: 6px 5px 0; width: 12px; } -@media screen and (max-width: 800px), - screen and (max-device-width: 932px) and (-webkit-min-device-pixel-ratio: 3) { - #header #header-main-bar { - height: 40px; - } - #header #header-main-bar .board-header-btns { - margin-top: 0px; - } - #header #header-main-bar .board-header-btn { - height: 32px; - line-height: 32px; - font-size: 15px; - } - #header #header-main-bar .board-header-btn i.fa { - line-height: 32px; - } - #header #header-main-bar .board-header-btn i.fa + span { - display: none; - } - #header-quick-access { - transition: background-color 0.4s; - width: 100%; - z-index: 30; - flex-wrap: nowrap !important; /* Force single row on mobile */ - overflow: hidden; /* Prevent content overflow */ - } - /* 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: 48px !important; /* Fixed height for mobile */ - min-height: 48px !important; /* Minimum height for mobile */ - flex-wrap: nowrap !important; /* Force single row */ - align-items: center !important; /* Center align items */ - padding: 8px 0px !important; /* Adjust padding for mobile */ - overflow: hidden !important; /* Prevent content overflow */ - } - #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: 80px !important; /* Wider to fit 100 */ - width: 80px !important; /* Fixed width to show 100 fully */ - flex: 0 0 80px !important; /* Prevent shrinking in flex */ - } - - /* 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; - } - #header-quick-access ul li { - height: 100%; - } - #header-quick-access ul li a { - height: 100%; - } - #header-quick-access #header-new-board-icon { - display: none; - } - #header-quick-access #header-user-bar { - right: 0px; - padding: 10px; - margin: -8px 0 -10px -10px; - } -} @media print { #header-quick-access .allBoards, #header-quick-access ul, @@ -1190,5 +356,8 @@ padding: 0; } #headerIsSettingDatabaseCallDone { - display: none; + display: flex; + visibility: hidden; + flex: 1; + align-items: center; } diff --git a/client/components/main/header.jade b/client/components/main/header.jade index 7f62889fb..32c3f0b27 100644 --- a/client/components/main/header.jade +++ b/client/components/main/header.jade @@ -5,100 +5,81 @@ template(name="header") Reddit "subreddit" bar. The first link goes to the boards page. if currentUser - #header-quick-access(class=currentBoard.colorClass) + #header-quick-access(class="currentBoard.colorClass {{#if isMiniScreen}}mobile-view{{/if}}") // Home icon - always at left side of logo - span.home-icon.allBoards - a(href="{{pathFor 'home'}}") - i.fa.fa-home - | {{_ 'all-boards'}} + #header-quick-access-left + span.home-icon.allBoards + a(href="{{pathFor 'home'}}") + span.emoji-icon + i.fa.fa-home + span + | {{_ 'all-boards'}} - // Logo - visible; on mobile constrained by CSS - 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;") - - // Drag handles toggle - between zoom and mobile mode toggle - a.board-header-btn.js-toggle-desktop-drag-handles(title="{{_ 'show-desktop-drag-handles'}}") - i.fa.fa-arrows - if isShowDesktopDragHandles - i.fa.fa-check - unless isShowDesktopDragHandles - i.fa.fa-ban - - if isMiniScreen - ul.header-quick-access-list - if currentList - each currentBoard.lists - li(class="{{#if $.Session.equals 'currentList' _id}}current{{/if}}") - a.js-select-list - +viewer - = title - else + if isMiniScreen + ul.header-quick-access-list + if currentList + each currentBoard.lists + li(class="{{#if $.Session.equals 'currentList' _id}}current{{/if}}") + a.js-select-list. + +viewer + = title + else + each currentUser.starredBoards + li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}") + a(href="{{pathFor 'board' id=_id slug=slug}}") + +viewer + = title + else + ul.header-quick-access-list + //li + // a(href="{{pathFor 'public'}}") + // span.fa.fa-globe + // | {{_ 'public'}} each currentUser.starredBoards li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}") a(href="{{pathFor 'board' id=_id slug=slug}}") +viewer = title + else + li.current.empty(title="{{_ 'quick-access-description'}}") + | {{_ 'quick-access-description'}} + #header-new-board-icon + // Next line is used only for spacing at header, + // there is no visible clickable icon. #header-new-board-icon - else - ul.header-quick-access-list - //li - // a(href="{{pathFor 'public'}}") - // span.fa.fa-globe - // | {{_ 'public'}} - each currentUser.starredBoards - li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}") - a(href="{{pathFor 'board' id=_id slug=slug}}") - +viewer - = title + // Hide duplicate create board button, + // because it did not show board templates correctly. + //a#header-new-board-icon.js-create-board + // i.fa.fa-plus(title="Create a new board") + // Logo - visible; on mobile constrained by CSS + unless currentSetting.hideLogo + .logo-container + if currentSetting.customTopLeftCornerLogoImageUrl + if currentSetting.customTopLeftCornerLogoLinkUrl + a.logo(href="{{currentSetting.customTopLeftCornerLogoLinkUrl}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") + +logo + else + +logo else - li.current.empty(title="{{_ 'quick-access-description'}}") - | {{_ 'quick-access-description'}} - #header-new-board-icon - // Next line is used only for spacing at header, - // there is no visible clickable icon. - #header-new-board-icon - // Hide duplicate create board button, - // because it did not show board templates correctly. - //a#header-new-board-icon.js-create-board - // i.fa.fa-plus(title="Create a new board") + div#headerIsSettingDatabaseCallDone.logo + img(src="{{pathFor '/logo-header.png'}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") - .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.mobile-icon(class="{{#if mobileMode}}active{{/if}}") - i.fa.fa-mobile - i.desktop-icon(class="{{#unless mobileMode}}active{{/unless}}") - i.fa.fa-desktop - - // Notifications - +notifications - - if currentSetting.customHelpLinkUrl - #header-help - a(href="{{currentSetting.customHelpLinkUrl}}", title="{{_ 'help'}}", target="_blank", rel="noopener noreferrer") - i.fa.fa-question-circle - - +headerUserBar + #header-quick-access-right + if currentSetting.customHelpLinkUrl + #header-help + a(href="{{currentSetting.customHelpLinkUrl}}", title="{{_ 'help'}}", target="_blank", rel="noopener noreferrer") + i.fa.fa-question-circle + #header-quick-access-icons + +headerUserBar + // Notifications + +notifications #header(class=currentBoard.colorClass) //- The main bar is a colorful bar that provide all the meta-data for the current page. This bar is contextual based. If the user is not connected we display "sign in" and "log in" buttons. - #header-main-bar(class="{{#if wrappedHeader}}wrapper{{/if}}") + #header-main-bar(class="{{#if isMiniScreen}}mobile-view{{/if}} {{#if wrappedHeader}}wrapper{{/if}}") +Template.dynamic(template=headerBar) if appIsOffline @@ -122,3 +103,7 @@ template(name="offlineWarning") | {{_ 'app-is-offline'}} a.app-try-reconnect {{_ 'app-try-reconnect'}} + +//- a little helper to avoid duplication +template(name="logo") + img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" style="{{#if currentSetting.customTopLeftCornerLogoHeight}}min-height: #{currentSetting.customTopLeftCornerLogoHeight};{{/if}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}") \ No newline at end of file diff --git a/client/components/main/header.js b/client/components/main/header.js index a0c451f4b..0b551f1fe 100644 --- a/client/components/main/header.js +++ b/client/components/main/header.js @@ -22,13 +22,13 @@ Template.header.onCreated(function () { ) document.getElementById( 'headerIsSettingDatabaseCallDone', - ).style.display = 'none'; + ).style.visibility = 'hidden'; else if ( document.getElementById('headerIsSettingDatabaseCallDone') != null ) document.getElementById( 'headerIsSettingDatabaseCallDone', - ).style.display = 'block'; + ).style.visibility = 'visible'; return this.stop(); }, }); @@ -57,14 +57,6 @@ Template.header.helpers({ 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) { @@ -76,51 +68,6 @@ Template.header.helpers({ 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-open-bookmarks'(evt) { // Already added but ensure single definition -- safe guard }, diff --git a/client/components/main/keyboardShortcuts.css b/client/components/main/keyboardShortcuts.css index 3391dcfc1..359cbf04b 100644 --- a/client/components/main/keyboardShortcuts.css +++ b/client/components/main/keyboardShortcuts.css @@ -12,7 +12,7 @@ .shortcuts-list .shortcuts-list-item .shortcuts-list-item-keys kbd { padding: 5px 8px; margin: 5px; - font-size: 18px; + } .shortcuts-list .shortcuts-list-item .shortcuts-list-item-action { font-size: 1.4em; diff --git a/client/components/main/layouts.css b/client/components/main/layouts.css index e646e1b78..7ea06d886 100644 --- a/client/components/main/layouts.css +++ b/client/components/main/layouts.css @@ -1,7 +1,33 @@ -* { - -webkit-box-sizing: unset; - box-sizing: unset; +/* Global variables that we can use to easily test and change layout +Later it could be useful to use a CSS superset */ +/* this makes the property computable */ +@property --popup-margin { + syntax: "