mirror of
https://github.com/wekan/wekan.git
synced 2026-11-05 09:40:20 -05:00
Match card chrome to title color
This commit is contained in:
1 parent
a8369e5cd0
commit
ebb35af50d
4 files changed
+135
-14
No files matched your search
@@ -263,6 +263,28 @@ body.desktop-mode .card-details.card-details-collapsed {
|
||||
display: flow-root;
|
||||
min-height: 44px;
|
||||
}
|
||||
/* Every piece of window chrome beside the title uses the title's computed
|
||||
contrast colour. This outranks the global `a i.fa` grey icon rule without
|
||||
duplicating the card palette, and therefore also follows custom hex colours.
|
||||
Hover/focus/active deliberately keep the same colour: the control may not
|
||||
become grey merely because it is being used. */
|
||||
.card-details .card-details-header .card-header-control,
|
||||
.card-details .card-details-header .card-header-control .fa,
|
||||
.card-details .card-details-header .card-header-control:hover,
|
||||
.card-details .card-details-header .card-header-control:hover .fa,
|
||||
.card-details .card-details-header .card-header-control:focus,
|
||||
.card-details .card-details-header .card-header-control:focus .fa,
|
||||
.card-details .card-details-header .card-header-control:active,
|
||||
.card-details .card-details-header .card-header-control:active .fa {
|
||||
color: inherit;
|
||||
}
|
||||
.card-details .card-details-header .card-details-title,
|
||||
.card-details .card-details-header .card-details-title .viewer,
|
||||
.card-details .card-details-header .card-details-title .viewer p,
|
||||
.card-details .card-details-header .card-details-title .viewer a,
|
||||
.card-details .card-details-header .card-details-title .viewer a:hover {
|
||||
color: inherit;
|
||||
}
|
||||
.card-details .card-details-header .card-number {
|
||||
color: #b3b3b3;
|
||||
display: inline-block;
|
||||
@@ -278,7 +300,7 @@ body.desktop-mode .card-details.card-details-collapsed {
|
||||
margin-inline-end: 5px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
color: #000;
|
||||
color: inherit;
|
||||
vertical-align: middle;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
@@ -28,18 +28,18 @@ template(name="cardDetails")
|
||||
+editCardTitleForm
|
||||
else
|
||||
unless isMiniScreen
|
||||
a.card-collapse-toggle.js-card-collapse-toggle(title="{{_ 'collapse-card'}}")
|
||||
a.card-header-control.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'}}")
|
||||
a.card-header-control.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'}}")
|
||||
a.card-header-control.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'}}")
|
||||
a.card-header-control.fa.fa-window-maximize.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}")
|
||||
a.card-header-control.card-details-menu.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
|
||||
i.fa.fa-bars
|
||||
//- The handle appears only when drag handles are ON, like the
|
||||
minicard's. With them off the window is dragged by its own title bar
|
||||
@@ -49,25 +49,25 @@ template(name="cardDetails")
|
||||
client/components/cards/minicard.jade
|
||||
if canModifyCard
|
||||
if isTouchScreenOrShowDesktopDragHandles
|
||||
span.card-drag-handle.js-card-drag-handle(title="Drag card")
|
||||
span.card-header-control.card-drag-handle.js-card-drag-handle(title="Drag card")
|
||||
i.fa.fa-arrows
|
||||
else
|
||||
a.close-card-details.js-close-card-details(title="{{_ 'close-card'}}")
|
||||
a.card-header-control.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'}}")
|
||||
a.card-header-control.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'}}")
|
||||
a.card-header-control.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'}}")
|
||||
a.card-header-control.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'}}")
|
||||
a.card-header-control.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'}}")
|
||||
a.card-header-control.fa.fa-window-maximize.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}")
|
||||
a.card-header-control.card-details-menu-mobile-web.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
|
||||
i.fa.fa-bars
|
||||
if canModifyCard
|
||||
if currentBoard.allowsDueComplete
|
||||
|
||||
@@ -72,6 +72,29 @@
|
||||
font-size: 0.875rem;
|
||||
padding-inline-start: 10px;
|
||||
}
|
||||
/* The minicard title and its chrome use the card's one computed text colour.
|
||||
The global Font Awesome rules otherwise turn the menu and handle grey even
|
||||
when the card palette says black or white. */
|
||||
.minicard .minicard-title,
|
||||
.minicard .minicard-details-menu,
|
||||
.minicard .minicard-details-menu-with-handle,
|
||||
.minicard .minicard-details-menu .fa,
|
||||
.minicard .minicard-details-menu-with-handle .fa,
|
||||
.minicard .handle,
|
||||
.minicard .handle .fa,
|
||||
.minicard .handle .drag-handle,
|
||||
.minicard .minicard-details-menu:hover .fa,
|
||||
.minicard .minicard-details-menu-with-handle:hover .fa,
|
||||
.minicard .handle:hover .fa,
|
||||
.minicard .handle:hover .drag-handle {
|
||||
color: inherit;
|
||||
}
|
||||
.minicard .minicard-title .viewer,
|
||||
.minicard .minicard-title .viewer p,
|
||||
.minicard .minicard-title .viewer a,
|
||||
.minicard .minicard-title .viewer a:hover {
|
||||
color: inherit;
|
||||
}
|
||||
@media print {
|
||||
.minicard-details-menu,
|
||||
.minicard-details-menu-with-handle {
|
||||
@@ -603,6 +626,10 @@
|
||||
}
|
||||
}
|
||||
/* https://github.com/wekan/wekan/issues/4254#issuecomment-1037192960 */
|
||||
.minicard-white {
|
||||
background-color: #fff !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.minicard-green {
|
||||
background-color: #3cb500 !important;
|
||||
color: #fff !important;
|
||||
@@ -617,6 +644,7 @@
|
||||
}
|
||||
.minicard-yellow {
|
||||
background-color: #fad900 !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.minicard-yellow:hover:not(.minicard-composer),
|
||||
.is-selected .minicard-yellow,
|
||||
@@ -628,6 +656,7 @@
|
||||
}
|
||||
.minicard-orange {
|
||||
background-color: #ff9f19 !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.minicard-orange:hover:not(.minicard-composer),
|
||||
.is-selected .minicard-orange,
|
||||
@@ -675,6 +704,7 @@
|
||||
}
|
||||
.minicard-pink {
|
||||
background-color: #ff78cb !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.minicard-pink:hover:not(.minicard-composer),
|
||||
.is-selected .minicard-pink,
|
||||
@@ -710,6 +740,7 @@
|
||||
}
|
||||
.minicard-lime {
|
||||
background-color: #51e898 !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.minicard-lime:hover:not(.minicard-composer),
|
||||
.is-selected .minicard-lime,
|
||||
@@ -721,6 +752,7 @@
|
||||
}
|
||||
.minicard-silver {
|
||||
background-color: #c0c0c0 !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.minicard-silver:hover:not(.minicard-composer),
|
||||
.is-selected .minicard-silver,
|
||||
@@ -732,6 +764,7 @@
|
||||
}
|
||||
.minicard-peachpuff {
|
||||
background-color: #ffdab9 !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.minicard-peachpuff:hover:not(.minicard-composer),
|
||||
.is-selected .minicard-peachpuff,
|
||||
@@ -755,6 +788,7 @@
|
||||
}
|
||||
.minicard-plum {
|
||||
background-color: #dda0dd !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.minicard-plum:hover:not(.minicard-composer),
|
||||
.is-selected .minicard-plum,
|
||||
@@ -802,6 +836,7 @@
|
||||
}
|
||||
.minicard-gold {
|
||||
background-color: #ffd700 !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.minicard-gold:hover:not(.minicard-composer),
|
||||
.is-selected .minicard-gold,
|
||||
@@ -849,6 +884,7 @@
|
||||
}
|
||||
.minicard-paleturquoise {
|
||||
background-color: #afeeee !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.minicard-paleturquoise:hover:not(.minicard-composer),
|
||||
.is-selected .minicard-paleturquoise,
|
||||
@@ -860,6 +896,7 @@
|
||||
}
|
||||
.minicard-mistyrose {
|
||||
background-color: #ffe4e1 !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.minicard-mistyrose:hover:not(.minicard-composer),
|
||||
.is-selected .minicard-mistyrose,
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const root = path.resolve(__dirname, '..');
|
||||
const read = relative => fs.readFileSync(path.join(root, relative), 'utf8');
|
||||
const detailsCss = read('client/components/cards/cardDetails.css');
|
||||
const detailsJade = read('client/components/cards/cardDetails.jade');
|
||||
const minicardCss = read('client/components/cards/minicard.css');
|
||||
|
||||
const chrome = [
|
||||
'card-collapse-toggle',
|
||||
'close-card-details',
|
||||
'minimize-card-details',
|
||||
'maximize-card-details',
|
||||
'card-details-menu',
|
||||
'card-drag-handle',
|
||||
'card-zoom-out',
|
||||
'card-zoom-in',
|
||||
'card-mobile-desktop-toggle',
|
||||
'card-details-menu-mobile-web',
|
||||
];
|
||||
for (const name of chrome) {
|
||||
assert.match(detailsJade, new RegExp(`card-header-control[^\\n]*${name}|${name}[^\\n]*card-header-control`),
|
||||
`${name} is part of the title-coloured header chrome`);
|
||||
}
|
||||
|
||||
const controlRule = detailsCss.slice(
|
||||
detailsCss.indexOf('.card-details .card-details-header .card-header-control,'),
|
||||
detailsCss.indexOf('}', detailsCss.indexOf('.card-details .card-details-header .card-header-control,')) + 1,
|
||||
);
|
||||
assert.match(controlRule, /card-header-control:hover \.fa/);
|
||||
assert.match(controlRule, /card-header-control:focus \.fa/);
|
||||
assert.match(controlRule, /card-header-control:active \.fa/);
|
||||
assert.match(controlRule, /color:\s*inherit;/);
|
||||
assert.doesNotMatch(controlRule, /color:\s*#[0-9a-f]{3,8}/i,
|
||||
'card header controls never hard-code black, white or grey');
|
||||
assert.match(detailsCss, /\.card-details-title \.viewer a:hover \{\s*color:\s*inherit;/,
|
||||
'formatted title content cannot override the header contrast colour');
|
||||
|
||||
assert.match(minicardCss, /\.minicard \.minicard-title,[\s\S]{0,700}\.minicard \.handle:hover \.drag-handle \{\s*color:\s*inherit;/,
|
||||
'minicard title, menu and handle share the card text colour in every state');
|
||||
assert.match(minicardCss, /\.minicard-title \.viewer a:hover \{\s*color:\s*inherit;/,
|
||||
'formatted minicard title content keeps the card contrast colour');
|
||||
|
||||
const lightColors = [
|
||||
'white', 'yellow', 'orange', 'pink', 'lime', 'silver', 'peachpuff',
|
||||
'plum', 'gold', 'paleturquoise', 'mistyrose',
|
||||
];
|
||||
for (const color of lightColors) {
|
||||
assert.match(minicardCss, new RegExp(`\\.minicard-${color} \\{[^}]*color: #000 !important;`, 's'),
|
||||
`${color} minicard uses the same black title contrast as opened cards`);
|
||||
}
|
||||
|
||||
for (const color of ['green', 'red', 'purple', 'blue', 'black', 'navy', 'indigo']) {
|
||||
assert.match(minicardCss, new RegExp(`\\.minicard-${color} \\{[^}]*color: #fff !important;`, 's'),
|
||||
`${color} minicard retains white title contrast`);
|
||||
}
|
||||
|
||||
console.log('cardHeaderColorInheritance: opened and mini card colors passed');
|
||||
Reference in new issue
Block a user