Name: [FIX] viin_brand_mail: fix chatter contrast in light and dark schemes

State: Succeed finished in 129m

PR State: merged

PR Author: David Tran

PR Author Email:

PR: #676

Committer: David Tran

Committer Email: david.tran@tvtmarine.com

Commit: 6a8d31b7f8fb5f5acd389eb8edc72be572cb8109

Description:

                                            [FIX] viin_brand_mail: fix chatter contrast, harden dark edited marker

DARK: the mail chatter embedded in the Odoo 19 spreadsheet editor's
comments side panel was unreadable. Odoo keeps the spreadsheet a light
island inside a dark app (its dark-bundle-only
o_spreadsheet_extended.dark.scss forces .bg-white back to white and
pins .btn to a dark label), but core repaints only the button label,
not the fill, leaving half of every pair in the wrong colour scheme.
Finish that light island for the embedded chatter instead of darkening
it, scoped entirely under .o-spreadsheet. Measured live at 1440px in
dark mode, before -> after: Log note 1.19 -> 7.92, Activity
1.19 -> 7.92, Send message 2.17 -> 8.24, author name 2.63 -> 10.31,
timestamp 2.59 -> 6.11, message body -> 9.25.

The same two message nodes the island fix above touches - the
empty-message placeholder (3.37:1 worst) and the (edited) marker
(4.04:1 worst) - were unreadable everywhere OUTSIDE that island too,
because core dims both a second time on top of a tier already tuned to
clear AA once. Fix them product-wide instead of leaving the island as
the one readable spot: every form-view chatter, the Discuss thread
canvas and every chat window, on the panel and on all three
message-bubble tints. With that rule in place the island's own
placeholder correction became a pure duplicate of it and was dropped.
The island's (edited) rule is kept and hardened with its own colour,
because the product-wide fix lands that marker on the dark metadata
tier, which measures 2.34-2.59:1 on the island's light bubbles - too
dark for that ground.

LIGHT: the mail message muted tier renders below AA wherever it lands
- 4.06:1 on a message bubble, 4.20:1 on the chatter panel - and two
nodes are dimmed further by opacity utilities to 2.7:1 and 2.4:1. The
shared $text-muted token is deliberately left untouched: it also paints
off/disabled affordances that WCAG exempts, and repointing it would
change roughly 380 nodes across 205 templates. Re-point the tier for
mail message surfaces only. After: 5.48-6.11 across the panel and all
bubble variants. Dark stays provably unaffected, since the light rules
compile to zero bytes in the dark bundle.

Also drop a rule that went dead once the comments panel lost its
background utility - it was this module's only reference to another
repo's class.

A comment on the read-conversation muted tier said its
--secondary-color token "does not flip" in dark - true only while
$o-main-color-muted and $body-secondary-color were two independent
Sass values. dark_palette.scss has since aliased the former onto the
latter, so both names now resolve to the one tier this rule already
reads: the rule was right, the explanation had gone stale. Reworded to
name the tier through its own alias chain instead of restating a
divergence that no longer exists.

Guard every case above with tests that assert computed WCAG ratios,
never colour values.

DARK EDITED MARKER, HARDENED: the product-wide dark rule just added
above (.o-mail-Message-edited .opacity-50 in mail_dark.scss) read the
bare Bootstrap Sass global $text-muted, which has no !default guard,
so any module sharing the web.assets_web_dark compile can reassign it
from under this one. Core's hr_skills does exactly that.
hr_skills/__manifest__.py:53 wildcard-globs
'hr_skills/static/src/scss/*.scss' into web.assets_backend, separately
from the intended web.report_assets_pdf entry on line 68; that glob
also catches report_employee_cv.scss, whose line 3 hard-assigns
$text-muted: #3b4757 with no !default; and the bundle chain
web.assets_web_dark -> web.assets_web -> web.assets_backend carries
that value in. So whenever hr_skills is installed alongside the
branding modules (always true on Runbot, which installs the whole
repo) the marker compiled to the wrong colour and failed WCAG AA
contrast (~1.3-2.0:1, needs >= 4.5:1).

A one-variable install-topology experiment proved it: same commit,
same suite - the three branding modules installed alone compiled
$text-muted to #8EA5A8 and passed all 147 tests; adding hr_skills to
the install set, nothing else changed, compiled it to #3b4757 and
failed 12 subtests. That asymmetry is exactly why the branch stayed
green on a local, branding-only run while Runbot - which always
installs the whole repo - was red on the same code.

Re-point the rule to var(--secondary-color) - the CSS custom property
Bootstrap emits from $body-secondary-color (a different Sass variable,
hard-assigned in dark_palette.scss:76 with no !default, which
hr_skills' write never touches) - matching an existing pattern already
used twice in this file (:56 and :245) for the analogous
chatter-timestamp / notification-item cases. Updated the neighbouring
comment to match, since it previously explained the value in terms of
$text-muted.

Added a regression guard,
test_dark_edited_marker_stays_readable_when_another_module_hijacks_text_muted,
that splices hr_skills' exact clobbering literal into the real
web.assets_web_dark bundle source and recompiles through Odoo's own
AssetsBundle.compile_css / ScssStylesheetAsset.compile (libsass),
proving the rule survives a hijacked $text-muted regardless of which
modules happen to be installed on whatever DB runs this module's own
suite (no cr.commit(), no real hr_skills install needed).

Verified RED before (12 genuine assertion failures on a live instance
with hr_skills installed) and GREEN after (0 failed, 0 errors across
187 tests in viin_backend_theme + viin_brand_web + viin_brand_mail,
same instance, hr_skills genuinely installed).

Also fixes a flake8 E303 (too many blank lines) left behind while
extending the compiled-CSS test suite above.

Signed-off-by: David Tran <david.tran@tvtmarine.com>
                                            

Branch: 19.0

Age:

Up-time:

Delete Date:

Subbuilds Name State Detail
Build 412607 Check the quality with Pylint: from test_lint to test_pylint 19m Succeed Log
Build 412608 At install tests: from account to website_timesheet 58m Succeed Log
Build 412609 Post install tests: step install all modules 8m Succeed Log
Build 412610 Post install tests: from account to hr_recruitment_survey 69m Succeed Log
Build 412611 Post install tests: from hr_skills to phone_validation 34m Succeed Log
Build 412612 Post install tests: from point_of_sale to purchase_requisition_stock 119m Succeed Log
Build 412613 Post install tests: from purchase_stock to test_lint 54m Succeed Log
Build 412614 Post install tests: from test_mail to to_product_odoo_version 34m Succeed Log
Build 412615 Post install tests: from to_sale_order_advance to viin_api_request_logger 9m Succeed Log
Build 412616 Post install tests: from viin_backend_theme to viin_maintenance_preventive_mode 19m Succeed Log
Build 412617 Post install tests: from viin_project to web_unsplash 69m Succeed Log
Build 412618 Post install tests: from website to website_timesheet 75m Succeed Log
Build 412619 Test install all modules without demo data: from account to website_timesheet 8m Succeed Log
Create Date Level Message
09/07/2026 18:10:52 INFO
Updated repository Viindoo-odoo
09/07/2026 18:10:52 INFO
Updated repository Viindoo-tvtmaaddons
09/07/2026 18:10:52 INFO
Cloned repository Viindoo-branding
09/07/2026 20:20:15 WARNING
Subbuild # 412612: odoo.http: You can only cancel a session that is in opening control state and has no orders.