Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f207762
fix(uxc-dark): restore bias-modal questions section + UXCG dark contrast
manager May 15, 2026
463d651
fix(uxc-dark): polish dropdown/button/icon/login contrast in dark mode
manager May 15, 2026
010358e
fix(uxc-dark): drop App-Router usePathname() from Pages-Router layout
manager May 15, 2026
fb2fe14
fix(uxc-dark): more router.asPath hydration leaks on /uxcore#hr
manager May 15, 2026
77085ad
fix(uxc): make View-type + Use-cases switcher buttons clickable
manager May 15, 2026
2fa2586
fix(fonts): consolidate UX Core @font-face into globals.scss
manager May 15, 2026
c8c48a4
Merge branch 'fix/uxc-layout-route-split' into feat/uxc-dark-2
manager May 15, 2026
4621907
fix(uxc-dark): keep lang flags coloured + dark bias-popup tooltip
manager May 15, 2026
5dd51b3
fix(uxc-dark): keep selected navbar icons visible on hover
manager May 15, 2026
6bb7c21
fix(uxc): unblock View-type + Use-cases switcher clicks
manager May 15, 2026
f606465
fix(uxc-dark): make UXCG stage filter buttons visible
manager May 15, 2026
55f030d
fix(uxc-dark): dark theme for Our Projects + Log In modals; kill layo…
manager May 15, 2026
95b7e6d
feat(uxc-dark): Contact Us dark theme + cross-realm theme sync
manager May 15, 2026
b52387b
fix(uxc-dark): unbreak DEV build — pure-selector rule for dark <hr>
manager May 15, 2026
a540f37
fix(uxc-dark): visible X icon + dark + scrollable keepsimple Log In m…
manager May 15, 2026
44a4ff8
feat(uxc-dark): polish modal scroll + fade transitions + UXCP dark mode
manager May 15, 2026
062cbc1
fix(uxc-dark): kill modal-open layout shift; polish UXCP dark theme
manager May 15, 2026
d33b4ed
fix(uxc-dark): unbreak UXCP dark page bg + allow flag CDN
manager May 15, 2026
b7d8f1a
fix(uxc-dark): close the rest of the UXCP dark-mode gaps
manager May 15, 2026
74fea32
fix(uxc-dark): unbreak Decision Table cells + pagination + stage chip
manager May 15, 2026
90da069
fix(uxc-dark): make UXCP cycling subtitle word visible on dark
manager May 15, 2026
c9bf087
fix(uxc-dark): force stage-pill label visible + lift question row text
manager May 15, 2026
f35d16b
feat(uxc-dark): dark theme for the UX Core Awareness Test (/uxcat)
manager May 15, 2026
8f1c6b9
fix(uxc-dark): close the rest of the UXCP dark-mode gaps
manager May 15, 2026
902577b
fix(uxc-dark): visible /uxcat accordion chevron, section titles, tool…
manager May 15, 2026
415dbd0
fix(uxc-dark): address Mary's PR #114 review
manager May 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ module.exports = withBundleAnalyzer({
"default-src 'self'",
`script-src ${scriptSrc}`,
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: blob: https://lh3.googleusercontent.com https://cdn.discordapp.com https://strapi.keepsimple.io https://staging-strapi.keepsimple.io https://www.google-analytics.com",
"img-src 'self' data: blob: https://lh3.googleusercontent.com https://cdn.discordapp.com https://strapi.keepsimple.io https://staging-strapi.keepsimple.io https://www.google-analytics.com https://flagcdn.com",
"font-src 'self' data:",
`connect-src ${connectSrc}`,
"frame-ancestors 'none'",
Expand Down
77 changes: 77 additions & 0 deletions src/components/LogIn/LogIn.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,34 +44,111 @@
justify-content: center;
align-items: center;
gap: 16px;
transition:
transform 0.15s ease,
box-shadow 0.15s ease,
filter 0.15s ease;

svg {
width: 24px;
height: 24px;
}

&:hover {
transform: translateY(-2px);
box-shadow:
0px 6px 10px rgba(0, 0, 0, 0.18),
0px 2px 4px rgba(0, 0, 0, 0.1);
filter: brightness(1.05);
}

&:active {
transform: translateY(0);
box-shadow:
0px 1px 2px rgba(0, 0, 0, 0.2) inset,
0px 1px 1px rgba(0, 0, 0, 0.08);
filter: brightness(0.95);
transition-duration: 0.05s;
}

&:focus-visible {
outline: 2px solid #b83232;
outline-offset: 2px;
}
}
.googleBtn {
background-color: #fff;
color: #0000008a;

&:hover {
background-color: #f7f7f7;
}
}
.discordBtn {
background-color: #5865f2;
color: white;

&:hover {
background-color: #4854e0;
}
}
.linkedinBtn {
background-color: #0177b5;
color: white;

&:hover {
background-color: #015d8d;
}
}
.twitterBtn {
background-color: #000;
color: white;

&:hover {
background-color: #1a1a1a;
}
}
.mailruBtn {
background-color: #168de2;
color: white;

&:hover {
background-color: #1078c0;
}
}
.yandexBtn {
background-color: #fc3f1d;
color: white;

&:hover {
background-color: #e0331a;
}
}
}
}

