mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-30 14:16:36 +00:00
# Which Problems Are Solved
This PR introduces a comprehensive theme customization system for the
login application with responsive behavior and enhanced visual options.
<img width="1122" height="578" alt="Screenshot 2025-08-19 at 09 55 24"
src="https://github.com/user-attachments/assets/cdcc8948-533d-4e13-bf45-fdcc24acfb2b"
/>
# How the Problems Are Solved
## ✨ Features Added
- **🔄 Responsive Layout System**: Automatic switching between
side-by-side and top-to-bottom layouts based on screen size
- **🖼️ Background Image Support**: Custom background images configurable
via environment variables
- **⚙️ Theme Configuration**: Complete theme system with roundness,
spacing, appearance, and layout options
- **📱 Mobile-First Design**: Intelligent layout adaptation for different
screen sizes
- **🎯 Enhanced Typography**: Improved visual hierarchy with larger
titles in side-by-side mode
## 🏗️ Architecture
- **Server-Safe Theme Functions**: Theme configuration accessible on
both server and client
- **SSR-Safe Hooks**: Proper hydration handling for responsive layouts
- **Component Separation**: Clear boundaries between server and client
components
- **Two-Section Layout**: Consistent content structure across all login
pages
## 🔧 Configuration Options
All theme options are configurable via environment variables:
- `NEXT_PUBLIC_THEME_ROUNDNESS`: `edgy` | `mid` | `full`
- `NEXT_PUBLIC_THEME_LAYOUT`: `side-by-side` | `top-to-bottom`
- `NEXT_PUBLIC_THEME_APPEARANCE`: `flat` | `material`
- `NEXT_PUBLIC_THEME_SPACING`: `regular` | `compact`
- `NEXT_PUBLIC_THEME_BACKGROUND_IMAGE`: Custom background image URL
## 📄 Pages Updated
Updated all major login pages to use the new two-section responsive
layout:
- Login name entry
- Password verification
- MFA verification
- User registration
- Account selection
- Device authorization
- Logout confirmation
## 📚 Documentation
- **THEME_ARCHITECTURE.md**: Complete technical documentation of the
theme system
- **THEME_CUSTOMIZATION.md**: User-friendly guide with examples and
troubleshooting
## 🚀 Benefits
- **Better UX**: Responsive design that works seamlessly across all
devices
- **Brand Flexibility**: Easy customization to match any brand identity
- **Maintainable Code**: Clean separation of concerns and
well-documented architecture
- **Future-Proof**: Extensible system for additional theme options
<img width="580" height="680" alt="Screenshot 2025-08-19 at 09 22 23"
src="https://github.com/user-attachments/assets/9de8da37-6d56-4fe9-b337-5d8ad2a3ba59"
/>
<img width="599" height="689" alt="Screenshot 2025-08-19 at 09 23 45"
src="https://github.com/user-attachments/assets/26a30cc7-4017-4f4b-8b87-a49466c42b94"
/>
<img width="595" height="681" alt="Screenshot 2025-08-19 at 09 23 17"
src="https://github.com/user-attachments/assets/a3d31088-4545-4f36-aafe-1aae1253d677"
/>
(cherry picked from commit 434aeb275a)
46 lines
1.2 KiB
TypeScript
46 lines
1.2 KiB
TypeScript
"use client";
|
|
|
|
import { setTheme } from "@/helpers/colors";
|
|
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
|
import { ReactNode, useEffect } from "react";
|
|
import { useTheme } from "next-themes";
|
|
|
|
type Props = {
|
|
branding: BrandingSettings | undefined;
|
|
children: ReactNode;
|
|
};
|
|
|
|
export const ThemeWrapper = ({ children, branding }: Props) => {
|
|
const { setTheme: setNextTheme } = useTheme();
|
|
|
|
useEffect(() => {
|
|
setTheme(document, branding);
|
|
}, [branding]);
|
|
|
|
// Handle branding themeMode to force specific theme
|
|
useEffect(() => {
|
|
if (branding?.themeMode !== undefined) {
|
|
// Based on the proto definition:
|
|
// THEME_MODE_UNSPECIFIED = 0
|
|
// THEME_MODE_AUTO = 1
|
|
// THEME_MODE_LIGHT = 2
|
|
// THEME_MODE_DARK = 3
|
|
switch (branding.themeMode) {
|
|
case 2: // THEME_MODE_LIGHT
|
|
setNextTheme("light");
|
|
break;
|
|
case 3: // THEME_MODE_DARK
|
|
setNextTheme("dark");
|
|
break;
|
|
case 1: // THEME_MODE_AUTO
|
|
case 0: // THEME_MODE_UNSPECIFIED
|
|
default:
|
|
setNextTheme("system");
|
|
break;
|
|
}
|
|
}
|
|
}, [branding?.themeMode, setNextTheme]);
|
|
|
|
return <div>{children}</div>;
|
|
};
|