Files
authser/themes/ecosplay/login/template.ftl
Serreau Jovann 1ed5c020b1 Style Keycloak PatternFly markup in login theme
Pages we don't override with a custom .ftl (change password, OTP,
verify email, required actions, etc.) render their inner form
with Keycloak's stock PatternFly/Bootstrap classes. The brutalist
card shell was styled but the fields inside were not.

Add resources/css/brutalist.css with targeted overrides on
.pf-c-form-control, .pf-c-button, .pf-c-input-group, .checkbox,
.form-group, alerts and headings, then link it from template.ftl
so every Keycloak auto-generated page inherits the E-Cosplay look
without touching each individual .ftl file.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 16:10:55 +02:00

129 lines
5.8 KiB
Plaintext

<#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true displayRequiredFields=false showAnotherWayIfPresent=true>
<!DOCTYPE html>
<html lang="${(locale.currentLanguageTag)!'en'}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="robots" content="noindex, nofollow">
<title>${msg("loginTitle",(realm.displayName!''))}</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="${url.resourcesPath}/css/brutalist.css">
<style>
@keyframes marquee {
0% { transform: translateX(0); }
100% { transform: translateX(-50%); }
}
.animate-marquee {
display: flex;
width: 200%;
animation: marquee 40s linear infinite;
}
body { font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
-webkit-text-fill-color: #111827;
-webkit-box-shadow: 0 0 0px 1000px #ffffff inset;
transition: background-color 5000s ease-in-out 0s;
}
</style>
</head>
<body class="bg-[#fbfbfb] italic min-h-screen flex flex-col overflow-x-hidden ${properties.kcBodyClass!}">
<!-- Background watermark -->
<div aria-hidden="true" class="fixed inset-0 opacity-[0.03] pointer-events-none select-none overflow-hidden">
<span class="text-[30rem] font-black uppercase leading-none block -rotate-12 translate-y-20">ECOSPLAY</span>
</div>
<!-- Top marquee -->
<div class="bg-gray-900 py-4 border-b-4 border-indigo-600 overflow-hidden relative z-10">
<div class="flex whitespace-nowrap animate-marquee italic">
<#list 1..6 as i>
<span class="text-white font-black uppercase mx-8 text-lg opacity-80">
Authentification // E-Cosplay // Communauté Inclusive // Hauts-de-France
</span>
</#list>
</div>
</div>
<main class="flex-grow flex items-center justify-center px-4 py-16 relative z-10">
<div class="w-full max-w-xl">
<!-- Logo above the card -->
<div class="flex justify-center mb-6">
<div class="bg-white border-4 border-gray-900 shadow-[8px_8px_0px_rgba(0,0,0,1)] p-3">
<img src="${url.resourcesPath}/img/logo.jpg" alt="E-Cosplay" class="block w-40 h-40 object-contain" />
</div>
</div>
<!-- Card -->
<div class="bg-white border-4 border-gray-900 shadow-[12px_12px_0px_rgba(0,0,0,1)] p-8 md:p-12">
<!-- Header -->
<div class="mb-8 pb-6 border-b-4 border-gray-900">
<p class="text-indigo-600 font-black uppercase tracking-[0.3em] mb-3 text-xs">// Connexion sécurisée</p>
<h1 class="text-4xl md:text-5xl font-black uppercase tracking-tighter leading-[0.9]">
<#nested "header">
</h1>
</div>
<!-- Messages -->
<#if displayMessage && message?has_content && (message.type != 'warning' || !isAppInitiatedAction??)>
<div class="mb-6 border-4 border-gray-900 p-4 font-black uppercase tracking-tight text-sm shadow-[6px_6px_0px_rgba(0,0,0,1)]
<#if message.type = 'success'>bg-green-200</#if>
<#if message.type = 'warning'>bg-yellow-300</#if>
<#if message.type = 'error'>bg-red-300</#if>
<#if message.type = 'info'>bg-indigo-200</#if>
">
${kcSanitize(message.summary)?no_esc}
</div>
</#if>
<!-- Required fields hint -->
<#if displayRequiredFields>
<p class="mb-6 text-xs font-black uppercase tracking-widest text-gray-500">
<span class="text-red-600">*</span> ${msg("requiredFields")}
</p>
</#if>
<!-- Main form / content -->
<div class="space-y-6">
<#nested "form">
</div>
<!-- Social providers -->
<#nested "socialProviders">
<!-- Info section -->
<#if displayInfo>
<div class="mt-8 pt-6 border-t-4 border-gray-900 text-sm font-bold">
<#nested "info">
</div>
</#if>
</div>
<!-- Locale selector -->
<#if realm.internationalizationEnabled?? && realm.internationalizationEnabled && locale?? && locale.supported?? && locale.supported?size gt 1>
<div class="mt-6 bg-white border-4 border-gray-900 p-3 shadow-[6px_6px_0px_rgba(0,0,0,1)] flex items-center justify-center gap-4 flex-wrap">
<span class="font-black uppercase text-xs tracking-widest text-gray-500">// Langue</span>
<#list locale.supported as l>
<a href="${l.url}" class="font-black uppercase text-xs tracking-widest <#if l.languageTag == locale.currentLanguageTag>text-indigo-600 underline decoration-4 underline-offset-4<#else>text-gray-900 hover:text-indigo-600</#if>">
${l.label}
</a>
</#list>
</div>
</#if>
</div>
</main>
<!-- Footer band -->
<footer class="bg-gray-900 border-t-4 border-indigo-600 py-6 px-4 relative z-10">
<p class="text-center text-white font-black uppercase tracking-widest text-xs italic">
&copy; E-Cosplay // Créer la réalité
</p>
</footer>
</body>
</html>
</#macro>