// Dark theme: flip the heading / subtitle to read on the dark modal bg.
// The brand-colored provider buttons stay as-is; only the Google button
// (white bg + dark text) gets a slight border so it doesn't blow out
// against the dark surface.
:global(body.darkTheme) .container {
.heading h3 {
color: #dadada !important;
}

.text {
color: rgba(218, 218, 218, 0.75);
}

.errorBanner {
background: rgba(180, 35, 24, 0.15);
border-color: rgba(245, 194, 199, 0.4);
color: #f5c2c7;
}

.btnWrapper {
.googleBtn {
border: 1px solid #303338;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,60 @@
margin: 0;
text-align: center;
}

// Dark theme: flip the "OR SIGN IN WITH EMAIL" divider, label, email
// input, submit button, banner and confirmation block.
:global(body.darkTheme) {
.divider {
color: rgba(218, 218, 218, 0.55);

&::before,
&::after {
background: #303338;
}
}

.label {
color: #dadada;
}

.input {
background: #151a26;
border-color: #303338;
color: #dadada;

&::placeholder {
color: rgba(218, 218, 218, 0.45);
}

&:focus {
border-color: #b83232;
}
}

.submit {
color: #dadada;
border-color: #303338;
background: transparent;

&:hover:not(:disabled) {
border-color: #b83232;
color: #ff8a8a;
}
}

.confirmation,
.banner {
background: rgba(127, 179, 213, 0.08);
border-color: #303338;
color: rgba(218, 218, 218, 0.85);
}

.confirmationHeading {
color: #dadada;
}

.confirmationBody {
color: rgba(218, 218, 218, 0.75);
}
}
63 changes: 63 additions & 0 deletions src/components/Modal/Modal.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
z-index: 80;
border-radius: 4px;
background-image: url('/keepsimple_/assets/landingPage/landing-bg.webp');
// Constrain wrapper height so a tall children tree (e.g. Log In with
// six providers + email form) does not push the modal above and below
// the viewport. Body has `overflow: auto`, so content scrolls inside.
max-height: calc(100dvh - 32px);
overflow: hidden;

.header {
.hadBorder {
Expand Down Expand Up @@ -146,6 +151,26 @@
.body {
padding: 16px 28px;
overflow: auto;
// Take remaining flex space and allow shrinking below content so
// overflow: auto can engage when wrapper is bounded by max-height.
flex: 1 1 auto;
min-height: 0;

// Slim scrollbar to match the rest of the site (default white/wide
// browser scrollbar is jarring inside the modal chrome).
scrollbar-width: thin;
scrollbar-color: rgba(40, 88, 123, 0.4) transparent;

&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-track {
background: transparent;
}
&::-webkit-scrollbar-thumb {
background: rgba(40, 88, 123, 0.4);
border-radius: 5px;
}
}
}

Expand Down Expand Up @@ -293,3 +318,41 @@
transform: scale(0.97) translateY(8px);
}
}

// Dark theme: re-skin the keepsimple modal chrome (wrapper bg, title,
// header dividers, close-icon SVGs). The wrapper carries a paper-texture
// background image on light theme — clear it out so the dark bg reads
// cleanly.
:global(body.darkTheme) .overlay {
background-color: rgba(0, 0, 0, 0.55);

.wrapper {
background-color: #1b1e26;
background-image: none;
border: 1px solid #303338;

.body {
scrollbar-color: rgba(127, 179, 213, 0.4) transparent;

&::-webkit-scrollbar-thumb {
background: rgba(127, 179, 213, 0.4);
}
}
}

.header {
.title,
.blackTitle,
.grayTitle {
color: #dadada;
}

.grayTitle {
color: rgba(218, 218, 218, 0.55);
}
}

.hasBorder {
border-bottom-color: #303338;
}
}
44 changes: 37 additions & 7 deletions src/hooks/useGlobals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,30 @@ const reducer = (newState: any) => {

/* ACTIONS */

// Cross-realm theme sync. The keepsimple side and the UX Core side each
// ship their own copy of useGlobals (separate module state, separate
// listener arrays). They share the same localStorage key + body class, so
// persistence is fine — but in-memory state diverges when the user toggles
// in one realm and navigates to the other. To keep them in lockstep
// within a single tab we dispatch a window event on every toggle; both
// realms subscribe and mirror the new value into their own state.
const DARK_THEME_EVENT = 'darktheme:change';

if (typeof window !== 'undefined') {
window.addEventListener(DARK_THEME_EVENT, (e: Event) => {
const next = !!(e as CustomEvent).detail?.isDarkTheme;
if (state.isDarkTheme !== next) {
// Side effects (body class, articleRef class, localStorage) are
// already applied by the dispatcher; we only mirror state so this
// realm's listeners re-render with the new value.
if (state.articleRef) {
state.articleRef.classList.toggle('darkTheme', next);
}
reducer({ isDarkTheme: next });
}
});
}

// dark theme action
const toggleIsDarkTheme = () => {
const newThemeState = !state.isDarkTheme;
Expand All @@ -45,6 +69,11 @@ const toggleIsDarkTheme = () => {
state.articleRef.classList.toggle('darkTheme', newThemeState);
}
reducer({ isDarkTheme: newThemeState });
window.dispatchEvent(
new CustomEvent(DARK_THEME_EVENT, {
detail: { isDarkTheme: newThemeState },
}),
);
};

// sidebar action
Expand Down Expand Up @@ -130,14 +159,15 @@ const initUseGlobals = (articleRef: HTMLElement) => {
// Init articleRef
setArticleRef(articleRef);

// Dark theme
// Dark theme — apply localStorage value unconditionally (true OR false)
// so navigation between realms always re-syncs in-memory state.
const isDarkTheme = localStorage.getItem('darkTheme') === 'true';
if (isDarkTheme) {
document.body.classList.add('darkTheme');
if (articleRef) {
articleRef.classList.add('darkTheme');
}
reducer({ isDarkTheme: true });
document.body.classList.toggle('darkTheme', isDarkTheme);
if (articleRef) {
articleRef.classList.toggle('darkTheme', isDarkTheme);
}
if (state.isDarkTheme !== isDarkTheme) {
reducer({ isDarkTheme });
}

window.addEventListener('resize', handleSidebarChanges);
Expand Down
14 changes: 13 additions & 1 deletion src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { LongevityProvider, useLongevity } from '../context/LongevityContext';
import '../styles/globals.scss';
import '../styles/vibesuite.scss';
import '../styles/ai-atlas.css';
import '../uxcore/styles/uxcore-fonts.scss';
// import '../styles/tom.scss';

type TApp = {
Expand Down Expand Up @@ -122,6 +121,19 @@ function AppContent({ Component, pageProps: { session, ...pageProps } }: TApp) {
});
}, []);

// Cold-load dark-theme bootstrap: not every route calls initUseGlobals
// on mount (e.g. /uxcore, /uxcg). Read the persisted flag once at the
// app root so dark theme applies on any deep-link, and dispatch the
// cross-realm sync event so both useGlobals stores see the value.
useEffect(() => {
if (typeof window === 'undefined') return;
const isDarkTheme = localStorage.getItem('darkTheme') === 'true';
document.body.classList.toggle('darkTheme', isDarkTheme);
window.dispatchEvent(
new CustomEvent('darktheme:change', { detail: { isDarkTheme } }),
);
}, []);

useEffect(() => {
initUseMobile();

Expand Down
Loading
Loading