KEYCLOAK-14138 Upgrade OTP login screen
* edited related css and ftl theme resources * added tile component * fixed IE11 compatibility * fixed affected tests Signed-off-by: Peter Zaoral <pzaoral@redhat.com>
This commit is contained in:
parent
a51e0cc484
commit
c8a2f82a50
5 changed files with 225 additions and 26 deletions
|
@ -89,7 +89,7 @@ public class LoginTotpPage extends LanguageComboboxAwarePage {
|
|||
// If false, we don't expect that credentials combobox is available. If true, we expect that it is available on the page
|
||||
public void assertOtpCredentialSelectorAvailability(boolean expectedAvailability) {
|
||||
try {
|
||||
driver.findElement(By.className("card-pf-view-single-select"));
|
||||
driver.findElement(By.className("otp-tile"));
|
||||
Assert.assertTrue(expectedAvailability);
|
||||
} catch (NoSuchElementException nse) {
|
||||
Assert.assertFalse(expectedAvailability);
|
||||
|
@ -114,15 +114,15 @@ public class LoginTotpPage extends LanguageComboboxAwarePage {
|
|||
}
|
||||
|
||||
private By getXPathForLookupAllCards() {
|
||||
return By.xpath("//div[contains(@class, 'card-pf-view-single-select')]//h2");
|
||||
return By.xpath("//div[contains(@class, 'pf-c-tile otp-tile')]");
|
||||
}
|
||||
|
||||
private By getXPathForLookupActiveCard() {
|
||||
return By.xpath("//div[contains(@class, 'card-pf-view-single-select active')]//h2");
|
||||
return By.xpath("//div[contains(@class, 'otp-tile pf-m-selected')]");
|
||||
}
|
||||
|
||||
private By getXPathForLookupCardWithName(String credentialName) {
|
||||
return By.xpath("//div[contains(@class, 'card-pf-view-single-select')]//h2[normalize-space() = '"+ credentialName +"']");
|
||||
return By.xpath("//div[contains(@class, 'otp-tile')][normalize-space() = '"+ credentialName +"']");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
<div class="${properties.kcFormGroupClass!}">
|
||||
<div class="${properties.kcInputWrapperClass!}">
|
||||
<#list otpLogin.userOtpCredentials as otpCredential>
|
||||
<div class="${properties.kcSelectOTPListClass!}">
|
||||
<div class="${properties.kcLoginOTPListClass!}" tabindex="${otpCredential?index}">
|
||||
<input type="hidden" value="${otpCredential.id}">
|
||||
<div class="${properties.kcSelectOTPListItemClass!}">
|
||||
<span class="${properties.kcAuthenticatorOtpCircleClass!}"></span>
|
||||
<h2 class="${properties.kcSelectOTPItemHeadingClass!}">
|
||||
${otpCredential.userLabel}
|
||||
</h2>
|
||||
<div class="${properties.kcLoginOTPListItemHeaderClass!}">
|
||||
<div class="${properties.kcLoginOTPListItemIconBodyClass!}">
|
||||
<i class="${properties.kcLoginOTPListItemIconClass!}" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="${properties.kcLoginOTPListItemTitleClass!}">${otpCredential.userLabel}</div>
|
||||
</div>
|
||||
</div>
|
||||
</#list>
|
||||
|
@ -58,16 +58,16 @@
|
|||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
// Card Single Select
|
||||
$('.card-pf-view-single-select').click(function() {
|
||||
if ($(this).hasClass('active'))
|
||||
{ $(this).removeClass('active'); $(this).children().removeAttr('name'); }
|
||||
$('.otp-tile').click(function() {
|
||||
if ($(this).hasClass('pf-m-selected'))
|
||||
{ $(this).removeClass('pf-m-selected'); $(this).children().removeAttr('name'); }
|
||||
else
|
||||
{ $('.card-pf-view-single-select').removeClass('active');
|
||||
$('.card-pf-view-single-select').children().removeAttr('name');
|
||||
$(this).addClass('active'); $(this).children().attr('name', 'selectedCredentialId'); }
|
||||
{ $('.otp-tile').removeClass('pf-m-selected');
|
||||
$('.otp-tile').children().removeAttr('name');
|
||||
$(this).addClass('pf-m-selected'); $(this).children().attr('name', 'selectedCredentialId'); }
|
||||
});
|
||||
|
||||
var defaultCred = $('.card-pf-view-single-select')[0];
|
||||
var defaultCred = $('.otp-tile')[0];
|
||||
if (defaultCred) {
|
||||
defaultCred.click();
|
||||
}
|
||||
|
|
|
@ -696,10 +696,6 @@ ul#kc-totp-supported-apps {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.login-pf-page .card-pf{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#kc-form-login div.form-group:last-of-type,
|
||||
#kc-register-form div.form-group:last-of-type,
|
||||
#kc-update-profile-form div.form-group:last-of-type {
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
/*Internet Explorer 11 compatibility workaround - IE does not support CSS variables */
|
||||
|
||||
@media all and (-ms-high-contrast: none),
|
||||
(-ms-high-contrast: active) {
|
||||
.pf-c-tile {
|
||||
position: relative;
|
||||
display: -ms-inline-grid;
|
||||
display: inline-grid;
|
||||
padding: 1.5rem 1.5rem 1.5rem 1.5rem;
|
||||
margin-bottom: 0.25rem;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
background-color: #fff;
|
||||
grid-template-rows: -webkit-min-content;
|
||||
-ms-grid-rows: -webkit-min-content;
|
||||
-ms-grid-rows: min-content;
|
||||
grid-template-rows: min-content;
|
||||
}
|
||||
.pf-c-tile::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
content: "";
|
||||
border: 1px solid #d2d2d2;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.pf-c-tile:hover {
|
||||
border: 1px solid #06c;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.pf-c-tile:hover .pf-c-tile__title,
|
||||
.pf-c-tile:hover .pf-c-tile__icon {
|
||||
color: #06c;
|
||||
}
|
||||
.pf-c-tile.pf-m-selected .pf-c-tile__title,
|
||||
.pf-c-tile.pf-m-selected .pf-c-tile__icon {
|
||||
color: #06c;
|
||||
}
|
||||
.pf-c-tile.pf-m-selected {
|
||||
border: 2px solid #06c;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.pf-c-tile.pf-m-disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
.pf-c-tile__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.pf-c-tile__header.pf-m-stacked {
|
||||
flex-direction: column;
|
||||
justify-content: initial;
|
||||
}
|
||||
.pf-c-tile__header.pf-m-stacked .pf-c-tile__icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
.pf-c-tile__title {
|
||||
color: #6a6e73;
|
||||
}
|
||||
.pf-c-tile__body {
|
||||
font-size: 0.75rem;
|
||||
color: #6a6e73;
|
||||
}
|
||||
.pf-c-tile__icon {
|
||||
margin-right: 0.5rem;
|
||||
font-size: 1.5rem;
|
||||
color: #6a6e73;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*End of the IE11 workaround*/
|
||||
|
||||
.pf-c-tile {
|
||||
--pf-c-tile--PaddingTop: var(--pf-global--spacer--lg);
|
||||
--pf-c-tile--PaddingRight: var(--pf-global--spacer--lg);
|
||||
--pf-c-tile--PaddingBottom: var(--pf-global--spacer--lg);
|
||||
--pf-c-tile--PaddingLeft: var(--pf-global--spacer--lg);
|
||||
--pf-c-tile--BackgroundColor: var(--pf-global--BackgroundColor--100);
|
||||
--pf-c-tile--before--BorderColor: var(--pf-global--BorderColor--100);
|
||||
--pf-c-tile--before--BorderWidth: var(--pf-global--BorderWidth--sm);
|
||||
--pf-c-tile--before--BorderRadius: var(--pf-global--BorderRadius--sm);
|
||||
--pf-c-tile--hover--before--BorderColor: var(--pf-global--primary-color--100);
|
||||
--pf-c-tile--m-selected--before--BorderWidth: var(--pf-global--BorderWidth--md);
|
||||
--pf-c-tile--m-selected--before--BorderColor: var(--pf-global--primary-color--100);
|
||||
--pf-c-tile--focus--before--BorderWidth: var(--pf-global--BorderWidth--md);
|
||||
--pf-c-tile--focus--before--BorderColor: var(--pf-global--primary-color--100);
|
||||
--pf-c-tile--m-disabled--BackgroundColor: var(--pf-global--disabled-color--300);
|
||||
--pf-c-tile__title--Color: var(--pf-global--Color--100);
|
||||
--pf-c-tile--hover__title--Color: var(--pf-global--primary-color--100);
|
||||
--pf-c-tile--m-selected__title--Color: var(--pf-global--primary-color--100);
|
||||
--pf-c-tile--focus__title--Color: var(--pf-global--primary-color--100);
|
||||
--pf-c-tile--m-disabled__title--Color: var(--pf-global--disabled-color--100);
|
||||
--pf-c-tile__icon--MarginRight: var(--pf-global--spacer--sm);
|
||||
--pf-c-tile__icon--FontSize: var(--pf-global--icon--FontSize--md);
|
||||
--pf-c-tile__icon--Color: var(--pf-global--Color--100);
|
||||
--pf-c-tile--hover__icon--Color: var(--pf-global--primary-color--100);
|
||||
--pf-c-tile--m-selected__icon--Color: var(--pf-global--primary-color--100);
|
||||
--pf-c-tile--m-disabled__icon--Color: var(--pf-global--disabled-color--100);
|
||||
--pf-c-tile--focus__icon--Color: var(--pf-global--primary-color--100);
|
||||
--pf-c-tile__header--m-stacked__icon--MarginBottom: var(--pf-global--spacer--xs);
|
||||
--pf-c-tile__header--m-stacked__icon--FontSize: var(--pf-global--icon--FontSize--lg);
|
||||
--pf-c-tile--m-display-lg__header--m-stacked__icon--FontSize: var(--pf-global--icon--FontSize--xl);
|
||||
--pf-c-tile__body--Color: var(--pf-global--Color--100);
|
||||
--pf-c-tile__body--FontSize: var(--pf-global--FontSize--xs);
|
||||
--pf-c-tile--m-disabled__body--Color: var(--pf-global--disabled-color--100);
|
||||
position: relative;
|
||||
display: inline-grid;
|
||||
padding: var(--pf-c-tile--PaddingTop) var(--pf-c-tile--PaddingRight) var(--pf-c-tile--PaddingBottom) var(--pf-c-tile--PaddingLeft);
|
||||
margin-bottom: 0.25rem;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
background-color: var(--pf-c-tile--BackgroundColor);
|
||||
grid-template-rows: min-content;
|
||||
}
|
||||
|
||||
.pf-c-tile::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
content: "";
|
||||
border: var(--pf-c-tile--before--BorderWidth) solid var(--pf-c-tile--before--BorderColor);
|
||||
border-radius: var(--pf-c-tile--before--BorderRadius);
|
||||
}
|
||||
|
||||
.pf-c-tile:hover {
|
||||
--pf-c-tile__title--Color: var(--pf-c-tile--hover__title--Color);
|
||||
--pf-c-tile__icon--Color: var(--pf-c-tile--hover__icon--Color);
|
||||
--pf-c-tile--before--BorderColor: var(--pf-c-tile--hover--before--BorderColor);
|
||||
}
|
||||
|
||||
.pf-c-tile.pf-m-selected {
|
||||
--pf-c-tile__title--Color: var(--pf-c-tile--m-selected__title--Color);
|
||||
--pf-c-tile__icon--Color: var(--pf-c-tile--m-selected__icon--Color);
|
||||
--pf-c-tile--before--BorderWidth: var(--pf-c-tile--m-selected--before--BorderWidth);
|
||||
--pf-c-tile--before--BorderColor: var(--pf-c-tile--m-selected--before--BorderColor);
|
||||
}
|
||||
|
||||
.pf-c-tile:focus {
|
||||
--pf-c-tile__title--Color: var(--pf-c-tile--focus__title--Color);
|
||||
--pf-c-tile__icon--Color: var(--pf-c-tile--focus__icon--Color);
|
||||
--pf-c-tile--before--BorderWidth: var(--pf-c-tile--focus--before--BorderWidth);
|
||||
--pf-c-tile--before--BorderColor: var(--pf-c-tile--focus--before--BorderColor);
|
||||
}
|
||||
|
||||
.pf-c-tile.pf-m-disabled {
|
||||
--pf-c-tile--BackgroundColor: var(--pf-c-tile--m-disabled--BackgroundColor);
|
||||
--pf-c-tile__title--Color: var(--pf-c-tile--m-disabled__title--Color);
|
||||
--pf-c-tile__body--Color: var(--pf-c-tile--m-disabled__body--Color);
|
||||
--pf-c-tile--before--BorderWidth: 0;
|
||||
--pf-c-tile__icon--Color: var(--pf-c-tile--m-disabled__icon--Color);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.pf-c-tile.pf-m-display-lg .pf-c-tile__header.pf-m-stacked {
|
||||
--pf-c-tile__icon--FontSize: var(--pf-c-tile--m-display-lg__header--m-stacked__icon--FontSize);
|
||||
}
|
||||
|
||||
.pf-c-tile__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.pf-c-tile__header.pf-m-stacked {
|
||||
--pf-c-tile__icon--MarginRight: 0;
|
||||
--pf-c-tile__icon--FontSize: var(--pf-c-tile__header--m-stacked__icon--FontSize);
|
||||
flex-direction: column;
|
||||
justify-content: initial;
|
||||
}
|
||||
|
||||
.pf-c-tile__header.pf-m-stacked .pf-c-tile__icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: var(--pf-c-tile__header--m-stacked__icon--MarginBottom);
|
||||
}
|
||||
|
||||
.pf-c-tile__title {
|
||||
color: var(--pf-c-tile__title--Color);
|
||||
}
|
||||
|
||||
.pf-c-tile__body {
|
||||
font-size: var(--pf-c-tile__body--FontSize);
|
||||
color: var(--pf-c-tile__body--Color);
|
||||
}
|
||||
|
||||
.pf-c-tile__icon {
|
||||
margin-right: var(--pf-c-tile__icon--MarginRight);
|
||||
font-size: var(--pf-c-tile__icon--FontSize);
|
||||
color: var(--pf-c-tile__icon--Color);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
parent=base
|
||||
import=common/keycloak
|
||||
|
||||
styles=css/login.css
|
||||
styles=css/login.css css/tile.css
|
||||
stylesCommon=web_modules/@fortawesome/fontawesome-free/css/icons/all.css web_modules/@patternfly/react-core/dist/styles/base.css web_modules/@patternfly/react-core/dist/styles/app.css node_modules/patternfly/dist/css/patternfly.min.css node_modules/patternfly/dist/css/patternfly-additions.min.css lib/pficon/pficon.css
|
||||
|
||||
meta=viewport==width=device-width,initial-scale=1
|
||||
|
@ -98,10 +98,11 @@ kcAuthenticatorWebAuthnClass=fa fa-key list-view-pf-icon-lg
|
|||
kcAuthenticatorWebAuthnPasswordlessClass=fa fa-key list-view-pf-icon-lg
|
||||
|
||||
##### css classes for the OTP Login Form
|
||||
kcSelectOTPListClass=card-pf card-pf-view card-pf-view-select card-pf-view-single-select
|
||||
kcSelectOTPListItemClass=card-pf-body card-pf-top-element
|
||||
kcAuthenticatorOtpCircleClass=fa fa-mobile card-pf-icon-circle
|
||||
kcSelectOTPItemHeadingClass=card-pf-title text-center
|
||||
kcLoginOTPListClass=pf-c-tile otp-tile
|
||||
kcLoginOTPListItemHeaderClass=pf-c-tile__header
|
||||
kcLoginOTPListItemIconBodyClass=pf-c-tile__icon otp-tile-icon
|
||||
kcLoginOTPListItemIconClass=fa fa-mobile
|
||||
kcLoginOTPListItemTitleClass=pf-c-tile__title
|
||||
|
||||
##### css classes for identity providers logos
|
||||
kcCommonLogoIdP=kc-social-provider-logo kc-social-gray
|
||||
|
|
Loading…
Reference in a new issue