Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 11 additions & 8 deletions app/src/WebsiteApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Provider } from 'react-redux';
import DevTools from '@/components/DevTools';
import { TooltipProvider } from '@/components/ui/tooltip';
import { AppProvider } from './contexts/AppContext';
import { ThemeProvider } from './contexts/ThemeContext';
import { store } from './store';
import { cacheMonitor } from './utils/cacheMonitor';
import { WebsiteRouter } from './WebsiteRouter';
Expand All @@ -26,14 +27,16 @@ cacheMonitor.init(queryClient);
export default function WebsiteApp() {
return (
<AppProvider mode="website">
<Provider store={store}>
<QueryClientProvider client={queryClient}>
<TooltipProvider>
<WebsiteRouter />
</TooltipProvider>
<DevTools />
</QueryClientProvider>
</Provider>
<ThemeProvider>
<Provider store={store}>
<QueryClientProvider client={queryClient}>
<TooltipProvider>
<WebsiteRouter />
</TooltipProvider>
<DevTools />
</QueryClientProvider>
</Provider>
</ThemeProvider>
</AppProvider>
);
}
106 changes: 106 additions & 0 deletions app/src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,112 @@
--spacing-container: 976px;
}

:root,
:root[data-pe-theme='light'] {
color-scheme: light;
--pe-color-surface-accent: #e6fffa;
--pe-color-surface-overlay: rgb(255 255 255 / 0.9);
--pe-color-surface-hover: #f9fafb;
--pe-shadow-light: rgb(16 24 40 / 0.05);
--pe-shadow-medium: rgb(16 24 40 / 0.1);
--pe-shadow-dark: rgb(16 24 40 / 0.2);

/* Compatibility variables for existing arbitrary Tailwind values. */
--color-primary-400: var(--tw-color-primary-400);
--color-primary-500: var(--tw-color-primary-500);
--color-primary-600: var(--tw-color-primary-600);
}

:root[data-pe-theme='dark'] {
color-scheme: dark;

--tw-color-primary-50: #0f302f;
--tw-color-primary-100: #15504e;
--tw-color-primary-200: #1f6f6c;
--tw-color-primary-300: #2b918d;
--tw-color-primary-400: #38b2ac;
--tw-color-primary-500: #4fd1c5;
--tw-color-primary-600: #63d9cf;
--tw-color-primary-700: #81e6d9;
--tw-color-primary-800: #b2f5ea;
--tw-color-primary-900: #e6fffa;

--tw-color-secondary-50: #101a1c;
--tw-color-secondary-100: #142225;
--tw-color-secondary-200: #1e3337;
--tw-color-secondary-300: #2b484d;
--tw-color-secondary-400: #49666a;
--tw-color-secondary-500: #73898b;
--tw-color-secondary-600: #9fb0b0;
--tw-color-secondary-700: #c5d0cf;
--tw-color-secondary-800: #e1e8e7;
--tw-color-secondary-900: #f5f8f8;

--tw-color-gray-50: #0d1719;
--tw-color-gray-100: #132124;
--tw-color-gray-200: #1d3034;
--tw-color-gray-300: #2c454a;
--tw-color-gray-400: #587276;
--tw-color-gray-500: #8ca0a2;
--tw-color-gray-600: #b5c4c5;
--tw-color-gray-700: #d3dddc;
--tw-color-gray-800: #ebf0ef;
--tw-color-gray-900: #f7fafa;

--tw-color-bg-primary: #071112;
--tw-color-bg-secondary: #0d1c1e;
--tw-color-bg-tertiary: #13272a;
--tw-color-text-primary: #f7fafa;
--tw-color-text-secondary: #bdcaca;
--tw-color-text-tertiary: #899fa1;
--tw-color-text-inverse: #061314;
--tw-color-text-link: #63d9cf;
--tw-color-text-link-hover: #81e6d9;
--tw-color-border-light: #20383c;
--tw-color-border-medium: #315257;
--tw-color-border-dark: #537276;

--tw-color-background: #071112;
--tw-color-foreground: #f7fafa;
--tw-color-primary: #4fd1c5;
--tw-color-primary-foreground: #061314;
--tw-color-secondary: #132124;
--tw-color-secondary-foreground: #f7fafa;
--tw-color-muted: #132124;
--tw-color-muted-foreground: #bdcaca;
--tw-color-accent: #173235;
--tw-color-accent-foreground: #f7fafa;
--tw-color-popover: #0d1c1e;
--tw-color-popover-foreground: #f7fafa;
--tw-color-card: #0d1c1e;
--tw-color-card-foreground: #f7fafa;
--tw-color-border: #20383c;
--tw-color-input: #20383c;
--tw-color-ring: #4fd1c5;

--pe-color-surface-accent: #102d2c;
--pe-color-surface-overlay: rgb(13 28 30 / 0.9);
--pe-color-surface-hover: #173235;
--pe-shadow-light: rgb(0 0 0 / 0.28);
--pe-shadow-medium: rgb(0 0 0 / 0.36);
--pe-shadow-dark: rgb(0 0 0 / 0.48);
}

