Login-page a11y improvements
Closes #27190 Signed-off-by: Peter Keuter <github@peterkeuter.nl>
This commit is contained in:
parent
788d146bf2
commit
9cced05049
4 changed files with 347 additions and 15 deletions
|
@ -11,7 +11,7 @@
|
||||||
<div class="${properties.kcFormGroupClass!}">
|
<div class="${properties.kcFormGroupClass!}">
|
||||||
<label for="username" class="${properties.kcLabelClass!}"><#if !realm.loginWithEmailAllowed>${msg("username")}<#elseif !realm.registrationEmailAsUsername>${msg("usernameOrEmail")}<#else>${msg("email")}</#if></label>
|
<label for="username" class="${properties.kcLabelClass!}"><#if !realm.loginWithEmailAllowed>${msg("username")}<#elseif !realm.registrationEmailAsUsername>${msg("usernameOrEmail")}<#else>${msg("email")}</#if></label>
|
||||||
|
|
||||||
<input tabindex="1" id="username" class="${properties.kcInputClass!}" name="username" value="${(login.username!'')}" type="text" autofocus autocomplete="off"
|
<input tabindex="2" id="username" class="${properties.kcInputClass!}" name="username" value="${(login.username!'')}" type="text" autofocus autocomplete="username"
|
||||||
aria-invalid="<#if messagesPerField.existsError('username','password')>true</#if>"
|
aria-invalid="<#if messagesPerField.existsError('username','password')>true</#if>"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -28,11 +28,11 @@
|
||||||
<label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
|
<label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
|
||||||
|
|
||||||
<div class="${properties.kcInputGroup!}">
|
<div class="${properties.kcInputGroup!}">
|
||||||
<input tabindex="2" id="password" class="${properties.kcInputClass!}" name="password" type="password" autocomplete="off"
|
<input tabindex="3" id="password" class="${properties.kcInputClass!}" name="password" type="password" autocomplete="current-password"
|
||||||
aria-invalid="<#if messagesPerField.existsError('username','password')>true</#if>"
|
aria-invalid="<#if messagesPerField.existsError('username','password')>true</#if>"
|
||||||
/>
|
/>
|
||||||
<button class="${properties.kcFormPasswordVisibilityButtonClass!}" type="button" aria-label="${msg("showPassword")}"
|
<button class="${properties.kcFormPasswordVisibilityButtonClass!}" type="button" aria-label="${msg("showPassword")}"
|
||||||
aria-controls="password" data-password-toggle
|
aria-controls="password" data-password-toggle tabindex="4"
|
||||||
data-icon-show="${properties.kcFormPasswordVisibilityIconShow!}" data-icon-hide="${properties.kcFormPasswordVisibilityIconHide!}"
|
data-icon-show="${properties.kcFormPasswordVisibilityIconShow!}" data-icon-hide="${properties.kcFormPasswordVisibilityIconHide!}"
|
||||||
data-label-show="${msg('showPassword')}" data-label-hide="${msg('hidePassword')}">
|
data-label-show="${msg('showPassword')}" data-label-hide="${msg('hidePassword')}">
|
||||||
<i class="${properties.kcFormPasswordVisibilityIconShow!}" aria-hidden="true"></i>
|
<i class="${properties.kcFormPasswordVisibilityIconShow!}" aria-hidden="true"></i>
|
||||||
|
@ -53,9 +53,9 @@
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<#if login.rememberMe??>
|
<#if login.rememberMe??>
|
||||||
<input tabindex="3" id="rememberMe" name="rememberMe" type="checkbox" checked> ${msg("rememberMe")}
|
<input tabindex="5" id="rememberMe" name="rememberMe" type="checkbox" checked> ${msg("rememberMe")}
|
||||||
<#else>
|
<#else>
|
||||||
<input tabindex="3" id="rememberMe" name="rememberMe" type="checkbox"> ${msg("rememberMe")}
|
<input tabindex="5" id="rememberMe" name="rememberMe" type="checkbox"> ${msg("rememberMe")}
|
||||||
</#if>
|
</#if>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="${properties.kcFormOptionsWrapperClass!}">
|
<div class="${properties.kcFormOptionsWrapperClass!}">
|
||||||
<#if realm.resetPasswordAllowed>
|
<#if realm.resetPasswordAllowed>
|
||||||
<span><a tabindex="5" href="${url.loginResetCredentialsUrl}">${msg("doForgotPassword")}</a></span>
|
<span><a tabindex="6" href="${url.loginResetCredentialsUrl}">${msg("doForgotPassword")}</a></span>
|
||||||
</#if>
|
</#if>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
|
|
||||||
<div id="kc-form-buttons" class="${properties.kcFormGroupClass!}">
|
<div id="kc-form-buttons" class="${properties.kcFormGroupClass!}">
|
||||||
<input type="hidden" id="id-hidden-input" name="credentialId" <#if auth.selectedCredential?has_content>value="${auth.selectedCredential}"</#if>/>
|
<input type="hidden" id="id-hidden-input" name="credentialId" <#if auth.selectedCredential?has_content>value="${auth.selectedCredential}"</#if>/>
|
||||||
<input tabindex="4" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}" name="login" id="kc-login" type="submit" value="${msg("doLogIn")}"/>
|
<input tabindex="7" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}" name="login" id="kc-login" type="submit" value="${msg("doLogIn")}"/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</#if>
|
</#if>
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
<#if realm.password && realm.registrationAllowed && !registrationDisabled??>
|
<#if realm.password && realm.registrationAllowed && !registrationDisabled??>
|
||||||
<div id="kc-registration-container">
|
<div id="kc-registration-container">
|
||||||
<div id="kc-registration">
|
<div id="kc-registration">
|
||||||
<span>${msg("noAccount")} <a tabindex="6"
|
<span>${msg("noAccount")} <a tabindex="8"
|
||||||
href="${url.registrationUrl}">${msg("doRegister")}</a></span>
|
href="${url.registrationUrl}">${msg("doRegister")}</a></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
<#if realm.password && social.providers??>
|
<#if realm.password && social.providers??>
|
||||||
<div id="kc-social-providers" class="${properties.kcFormSocialAccountSectionClass!}">
|
<div id="kc-social-providers" class="${properties.kcFormSocialAccountSectionClass!}">
|
||||||
<hr/>
|
<hr/>
|
||||||
<h4>${msg("identity-provider-login-label")}</h4>
|
<h2>${msg("identity-provider-login-label")}</h2>
|
||||||
|
|
||||||
<ul class="${properties.kcFormSocialAccountListClass!} <#if social.providers?size gt 3>${properties.kcFormSocialAccountListGridClass!}</#if>">
|
<ul class="${properties.kcFormSocialAccountListClass!} <#if social.providers?size gt 3>${properties.kcFormSocialAccountListGridClass!}</#if>">
|
||||||
<#list social.providers as p>
|
<#list social.providers as p>
|
||||||
|
|
|
@ -0,0 +1,315 @@
|
||||||
|
// @ts-check
|
||||||
|
/*
|
||||||
|
* This content is licensed according to the W3C Software License at
|
||||||
|
* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
|
||||||
|
*
|
||||||
|
* File: menu-button-links.js
|
||||||
|
*
|
||||||
|
* Desc: Creates a menu button that opens a menu of links
|
||||||
|
*
|
||||||
|
* Modified by Peter Keuter to adhere to the coding standards of Keycloak
|
||||||
|
* Original file: https://www.w3.org/WAI/content-assets/wai-aria-practices/patterns/menu-button/examples/js/menu-button-links.js
|
||||||
|
* Source: https://www.w3.org/TR/wai-aria-practices/examples/menu-button/menu-button-links.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MenuButtonLinks {
|
||||||
|
constructor(domNode) {
|
||||||
|
this.domNode = domNode;
|
||||||
|
this.buttonNode = domNode.querySelector("button");
|
||||||
|
this.menuNode = domNode.querySelector('[role="menu"]');
|
||||||
|
this.menuitemNodes = [];
|
||||||
|
this.firstMenuitem = false;
|
||||||
|
this.lastMenuitem = false;
|
||||||
|
this.firstChars = [];
|
||||||
|
|
||||||
|
this.buttonNode.addEventListener("keydown", (e) => this.onButtonKeydown(e));
|
||||||
|
this.buttonNode.addEventListener("click", (e) => this.onButtonClick(e));
|
||||||
|
|
||||||
|
const nodes = domNode.querySelectorAll('[role="menuitem"]');
|
||||||
|
|
||||||
|
for (const menuitem of nodes) {
|
||||||
|
this.menuitemNodes.push(menuitem);
|
||||||
|
menuitem.tabIndex = -1;
|
||||||
|
this.firstChars.push(menuitem.textContent.trim()[0].toLowerCase());
|
||||||
|
|
||||||
|
menuitem.addEventListener("keydown", (e) => this.onMenuitemKeydown(e));
|
||||||
|
|
||||||
|
menuitem.addEventListener("mouseover", (e) =>
|
||||||
|
this.onMenuitemMouseover(e)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!this.firstMenuitem) {
|
||||||
|
this.firstMenuitem = menuitem;
|
||||||
|
}
|
||||||
|
this.lastMenuitem = menuitem;
|
||||||
|
}
|
||||||
|
|
||||||
|
domNode.addEventListener("focusin", () => this.onFocusin());
|
||||||
|
domNode.addEventListener("focusout", () => this.onFocusout());
|
||||||
|
|
||||||
|
window.addEventListener(
|
||||||
|
"mousedown",
|
||||||
|
(e) => this.onBackgroundMousedown(e),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setFocusToMenuitem = (newMenuitem) =>
|
||||||
|
this.menuitemNodes.forEach((item) => {
|
||||||
|
if (item === newMenuitem) {
|
||||||
|
item.tabIndex = 0;
|
||||||
|
newMenuitem.focus();
|
||||||
|
} else {
|
||||||
|
item.tabIndex = -1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setFocusToFirstMenuitem = () => this.setFocusToMenuitem(this.firstMenuitem);
|
||||||
|
|
||||||
|
setFocusToLastMenuitem = () => this.setFocusToMenuitem(this.lastMenuitem);
|
||||||
|
|
||||||
|
setFocusToPreviousMenuitem = (currentMenuitem) => {
|
||||||
|
let newMenuitem, index;
|
||||||
|
|
||||||
|
if (currentMenuitem === this.firstMenuitem) {
|
||||||
|
newMenuitem = this.lastMenuitem;
|
||||||
|
} else {
|
||||||
|
index = this.menuitemNodes.indexOf(currentMenuitem);
|
||||||
|
newMenuitem = this.menuitemNodes[index - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setFocusToMenuitem(newMenuitem);
|
||||||
|
|
||||||
|
return newMenuitem;
|
||||||
|
};
|
||||||
|
|
||||||
|
setFocusToNextMenuitem = (currentMenuitem) => {
|
||||||
|
let newMenuitem, index;
|
||||||
|
|
||||||
|
if (currentMenuitem === this.lastMenuitem) {
|
||||||
|
newMenuitem = this.firstMenuitem;
|
||||||
|
} else {
|
||||||
|
index = this.menuitemNodes.indexOf(currentMenuitem);
|
||||||
|
newMenuitem = this.menuitemNodes[index + 1];
|
||||||
|
}
|
||||||
|
this.setFocusToMenuitem(newMenuitem);
|
||||||
|
|
||||||
|
return newMenuitem;
|
||||||
|
};
|
||||||
|
|
||||||
|
setFocusByFirstCharacter = (currentMenuitem, char) => {
|
||||||
|
let start, index;
|
||||||
|
|
||||||
|
if (char.length > 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char = char.toLowerCase();
|
||||||
|
|
||||||
|
// Get start index for search based on position of currentItem
|
||||||
|
start = this.menuitemNodes.indexOf(currentMenuitem) + 1;
|
||||||
|
if (start >= this.menuitemNodes.length) {
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check remaining slots in the menu
|
||||||
|
index = this.firstChars.indexOf(char, start);
|
||||||
|
|
||||||
|
// If not found in remaining slots, check from beginning
|
||||||
|
if (index === -1) {
|
||||||
|
index = this.firstChars.indexOf(char, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If match was found...
|
||||||
|
if (index > -1) {
|
||||||
|
this.setFocusToMenuitem(this.menuitemNodes[index]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
|
||||||
|
getIndexFirstChars = (startIndex, char) => {
|
||||||
|
for (let i = startIndex; i < this.firstChars.length; i++) {
|
||||||
|
if (char === this.firstChars[i]) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Popup menu methods
|
||||||
|
|
||||||
|
openPopup = () => {
|
||||||
|
this.menuNode.style.display = "block";
|
||||||
|
this.buttonNode.setAttribute("aria-expanded", "true");
|
||||||
|
};
|
||||||
|
|
||||||
|
closePopup = () => {
|
||||||
|
if (this.isOpen()) {
|
||||||
|
this.buttonNode.setAttribute("aria-expanded", "false");
|
||||||
|
this.menuNode.style.removeProperty("display");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
isOpen = () => {
|
||||||
|
return this.buttonNode.getAttribute("aria-expanded") === "true";
|
||||||
|
};
|
||||||
|
|
||||||
|
// Menu event handlers
|
||||||
|
|
||||||
|
onFocusin = () => {
|
||||||
|
this.domNode.classList.add("focus");
|
||||||
|
};
|
||||||
|
|
||||||
|
onFocusout = () => {
|
||||||
|
this.domNode.classList.remove("focus");
|
||||||
|
};
|
||||||
|
|
||||||
|
onButtonKeydown = (event) => {
|
||||||
|
const key = event.key;
|
||||||
|
let flag = false;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case " ":
|
||||||
|
case "Enter":
|
||||||
|
case "ArrowDown":
|
||||||
|
case "Down":
|
||||||
|
this.openPopup();
|
||||||
|
this.setFocusToFirstMenuitem();
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Esc":
|
||||||
|
case "Escape":
|
||||||
|
this.closePopup();
|
||||||
|
this.buttonNode.focus();
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Up":
|
||||||
|
case "ArrowUp":
|
||||||
|
this.openPopup();
|
||||||
|
this.setFocusToLastMenuitem();
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onButtonClick(event) {
|
||||||
|
if (this.isOpen()) {
|
||||||
|
this.closePopup();
|
||||||
|
this.buttonNode.focus();
|
||||||
|
} else {
|
||||||
|
this.openPopup();
|
||||||
|
this.setFocusToFirstMenuitem();
|
||||||
|
}
|
||||||
|
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMenuitemKeydown(event) {
|
||||||
|
const tgt = event.currentTarget;
|
||||||
|
const key = event.key;
|
||||||
|
let flag = false;
|
||||||
|
|
||||||
|
const isPrintableCharacter = (str) => str.length === 1 && str.match(/\S/);
|
||||||
|
|
||||||
|
if (event.ctrlKey || event.altKey || event.metaKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.shiftKey) {
|
||||||
|
if (isPrintableCharacter(key)) {
|
||||||
|
this.setFocusByFirstCharacter(tgt, key);
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === "Tab") {
|
||||||
|
this.buttonNode.focus();
|
||||||
|
this.closePopup();
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (key) {
|
||||||
|
case " ":
|
||||||
|
window.location.href = tgt.href;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Esc":
|
||||||
|
case "Escape":
|
||||||
|
this.closePopup();
|
||||||
|
this.buttonNode.focus();
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Up":
|
||||||
|
case "ArrowUp":
|
||||||
|
this.setFocusToPreviousMenuitem(tgt);
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "ArrowDown":
|
||||||
|
case "Down":
|
||||||
|
this.setFocusToNextMenuitem(tgt);
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Home":
|
||||||
|
case "PageUp":
|
||||||
|
this.setFocusToFirstMenuitem();
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "End":
|
||||||
|
case "PageDown":
|
||||||
|
this.setFocusToLastMenuitem();
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Tab":
|
||||||
|
this.closePopup();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (isPrintableCharacter(key)) {
|
||||||
|
this.setFocusByFirstCharacter(tgt, key);
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMenuitemMouseover(event) {
|
||||||
|
const tgt = event.currentTarget;
|
||||||
|
tgt.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
onBackgroundMousedown(event) {
|
||||||
|
if (!this.domNode.contains(event.target)) {
|
||||||
|
if (this.isOpen()) {
|
||||||
|
this.closePopup();
|
||||||
|
this.buttonNode.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const menuButtons = document.querySelectorAll(".menu-button-links");
|
||||||
|
for (const button of menuButtons) {
|
||||||
|
new MenuButtonLinks(button);
|
||||||
|
}
|
|
@ -29,6 +29,7 @@
|
||||||
<script src="${url.resourcesPath}/${script}" type="text/javascript"></script>
|
<script src="${url.resourcesPath}/${script}" type="text/javascript"></script>
|
||||||
</#list>
|
</#list>
|
||||||
</#if>
|
</#if>
|
||||||
|
<script src="${url.resourcesPath}/js/menu-button-links.js" type="module"></script>
|
||||||
<#if scripts??>
|
<#if scripts??>
|
||||||
<#list scripts as script>
|
<#list scripts as script>
|
||||||
<script src="${script}" type="text/javascript"></script>
|
<script src="${script}" type="text/javascript"></script>
|
||||||
|
@ -58,13 +59,15 @@
|
||||||
<#if realm.internationalizationEnabled && locale.supported?size gt 1>
|
<#if realm.internationalizationEnabled && locale.supported?size gt 1>
|
||||||
<div class="${properties.kcLocaleMainClass!}" id="kc-locale">
|
<div class="${properties.kcLocaleMainClass!}" id="kc-locale">
|
||||||
<div id="kc-locale-wrapper" class="${properties.kcLocaleWrapperClass!}">
|
<div id="kc-locale-wrapper" class="${properties.kcLocaleWrapperClass!}">
|
||||||
<div id="kc-locale-dropdown" class="${properties.kcLocaleDropDownClass!}">
|
<div id="kc-locale-dropdown" class="menu-button-links ${properties.kcLocaleDropDownClass!}">
|
||||||
<a href="#" id="kc-current-locale-link">${locale.current}</a>
|
<button tabindex="1" id="kc-current-locale-link" aria-label="${msg("languages")}" aria-haspopup="true" aria-expanded="false" aria-controls="language-switch1">${locale.current}</button>
|
||||||
<ul class="${properties.kcLocaleListClass!}">
|
<ul role="menu" tabindex="-1" aria-labelledby="kc-current-locale-link" aria-activedescendant="" id="language-switch1" class="${properties.kcLocaleListClass!}">
|
||||||
|
<#assign i = 1>
|
||||||
<#list locale.supported as l>
|
<#list locale.supported as l>
|
||||||
<li class="${properties.kcLocaleListItemClass!}">
|
<li class="${properties.kcLocaleListItemClass!}" role="none">
|
||||||
<a class="${properties.kcLocaleItemClass!}" href="${l.url}">${l.label}</a>
|
<a role="menuitem" id="language-${i}" class="${properties.kcLocaleItemClass!}" href="${l.url}">${l.label}</a>
|
||||||
</li>
|
</li>
|
||||||
|
<#assign i++>
|
||||||
</#list>
|
</#list>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -53,7 +53,17 @@ h1#kc-page-title {
|
||||||
font-size: var(--pf-global--FontSize--sm);
|
font-size: var(--pf-global--FontSize--sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
a#kc-current-locale-link::after {
|
#kc-locale-dropdown button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--pf-global--Color--200);
|
||||||
|
text-align: right;
|
||||||
|
font-size: var(--pf-global--FontSize--sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
button#kc-current-locale-link::after {
|
||||||
content: "\2c5";
|
content: "\2c5";
|
||||||
margin-left: var(--pf-global--spacer--xs)
|
margin-left: var(--pf-global--spacer--xs)
|
||||||
}
|
}
|
||||||
|
@ -274,6 +284,10 @@ ul#kc-totp-supported-apps {
|
||||||
color: var(--pf-global--Color--200);
|
color: var(--pf-global--Color--200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kc-social-gray h2 {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
.kc-social-item {
|
.kc-social-item {
|
||||||
margin-bottom: var(--pf-global--spacer--sm);
|
margin-bottom: var(--pf-global--spacer--sm);
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
|
Loading…
Reference in a new issue