mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-12 02:38:15 +00:00
feat: design tokens — multi-hospital theming system
Backend (sidecar): - ThemeService: read/write/backup/reset theme.json with versioning - ThemeController: GET/PUT/POST /api/config/theme endpoints - ConfigThemeModule registered in app Frontend: - ThemeTokenProvider: fetches theme, injects CSS variables on <html> - Login page: logo, title, subtitle, Google/forgot toggles from tokens - Sidebar: title, subtitle, active highlight from brand color scale - AI chat: quick actions from tokens - Branding settings page: 2-column layout, file upload for logo/favicon, single color picker with palette generation, font dropdowns, presets, pinned footer, versioning Theme CSS: - Sidebar active/hover text now references --color-brand-400 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,7 @@ import type { NavItemType } from "@/components/application/app-navigation/config
|
||||
import { Avatar } from "@/components/base/avatar/avatar";
|
||||
import { useAuth } from "@/providers/auth-provider";
|
||||
import { useAgentState } from "@/hooks/use-agent-state";
|
||||
import { useThemeTokens } from "@/providers/theme-token-provider";
|
||||
import { sidebarCollapsedAtom } from "@/state/sidebar-state";
|
||||
import { cx } from "@/utils/cx";
|
||||
|
||||
@@ -80,6 +81,7 @@ const getNavSections = (role: string): NavSection[] => {
|
||||
]},
|
||||
{ label: 'Configuration', items: [
|
||||
{ label: 'Rules Engine', href: '/rules', icon: IconSlidersUp },
|
||||
{ label: 'Branding', href: '/branding', icon: IconGear },
|
||||
]},
|
||||
{ label: 'Admin', items: [
|
||||
{ label: 'Settings', href: '/settings', icon: IconGear },
|
||||
@@ -128,6 +130,7 @@ interface SidebarProps {
|
||||
|
||||
export const Sidebar = ({ activeUrl = "/" }: SidebarProps) => {
|
||||
const { logout, user } = useAuth();
|
||||
const { tokens } = useThemeTokens();
|
||||
const navigate = useNavigate();
|
||||
const [collapsed, setCollapsed] = useAtom(sidebarCollapsedAtom);
|
||||
const agentConfig = typeof window !== 'undefined' ? localStorage.getItem('helix_agent_config') : null;
|
||||
@@ -161,11 +164,11 @@ export const Sidebar = ({ activeUrl = "/" }: SidebarProps) => {
|
||||
{/* Logo + collapse toggle */}
|
||||
<div className={cx("flex items-center gap-2", collapsed ? "justify-center px-2" : "justify-between px-4 lg:px-5")}>
|
||||
{collapsed ? (
|
||||
<img src="/favicon-32.png" alt="Helix Engage" className="size-8 rounded-lg shrink-0" />
|
||||
<img src={tokens.brand.logo} alt={tokens.brand.name} className="size-8 rounded-lg shrink-0" />
|
||||
) : (
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-md font-bold text-white">Helix Engage</span>
|
||||
<span className="text-xs text-white opacity-70">Global Hospital · {getRoleSubtitle(user.role)}</span>
|
||||
<span className="text-md font-bold text-white">{tokens.sidebar.title}</span>
|
||||
<span className="text-xs text-white opacity-70">{tokens.sidebar.subtitle.replace('{role}', getRoleSubtitle(user.role))}</span>
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
@@ -204,7 +207,7 @@ export const Sidebar = ({ activeUrl = "/" }: SidebarProps) => {
|
||||
className={cx(
|
||||
"flex size-10 items-center justify-center rounded-lg transition duration-100 ease-linear",
|
||||
item.href === activeUrl
|
||||
? "bg-active text-fg-brand-primary"
|
||||
? "bg-sidebar-active text-sidebar-active"
|
||||
: "text-fg-quaternary hover:bg-(--hover-bg) hover:text-(--hover-text)",
|
||||
)}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user