:root[data-pe-theme='dark'] .tw\:bg-white {
background-color: var(--tw-color-card);
}

:root[data-pe-theme='dark'] .tw\:text-gray-900,
:root[data-pe-theme='dark'] .tw\:text-gray-800,
:root[data-pe-theme='dark'] .tw\:text-gray-700 {
color: var(--tw-color-foreground);
}

:root[data-pe-theme='dark'] .tw\:bg-gray-50,
:root[data-pe-theme='dark'] .tw\:bg-gray-100 {
background-color: var(--tw-color-bg-secondary);
}

/*
* =========================================================
* Base styles
Expand Down
14 changes: 7 additions & 7 deletions app/src/components/IframeContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export default function IframeContent({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: colors.gray[50],
backgroundColor: colors.background.secondary,
zIndex: 1,
}}
>
Expand All @@ -97,14 +97,14 @@ export default function IframeContent({
style={{
width: '48px',
height: '48px',
border: `4px solid ${colors.gray[200]}`,
border: `4px solid ${colors.border.light}`,
borderTop: `4px solid ${colors.primary[600]}`,
borderRadius: '50%',
margin: `0 auto ${spacing.lg}`,
animation: 'spin 1s linear infinite',
}}
/>
<p style={{ color: colors.gray[500], fontSize: typography.fontSize.sm }}>
<p style={{ color: colors.text.secondary, fontSize: typography.fontSize.sm }}>
Loading calculator...
</p>
</div>
Expand All @@ -121,7 +121,7 @@ export default function IframeContent({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: colors.gray[50],
backgroundColor: colors.background.secondary,
zIndex: 1,
}}
>
Expand All @@ -132,10 +132,10 @@ export default function IframeContent({
maxWidth: '500px',
}}
>
<h2 style={{ color: colors.gray[900], marginBottom: spacing.lg }}>
<h2 style={{ color: colors.text.primary, marginBottom: spacing.lg }}>
Unable to load calculator
</h2>
<p style={{ color: colors.gray[500], marginBottom: spacing.lg }}>
<p style={{ color: colors.text.secondary, marginBottom: spacing.lg }}>
The embedded calculator could not be loaded. You can try opening it directly:
</p>
<a
Expand All @@ -146,7 +146,7 @@ export default function IframeContent({
display: 'inline-block',
padding: `${spacing.sm} ${spacing.lg}`,
backgroundColor: colors.primary[600],
color: colors.white,
color: colors.text.inverse,
textDecoration: 'none',
borderRadius: spacing.radius.element,
}}
Expand Down
45 changes: 45 additions & 0 deletions app/src/components/ThemeToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { IconMoon, IconSun } from '@tabler/icons-react';
import { useTheme } from '@/contexts/ThemeContext';
import { colors, spacing } from '@/designTokens';

const buttonSize = 32;

export default function ThemeToggle() {
const { resolvedTheme, toggleTheme } = useTheme();
const isDark = resolvedTheme === 'dark';
const label = isDark ? 'Switch to light mode' : 'Switch to dark mode';
const Icon = isDark ? IconSun : IconMoon;

return (
<button
type="button"
aria-label={label}
aria-pressed={isDark}
title={label}
onClick={toggleTheme}
style={{
width: buttonSize,
height: buttonSize,
borderRadius: spacing.radius.container,
border: `1px solid ${colors.primary.alpha[40]}`,
background: 'rgba(255, 255, 255, 0.1)',
color: colors.text.inverse,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer',
transition: 'background-color 0.15s ease, border-color 0.15s ease',
}}
onMouseEnter={(event) => {
event.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.18)';
event.currentTarget.style.borderColor = colors.primary[300];
}}
onMouseLeave={(event) => {
event.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
event.currentTarget.style.borderColor = colors.primary.alpha[40];
}}
>
<Icon size={18} aria-hidden="true" />
</button>
);
}
6 changes: 3 additions & 3 deletions app/src/components/TwoColumnView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ interface TwoColumnViewProps {
function TwoColumnView({ title, leftColumn, rightColumn, backgroundColor }: TwoColumnViewProps) {
function getBackgroundColor(): string {
if (backgroundColor === 'primary') {
return colors.primary[100];
return colors.background.accent;
}
if (backgroundColor === 'secondary') {
return colors.secondary[100];
return colors.background.secondary;
}
return colors.white;
return colors.background.elevated;
}

return (
Expand Down
4 changes: 2 additions & 2 deletions app/src/components/charts/tooltipStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { colors, spacing } from '@/designTokens';
* Shared tooltip container style for all Recharts custom tooltips.
*/
export const TOOLTIP_STYLE: CSSProperties = {
background: colors.white,
border: `1px solid ${colors.gray[200]}`,
background: colors.background.elevated,
border: `1px solid ${colors.border.light}`,
borderRadius: spacing.radius.element,
padding: `${spacing.sm} ${spacing.md}`,
};
4 changes: 2 additions & 2 deletions app/src/components/common/MetadataLoadingExperience.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ export function MetadataLoadingExperience({ countryId }: MetadataLoadingExperien
return (
<Container>
<Title order={2}>Loading</Title>
<Text className="tw:mb-sm" style={{ color: colors.gray[600] }}>
<Text className="tw:mb-sm" style={{ color: colors.text.secondary }}>
Fetching {countryName} policy data
</Text>
<hr className="tw:border-border-light tw:my-sm" />

<Stack className="tw:items-center tw:justify-center tw:py-20">
<Spinner size="lg" />
<Text size="sm" className="tw:mt-md" style={{ color: colors.gray[600] }}>
<Text size="sm" className="tw:mt-md" style={{ color: colors.text.secondary }}>
This may take a moment for first-time loads
</Text>
</Stack>
Expand Down
18 changes: 9 additions & 9 deletions app/src/components/interactive/StreamlitEmbed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ export default function StreamlitEmbed({
left: 0,
right: 0,
zIndex: 1000,
backgroundColor: colors.gray[100],
borderBottom: `1px solid ${colors.gray[300]}`,
backgroundColor: colors.background.secondary,
borderBottom: `1px solid ${colors.border.light}`,
padding: `${spacing.sm} ${spacing.lg}`,
fontSize: typography.fontSize.sm,
color: colors.gray[600],
color: colors.text.secondary,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
Expand All @@ -92,12 +92,12 @@ export default function StreamlitEmbed({
target="_blank"
rel="noopener noreferrer"
style={{
backgroundColor: colors.white,
border: `1px solid ${colors.gray[300]}`,
backgroundColor: colors.background.elevated,
border: `1px solid ${colors.border.light}`,
borderRadius: spacing.radius.element,
padding: `2px ${spacing.md}`,
fontSize: typography.fontSize.xs,
color: colors.gray[600],
color: colors.text.secondary,
textDecoration: 'none',
display: 'inline-block',
transition: 'all 0.2s',
Expand All @@ -107,8 +107,8 @@ export default function StreamlitEmbed({
e.currentTarget.style.color = colors.primary[500];
}}
onMouseLeave={(e) => {
e.currentTarget.style.borderColor = colors.gray[300];
e.currentTarget.style.color = colors.gray[600];
e.currentTarget.style.borderColor = colors.border.light;
e.currentTarget.style.color = colors.text.secondary;
}}
>
Wake it up
Expand All @@ -120,7 +120,7 @@ export default function StreamlitEmbed({
style={{
background: 'none',
border: 'none',
color: colors.gray[500],
color: colors.text.tertiary,
cursor: 'pointer',
fontSize: '16px',
padding: `0 ${spacing.xs}`,
Expand Down
2 changes: 1 addition & 1 deletion app/src/components/ui/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { cn } from '@/lib/utils';

// Mantine color aliases — "dimmed" was the most common
const COLOR_ALIASES: Record<string, string> = {
dimmed: '#9CA3AF',
dimmed: 'var(--tw-color-text-tertiary)',
};

const textVariants = cva('', {
Expand Down
Loading
Loading