[FIX] web, mail: Dropdown and PopoverWowl, increase contrast

This commit adapt several components and utility-classes in order to
increase visual contrast.

In the case of `o-mail-ActivityGroup` and `o-mail-NotificationItem`
templates, these has been reworked in order to use default BS components
and consequently automatically inheriting the improved design.

task-3338419

closes odoo/odoo#124903

Part-of: task-3326263
X-original-commit: 190ec1c947e17b2b4aa8614e9e0a04d00cb38d90
Related: odoo/enterprise#42507
Signed-off-by: Bruno Boi (boi) <boi@odoo.com>
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
stefanorigano (SRI)
2023-06-21 00:13:49 +02:00
committed by Alexandre Kühn
parent 3168ae5fcc
commit b0baac6fc4
15 changed files with 65 additions and 83 deletions
@@ -4,12 +4,8 @@
min-height: 50px;
img {
width: 40px;
height: 40px;
}
.o-mail-ActivityGroup:hover {
background-color: map-get($theme-colors, "light");
height: 3em;
aspect-ratio: 1;
}
}
@@ -12,28 +12,28 @@
<div t-if="store.activityGroups.length === 0" class="o-mail-ActivityMenu-empty align-items-center text-muted p-2 opacity-50 d-flex justify-content-center">
<span>Congratulations, you're done with your activities.</span>
</div>
<div class="d-flex flex-column cursor-pointer" name="activityGroups">
<div class="d-flex flex-column list-group-flush" name="activityGroups">
<t t-foreach="store.activityGroups" t-as="group" t-key="group.id" name="activityGroupLoop">
<div class="o-mail-ActivityGroup d-flex p-2 border-bottom" t-att-data-model_name="group.model" t-on-click="() => this.openActivityGroup(group)">
<button class="o-mail-ActivityGroup list-group-item list-group-item-action d-flex p-2" t-att-data-model_name="group.model" t-on-click="() => this.openActivityGroup(group)">
<img alt="Activity" t-att-src="group.icon"/>
<div class="flex-grow-1 overflow-hidden">
<div class="d-flex px-2" name="activityTitle">
<span class="flex-grow-1"><t t-esc="group.name"/></span>
<t t-foreach="group.actions or []" t-as="action" t-key="action_index">
<button class="btn btn-link fa p-0" type="button" t-att-title="action.name" t-att-class="action.icon" t-on-click.stop="() => this.onClickAction(action, group)"/>
<button class="btn btn-link text-action fa p-0" type="button" t-att-title="action.name" t-att-class="action.icon" t-on-click.stop="() => this.onClickAction(action, group)"/>
</t>
</div>
<div t-if="group.type === 'activity'" class="d-flex">
<button t-if="group.overdue_count" type="button" class="btn btn-link py-0 px-2" t-on-click.stop="() => this.openActivityGroup(group, 'overdue')"><t t-esc="group.overdue_count"/> Late</button>
<span t-else="" class="text-muted py-0 px-2">0 Late</span>
<button t-if="group.today_count" type="button" class="btn btn-link py-0 px-2" t-on-click.stop="() => this.openActivityGroup(group, 'today')"><t t-esc="group.today_count"/> Today</button>
<span t-else="" class="text-muted py-0 px-2">0 Today</span>
<button t-if="group.overdue_count" type="button" class="btn btn-link text-action py-0 px-2" t-on-click.stop="() => this.openActivityGroup(group, 'overdue')"><t t-esc="group.overdue_count"/> Late</button>
<em t-else="" class="text-muted py-0 px-2">0 Late</em>
<button t-if="group.today_count" type="button" class="btn btn-link text-action py-0 px-2" t-on-click.stop="() => this.openActivityGroup(group, 'today')"><t t-esc="group.today_count"/> Today</button>
<em t-else="" class="text-muted py-0 px-2">0 Today</em>
<span class="flex-grow-1"/>
<button t-if="group.planned_count" type="button" class="btn btn-link py-0 px-2" t-on-click.stop="() => this.openActivityGroup(group, 'upcoming_all')"><t t-esc="group.planned_count"/> Future</button>
<span t-else="" class="text-muted py-0 px-2">0 Future</span>
<button t-if="group.planned_count" type="button" class="btn btn-link text-action py-0 px-2" t-on-click.stop="() => this.openActivityGroup(group, 'upcoming_all')"><t t-esc="group.planned_count"/> Future</button>
<em t-else="" class="text-muted py-0 px-2">0 Future</em>
</div>
</div>
</div>
</button>
</t>
</div>
</div>
@@ -24,7 +24,7 @@
<button class="btn btn-link" t-att-class="store.discuss.activeTab === 'channel' ? 'fw-bolder' : 'text-muted'" type="button" role="tab" t-on-click="() => store.discuss.activeTab = 'channel'">Channels</button>
</t>
</div>
<div t-if="!env.inDiscussApp or ['chat', 'channel'].includes(store.discuss.activeTab)" class="d-flex flex-column overflow-auto flex-grow-1">
<div t-if="!env.inDiscussApp or ['chat', 'channel'].includes(store.discuss.activeTab)" class="list-group-flush d-flex flex-column overflow-auto flex-grow-1">
<div class="d-flex justify-content-center py-4 px-2 text-muted" t-if="!hasPreviews">
No conversation yet...
</div>
@@ -39,7 +39,6 @@
<ImStatus persona="notificationRequest.partner" className="'position-absolute top-100 start-100 translate-middle mt-n1 ms-n1'"/>
</t>
</NotificationItem>
<hr t-if="!notificationRequest.isLast" class="my-0"/>
</t>
<t t-if="store.discuss.activeTab === 'all'">
<t t-foreach="failures" t-as="failure" t-key="failure.id">
@@ -53,7 +52,6 @@
onClick="(isMarkAsRead) => isMarkAsRead ? this.cancelNotifications(failure) : this.onClickFailure(failure)"
onSwipeRight="hasTouch() ? { action: () => this.cancelNotifications(failure), icon: 'fa-times-circle', bgColor: 'bg-warning' } : undefined"
/>
<hr t-if="threads.length !== 0 or !failure_last" class="my-0"/>
</t>
</t>
<t t-foreach="threads" t-as="thread" t-key="thread.localId">
@@ -81,7 +79,6 @@
</t>
</t>
</NotificationItem>
<hr t-if="!thread_last" class="my-0"/>
</t>
</div>
</div>
@@ -3,7 +3,7 @@
<t t-name="mail.NotificationItem" owl="1">
<ActionSwiper onLeftSwipe="props.onSwipeLeft ? props.onSwipeLeft : undefined" onRightSwipe="props.onSwipeRight ? props.onSwipeRight : undefined">
<div class="o-mail-NotificationItem d-flex cursor-pointer align-items-center p-1" t-att-class="{ 'o-muted': !props.hasMarkAsReadButton }" t-on-click="onClick" t-ref="root">
<button class="o-mail-NotificationItem list-group-item list-group-item-action d-flex cursor-pointer align-items-center p-1" t-att-class="{ 'o-muted': !props.hasMarkAsReadButton }" t-on-click="onClick" t-ref="root">
<div class="position-relative o-bg-inherit m-1 flex-shrink-0" style="width:40px;height:40px;">
<img class="o_avatar w-100 h-100 rounded" alt="Notification Item Image" t-att-src="props.iconSrc"/>
<t t-slot="icon"/>
@@ -29,7 +29,7 @@
</div>
</div>
</div>
</div>
</button>
</ActionSwiper>
</t>
@@ -20,31 +20,31 @@ QUnit.test("create todo from activity menu without date", async function (assert
target,
".o-mail-ActivityMenu:contains(Congratulations, you're done with your activities.)"
);
assert.containsOnce(target, "button:contains(Add a To-do)");
await click("button:contains(Add a To-do)");
assert.containsNone(target, "button:contains(Add a To-do)");
assert.containsOnce(target, ".btn:contains(Add a To-do)");
await click(".btn:contains(Add a To-do)");
assert.containsNone(target, ".btn:contains(Add a To-do)");
assert.containsOnce(target, ".o-mail-ActivityMenu-show");
await editInput(target, "input.o-mail-ActivityMenu-input", "New To-do");
await click("button:contains(SAVE)");
await click(".btn:contains(SAVE)");
// Need to reopen systray as it automatically closes when a todo is created
assert.containsOnce(target, ".o_menu_systray i[aria-label='Activities']");
await click(".o_menu_systray i[aria-label='Activities']");
assert.containsOnce(target, ".o-mail-ActivityMenu-counter:contains(1)");
assert.containsOnce(target, ".o-mail-ActivityGroup");
assert.containsOnce(target, ".o-mail-ActivityGroup:contains(project.task)");
assert.containsOnce(target, "button:contains(1 Today)");
assert.containsOnce(target, "button:contains(Add a To-do)");
assert.containsOnce(target, ".btn:contains(1 Today)");
assert.containsOnce(target, ".btn:contains(Add a To-do)");
assert.containsNone(target, ".o-mail-ActivityMenu-show");
assert.containsNone(target, ".o-mail-ActivityMenu-input");
await click("button:contains(Add a To-do)");
assert.containsNone(target, "button:contains(Add a To-do)");
await click(".btn:contains(Add a To-do)");
assert.containsNone(target, ".btn:contains(Add a To-do)");
await editInput(target, "input.o-mail-ActivityMenu-input", "New To-do");
await click("button:contains(SAVE)");
await click(".btn:contains(SAVE)");
// Need to reopen systray as it automatically closes when a todo is created
assert.containsOnce(target, ".o_menu_systray i[aria-label='Activities']");
await click(".o_menu_systray i[aria-label='Activities']");
assert.containsOnce(target, ".o-mail-ActivityMenu-counter:contains(2)");
assert.containsOnce(target, "button:contains(2 Today)");
assert.containsOnce(target, ".btn:contains(2 Today)");
});
QUnit.test("create to-do from activity menu with date", async function (assert) {
@@ -57,19 +57,19 @@ QUnit.test("create to-do from activity menu with date", async function (assert)
assert.containsNone(target, ".o-mail-ActivityMenu-counter");
await click(".o_menu_systray i[aria-label='Activities']");
await click("button:contains(Add a To-do)");
await click(".btn:contains(Add a To-do)");
await editInput(target, "input.o-mail-ActivityMenu-input", "New To-do");
await editInput(
target,
"input.o_datetime_input",
futureDay.toString(luxon.DateTime.DATE_SHORT)
);
await click("button:contains(SAVE)");
await click(".btn:contains(SAVE)");
// Need to reopen systray as it automatically closes when a todo is created
assert.containsOnce(target, ".o_menu_systray i[aria-label='Activities']");
await click(".o_menu_systray i[aria-label='Activities']");
assert.containsOnce(target, ".o-mail-ActivityMenu-counter:contains(1)");
assert.containsOnce(target, ".o-mail-ActivityGroup");
assert.containsOnce(target, ".o-mail-ActivityGroup:contains(project.task)");
assert.containsOnce(target, "button:contains(1 Future)");
assert.containsOnce(target, ".btn:contains(1 Future)");
});
@@ -24,7 +24,7 @@ export class Popover extends Component {
right: "end",
};
el.classList = [
"o_popover popover mw-100 shadow-sm",
"o_popover popover mw-100",
`bs-popover-${directionMap[direction]}`,
`o-popover-${direction}`,
`o-popover--${position}`,
@@ -286,23 +286,10 @@
padding: if(type-of($padding-base) == 'string', calc(#{$padding-base}/2) $padding-base, $padding-base/2 $padding-base);
vertical-align: top;
@include o-hover-text-color($body-color, $headings-color);
&:focus, &:active, &:focus:active {
outline: none;
box-shadow: none;
}
}
@mixin o-kanban-dropdown-open {
position: relative;
background: $dropdown-bg;
z-index: $zindex-dropdown + 1;
&:before {
@include o-position-absolute(100%, 0, auto, 0);
height: $dropdown-border-radius;
background-color: $dropdown-bg;
content: "";
}
}
@mixin o-kanban-colorpicker {
max-width: 150px;
+4 -4
View File
@@ -91,12 +91,11 @@ $grid-gutter-width: $o-horizontal-padding * 2 !default;
//
// Define common padding and border radius sizes and more.
$border-color: $o-border-color!default;
$border-color: $o-border-color !default;
$border-radius: $o-border-radius !default;
$border-radius-sm: $o-border-radius-sm !default;
$border-radius-lg: $o-border-radius-lg !default;
$border-color: $o-gray-300 !default;
$component-active-color: $o-component-active-color !default;
$component-active-bg: $o-component-active-bg !default;
@@ -174,7 +173,7 @@ $btn-border-radius-lg: $border-radius !default;
//
// Dropdown menu container and contents.
$dropdown-border-color: $gray-300 !default;
$dropdown-border-color: $border-color !default;
$dropdown-link-color: $o-main-text-color !default;
$dropdown-link-hover-color: $gray-900 !default;
@@ -233,9 +232,10 @@ $tooltip-opacity: 1 !default;
// Popovers
$popover-bg: $white !default;
$popover-border-width: 0 !default;
$popover-border-color: $border-color !default;
$popover-border-radius: $border-radius !default;
$popover-arrow-color: var(--popover-arrow-color, #{$popover-bg}) !default;
$popover-arrow-outer-color: $popover-border-color !default;
// Toasts
+2 -2
View File
@@ -111,7 +111,7 @@ $-o-theme-text-colors: map-merge($theme-colors, $o-theme-text-colors);
@each $-name, $-color in $-o-theme-text-colors{
&.btn-#{$-name}, &.text-#{$-name} {
@include o-btn-link-variant($o-main-color-muted!important, o-text-color($-name) or $-color!important);
@include o-btn-link-variant($o-gray-600!important, o-text-color($-name) or $-color!important);
}
}
}
@@ -246,7 +246,7 @@ $-o-bg-colors-custom: null;
.btn-link {
@each $-name, $-color in $o-text-colors-custom{
&.btn-#{$-name}, &.text-#{$-name} {
@include o-btn-link-variant($o-main-color-muted!important, o-text-color($-name) or $-color!important);
@include o-btn-link-variant($o-gray-600!important, o-text-color($-name) or $-color!important);
}
}
}
@@ -168,7 +168,6 @@ $o-horizontal-padding: $o-spacer !default;
$o-innergroup-rpadding: 45px !default;
$o-dropdown-hpadding: 20px !default;
$o-dropdown-vpadding: 3px !default;
$o-dropdown-box-shadow: 0 1rem 1.1rem rgba(#000, .1) !default;
$o-sheet-vpadding: 24px !default;
@@ -259,8 +258,8 @@ $o-btns-bs-override: map-merge((
border: $o-white,
color: $o-gray-700,
hover-background: $o-gray-100,
hover-border: $o-gray-100,
hover-background: $o-gray-200,
hover-border: $o-gray-200,
hover-color: $o-gray-900,
active-background: $o-component-active-bg,
@@ -28,34 +28,33 @@
.o_nav_entry, .dropdown-toggle {
@extend %-main-navbar-entry-base;
@extend %-main-navbar-entry-spacing;
border: 0;
border-color: transparent;
}
.o_menu_sections {
.o_nav_entry, .dropdown-toggle {
@extend %-main-navbar-entry-bg-hover;
@extend %-main-navbar-entry-bg-hover !optional;
}
.dropdown.show > .dropdown-toggle {
@extend %-main-navbar-entry-active;
@extend %-main-navbar-entry-active !optional;
}
}
@if (not $o-navbar-use-pills) {
.o_menu_systray {
.o_nav_entry, .dropdown-toggle {
@extend %-main-navbar-entry-bg-hover;
@extend %-main-navbar-entry-bg-hover !optional;
}
.dropdown.show > .dropdown-toggle {
@extend %-main-navbar-entry-active;
@extend %-main-navbar-entry-active !optional;
}
}
}
.dropdown-menu {
border-top: 0;
margin-top: $o-navbar-dropdown-menu-margin-top;
border-top: $o-navbar-dropdown-menu-border-top;
border-radius: $o-navbar-dropdown-menu-border-radius;
}
@@ -108,6 +107,9 @@
}
.o_menu_systray {
--NavBar-entry-padding-left: #{$o-navbar-entry-padding-h * 0.5};
--NavBar-entry-padding-right: #{$o-navbar-entry-padding-h * 0.5};
.badge {
margin-right: -.5em;
border: 0;
@@ -19,7 +19,7 @@ $o-navbar-entry-bg--hover: rgba($o-black, .08) !default;
$o-navbar-entry-color--active: $o-navbar-entry-color--hover !default;
$o-navbar-entry-bg--active: $o-navbar-entry-bg--hover !default;
$o-navbar-dropdown-menu-margin-top: 0px !default;
$o-navbar-dropdown-menu-border-top: 0 !default;
$o-navbar-dropdown-menu-border-radius: 0 0 $o-border-radius $o-border-radius !default;
$o-navbar-brand-font-size: 1.2em !default;
@@ -46,10 +46,12 @@ $o-navbar-badge-text-shadow: 1px 1px 0 rgba($o-black, .3) !default;
background: transparent;
font-size: $o-navbar-entry-font-size;
@include o-hover-text-color(
var(--NavBar-entry-color, #{$o-navbar-entry-color}),
var(--NavBar-entry-color--hover, #{$o-navbar-entry-color--hover})
);
@if ($o-navbar-use-pills == false) {
@include o-hover-text-color(
var(--NavBar-entry-color, #{$o-navbar-entry-color}),
var(--NavBar-entry-color--hover, #{$o-navbar-entry-color--hover})
);
}
}
%-main-navbar-entry-spacing {
@@ -62,15 +64,17 @@ $o-navbar-badge-text-shadow: 1px 1px 0 rgba($o-black, .3) !default;
line-height: calc(var(--o-navbar-height) - #{$o-navbar-padding-v * 2});
}
%-main-navbar-entry-bg-hover {
&:hover {
background-color: var(--NavBar-entry-backgroundColor--hover, #{$o-navbar-entry-bg--hover});
@if ($o-navbar-use-pills == false) {
%-main-navbar-entry-bg-hover {
&:hover {
background-color: var(--NavBar-entry-backgroundColor--hover, #{$o-navbar-entry-bg--hover});
}
}
}
%-main-navbar-entry-active {
%-main-navbar-entry-active {
&, &:hover, &:focus {
background: var(--NavBar-entry-backgroundColor--active, #{$o-navbar-entry-bg--active});
color: var(--NavBar-entry-color--active, #{$o-navbar-entry-color--active});
background: var(--NavBar-entry-backgroundColor--active, #{$o-navbar-entry-bg--active});
color: var(--NavBar-entry-color--active, #{$o-navbar-entry-color--active});
}
}
}
@@ -1,7 +1,5 @@
.o_user_menu .dropdown-toggle {
--NavBar-entry-padding-right: 0;
margin-right: $o-horizontal-padding;
--NavBar-entry-padding-right: #{$o-horizontal-padding};
.o_user_avatar {
height: calc(var(--o-navbar-height) - 20px);
@@ -77,7 +77,6 @@ kbd {
max-height: 70vh;
overflow: auto;
background-clip: border-box;
box-shadow: $o-dropdown-box-shadow;
}
:not(.dropstart) > .dropdown-item {
@@ -194,7 +194,7 @@ QUnit.test("reposition popover should properly change classNames", async (assert
// Should have classes for a "bottom-middle" placement
assert.strictEqual(
popover.className,
"o_popover popover mw-100 shadow-sm bs-popover-bottom o-popover-bottom o-popover--bm"
"o_popover popover mw-100 bs-popover-bottom o-popover-bottom o-popover--bm"
);
assert.strictEqual(arrow.className, "popover-arrow start-0 end-0 mx-auto");
@@ -207,7 +207,7 @@ QUnit.test("reposition popover should properly change classNames", async (assert
// Should have classes for a "right-end" placement
assert.strictEqual(
popover.className,
"o_popover popover mw-100 shadow-sm bs-popover-end o-popover-right o-popover--re"
"o_popover popover mw-100 bs-popover-end o-popover-right o-popover--re"
);
assert.strictEqual(arrow.className, "popover-arrow top-auto");
});