From 9cb6c501b57e877262d944b3fd7afa59adce48dd Mon Sep 17 00:00:00 2001 From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Date: Thu, 16 Jul 2026 12:21:01 +0530 Subject: [PATCH] fix: html/body background not applied in appearance mode (#13989) # Pull Request Template ## Description This PR fixes the white background bleed visible in the widget, article viewer, and Help Center when dark mode is active. This change was previously merged but later reverted due to a background being added for the unread bubble. Reverted PR: https://github.com/chatwoot/chatwoot/pull/13955, https://github.com/chatwoot/chatwoot/pull/13981 **What was happening** While scrolling, the `` element retained a white background in dark mode. This occurred because dark mode classes were only applied to inner container elements, not the root. **What changed** * **Widget:** Updated the `useDarkMode` composable to sync the `dark` class to `` using `watchEffect`, allowing `` to inherit dark theme variables. Also added background styles to `html`, `body`, and `#app` in `woot.scss`. * **Help center portal:** Moved `bg-white dark:bg-slate-900` from `
` to `` in the portal layout so the entire page background responds correctly to dark mode, including within the widget iframe. * **ArticleViewer:** Replaced hardcoded `bg-white` with `bg-n-solid-1` to ensure better theming. Fixes https://linear.app/chatwoot/issue/CW-6704/widget-body-colour-not-implemented ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? ### Screencasts ### Before **Widget** https://github.com/user-attachments/assets/e0224ad1-81a6-440a-a824-e115fb806728 **Help center** https://github.com/user-attachments/assets/40a8ded5-5360-474d-9ec5-fd23e037c845 ### After **Widget** https://github.com/user-attachments/assets/dd37cc68-99fc-4d60-b2ae-cf41f9d4d38c image **Help center** https://github.com/user-attachments/assets/bc998c4e-ef77-46fa-ac7f-4ea16d912ce3 ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Muhsin Keloth --- app/javascript/widget/App.vue | 4 ++++ app/javascript/widget/views/ArticleViewer.vue | 2 +- app/views/layouts/portal.html.erb | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/javascript/widget/App.vue b/app/javascript/widget/App.vue index 19a33b8a4..7637ffc2f 100755 --- a/app/javascript/widget/App.vue +++ b/app/javascript/widget/App.vue @@ -66,6 +66,9 @@ export default { ? getLanguageDirection(this.$root.$i18n.locale) : false; }, + isUnreadOrCampaignView() { + return ['unread-messages', 'campaigns'].includes(this.$route.name); + }, }, watch: { activeCampaign() { @@ -374,6 +377,7 @@ export default { 'is-widget-right': isRightAligned, 'is-bubble-hidden': hideMessageBubble, 'is-flat-design': isWidgetStyleFlat, + 'bg-n-slate-2 dark:bg-n-solid-1': !isUnreadOrCampaignView, dark: prefersDarkMode, }" > diff --git a/app/javascript/widget/views/ArticleViewer.vue b/app/javascript/widget/views/ArticleViewer.vue index 9289d0546..bc4cf775c 100644 --- a/app/javascript/widget/views/ArticleViewer.vue +++ b/app/javascript/widget/views/ArticleViewer.vue @@ -10,7 +10,7 @@ export default { diff --git a/app/views/layouts/portal.html.erb b/app/views/layouts/portal.html.erb index ac3f7e574..3085106dd 100644 --- a/app/views/layouts/portal.html.erb +++ b/app/views/layouts/portal.html.erb @@ -3,9 +3,9 @@ <%= render 'layouts/portal_head' %> - +
-
+
<%= render 'public/api/v1/portals/header', portal: @portal unless @is_plain_layout_enabled %> <%= yield %> <%= render 'public/api/v1/portals/footer' unless @is_plain_layout_enabled || @portal.account.feature_enabled?('disable_branding') %>