From 76f56c1571b75efadf772b6476140c8757124b8e Mon Sep 17 00:00:00 2001 From: Zeusina Date: Wed, 1 Jul 2026 18:30:14 +0000 Subject: [PATCH] feat: add basic glassmorphism --- src/login/KcPage.tsx | 6 +- src/login/Template.tsx | 203 ++++++++++---------- src/login/glass/GlassAmbientBackground.tsx | 71 +++++++ src/login/glass/GlassCard.tsx | 26 +++ src/login/glass/glass-theme.css | 209 +++++++++++++++++++++ src/login/glass/index.ts | 2 + src/login/tailwind.css | 55 +++++- 7 files changed, 462 insertions(+), 110 deletions(-) create mode 100644 src/login/glass/GlassAmbientBackground.tsx create mode 100644 src/login/glass/GlassCard.tsx create mode 100644 src/login/glass/glass-theme.css create mode 100644 src/login/glass/index.ts diff --git a/src/login/KcPage.tsx b/src/login/KcPage.tsx index 19121a1..83c6e42 100644 --- a/src/login/KcPage.tsx +++ b/src/login/KcPage.tsx @@ -100,14 +100,14 @@ const classes = { kcBodyClass: "", kcLoginClass: - "relative z-[1] min-h-screen flex flex-col items-center pt-[15vh] px-4 pb-8 sm:px-[18px] mac-slide-up", + "relative z-[1] min-h-screen flex flex-col items-center justify-center px-4 pb-8 sm:px-[18px] mac-slide-up", kcHeaderWrapperClass: "max-w-[600px] mx-auto", kcHeaderClass: - "mb-6 text-center text-[0.93rem] tracking-[0.01em] text-muted-foreground", + "mb-6 text-center text-[0.93rem] tracking-[0.01em] text-foreground/90 glass-text-stable", kcFormCardClass: - "relative w-full sm:w-[460px] rounded-xl border border-border bg-card px-4 py-5 sm:px-7 sm:py-[30px]", + "glass relative w-full sm:w-[460px] rounded-xl px-4 py-5 sm:px-7 sm:py-[30px]", kcFormHeaderClass: "relative grid grid-cols-[1fr_auto] gap-3 items-baseline mb-1", kcLocaleMainClass: "m-0 col-start-2 row-start-1 flex items-center", diff --git a/src/login/Template.tsx b/src/login/Template.tsx index 94fa89a..c7eab1a 100644 --- a/src/login/Template.tsx +++ b/src/login/Template.tsx @@ -5,7 +5,8 @@ import { getKcClsx } from "keycloakify/login/lib/kcClsx"; import { useSetClassName } from "keycloakify/tools/useSetClassName"; import { useInitialize } from "keycloakify/login/Template.useInitialize"; import type { TemplateProps } from "keycloakify/login/TemplateProps"; -import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"; +import { CardContent, CardFooter, CardHeader } from "@/components/ui/card"; +import { GlassAmbientBackground, GlassCard } from "./glass"; import { Alert, AlertDescription } from "@/components/ui/alert"; import type { KcContext } from "./KcContext"; import type { I18n } from "./i18n"; @@ -86,106 +87,108 @@ export default function Template(props: TemplateProps) { })(); return ( -
-
-
- {msg("loginTitleHtml", realm.displayNameHtml || realm.name)} -
-
- - - - {enabledLanguages.length > 1 && ( -
-
-
- - -
-
-
- )} - {header} -
- - -
- {displayMessage && message !== undefined && (message.type !== "warning" || !isAppInitiatedAction) && ( - - - - )} - - {children} - - {auth !== undefined && auth.showTryAnotherWayLink && ( -
- -
- )} - - {socialProvidersNode} - - {displayInfo && ( -
-
- {infoNode} -
-
- )} + +
+
+
+ {msg("loginTitleHtml", realm.displayNameHtml || realm.name)}
- +
- {infoNode && !displayInfo && {infoNode}} - -
+ + + {enabledLanguages.length > 1 && ( +
+
+
+ + +
+
+
+ )} + {header} +
+ + +
+ {displayMessage && message !== undefined && (message.type !== "warning" || !isAppInitiatedAction) && ( + + + + )} + + {children} + + {auth !== undefined && auth.showTryAnotherWayLink && ( +
+ +
+ )} + + {socialProvidersNode} + + {displayInfo && ( +
+
+ {infoNode} +
+
+ )} +
+
+ + {infoNode && !displayInfo && {infoNode}} +
+
+ ); } diff --git a/src/login/glass/GlassAmbientBackground.tsx b/src/login/glass/GlassAmbientBackground.tsx new file mode 100644 index 0000000..351fdeb --- /dev/null +++ b/src/login/glass/GlassAmbientBackground.tsx @@ -0,0 +1,71 @@ +import * as React from "react"; + +/** + * Animated ambient background for the glassmorphism login theme. + * Uses only CSS transforms/opacity for GPU-composited motion. + * Respects `prefers-reduced-motion` (animation stops) and is aria-hidden. + */ +export function GlassAmbientBackground({ children }: { children: React.ReactNode }) { + return ( + <> +