mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-30 02:52:16 +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" />
63 lines
2.0 KiB
TypeScript
63 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect } from "react";
|
|
import { getThemeConfig } from "./theme";
|
|
|
|
/**
|
|
* Custom hook that returns the effective layout mode, taking into account
|
|
* both the theme configuration and responsive breakpoints.
|
|
*
|
|
* On medium screens and below (md: max-width 767px), it will automatically
|
|
* switch to top-to-bottom layout regardless of the theme setting.
|
|
*
|
|
* NOTE: This is a client-side hook and requires "use client" directive.
|
|
*/
|
|
export function useResponsiveLayout(): { isSideBySide: boolean; isResponsiveOverride: boolean } {
|
|
const themeConfig = getThemeConfig();
|
|
const [isMdOrSmaller, setIsMdOrSmaller] = useState(false);
|
|
const [isHydrated, setIsHydrated] = useState(false);
|
|
|
|
useEffect(() => {
|
|
// Mark as hydrated on client side
|
|
setIsHydrated(true);
|
|
|
|
// Check if we're in a browser environment
|
|
if (typeof window === "undefined") {
|
|
return;
|
|
}
|
|
|
|
const mediaQuery = window.matchMedia("(max-width: 767px)"); // md breakpoint is 768px in Tailwind
|
|
|
|
// Set initial value
|
|
setIsMdOrSmaller(mediaQuery.matches);
|
|
|
|
// Listen for changes
|
|
const handleChange = (e: MediaQueryListEvent) => {
|
|
setIsMdOrSmaller(e.matches);
|
|
};
|
|
|
|
mediaQuery.addEventListener("change", handleChange);
|
|
|
|
// Cleanup
|
|
return () => mediaQuery.removeEventListener("change", handleChange);
|
|
}, []);
|
|
|
|
const configuredSideBySide = themeConfig.layout === "side-by-side";
|
|
|
|
// During SSR or before hydration, assume desktop (side-by-side if configured)
|
|
// This prevents hydration mismatches
|
|
const isSideBySide = configuredSideBySide && (isHydrated ? !isMdOrSmaller : true);
|
|
const isResponsiveOverride = configuredSideBySide && isHydrated && isMdOrSmaller;
|
|
|
|
return { isSideBySide, isResponsiveOverride };
|
|
}
|
|
|
|
/**
|
|
* Custom hook that returns the theme configuration for client-side usage.
|
|
*
|
|
* NOTE: This is a client-side hook and requires "use client" directive.
|
|
*/
|
|
export function useThemeConfig() {
|
|
return getThemeConfig();
|
|
}
|