Skip to content

Commit 890cedb

Browse files
committed
fix: dark mode
1 parent 5cbd3d7 commit 890cedb

3 files changed

Lines changed: 15 additions & 36 deletions

File tree

examples/playground/src/app/providers/VechainKitProviderWrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ export function VechainKitProviderWrapper({ children }: Props) {
226226
]}
227227
darkMode={isDarkMode}
228228
network={{
229-
type: 'test',
229+
type: 'main',
230230
// nodeUrl: 'http://localhost:8669',
231231
}}
232232
allowCustomTokens={true}

packages/vechain-kit/src/theme/theme.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ import {
1616
} from './tokens';
1717

1818
/**
19-
* Best-effort RGBA helper that handles hex (`#rrggbb`), `rgb(...)` and
20-
* `rgba(...)` inputs. Mirrors the logic in `tokens.ts:applyOpacity` (kept
21-
* inline so theme.tsx doesn't pull in the heavier helper that depends on
22-
* `window`).
19+
* Opacity helper that handles hex / rgb(a) literals directly and falls back to
20+
* `color-mix` for anything else (CSS var refs, named colors, etc.) so the
21+
* resolved color tracks host theme changes at paint time. Mirrors
22+
* `tokens.ts:applyOpacity`.
2323
*/
2424
const applyOpacityHelper = (color: string, opacity: number): string => {
2525
const rgba = color.match(
@@ -35,7 +35,8 @@ const applyOpacityHelper = (color: string, opacity: number): string => {
3535
const b = parseInt(hex.slice(4, 6), 16);
3636
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
3737
}
38-
return color;
38+
const percent = Math.round(opacity * 10000) / 100;
39+
return `color-mix(in srgb, ${color} ${percent}%, transparent)`;
3940
};
4041

4142
// minimal theme that completely disables global styles

packages/vechain-kit/src/theme/tokens.ts

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -230,36 +230,14 @@ function applyOpacity(color: string, opacity: number): string {
230230
return hexToRgba(color, opacity);
231231
}
232232

233-
// Try to parse named colors or other formats by creating a temporary element
234-
// This handles CSS named colors like 'red', 'blue', etc.
235-
// Only works in browser environment (not SSR)
236-
if (
237-
typeof window !== 'undefined' &&
238-
typeof document !== 'undefined' &&
239-
document.body
240-
) {
241-
try {
242-
const tempEl = document.createElement('div');
243-
tempEl.style.color = color;
244-
document.body.appendChild(tempEl);
245-
const computedColor = window.getComputedStyle(tempEl).color;
246-
document.body.removeChild(tempEl);
247-
248-
// If we got a valid rgb/rgba color, extract and apply opacity
249-
const computedMatch = computedColor.match(
250-
/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/,
251-
);
252-
if (computedMatch) {
253-
return `rgba(${computedMatch[1]}, ${computedMatch[2]}, ${computedMatch[3]}, ${opacity})`;
254-
}
255-
} catch {
256-
// Fall through to fallback
257-
}
258-
}
259-
260-
// Fallback: return as-is (for SSR or unsupported formats)
261-
// In practice, users should use hex or rgba colors
262-
return color;
233+
// For CSS var() references, named colors, or any other format, emit a
234+
// color-mix expression so the browser resolves the underlying color at
235+
// paint time. This keeps the result reactive to host theme changes (e.g.
236+
// next-themes toggling html.dark) — snapshotting via a temporary DOM
237+
// element here would freeze whichever value the host had applied at
238+
// render time, leaving downstream tokens one toggle behind.
239+
const percent = Math.round(opacity * 10000) / 100;
240+
return `color-mix(in srgb, ${color} ${percent}%, transparent)`;
263241
}
264242

265243
/**

0 commit comments

Comments
 (0)