TorbatYar/frontend/modules/experience/design-system/ExperienceThemeProvider.tsx
Mortezakoohjani 0eec9f729b feat(experience): deploy Experience frontend FE-11.0-11.5 portal
Commit completed Torbat Pages admin frontend module, BFF proxy, routes, and validation artifacts for official platform deploy.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 21:01:50 +03:30

81 lines
2.2 KiB
TypeScript

"use client";
import { createContext, useContext, useEffect, useMemo, type ReactNode } from "react";
export type ExperienceBrandTokens = {
accent?: string;
accentSoft?: string;
success?: string;
warning?: string;
danger?: string;
};
export type ExperienceDirection = "rtl" | "ltr";
type ThemeContextValue = {
direction: ExperienceDirection;
brand: ExperienceBrandTokens;
tenantThemeId?: string | null;
};
const ExperienceThemeContext = createContext<ThemeContextValue>({
direction: "rtl",
brand: {},
tenantThemeId: null,
});
export function useExperienceTheme() {
return useContext(ExperienceThemeContext);
}
/** Applies tenant/brand CSS variables on a scoped subtree; inherits platform light/dark. */
export function ExperienceThemeProvider({
children,
direction = "rtl",
brand,
tenantThemeId,
className,
}: {
children: ReactNode;
direction?: ExperienceDirection;
brand?: ExperienceBrandTokens;
tenantThemeId?: string | null;
className?: string;
}) {
const value = useMemo(
() => ({
direction,
brand: brand ?? {},
tenantThemeId: tenantThemeId ?? null,
}),
[direction, brand, tenantThemeId]
);
useEffect(() => {
const root = document.documentElement;
root.setAttribute("data-experience-dir", direction);
}, [direction]);
const style: React.CSSProperties = {
direction,
...(brand?.accent ? { ["--experience-accent" as string]: brand.accent } : {}),
...(brand?.accentSoft ? { ["--experience-accent-soft" as string]: brand.accentSoft } : {}),
...(brand?.success ? { ["--experience-success" as string]: brand.success } : {}),
...(brand?.warning ? { ["--experience-warning" as string]: brand.warning } : {}),
...(brand?.danger ? { ["--experience-danger" as string]: brand.danger } : {}),
};
return (
<ExperienceThemeContext.Provider value={value}>
<div
className={className}
data-experience-theme={tenantThemeId ?? "default"}
data-experience-dir={direction}
style={style}
>
{children}
</div>
</ExperienceThemeContext.Provider>
);
}