From 53d7dbba0cc417c99336b153d9a6ada00c0990c8 Mon Sep 17 00:00:00 2001 From: MaryWylde Date: Mon, 25 May 2026 17:23:58 +0400 Subject: [PATCH 1/3] fix(ui): dark-theme polish for mobile biases + center mobile Box Co-Authored-By: Claude Opus 4.7 (1M context) --- src/components/Box/Box.module.scss | 7 +- src/components/Headline/Headline.module.scss | 10 +++ src/uxcore/components/Logos/Logos.module.scss | 9 +++ .../PageSwitcher/PageSwitcher.module.scss | 28 +++++++ .../UXCoreModalMobile.module.scss | 66 ++++++++++++++++ .../MobileHeader/MobileHeader.module.scss | 18 +++++ .../_biases/MobileHeader/MobileHeader.tsx | 8 +- .../_biases/MobileView/MobileView.module.scss | 76 +++++++++++++++++++ 8 files changed, 217 insertions(+), 5 deletions(-) diff --git a/src/components/Box/Box.module.scss b/src/components/Box/Box.module.scss index 60aaf94b..1dc7f6dc 100644 --- a/src/components/Box/Box.module.scss +++ b/src/components/Box/Box.module.scss @@ -4,7 +4,8 @@ env() is 0 on devices without a safe area, so desktop layout is unchanged. Pairs with `viewport-fit=cover` in SeoGenerator. */ bottom: max(15px, env(safe-area-inset-bottom)); - right: 15px; + left: 50%; + transform: translateX(-50%); width: 100%; max-width: 480px; padding: 20px; @@ -154,10 +155,8 @@ @media (max-width: 500px) { .content { - right: unset; - margin: 0 15px; + width: calc(100% - 30px); max-width: unset; - width: unset; bottom: max(15px, env(safe-area-inset-bottom)); } } diff --git a/src/components/Headline/Headline.module.scss b/src/components/Headline/Headline.module.scss index a2bc14bc..b2c13dad 100644 --- a/src/components/Headline/Headline.module.scss +++ b/src/components/Headline/Headline.module.scss @@ -301,6 +301,16 @@ } } } + + .darkTheme { + .headlineInfo { + .videoContainer { + .video { + background-color: #1c1c1c; + } + } + } + } } @media (max-width: 1440px) { diff --git a/src/uxcore/components/Logos/Logos.module.scss b/src/uxcore/components/Logos/Logos.module.scss index 1c68ee9a..58ff4089 100644 --- a/src/uxcore/components/Logos/Logos.module.scss +++ b/src/uxcore/components/Logos/Logos.module.scss @@ -67,6 +67,9 @@ // Dark theme: lift the description text, then desaturate + invert the // partner logos so the black-on-white marks read as soft light marks on dark. +// The mobile breakpoint above paints `.logoWrapper` solid white to give the +// logos breathing room on the cramped mobile column — on dark that becomes +// a bright slab mid-page, so blank the background out here. :global(body.darkTheme) { .title { color: rgba(218, 218, 218, 0.65); @@ -76,4 +79,10 @@ filter: invert(1) hue-rotate(180deg) brightness(0.95) saturate(0.85); opacity: 0.85; } + + @media (max-width: 1010px) { + .logoWrapper { + background-color: transparent; + } + } } diff --git a/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss b/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss index 9a365d97..e7fe1f99 100644 --- a/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss +++ b/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss @@ -84,3 +84,31 @@ $active-color: #359eff; grid-template-columns: 1fr; } } + +// Dark theme: default button rail is a white panel with hairline-gray +// borders and black labels — on the dark page that becomes a bright slab +// with invisible text. Repaint to the dark surface and lift the labels +// and active accent to the dark-mode palette. +:global(body.darkTheme) .PageSwitcher { + background-color: transparent; + + & .Button { + border-color: #303338; + + & .Description { + color: #dadada; + } + + &.Active { + border-color: #7fb3d5; + + & svg > path { + fill: #7fb3d5; + } + + & .Description { + color: #7fb3d5; + } + } + } +} diff --git a/src/uxcore/components/UXCoreModalMobile/UXCoreModalMobile.module.scss b/src/uxcore/components/UXCoreModalMobile/UXCoreModalMobile.module.scss index a4026c1c..2fe15af4 100644 --- a/src/uxcore/components/UXCoreModalMobile/UXCoreModalMobile.module.scss +++ b/src/uxcore/components/UXCoreModalMobile/UXCoreModalMobile.module.scss @@ -278,3 +278,69 @@ opacity: 0; } } + +// Dark theme: bias detail modal defaults to a white card with black body +// text, a faint gray hairline border, and a near-white "mentioned in" +// strip. On the dark page the whole sheet reads as a bright slab and the +// body text falls back to invisible. Repaint surfaces + borders to the +// dark palette and lift content + accents to dark-mode foreground. +:global(body.darkTheme) { + .ModalOverlay { + background-color: rgba(0, 0, 0, 0.6); + + & .Modal { + color: #dadada; + background: #1b1e26; + border-color: #303338; + box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.5); + + & .ModalBody { + &::-webkit-scrollbar { + border-left-color: #303338; + } + + &::-webkit-scrollbar-thumb { + background: rgba(127, 179, 213, 0.5); + border-left-color: #303338; + } + + & .ModalBodyTitle.mentionedIn { + background-color: #15171f; + + span { + color: rgba(218, 218, 218, 0.65); + } + } + + .ModalBodyContent .switcher { + .switcherItem { + border-color: #303338; + } + + .activeProduct, + .activeHr { + border-color: #7fb3d5; + color: #7fb3d5; + + svg { + fill: #7fb3d5; + } + } + } + } + + .ModalButtons { + .arrowRight, + .arrowLeft { + > svg { + fill: #7fb3d5; + } + } + } + } + } + + .a { + color: #dadada !important; + } +} diff --git a/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss b/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss index d8e2066a..f10c13e5 100644 --- a/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss +++ b/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss @@ -48,3 +48,21 @@ position: relative; z-index: 5; } + +// Dark theme: the sticky header defaults to white bg + brand-blue title, +// which reads as a hard white bar across the top of the dark mobile page. +// Repaint the bar to the dark surface, lift the accent so it still reads +// as the brand color, and replace the soft light shadow with a darker +// drop so the header still feels lifted from the page. +:global(body.darkTheme) { + .MobileHeader, + .disablePageSwitcher { + background-color: #1b1e26; + color: #7fb3d5; + box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.5); + + & .Actions .active > svg { + fill: #7fb3d5; + } + } +} diff --git a/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx b/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx index 0f22363f..4134b659 100644 --- a/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx +++ b/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx @@ -7,6 +7,7 @@ import LanguageSwitcher from '@uxcore/components/LanguageSwitcher'; import SettingsModal from '@uxcore/components/SettingsModal'; import UserDropdown from '@uxcore/components/UserDropdown'; import toolHeaderData from '@uxcore/data/toolHeader'; +import useGlobals from '@uxcore/hooks/useGlobals'; import { isLevelMilestone } from '@uxcore/lib/uxcat-helpers'; import type { TRouter } from '@uxcore/local-types/global'; import { UserTypes } from '@uxcore/local-types/uxcat-types/types'; @@ -46,6 +47,7 @@ const MobileHeader: FC = ({ const router = useRouter(); const { locale } = router as TRouter; const { accountData, setAccountData } = useContext(GlobalContext); + const [, { isDarkTheme }] = useGlobals(); const { usernameIsTaken, settingsTxt, myProfileTxt } = toolHeaderData[locale]; const imageSrc = useMemo(() => accountData?.picture, [accountData]); const [showDropdown, setShowDropdown] = useState(false); @@ -151,7 +153,11 @@ const MobileHeader: FC = ({
keepsimple logo Date: Mon, 25 May 2026 17:10:46 +0200 Subject: [PATCH 2/3] fix(ui): dark-theme polish + wide-screen layout fixes Co-Authored-By: Claude Opus 4.7 --- src/components/Headline/Headline.module.scss | 25 --------- src/styles/404.module.scss | 13 +++++ .../CompletionBar/CompletionBar.module.scss | 8 ++- .../PageSwitcher/PageSwitcher.module.scss | 4 ++ .../ToolHeader/ToolHeader.module.scss | 10 +++- .../_biases/BiasLabel/BiasLabel.module.scss | 8 +-- .../MobileHeader/MobileHeader.module.scss | 51 ++++++++++++++++++- .../_biases/MobileHeader/MobileHeader.tsx | 41 ++++++++++++++- .../CoreViewLayout/CoreViewLayout.module.scss | 6 +-- 9 files changed, 128 insertions(+), 38 deletions(-) diff --git a/src/components/Headline/Headline.module.scss b/src/components/Headline/Headline.module.scss index b2c13dad..3ba63fc7 100644 --- a/src/components/Headline/Headline.module.scss +++ b/src/components/Headline/Headline.module.scss @@ -276,8 +276,6 @@ @media (min-width: 1921px) { .headline { - height: 800px; - .contentWrapper { padding-left: 0; padding-top: 0; @@ -286,29 +284,6 @@ .headlineInfo { justify-content: center; align-items: center; - - .videoContainer { - .poster { - height: 800px; - object-fit: none; - } - - .video { - height: 800px; - object-fit: none; - background-color: #e7e7e7; - } - } - } - } - - .darkTheme { - .headlineInfo { - .videoContainer { - .video { - background-color: #1c1c1c; - } - } } } } diff --git a/src/styles/404.module.scss b/src/styles/404.module.scss index ef723276..29d5e0a2 100644 --- a/src/styles/404.module.scss +++ b/src/styles/404.module.scss @@ -91,3 +91,16 @@ } } } + +:global(body.darkTheme) .pageNotFound { + background-image: none; + background-color: #1b1e26; + + .content { + color: #dadada; + + .image { + filter: invert(1) hue-rotate(180deg); + } + } +} diff --git a/src/uxcore/components/CompletionBar/CompletionBar.module.scss b/src/uxcore/components/CompletionBar/CompletionBar.module.scss index 5d336083..5a7fc3bd 100644 --- a/src/uxcore/components/CompletionBar/CompletionBar.module.scss +++ b/src/uxcore/components/CompletionBar/CompletionBar.module.scss @@ -537,11 +537,15 @@ } .progressBar .levelTxt { - color: rgba(218, 218, 218, 0.55); + color: #dadada; } .step { - color: rgba(218, 218, 218, 0.5); + color: #dadada; + } + + .step:not(.completed):not(.completedMilestone):not(.hoveredLvl):not(.singleHoveredLvl) { + background-image: url("data:image/svg+xml;utf8,"); } .bar, diff --git a/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss b/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss index e7fe1f99..3a9e2ee5 100644 --- a/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss +++ b/src/uxcore/components/PageSwitcher/PageSwitcher.module.scss @@ -95,6 +95,10 @@ $active-color: #359eff; & .Button { border-color: #303338; + & svg path { + fill: #dadada; + } + & .Description { color: #dadada; } diff --git a/src/uxcore/components/ToolHeader/ToolHeader.module.scss b/src/uxcore/components/ToolHeader/ToolHeader.module.scss index 18c1f8a7..8402696a 100644 --- a/src/uxcore/components/ToolHeader/ToolHeader.module.scss +++ b/src/uxcore/components/ToolHeader/ToolHeader.module.scss @@ -13,7 +13,7 @@ $headerHeight: 46px; flex-direction: row; align-items: center; box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.05); - z-index: 2; + z-index: 10; box-sizing: border-box; justify-content: space-between; @@ -550,6 +550,14 @@ $headerHeight: 46px; .openLink { filter: invert(1) brightness(2) saturate(0); } + + .PageSwitcherItem { + color: #dadada; + + svg path { + fill: #dadada; + } + } } @media (max-width: 920px) { diff --git a/src/uxcore/components/_biases/BiasLabel/BiasLabel.module.scss b/src/uxcore/components/_biases/BiasLabel/BiasLabel.module.scss index 018099bd..86a14d1f 100644 --- a/src/uxcore/components/_biases/BiasLabel/BiasLabel.module.scss +++ b/src/uxcore/components/_biases/BiasLabel/BiasLabel.module.scss @@ -224,20 +224,20 @@ $purple-border: #8073ff; @media (min-width: 2500px) { .label { - height: 1.4vh; + height: 0.6vw; .txt { - font-size: 1.2vh; + font-size: 0.45vw; } } } @media (min-width: 3500px) { .label { - height: 1vh; + height: 0.55vw; .txt { - font-size: 0.8vh; + font-size: 0.42vw; } } } diff --git a/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss b/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss index f10c13e5..5e13dca0 100644 --- a/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss +++ b/src/uxcore/components/_biases/MobileHeader/MobileHeader.module.scss @@ -26,6 +26,7 @@ padding-top: 0rem; float: right; display: flex; + align-items: center; gap: 10px; .PodcastWrapper { @@ -41,6 +42,37 @@ & a { font-size: 21px; } + + .themeToggle { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + padding: 0; + background: transparent; + border: 0; + border-radius: 50%; + color: #4a4a4a; + cursor: pointer; + transition: + background-color 0.18s ease, + color 0.18s ease; + + &:hover { + background-color: rgba(0, 0, 0, 0.06); + color: #131313; + } + + &:focus-visible { + outline: 2px solid rgba(76, 140, 193, 0.6); + outline-offset: 2px; + } + + svg { + display: block; + } + } } } @@ -61,8 +93,23 @@ color: #7fb3d5; box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.5); - & .Actions .active > svg { - fill: #7fb3d5; + & .Actions { + .PodcastWrapper > svg { + fill: #dadada; + } + + .active > svg { + fill: #7fb3d5; + } + + .themeToggle { + color: #dadada; + + &:hover { + background-color: rgba(255, 255, 255, 0.08); + color: #ffffff; + } + } } } } diff --git a/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx b/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx index 4134b659..1faa514c 100644 --- a/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx +++ b/src/uxcore/components/_biases/MobileHeader/MobileHeader.tsx @@ -47,7 +47,7 @@ const MobileHeader: FC = ({ const router = useRouter(); const { locale } = router as TRouter; const { accountData, setAccountData } = useContext(GlobalContext); - const [, { isDarkTheme }] = useGlobals(); + const [{ toggleIsDarkTheme }, { isDarkTheme }] = useGlobals(); const { usernameIsTaken, settingsTxt, myProfileTxt } = toolHeaderData[locale]; const imageSrc = useMemo(() => accountData?.picture, [accountData]); const [showDropdown, setShowDropdown] = useState(false); @@ -176,6 +176,45 @@ const MobileHeader: FC = ({
)} + Date: Mon, 25 May 2026 17:15:46 +0200 Subject: [PATCH 3/3] refactor(uxcore): extract SunIcon + MoonIcon, drop inline theme-toggle SVGs Co-Authored-By: Claude Opus 4.7 --- src/uxcore/assets/icons/MoonIcon.tsx | 17 ++++++++++ src/uxcore/assets/icons/SunIcon.tsx | 18 +++++++++++ .../components/ToolHeader/ToolHeader.tsx | 31 ++----------------- .../_biases/MobileHeader/MobileHeader.tsx | 31 ++----------------- 4 files changed, 41 insertions(+), 56 deletions(-) create mode 100644 src/uxcore/assets/icons/MoonIcon.tsx create mode 100644 src/uxcore/assets/icons/SunIcon.tsx diff --git a/src/uxcore/assets/icons/MoonIcon.tsx b/src/uxcore/assets/icons/MoonIcon.tsx new file mode 100644 index 00000000..15fa4ebc --- /dev/null +++ b/src/uxcore/assets/icons/MoonIcon.tsx @@ -0,0 +1,17 @@ +const MoonIcon = () => ( + + + +); + +export default MoonIcon; diff --git a/src/uxcore/assets/icons/SunIcon.tsx b/src/uxcore/assets/icons/SunIcon.tsx new file mode 100644 index 00000000..b5739451 --- /dev/null +++ b/src/uxcore/assets/icons/SunIcon.tsx @@ -0,0 +1,18 @@ +const SunIcon = () => ( + + + + +); + +export default SunIcon; diff --git a/src/uxcore/components/ToolHeader/ToolHeader.tsx b/src/uxcore/components/ToolHeader/ToolHeader.tsx index 21de6552..45b3fe9b 100644 --- a/src/uxcore/components/ToolHeader/ToolHeader.tsx +++ b/src/uxcore/components/ToolHeader/ToolHeader.tsx @@ -3,7 +3,9 @@ import { userInfoUpdate } from '@uxcore/api/uxcat/settings'; import { getUserInfo } from '@uxcore/api/uxcat/users-me'; import CloseIcon from '@uxcore/assets/icons/CloseIcon'; import DiamondIcon from '@uxcore/assets/icons/DiamondIcon'; +import MoonIcon from '@uxcore/assets/icons/MoonIcon'; import PodcastIcon from '@uxcore/assets/icons/PodcastIcon'; +import SunIcon from '@uxcore/assets/icons/SunIcon'; import MobileHeader from '@uxcore/components/_biases/MobileHeader'; import { GlobalContext } from '@uxcore/components/Context/GlobalContext'; import LanguageSwitcher from '@uxcore/components/LanguageSwitcher'; @@ -464,34 +466,7 @@ const ToolHeader: FC = ({ aria-pressed={isDarkTheme} data-cy="theme-toggle" > - {isDarkTheme ? ( - - - - - ) : ( - - - - )} + {isDarkTheme ? : } = ({ aria-pressed={isDarkTheme} data-cy="theme-toggle" > - {isDarkTheme ? ( - - - - - ) : ( - - - - )} + {isDarkTheme ? : }