diff --git a/src/data/webAuthnAuthenticate.ts b/src/data/webAuthnAuthenticate.ts index 8aab5bb94..f1bd8fb4e 100644 --- a/src/data/webAuthnAuthenticate.ts +++ b/src/data/webAuthnAuthenticate.ts @@ -58,7 +58,7 @@ document.addEventListener('alpine:init', () => { } const publicKey: PublicKeyCredentialRequestOptions = { - challenge: base64url.parse(challenge, { loose: true }), + challenge: new Uint8Array(base64url.parse(challenge, { loose: true })), rpId: rpId, }; @@ -121,7 +121,7 @@ document.addEventListener('alpine:init', () => { authnSelectFormElements.forEach((element) => { if (element instanceof HTMLInputElement) { allowCredentials.push({ - id: base64url.parse(element.value, { loose: true }), + id: new Uint8Array(base64url.parse(element.value, { loose: true })), type: 'public-key', }); } diff --git a/src/data/webAuthnRegister.ts b/src/data/webAuthnRegister.ts index 23744df96..f51c41282 100644 --- a/src/data/webAuthnRegister.ts +++ b/src/data/webAuthnRegister.ts @@ -91,7 +91,7 @@ document.addEventListener('alpine:init', () => { excludeCredentialIdsList.forEach((value) => { excludeCredentials.push({ - id: base64url.parse(value, { loose: true }), + id: new Uint8Array(base64url.parse(value, { loose: true })), type: 'public-key', }); }); @@ -121,7 +121,7 @@ document.addEventListener('alpine:init', () => { } const publicKey: PublicKeyCredentialCreationOptions = { - challenge: base64url.parse(challenge, { loose: true }), + challenge: new Uint8Array(base64url.parse(challenge, { loose: true })), pubKeyCredParams: getPubKeyCredParams(signatureAlgorithms), rp: { id: rpId, @@ -129,7 +129,7 @@ document.addEventListener('alpine:init', () => { }, user: { displayName: username, - id: base64url.parse(userId, { loose: true }), + id: new Uint8Array(base64url.parse(userId, { loose: true })), name: username, }, }; diff --git a/src/index.css b/src/index.css index 06248629a..ee6ddebca 100644 --- a/src/index.css +++ b/src/index.css @@ -20,7 +20,7 @@ .separate::after, .separate::before { content: ''; - @apply border-b border-secondary-200 flex-1; + @apply border-b border-secondary-200 dark:border-gray-700 flex-1; } .separate:not(:empty)::after { diff --git a/src/index.ts b/src/index.ts index 213348173..1a9f331d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,3 +5,39 @@ import Alpine from 'alpinejs'; window.Alpine = Alpine; Alpine.start(); + +// Dark mode detection and class management +// This runs after page load to handle dynamic changes +function initDarkMode() { + const htmlElement = document.documentElement; + + // Check if Keycloak has already added the dark class + // If not, detect system preference and add it + const hasDarkClass = htmlElement.classList.contains('dark'); + const hasLightClass = htmlElement.classList.contains('light'); + + if (!hasDarkClass && !hasLightClass) { + // Check system preference + const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + + if (prefersDark) { + htmlElement.classList.add('dark'); + } else { + htmlElement.classList.add('light'); + } + } + + // Listen for system preference changes + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => { + if (e.matches) { + htmlElement.classList.add('dark'); + htmlElement.classList.remove('light'); + } else { + htmlElement.classList.remove('dark'); + htmlElement.classList.add('light'); + } + }); +} + +// Initialize dark mode +initDarkMode(); diff --git a/tailwind.config.ts b/tailwind.config.ts index cb7d1a0d6..67ed04b99 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -3,6 +3,7 @@ import colors from 'tailwindcss/colors'; export default { content: ['./theme/**/*.ftl'], + darkMode: 'class', experimental: { optimizeUniversalDefaults: true, }, diff --git a/theme/keywind/login/components/atoms/alert.ftl b/theme/keywind/login/components/atoms/alert.ftl index 58e8309f0..345e8c1e3 100644 --- a/theme/keywind/login/components/atoms/alert.ftl +++ b/theme/keywind/login/components/atoms/alert.ftl @@ -1,19 +1,19 @@ <#macro kw color=""> <#switch color> <#case "error"> - <#assign colorClass="bg-red-100 text-red-600"> + <#assign colorClass="bg-red-100 dark:bg-red-900/30 text-red-600 dark:text-red-400"> <#break> <#case "info"> - <#assign colorClass="bg-blue-100 text-blue-600"> + <#assign colorClass="bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400"> <#break> <#case "success"> - <#assign colorClass="bg-green-100 text-green-600"> + <#assign colorClass="bg-green-100 dark:bg-green-900/30 text-green-600 dark:text-green-400"> <#break> <#case "warning"> - <#assign colorClass="bg-orange-100 text-orange-600"> + <#assign colorClass="bg-orange-100 dark:bg-orange-900/30 text-orange-600 dark:text-orange-400"> <#break> <#default> - <#assign colorClass="bg-blue-100 text-blue-600"> + <#assign colorClass="bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400">