Compare commits
2
Commits
78743fb436
...
e6945ca09a
+3
-3
@@ -7,6 +7,8 @@
|
|||||||
# admin/index.css
|
# admin/index.css
|
||||||
# admin/KcAdminUi.tsx
|
# admin/KcAdminUi.tsx
|
||||||
# account/assets/logo.svg
|
# account/assets/logo.svg
|
||||||
|
# account/personal-info/PersonalInfo.tsx
|
||||||
|
# account/root/PageNav.tsx
|
||||||
# admin/assets/logo.svg
|
# admin/assets/logo.svg
|
||||||
# admin/i18n/messages_en.properties
|
# admin/i18n/messages_en.properties
|
||||||
# admin/i18n/messages_zh_Hans.properties
|
# admin/i18n/messages_zh_Hans.properties
|
||||||
@@ -15,6 +17,7 @@
|
|||||||
# email/messages/messages_en.properties
|
# email/messages/messages_en.properties
|
||||||
# email/messages/messages_zh_CN.properties
|
# email/messages/messages_zh_CN.properties
|
||||||
# email/messages/messages_zh_TW.properties
|
# email/messages/messages_zh_TW.properties
|
||||||
|
# account/components/page/Page.tsx
|
||||||
# === Owned files end =====
|
# === Owned files end =====
|
||||||
|
|
||||||
# === @keycloakify/email-native v260007.0.0 ===
|
# === @keycloakify/email-native v260007.0.0 ===
|
||||||
@@ -904,7 +907,6 @@
|
|||||||
/account/i18n/messages_zh_Hans.properties
|
/account/i18n/messages_zh_Hans.properties
|
||||||
/account/i18n/messages_zh_Hant.properties
|
/account/i18n/messages_zh_Hant.properties
|
||||||
/account/organizations/Organizations.tsx
|
/account/organizations/Organizations.tsx
|
||||||
/account/personal-info/PersonalInfo.tsx
|
|
||||||
/account/resources/EditTheResource.tsx
|
/account/resources/EditTheResource.tsx
|
||||||
/account/resources/PermissionRequest.tsx
|
/account/resources/PermissionRequest.tsx
|
||||||
/account/resources/Resources.tsx
|
/account/resources/Resources.tsx
|
||||||
@@ -914,7 +916,6 @@
|
|||||||
/account/resources/ShareTheResource.tsx
|
/account/resources/ShareTheResource.tsx
|
||||||
/account/root/header.module.css
|
/account/root/header.module.css
|
||||||
/account/root/Header.tsx
|
/account/root/Header.tsx
|
||||||
/account/root/PageNav.tsx
|
|
||||||
/account/root/Root.tsx
|
/account/root/Root.tsx
|
||||||
/account/utils/formatDate.ts
|
/account/utils/formatDate.ts
|
||||||
/account/utils/joinPath.ts
|
/account/utils/joinPath.ts
|
||||||
@@ -1074,4 +1075,3 @@
|
|||||||
/account/assets/passkeys/zoho-light.svg
|
/account/assets/passkeys/zoho-light.svg
|
||||||
/account/assets/passkeys/ztpass-light.png
|
/account/assets/passkeys/ztpass-light.png
|
||||||
/account/components/datalist/EmptyRow.tsx
|
/account/components/datalist/EmptyRow.tsx
|
||||||
/account/components/page/Page.tsx
|
|
||||||
|
|||||||
@@ -16,8 +16,12 @@ import { environment } from "./environment";
|
|||||||
import { i18n } from "./i18n/i18n";
|
import { i18n } from "./i18n/i18n";
|
||||||
import { Root } from "./root/Root";
|
import { Root } from "./root/Root";
|
||||||
import { SessionExpirationWarningOverlay } from "../shared/SessionExpirationWarningOverlay";
|
import { SessionExpirationWarningOverlay } from "../shared/SessionExpirationWarningOverlay";
|
||||||
|
import { getKcContext } from "./KcContext";
|
||||||
|
|
||||||
document.title = "NEXUS / ID";
|
const { kcContext } = getKcContext();
|
||||||
|
|
||||||
|
document.documentElement.dataset.kcThemeName = kcContext.themeName;
|
||||||
|
document.title = kcContext.themeName === "class" ? "612 / 账户中心" : "NEXUS / ID";
|
||||||
|
|
||||||
const prI18nInitialized = i18n.init();
|
const prI18nInitialized = i18n.init();
|
||||||
startColorSchemeManagement();
|
startColorSchemeManagement();
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* This file has been claimed for ownership from @keycloakify/keycloak-account-ui version 260700.0.3.
|
||||||
|
* To relinquish ownership and restore this file to its original content, run the following command:
|
||||||
|
*
|
||||||
|
* $ npx keycloakify own --path "account/components/page/Page.tsx" --revert
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import {
|
||||||
|
PageSection,
|
||||||
|
Text,
|
||||||
|
TextContent,
|
||||||
|
Title
|
||||||
|
} from "../../../shared/@patternfly/react-core";
|
||||||
|
import { PropsWithChildren } from "react";
|
||||||
|
|
||||||
|
type PageProps = {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Page = ({ title, description, children }: PropsWithChildren<PageProps>) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PageSection variant="light">
|
||||||
|
<div className="nexus-page-intro">
|
||||||
|
<div className="nexus-page-intro__copy">
|
||||||
|
<span className="nexus-page-intro__kicker">
|
||||||
|
NEXUS / Identity control
|
||||||
|
</span>
|
||||||
|
<TextContent>
|
||||||
|
<Title headingLevel="h1" data-testid="page-heading">
|
||||||
|
{title}
|
||||||
|
</Title>
|
||||||
|
<Text component="p">{description}</Text>
|
||||||
|
</TextContent>
|
||||||
|
</div>
|
||||||
|
<div className="nexus-page-intro__mark" aria-hidden="true">
|
||||||
|
<span>ID</span>
|
||||||
|
<i />
|
||||||
|
<span>ACCOUNT</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PageSection>
|
||||||
|
<PageSection variant="light">{children}</PageSection>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,259 @@
|
|||||||
|
/**
|
||||||
|
* This file has been claimed for ownership from @keycloakify/keycloak-account-ui version 260700.0.3.
|
||||||
|
* To relinquish ownership and restore this file to its original content, run the following command:
|
||||||
|
*
|
||||||
|
* $ npx keycloakify own --path "account/personal-info/PersonalInfo.tsx" --revert
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import {
|
||||||
|
UserProfileFields,
|
||||||
|
beerify,
|
||||||
|
debeerify,
|
||||||
|
setUserProfileServerError,
|
||||||
|
useEnvironment
|
||||||
|
} from "../../shared/keycloak-ui-shared";
|
||||||
|
import {
|
||||||
|
ActionGroup,
|
||||||
|
Alert,
|
||||||
|
AlertVariant,
|
||||||
|
Button,
|
||||||
|
ExpandableSection,
|
||||||
|
Form,
|
||||||
|
Spinner
|
||||||
|
} from "../../shared/@patternfly/react-core";
|
||||||
|
import { ExternalLinkSquareAltIcon } from "../../shared/@patternfly/react-icons";
|
||||||
|
import { TFunction } from "i18next";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { ErrorOption, useForm } from "react-hook-form";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
import { getPersonalInfo, getSupportedLocales, savePersonalInfo } from "../api/methods";
|
||||||
|
import { UserProfileMetadata, UserRepresentation } from "../api/representations";
|
||||||
|
import { Page } from "../components/page/Page";
|
||||||
|
import { type AccountEnvironment } from "..";
|
||||||
|
import type { TFuncKey } from "../i18n-type";
|
||||||
|
import { useAccountAlerts } from "../utils/useAccountAlerts";
|
||||||
|
import { usePromise } from "../utils/usePromise";
|
||||||
|
|
||||||
|
export const PersonalInfo = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const context = useEnvironment<AccountEnvironment>();
|
||||||
|
const [userProfileMetadata, setUserProfileMetadata] = useState<UserProfileMetadata>();
|
||||||
|
const [supportedLocales, setSupportedLocales] = useState<string[]>([]);
|
||||||
|
const form = useForm<UserRepresentation>({ mode: "onChange" });
|
||||||
|
const { handleSubmit, reset, setValue, setError } = form;
|
||||||
|
const profile = form.watch();
|
||||||
|
const { addAlert } = useAccountAlerts();
|
||||||
|
|
||||||
|
usePromise(
|
||||||
|
signal =>
|
||||||
|
Promise.all([
|
||||||
|
getPersonalInfo({ signal, context }),
|
||||||
|
getSupportedLocales({ signal, context })
|
||||||
|
]),
|
||||||
|
([personalInfo, supportedLocales]) => {
|
||||||
|
setUserProfileMetadata(personalInfo.userProfileMetadata);
|
||||||
|
setSupportedLocales(supportedLocales);
|
||||||
|
reset(personalInfo);
|
||||||
|
Object.entries(personalInfo.attributes || {}).forEach(([k, v]) =>
|
||||||
|
setValue(`attributes[${beerify(k)}]`, v)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const onSubmit = async (user: UserRepresentation) => {
|
||||||
|
try {
|
||||||
|
const attributes = Object.fromEntries(
|
||||||
|
Object.entries(user.attributes || {}).map(([k, v]) => [debeerify(k), v])
|
||||||
|
);
|
||||||
|
await savePersonalInfo(context, { ...user, attributes });
|
||||||
|
const locale = attributes["locale"]?.toString();
|
||||||
|
if (locale) {
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent("languageChanged", { detail: { language: locale } })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await context.keycloak.updateToken();
|
||||||
|
addAlert(t("accountUpdatedMessage"));
|
||||||
|
} catch (error) {
|
||||||
|
addAlert(t("accountUpdatedError"), AlertVariant.danger);
|
||||||
|
|
||||||
|
setUserProfileServerError(
|
||||||
|
{ responseData: { errors: error as any } },
|
||||||
|
(name: string | number, error: unknown) =>
|
||||||
|
setError(name as string, error as ErrorOption),
|
||||||
|
((key: TFuncKey, param?: object) => t(key, param as any)) as TFunction
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!userProfileMetadata) {
|
||||||
|
return <Spinner />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const allFieldsReadOnly = () =>
|
||||||
|
userProfileMetadata.attributes
|
||||||
|
.map(a => a.readOnly)
|
||||||
|
.reduce((p, c) => p && c, true);
|
||||||
|
|
||||||
|
const {
|
||||||
|
updateEmailFeatureEnabled,
|
||||||
|
updateEmailActionEnabled,
|
||||||
|
isRegistrationEmailAsUsername,
|
||||||
|
isEditUserNameAllowed
|
||||||
|
} = context.environment.features;
|
||||||
|
|
||||||
|
const displayName =
|
||||||
|
[profile.firstName, profile.lastName].filter(Boolean).join(" ").trim() ||
|
||||||
|
profile.username ||
|
||||||
|
t("personalInfo");
|
||||||
|
const initials =
|
||||||
|
[profile.firstName, profile.lastName]
|
||||||
|
.filter(Boolean)
|
||||||
|
.map(value => value!.trim().charAt(0))
|
||||||
|
.join("")
|
||||||
|
.slice(0, 2)
|
||||||
|
.toUpperCase() || displayName.slice(0, 2).toUpperCase();
|
||||||
|
const profileLocale =
|
||||||
|
profile.attributes?.locale?.toString() || context.environment.locale;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page title={t("personalInfo")} description={t("personalInfoDescription")}>
|
||||||
|
<div className="nexus-profile-layout">
|
||||||
|
<aside className="nexus-identity-card" aria-label={t("personalInfo")}>
|
||||||
|
<div className="nexus-identity-card__topline">
|
||||||
|
<span>Identity record</span>
|
||||||
|
<i aria-hidden="true" />
|
||||||
|
</div>
|
||||||
|
<div className="nexus-identity-card__avatar" aria-hidden="true">
|
||||||
|
<span>{initials}</span>
|
||||||
|
</div>
|
||||||
|
<div className="nexus-identity-card__name">
|
||||||
|
<span>{t("personalInfo")}</span>
|
||||||
|
<h2>{displayName}</h2>
|
||||||
|
<p>{profile.email || profile.username}</p>
|
||||||
|
</div>
|
||||||
|
<dl className="nexus-identity-card__facts">
|
||||||
|
<div>
|
||||||
|
<dt>{t("username")}</dt>
|
||||||
|
<dd>{profile.username || "—"}</dd>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<dt>{t("email")}</dt>
|
||||||
|
<dd>{profile.email || "—"}</dd>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<dt>Locale</dt>
|
||||||
|
<dd>{profileLocale}</dd>
|
||||||
|
</div>
|
||||||
|
</dl>
|
||||||
|
<div className="nexus-identity-card__footer">
|
||||||
|
<span aria-hidden="true" />
|
||||||
|
NEXUS identity directory
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<section className="nexus-profile-editor">
|
||||||
|
<header className="nexus-profile-editor__header">
|
||||||
|
<span>Profile data</span>
|
||||||
|
<div>
|
||||||
|
<h2>{t("personalInfo")}</h2>
|
||||||
|
<p>{t("personalInfoDescription")}</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<Form isHorizontal onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<UserProfileFields
|
||||||
|
form={form}
|
||||||
|
userProfileMetadata={userProfileMetadata}
|
||||||
|
supportedLocales={supportedLocales}
|
||||||
|
currentLocale={context.environment.locale}
|
||||||
|
t={
|
||||||
|
((key: unknown, params) =>
|
||||||
|
t(key as TFuncKey, params as any)) as TFunction
|
||||||
|
}
|
||||||
|
renderer={attribute => {
|
||||||
|
const annotations = attribute.annotations
|
||||||
|
? attribute.annotations
|
||||||
|
: {};
|
||||||
|
return attribute.name === "email" &&
|
||||||
|
updateEmailFeatureEnabled &&
|
||||||
|
updateEmailActionEnabled &&
|
||||||
|
annotations["kc.required.action.supported"] &&
|
||||||
|
(!isRegistrationEmailAsUsername ||
|
||||||
|
isEditUserNameAllowed) ? (
|
||||||
|
<Button
|
||||||
|
id="update-email-btn"
|
||||||
|
variant="link"
|
||||||
|
onClick={() =>
|
||||||
|
context.keycloak.login({
|
||||||
|
action: "UPDATE_EMAIL"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
icon={<ExternalLinkSquareAltIcon />}
|
||||||
|
iconPosition="right"
|
||||||
|
>
|
||||||
|
{t("updateEmail")}
|
||||||
|
</Button>
|
||||||
|
) : undefined;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{!allFieldsReadOnly() && (
|
||||||
|
<ActionGroup>
|
||||||
|
<Button
|
||||||
|
data-testid="save"
|
||||||
|
type="submit"
|
||||||
|
id="save-btn"
|
||||||
|
variant="primary"
|
||||||
|
>
|
||||||
|
{t("save")}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
data-testid="cancel"
|
||||||
|
id="cancel-btn"
|
||||||
|
variant="link"
|
||||||
|
onClick={() => reset()}
|
||||||
|
>
|
||||||
|
{t("cancel")}
|
||||||
|
</Button>
|
||||||
|
</ActionGroup>
|
||||||
|
)}
|
||||||
|
{context.environment.features.deleteAccountAllowed && (
|
||||||
|
<ExpandableSection
|
||||||
|
data-testid="delete-account"
|
||||||
|
toggleText={t("deleteAccount")}
|
||||||
|
>
|
||||||
|
<Alert
|
||||||
|
isInline
|
||||||
|
title={t("deleteAccount")}
|
||||||
|
variant="danger"
|
||||||
|
actionLinks={
|
||||||
|
<Button
|
||||||
|
id="delete-account-btn"
|
||||||
|
variant="danger"
|
||||||
|
onClick={() =>
|
||||||
|
context.keycloak.login({
|
||||||
|
action: "delete_account"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
className="delete-button"
|
||||||
|
>
|
||||||
|
{t("delete")}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t("deleteAccountWarning")}
|
||||||
|
</Alert>
|
||||||
|
</ExpandableSection>
|
||||||
|
)}
|
||||||
|
</Form>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PersonalInfo;
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
/**
|
||||||
|
* This file has been claimed for ownership from @keycloakify/keycloak-account-ui version 260700.0.3.
|
||||||
|
* To relinquish ownership and restore this file to its original content, run the following command:
|
||||||
|
*
|
||||||
|
* $ npx keycloakify own --path "account/root/PageNav.tsx" --revert
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { useEnvironment } from "../../shared/keycloak-ui-shared";
|
||||||
|
import {
|
||||||
|
Nav,
|
||||||
|
NavExpandable,
|
||||||
|
NavItem,
|
||||||
|
NavList,
|
||||||
|
PageSidebar,
|
||||||
|
PageSidebarBody,
|
||||||
|
Spinner
|
||||||
|
} from "../../shared/@patternfly/react-core";
|
||||||
|
import {
|
||||||
|
Children,
|
||||||
|
PropsWithChildren,
|
||||||
|
MouseEvent as ReactMouseEvent,
|
||||||
|
Suspense,
|
||||||
|
useMemo,
|
||||||
|
useState
|
||||||
|
} from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { matchPath, useHref, useLinkClickHandler, useLocation } from "react-router-dom";
|
||||||
|
import {
|
||||||
|
ApplicationsIcon,
|
||||||
|
BuildingIcon,
|
||||||
|
DesktopIcon,
|
||||||
|
FolderOpenAltIcon,
|
||||||
|
KeyIcon,
|
||||||
|
LinkIcon,
|
||||||
|
ShieldAltIcon,
|
||||||
|
UserAltIcon,
|
||||||
|
UserFriendsIcon
|
||||||
|
} from "../../shared/@patternfly/react-icons";
|
||||||
|
|
||||||
|
import fetchContentJson from "../content/fetchContent";
|
||||||
|
import type { TFuncKey } from "../i18n-type";
|
||||||
|
import type { AccountEnvironment, Feature } from "..";
|
||||||
|
import { usePromise } from "../utils/usePromise";
|
||||||
|
|
||||||
|
type RootMenuItem = {
|
||||||
|
id?: string;
|
||||||
|
label: TFuncKey;
|
||||||
|
path: string;
|
||||||
|
isVisible?: keyof Feature;
|
||||||
|
modulePath?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MenuItemWithChildren = {
|
||||||
|
label: TFuncKey;
|
||||||
|
children: MenuItem[];
|
||||||
|
isVisible?: keyof Feature;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MenuItem = RootMenuItem | MenuItemWithChildren;
|
||||||
|
|
||||||
|
export const PageNav = () => {
|
||||||
|
const [menuItems, setMenuItems] = useState<MenuItem[]>();
|
||||||
|
const context = useEnvironment<AccountEnvironment>();
|
||||||
|
|
||||||
|
usePromise(signal => fetchContentJson({ signal, context }), setMenuItems);
|
||||||
|
return (
|
||||||
|
<PageSidebar>
|
||||||
|
<PageSidebarBody>
|
||||||
|
<div className="nexus-nav-context">
|
||||||
|
<span className="nexus-nav-context__eyebrow">NEXUS / ID</span>
|
||||||
|
<strong>Identity control</strong>
|
||||||
|
<span className="nexus-nav-context__rule" aria-hidden="true" />
|
||||||
|
</div>
|
||||||
|
<Nav>
|
||||||
|
<NavList>
|
||||||
|
<Suspense fallback={<Spinner />}>
|
||||||
|
{menuItems
|
||||||
|
?.filter(menuItem =>
|
||||||
|
menuItem.isVisible
|
||||||
|
? context.environment.features[menuItem.isVisible]
|
||||||
|
: true
|
||||||
|
)
|
||||||
|
.map(menuItem => (
|
||||||
|
<NavMenuItem
|
||||||
|
key={menuItem.label as string}
|
||||||
|
menuItem={menuItem}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Suspense>
|
||||||
|
</NavList>
|
||||||
|
</Nav>
|
||||||
|
</PageSidebarBody>
|
||||||
|
</PageSidebar>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const menuIcons: Record<string, JSX.Element> = {
|
||||||
|
personalInfo: <UserAltIcon />,
|
||||||
|
accountSecurity: <ShieldAltIcon />,
|
||||||
|
signingIn: <KeyIcon />,
|
||||||
|
deviceActivity: <DesktopIcon />,
|
||||||
|
linkedAccounts: <LinkIcon />,
|
||||||
|
applications: <ApplicationsIcon />,
|
||||||
|
verifiableCredentials: <ShieldAltIcon />,
|
||||||
|
groups: <UserFriendsIcon />,
|
||||||
|
organizations: <BuildingIcon />,
|
||||||
|
resources: <FolderOpenAltIcon />
|
||||||
|
};
|
||||||
|
|
||||||
|
const NavLabel = ({ label }: { label: TFuncKey }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className="nexus-nav-label">
|
||||||
|
<span className="nexus-nav-label__icon" aria-hidden="true">
|
||||||
|
{menuIcons[label as string] ?? <UserAltIcon />}
|
||||||
|
</span>
|
||||||
|
<span>{t(label)}</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type NavMenuItemProps = {
|
||||||
|
menuItem: MenuItem;
|
||||||
|
};
|
||||||
|
|
||||||
|
function NavMenuItem({ menuItem }: NavMenuItemProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { environment } = useEnvironment<AccountEnvironment>();
|
||||||
|
const { pathname } = useLocation();
|
||||||
|
const isActive = useMemo(
|
||||||
|
() => matchMenuItem(pathname, menuItem, environment.baseUrl),
|
||||||
|
[pathname, menuItem, environment.baseUrl]
|
||||||
|
);
|
||||||
|
|
||||||
|
if ("path" in menuItem) {
|
||||||
|
return (
|
||||||
|
<NavLink path={menuItem.path} isActive={isActive}>
|
||||||
|
<NavLabel label={menuItem.label} />
|
||||||
|
</NavLink>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavExpandable
|
||||||
|
data-testid={menuItem.label}
|
||||||
|
title={<NavLabel label={menuItem.label} />}
|
||||||
|
isActive={isActive}
|
||||||
|
isExpanded={isActive}
|
||||||
|
>
|
||||||
|
{menuItem.children
|
||||||
|
.filter(menuItem =>
|
||||||
|
menuItem.isVisible ? environment.features[menuItem.isVisible] : true
|
||||||
|
)
|
||||||
|
.map(child => (
|
||||||
|
<NavMenuItem key={child.label as string} menuItem={child} />
|
||||||
|
))}
|
||||||
|
</NavExpandable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFullUrl(path: string, baseUrl: string) {
|
||||||
|
return `${new URL(baseUrl).pathname}${path}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchMenuItem(
|
||||||
|
currentPath: string,
|
||||||
|
menuItem: MenuItem,
|
||||||
|
baseUrl: string
|
||||||
|
): boolean {
|
||||||
|
if ("path" in menuItem) {
|
||||||
|
return !!matchPath(getFullUrl(menuItem.path, baseUrl), currentPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return menuItem.children.some(child => matchMenuItem(currentPath, child, baseUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
type NavLinkProps = {
|
||||||
|
path: string;
|
||||||
|
isActive: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NavLink = ({
|
||||||
|
path,
|
||||||
|
isActive,
|
||||||
|
children
|
||||||
|
}: PropsWithChildren<NavLinkProps>) => {
|
||||||
|
const { environment } = useEnvironment<AccountEnvironment>();
|
||||||
|
const menuItemPath = getFullUrl(path, environment.baseUrl) + location.search;
|
||||||
|
const href = useHref(menuItemPath);
|
||||||
|
const handleClick = useLinkClickHandler(menuItemPath);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavItem
|
||||||
|
data-testid={path}
|
||||||
|
to={href}
|
||||||
|
isActive={isActive}
|
||||||
|
onClick={event =>
|
||||||
|
// PatternFly does not have the correct type for this event, so we need to cast it.
|
||||||
|
handleClick(event as unknown as ReactMouseEvent<HTMLAnchorElement>)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Children.toArray(children)}
|
||||||
|
</NavItem>
|
||||||
|
);
|
||||||
|
};
|
||||||
+957
-138
File diff suppressed because it is too large
Load Diff
@@ -13,9 +13,14 @@ import { createHashRouter, RouterProvider } from "react-router-dom";
|
|||||||
import { i18n } from "./i18n/i18n";
|
import { i18n } from "./i18n/i18n";
|
||||||
import { Root } from "./Root";
|
import { Root } from "./Root";
|
||||||
import { routes } from "./routes";
|
import { routes } from "./routes";
|
||||||
|
import { getKcContext } from "./KcContext";
|
||||||
|
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
|
|
||||||
|
const { kcContext } = getKcContext();
|
||||||
|
|
||||||
|
document.documentElement.dataset.kcThemeName = kcContext.themeName;
|
||||||
|
|
||||||
const router = createHashRouter([
|
const router = createHashRouter([
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
|
|||||||
+561
-121
@@ -1,45 +1,57 @@
|
|||||||
:root {
|
:root {
|
||||||
--nexus-admin-void: #070b16;
|
--nexus-admin-void: #07101e;
|
||||||
--nexus-admin-chrome: #0b1120;
|
--nexus-admin-chrome: #0b1728;
|
||||||
--nexus-admin-panel: #ffffff;
|
--nexus-admin-panel: #ffffff;
|
||||||
--nexus-admin-canvas: #f3f6fb;
|
--nexus-admin-canvas: #f2f5f8;
|
||||||
--nexus-admin-ice: #2dc7e5;
|
--nexus-admin-canvas-strong: #e8edf2;
|
||||||
--nexus-admin-violet: #7569f2;
|
--nexus-admin-signal: #00a3b4;
|
||||||
--nexus-admin-text: #172033;
|
--nexus-admin-signal-bright: #58d7e3;
|
||||||
--nexus-admin-muted: #63708a;
|
--nexus-admin-indigo: #5d63d8;
|
||||||
--nexus-admin-line: #dce3ef;
|
--nexus-admin-mint: #8de3cf;
|
||||||
--pf-v5-global--primary-color--100: #007f9b;
|
--nexus-admin-text: #142033;
|
||||||
--pf-v5-global--primary-color--200: #00677e;
|
--nexus-admin-muted: #607087;
|
||||||
--pf-v5-global--link--Color: #00758d;
|
--nexus-admin-line: #d8e0e8;
|
||||||
--pf-v5-global--link--Color--hover: #004f62;
|
--nexus-admin-line-strong: #becad6;
|
||||||
|
--nexus-admin-danger: #c33d4d;
|
||||||
|
--nexus-admin-radius-sm: 5px;
|
||||||
|
--nexus-admin-radius-md: 9px;
|
||||||
|
--nexus-admin-shadow: 0 1px 2px rgba(20, 32, 51, 0.04),
|
||||||
|
0 12px 34px rgba(20, 32, 51, 0.07);
|
||||||
|
--pf-v5-global--primary-color--100: #007f8e;
|
||||||
|
--pf-v5-global--primary-color--200: #006773;
|
||||||
|
--pf-v5-global--link--Color: #007985;
|
||||||
|
--pf-v5-global--link--Color--hover: #005963;
|
||||||
--pf-v5-global--BackgroundColor--100: var(--nexus-admin-panel);
|
--pf-v5-global--BackgroundColor--100: var(--nexus-admin-panel);
|
||||||
--pf-v5-global--BackgroundColor--150: #f7f9fc;
|
--pf-v5-global--BackgroundColor--150: #f8fafb;
|
||||||
--pf-v5-global--BackgroundColor--200: var(--nexus-admin-canvas);
|
--pf-v5-global--BackgroundColor--200: var(--nexus-admin-canvas);
|
||||||
--pf-v5-global--Color--100: var(--nexus-admin-text);
|
--pf-v5-global--Color--100: var(--nexus-admin-text);
|
||||||
--pf-v5-global--Color--200: var(--nexus-admin-muted);
|
--pf-v5-global--Color--200: var(--nexus-admin-muted);
|
||||||
--pf-v5-global--BorderColor--100: var(--nexus-admin-line);
|
--pf-v5-global--BorderColor--100: var(--nexus-admin-line);
|
||||||
--pf-v5-global--BorderColor--200: #c9d3e2;
|
--pf-v5-global--BorderColor--200: var(--nexus-admin-line-strong);
|
||||||
--pf-v5-c-page__main-section--m-light--BackgroundColor: var(--nexus-admin-canvas);
|
--pf-v5-c-page__main-section--m-light--BackgroundColor: var(--nexus-admin-canvas);
|
||||||
color-scheme: light;
|
color-scheme: light;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-theme-dark {
|
.pf-v5-theme-dark {
|
||||||
--nexus-admin-panel: #101827;
|
--nexus-admin-panel: #111d2e;
|
||||||
--nexus-admin-canvas: #080d18;
|
--nexus-admin-canvas: #08111f;
|
||||||
--nexus-admin-text: #edf3ff;
|
--nexus-admin-canvas-strong: #0d192a;
|
||||||
--nexus-admin-muted: #a6b2c8;
|
--nexus-admin-text: #edf4fb;
|
||||||
--nexus-admin-line: #2d3b52;
|
--nexus-admin-muted: #a6b5c8;
|
||||||
--pf-v5-global--primary-color--100: #55d9ef;
|
--nexus-admin-line: #2a3a50;
|
||||||
--pf-v5-global--primary-color--200: #82e5f5;
|
--nexus-admin-line-strong: #40516a;
|
||||||
--pf-v5-global--link--Color: #67dcef;
|
--nexus-admin-shadow: 0 1px 2px rgba(0, 0, 0, 0.18), 0 16px 40px rgba(0, 0, 0, 0.28);
|
||||||
--pf-v5-global--link--Color--hover: #a6effa;
|
--pf-v5-global--primary-color--100: #58d7e3;
|
||||||
|
--pf-v5-global--primary-color--200: #8de7ee;
|
||||||
|
--pf-v5-global--link--Color: #68dbe5;
|
||||||
|
--pf-v5-global--link--Color--hover: #a0edf2;
|
||||||
--pf-v5-global--BackgroundColor--100: var(--nexus-admin-panel);
|
--pf-v5-global--BackgroundColor--100: var(--nexus-admin-panel);
|
||||||
--pf-v5-global--BackgroundColor--150: #151f30;
|
--pf-v5-global--BackgroundColor--150: #162338;
|
||||||
--pf-v5-global--BackgroundColor--200: var(--nexus-admin-canvas);
|
--pf-v5-global--BackgroundColor--200: var(--nexus-admin-canvas);
|
||||||
--pf-v5-global--Color--100: var(--nexus-admin-text);
|
--pf-v5-global--Color--100: var(--nexus-admin-text);
|
||||||
--pf-v5-global--Color--200: var(--nexus-admin-muted);
|
--pf-v5-global--Color--200: var(--nexus-admin-muted);
|
||||||
--pf-v5-global--BorderColor--100: var(--nexus-admin-line);
|
--pf-v5-global--BorderColor--100: var(--nexus-admin-line);
|
||||||
--pf-v5-global--BorderColor--200: #3a4a63;
|
--pf-v5-global--BorderColor--200: var(--nexus-admin-line-strong);
|
||||||
--pf-v5-c-page__main-section--m-light--BackgroundColor: var(--nexus-admin-canvas);
|
--pf-v5-c-page__main-section--m-light--BackgroundColor: var(--nexus-admin-canvas);
|
||||||
color-scheme: dark;
|
color-scheme: dark;
|
||||||
}
|
}
|
||||||
@@ -51,9 +63,12 @@ body,
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
margin: 0;
|
||||||
color: var(--nexus-admin-text);
|
color: var(--nexus-admin-text);
|
||||||
background: var(--nexus-admin-canvas);
|
background: var(--nexus-admin-canvas);
|
||||||
font-family: "Segoe UI Variable", "Segoe UI", sans-serif;
|
font-family: "Segoe UI Variable", "Segoe UI", system-ui, sans-serif;
|
||||||
|
font-size: 15px;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-page,
|
.pf-v5-c-page,
|
||||||
@@ -63,73 +78,195 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-page__main {
|
.pf-v5-c-page__main {
|
||||||
background-image: linear-gradient(rgba(32, 62, 104, 0.025) 1px, transparent 1px),
|
position: relative;
|
||||||
linear-gradient(90deg, rgba(32, 62, 104, 0.025) 1px, transparent 1px);
|
isolation: isolate;
|
||||||
background-size: 44px 44px;
|
background-image: radial-gradient(
|
||||||
|
circle at 94% 9%,
|
||||||
|
color-mix(in srgb, var(--nexus-admin-signal) 8%, transparent) 0,
|
||||||
|
transparent 24rem
|
||||||
|
),
|
||||||
|
linear-gradient(rgba(41, 73, 104, 0.025) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(41, 73, 104, 0.025) 1px, transparent 1px);
|
||||||
|
background-size:
|
||||||
|
auto,
|
||||||
|
48px 48px,
|
||||||
|
48px 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-masthead {
|
.pf-v5-c-masthead {
|
||||||
border-bottom: 1px solid rgba(99, 230, 255, 0.18);
|
min-height: 72px;
|
||||||
background: linear-gradient(90deg, rgba(99, 230, 255, 0.035), transparent 36%),
|
border-bottom: 1px solid rgba(88, 215, 227, 0.2);
|
||||||
|
background: linear-gradient(90deg, rgba(88, 215, 227, 0.06), transparent 32%),
|
||||||
var(--nexus-admin-void);
|
var(--nexus-admin-void);
|
||||||
box-shadow: 0 8px 28px rgba(5, 9, 21, 0.18);
|
box-shadow: 0 10px 30px rgba(3, 9, 20, 0.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-masthead::after {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: -1px;
|
||||||
|
width: min(36vw, 34rem);
|
||||||
|
height: 1px;
|
||||||
|
background: linear-gradient(90deg, transparent, var(--nexus-admin-signal-bright));
|
||||||
|
content: "";
|
||||||
|
opacity: 0.65;
|
||||||
}
|
}
|
||||||
|
|
||||||
img.keycloak__pageheader_brand {
|
img.keycloak__pageheader_brand {
|
||||||
width: 190px;
|
width: 192px;
|
||||||
height: 38px;
|
height: 42px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
object-position: left center;
|
object-position: left center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-masthead .pf-v5-c-button.pf-m-link,
|
||||||
|
.pf-v5-c-masthead .pf-v5-c-button.pf-m-plain {
|
||||||
|
color: #b9c8da;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-masthead .pf-v5-c-button:hover {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
.pf-v5-c-page__sidebar,
|
.pf-v5-c-page__sidebar,
|
||||||
.pf-v5-c-page__sidebar-body {
|
.pf-v5-c-page__sidebar-body {
|
||||||
border-right: 1px solid rgba(117, 105, 242, 0.16);
|
color: #dce8f5;
|
||||||
color: #d8e2f5;
|
|
||||||
background: radial-gradient(
|
background: radial-gradient(
|
||||||
circle at 20% 88%,
|
circle at 28% 92%,
|
||||||
rgba(99, 230, 255, 0.07),
|
rgba(88, 215, 227, 0.1),
|
||||||
transparent 14rem
|
transparent 15rem
|
||||||
),
|
),
|
||||||
|
linear-gradient(165deg, rgba(93, 99, 216, 0.08), transparent 38%),
|
||||||
var(--nexus-admin-chrome);
|
var(--nexus-admin-chrome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-page__sidebar {
|
||||||
|
width: 284px;
|
||||||
|
border-right: 1px solid rgba(88, 215, 227, 0.14);
|
||||||
|
box-shadow: 12px 0 32px rgba(5, 13, 25, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-page__sidebar-body {
|
||||||
|
position: relative;
|
||||||
|
padding: 1.25rem 0.9rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-page__sidebar-body::before {
|
||||||
|
display: block;
|
||||||
|
width: 72px;
|
||||||
|
height: 10px;
|
||||||
|
margin: 0.15rem 0.8rem 1.1rem;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle,
|
||||||
|
var(--nexus-admin-signal-bright) 0 2px,
|
||||||
|
transparent 2.5px
|
||||||
|
)
|
||||||
|
left center / 12px 10px repeat-x;
|
||||||
|
content: "";
|
||||||
|
opacity: 0.9;
|
||||||
|
mask-image: linear-gradient(90deg, #000 55%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-nav__section-title {
|
||||||
|
padding-inline: 1rem;
|
||||||
|
color: #d9e5f2;
|
||||||
|
font-family: "Bahnschrift SemiCondensed", "Arial Narrow", sans-serif;
|
||||||
|
font-size: 1rem;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-nav__section-title .pf-v5-c-label {
|
||||||
|
margin-top: 0.55rem;
|
||||||
|
border-color: rgba(88, 215, 227, 0.24);
|
||||||
|
color: var(--nexus-admin-signal-bright);
|
||||||
|
background: rgba(88, 215, 227, 0.08);
|
||||||
|
font-family: "Cascadia Code", Consolas, monospace;
|
||||||
|
font-size: 0.62rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-nav__section-title,
|
||||||
|
.pf-v5-c-nav__link,
|
||||||
|
.pf-v5-c-nav__group-title {
|
||||||
|
color: #9fb0c6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-nav__group-title {
|
||||||
|
padding: 1.25rem 1rem 0.45rem;
|
||||||
|
font-family: "Cascadia Code", Consolas, monospace;
|
||||||
|
font-size: 0.65rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-nav__list {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.18rem;
|
||||||
|
}
|
||||||
|
|
||||||
.pf-v5-c-nav__link {
|
.pf-v5-c-nav__link {
|
||||||
border-radius: 2px;
|
position: relative;
|
||||||
color: #9daac3;
|
min-height: 42px;
|
||||||
font-size: 0.86rem;
|
padding: 0.68rem 0.9rem 0.68rem 1rem;
|
||||||
|
border-radius: var(--nexus-admin-radius-sm);
|
||||||
|
font-size: 0.88rem;
|
||||||
|
font-weight: 560;
|
||||||
|
transition:
|
||||||
|
color 150ms ease,
|
||||||
|
background-color 150ms ease,
|
||||||
|
transform 150ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-nav__link:hover,
|
.pf-v5-c-nav__link:hover,
|
||||||
.pf-v5-c-nav__link:focus {
|
.pf-v5-c-nav__link:focus {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
background: rgba(99, 230, 255, 0.06);
|
background: rgba(88, 215, 227, 0.07);
|
||||||
|
transform: translateX(2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-nav__link.pf-m-current,
|
.pf-v5-c-nav__link.pf-m-current,
|
||||||
.pf-v5-c-nav__item.pf-m-current > .pf-v5-c-nav__link {
|
.pf-v5-c-nav__item.pf-m-current > .pf-v5-c-nav__link {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
background: linear-gradient(
|
background: linear-gradient(90deg, rgba(88, 215, 227, 0.16), rgba(93, 99, 216, 0.08));
|
||||||
90deg,
|
box-shadow:
|
||||||
rgba(99, 230, 255, 0.15),
|
inset 3px 0 var(--nexus-admin-signal-bright),
|
||||||
rgba(117, 105, 242, 0.08)
|
0 6px 18px rgba(0, 0, 0, 0.12);
|
||||||
);
|
|
||||||
box-shadow: inset 2px 0 var(--nexus-admin-ice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-nav__link.pf-m-current::after {
|
.pf-v5-c-nav__link.pf-m-current::after {
|
||||||
border-color: transparent;
|
top: 50%;
|
||||||
|
right: 0.85rem;
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--nexus-admin-mint);
|
||||||
|
box-shadow: 0 0 0 4px rgba(141, 227, 207, 0.1);
|
||||||
|
transform: translateY(-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-card,
|
.pf-v5-c-page__main-section,
|
||||||
.pf-v5-c-modal-box,
|
.pf-v5-c-page__main-breadcrumb {
|
||||||
.pf-v5-c-drawer__panel,
|
padding-inline: clamp(1.25rem, 3vw, 3.5rem);
|
||||||
.pf-v5-c-popover__content,
|
}
|
||||||
.pf-v5-c-menu {
|
|
||||||
border: 1px solid var(--nexus-admin-line);
|
.pf-v5-c-page__main-section > *,
|
||||||
border-radius: 3px;
|
.pf-v5-c-page__main-breadcrumb > * {
|
||||||
background: var(--nexus-admin-panel);
|
width: 100%;
|
||||||
box-shadow: 0 15px 42px rgba(27, 43, 72, 0.08);
|
max-width: 1440px;
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-page__main-breadcrumb {
|
||||||
|
border-bottom: 1px solid color-mix(in srgb, var(--nexus-admin-line) 82%, transparent);
|
||||||
|
background: color-mix(in srgb, var(--nexus-admin-panel) 80%, transparent);
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-page__main-section {
|
||||||
|
padding-top: clamp(1.5rem, 2.5vw, 2.75rem);
|
||||||
|
padding-bottom: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-title,
|
.pf-v5-c-title,
|
||||||
@@ -138,115 +275,252 @@ img.keycloak__pageheader_brand {
|
|||||||
.pf-v5-c-page__main-title {
|
.pf-v5-c-page__main-title {
|
||||||
color: var(--nexus-admin-text);
|
color: var(--nexus-admin-text);
|
||||||
font-family: "Bahnschrift SemiCondensed", "Arial Narrow", sans-serif;
|
font-family: "Bahnschrift SemiCondensed", "Arial Narrow", sans-serif;
|
||||||
letter-spacing: -0.018em;
|
letter-spacing: -0.025em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-page__main-breadcrumb {
|
.pf-v5-c-title.pf-m-2xl,
|
||||||
border-bottom: 1px solid rgba(220, 227, 239, 0.74);
|
.pf-v5-c-page__main-title {
|
||||||
background: color-mix(in srgb, var(--nexus-admin-panel) 72%, transparent);
|
font-size: clamp(2rem, 3vw, 2.8rem);
|
||||||
backdrop-filter: blur(12px);
|
line-height: 1.05;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-button {
|
.pf-v5-c-title.pf-m-2xl::before,
|
||||||
border-radius: 2px;
|
.pf-v5-c-page__main-title::before {
|
||||||
font-weight: 620;
|
display: inline-block;
|
||||||
|
width: 0.48rem;
|
||||||
|
height: 0.48rem;
|
||||||
|
margin: 0 0.72rem 0.2rem 0;
|
||||||
|
border: 2px solid var(--nexus-admin-signal);
|
||||||
|
content: "";
|
||||||
|
transform: rotate(45deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-button.pf-m-primary {
|
.pf-v5-c-content > p,
|
||||||
color: #ffffff;
|
.pf-v5-c-helper-text {
|
||||||
background: linear-gradient(105deg, #007f9b, #087f91 58%, #655bd7);
|
color: var(--nexus-admin-muted);
|
||||||
box-shadow: 0 6px 18px rgba(0, 127, 155, 0.16);
|
line-height: 1.65;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-button.pf-m-primary:hover {
|
.pf-v5-c-card,
|
||||||
filter: brightness(1.08);
|
.pf-v5-c-data-list,
|
||||||
}
|
.pf-v5-c-modal-box,
|
||||||
|
.pf-v5-c-drawer__panel,
|
||||||
.pf-v5-c-form-control,
|
.pf-v5-c-popover__content,
|
||||||
.pf-v5-c-select__toggle,
|
.pf-v5-c-menu {
|
||||||
.pf-v5-c-menu-toggle {
|
border: 1px solid var(--nexus-admin-line);
|
||||||
border-radius: 2px;
|
border-radius: var(--nexus-admin-radius-md);
|
||||||
border-color: var(--pf-v5-global--BorderColor--200);
|
|
||||||
color: var(--nexus-admin-text);
|
|
||||||
background: var(--nexus-admin-panel);
|
background: var(--nexus-admin-panel);
|
||||||
box-shadow: none;
|
box-shadow: var(--nexus-admin-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-form-control:focus-within,
|
.pf-v5-c-card {
|
||||||
.pf-v5-c-menu-toggle:focus {
|
overflow: hidden;
|
||||||
border-color: #008eaa;
|
}
|
||||||
box-shadow: 0 0 0 3px rgba(45, 199, 229, 0.12);
|
|
||||||
|
.pf-v5-c-card__title {
|
||||||
|
font-family: "Bahnschrift SemiCondensed", "Arial Narrow", sans-serif;
|
||||||
|
font-size: 1.12rem;
|
||||||
|
letter-spacing: -0.012em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-table {
|
.pf-v5-c-table {
|
||||||
|
overflow: hidden;
|
||||||
border: 1px solid var(--nexus-admin-line);
|
border: 1px solid var(--nexus-admin-line);
|
||||||
|
border-radius: var(--nexus-admin-radius-md);
|
||||||
background: var(--nexus-admin-panel);
|
background: var(--nexus-admin-panel);
|
||||||
|
box-shadow: 0 8px 28px rgba(20, 32, 51, 0.055);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-table thead {
|
.pf-v5-c-table thead {
|
||||||
color: var(--nexus-admin-muted);
|
color: var(--nexus-admin-muted);
|
||||||
background: color-mix(
|
background: color-mix(
|
||||||
in srgb,
|
in srgb,
|
||||||
var(--nexus-admin-panel) 72%,
|
var(--nexus-admin-canvas) 64%,
|
||||||
var(--nexus-admin-canvas)
|
var(--nexus-admin-panel)
|
||||||
);
|
);
|
||||||
font-family: "Cascadia Code", Consolas, monospace;
|
font-family: "Cascadia Code", Consolas, monospace;
|
||||||
font-size: 0.72rem;
|
font-size: 0.69rem;
|
||||||
letter-spacing: 0.025em;
|
letter-spacing: 0.045em;
|
||||||
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-table tr:hover > * {
|
.pf-v5-c-table tr > * {
|
||||||
|
border-bottom-color: var(--nexus-admin-line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-table tbody tr {
|
||||||
|
transition: background-color 140ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-table tbody tr:hover > * {
|
||||||
background-color: color-mix(
|
background-color: color-mix(
|
||||||
in srgb,
|
in srgb,
|
||||||
var(--nexus-admin-ice) 7%,
|
var(--nexus-admin-signal) 5%,
|
||||||
var(--nexus-admin-panel)
|
var(--nexus-admin-panel)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-toolbar {
|
||||||
|
border-radius: var(--nexus-admin-radius-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-toolbar__content {
|
||||||
|
padding-inline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-form__label-text {
|
||||||
|
color: var(--nexus-admin-text);
|
||||||
|
font-weight: 620;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-form__helper-text {
|
||||||
|
color: var(--nexus-admin-muted);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-form-control,
|
||||||
|
.pf-v5-c-select__toggle,
|
||||||
|
.pf-v5-c-menu-toggle,
|
||||||
|
.pf-v5-c-number-input,
|
||||||
|
.pf-v5-c-search-input {
|
||||||
|
min-height: 40px;
|
||||||
|
border-color: var(--nexus-admin-line-strong);
|
||||||
|
border-radius: var(--nexus-admin-radius-sm);
|
||||||
|
color: var(--nexus-admin-text);
|
||||||
|
background: var(--nexus-admin-panel);
|
||||||
|
box-shadow: inset 0 1px 1px rgba(20, 32, 51, 0.025);
|
||||||
|
transition:
|
||||||
|
border-color 140ms ease,
|
||||||
|
box-shadow 140ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-form-control:hover,
|
||||||
|
.pf-v5-c-menu-toggle:hover,
|
||||||
|
.pf-v5-c-search-input:hover {
|
||||||
|
border-color: color-mix(
|
||||||
|
in srgb,
|
||||||
|
var(--nexus-admin-signal) 58%,
|
||||||
|
var(--nexus-admin-line)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-form-control:focus-within,
|
||||||
|
.pf-v5-c-menu-toggle:focus,
|
||||||
|
.pf-v5-c-menu-toggle.pf-m-expanded,
|
||||||
|
.pf-v5-c-search-input:focus-within {
|
||||||
|
border-color: var(--nexus-admin-signal);
|
||||||
|
box-shadow: 0 0 0 3px color-mix(in srgb, var(--nexus-admin-signal) 15%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button {
|
||||||
|
min-height: 38px;
|
||||||
|
border-radius: var(--nexus-admin-radius-sm);
|
||||||
|
font-weight: 650;
|
||||||
|
letter-spacing: 0.005em;
|
||||||
|
transition:
|
||||||
|
transform 140ms ease,
|
||||||
|
box-shadow 140ms ease,
|
||||||
|
filter 140ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button.pf-m-primary {
|
||||||
|
color: #ffffff;
|
||||||
|
background: var(--pf-v5-global--primary-color--100);
|
||||||
|
box-shadow: 0 7px 18px color-mix(in srgb, var(--nexus-admin-signal) 22%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button.pf-m-primary:hover {
|
||||||
|
background: var(--pf-v5-global--primary-color--200);
|
||||||
|
box-shadow: 0 9px 22px color-mix(in srgb, var(--nexus-admin-signal) 28%, transparent);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button.pf-m-secondary {
|
||||||
|
border-color: var(--nexus-admin-line-strong);
|
||||||
|
color: var(--nexus-admin-text);
|
||||||
|
background: var(--nexus-admin-panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-button.pf-m-danger {
|
||||||
|
background: var(--nexus-admin-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-tabs {
|
||||||
|
border-bottom: 1px solid var(--nexus-admin-line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-tabs__link {
|
||||||
|
color: var(--nexus-admin-muted);
|
||||||
|
font-weight: 620;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-tabs__item.pf-m-current .pf-v5-c-tabs__link {
|
||||||
|
color: var(--nexus-admin-text);
|
||||||
|
}
|
||||||
|
|
||||||
.pf-v5-c-tabs__link::after {
|
.pf-v5-c-tabs__link::after {
|
||||||
border-color: var(--nexus-admin-ice);
|
height: 3px;
|
||||||
|
border-color: var(--nexus-admin-signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-c-label {
|
.pf-v5-c-label {
|
||||||
border-radius: 2px;
|
border-radius: 999px;
|
||||||
|
font-weight: 620;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-alert {
|
||||||
|
border: 1px solid var(--nexus-admin-line);
|
||||||
|
border-radius: var(--nexus-admin-radius-md);
|
||||||
|
box-shadow: 0 8px 24px rgba(20, 32, 51, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-empty-state {
|
||||||
|
border: 1px dashed var(--nexus-admin-line-strong);
|
||||||
|
border-radius: var(--nexus-admin-radius-md);
|
||||||
|
background: color-mix(in srgb, var(--nexus-admin-panel) 70%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-pagination {
|
||||||
|
color: var(--nexus-admin-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-pagination .pf-v5-c-menu-toggle,
|
||||||
|
.pf-v5-c-pagination .pf-v5-c-button {
|
||||||
|
min-height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-modal-box {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-modal-box__header {
|
||||||
|
border-bottom: 1px solid var(--nexus-admin-line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-switch__input:checked ~ .pf-v5-c-switch__toggle {
|
||||||
|
background: var(--nexus-admin-signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.keycloak__form {
|
.keycloak__form {
|
||||||
max-width: 1100px;
|
max-width: 1160px;
|
||||||
padding-bottom: var(--pf-v5-global--spacer--4xl);
|
padding-bottom: var(--pf-v5-global--spacer--4xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
vertical-align: baseline;
|
|
||||||
accent-color: #0087a1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.keycloak__form_actions {
|
.keycloak__form_actions {
|
||||||
position: fixed;
|
position: sticky;
|
||||||
z-index: 15;
|
z-index: 15;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 100%;
|
margin: 2rem calc(-1 * clamp(1.25rem, 3vw, 3.5rem)) -4rem;
|
||||||
margin-left: calc(-1 * var(--pf-v5-global--spacer--lg));
|
padding: 0.9rem clamp(1.25rem, 3vw, 3.5rem);
|
||||||
padding: var(--pf-v5-global--spacer--md);
|
|
||||||
border-top: 1px solid var(--nexus-admin-line);
|
border-top: 1px solid var(--nexus-admin-line);
|
||||||
background: color-mix(in srgb, var(--nexus-admin-panel) 90%, transparent);
|
background: color-mix(in srgb, var(--nexus-admin-panel) 90%, transparent);
|
||||||
box-shadow: 0 -10px 30px rgba(27, 43, 72, 0.06);
|
box-shadow: 0 -10px 30px rgba(20, 32, 51, 0.06);
|
||||||
backdrop-filter: blur(14px);
|
backdrop-filter: blur(16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pf-v5-theme-dark .pf-v5-c-page__main {
|
input[type="checkbox"],
|
||||||
background-image: linear-gradient(rgba(99, 230, 255, 0.035) 1px, transparent 1px),
|
input[type="radio"] {
|
||||||
linear-gradient(90deg, rgba(99, 230, 255, 0.035) 1px, transparent 1px);
|
accent-color: var(--nexus-admin-signal);
|
||||||
}
|
|
||||||
|
|
||||||
.pf-v5-theme-dark .pf-v5-c-card,
|
|
||||||
.pf-v5-theme-dark .pf-v5-c-modal-box,
|
|
||||||
.pf-v5-theme-dark .pf-v5-c-drawer__panel,
|
|
||||||
.pf-v5-theme-dark .pf-v5-c-popover__content,
|
|
||||||
.pf-v5-theme-dark .pf-v5-c-menu {
|
|
||||||
box-shadow: 0 15px 42px rgba(0, 0, 0, 0.28);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.keycloak__section_intro__help {
|
.keycloak__section_intro__help {
|
||||||
@@ -256,19 +530,185 @@ input[type="checkbox"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.w-tc-editor {
|
div.w-tc-editor {
|
||||||
|
border: 1px solid var(--nexus-admin-line);
|
||||||
|
border-radius: var(--nexus-admin-radius-sm);
|
||||||
font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace;
|
font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
:focus-visible {
|
:focus-visible {
|
||||||
outline: 2px solid var(--nexus-admin-ice) !important;
|
outline: 2px solid var(--nexus-admin-signal-bright) !important;
|
||||||
outline-offset: 2px;
|
outline-offset: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 769px) {
|
||||||
|
.pf-v5-c-page__main-section > .pf-v5-c-card,
|
||||||
|
.pf-v5-c-page__main-section > .pf-v5-c-table,
|
||||||
|
.pf-v5-c-page__main-section > .pf-v5-c-form {
|
||||||
|
animation: nexus-admin-arrive 360ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes nexus-admin-arrive {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(8px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.pf-v5-c-masthead {
|
||||||
|
min-height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.keycloak__pageheader_brand {
|
||||||
|
width: 158px;
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-page__sidebar {
|
||||||
|
width: min(88vw, 310px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-page__main-section,
|
||||||
|
.pf-v5-c-page__main-breadcrumb {
|
||||||
|
padding-inline: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-v5-c-title.pf-m-2xl,
|
||||||
|
.pf-v5-c-page__main-title {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keycloak__form_actions {
|
||||||
|
margin-inline: -1rem;
|
||||||
|
padding-inline: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
*,
|
*,
|
||||||
*::before,
|
*::before,
|
||||||
*::after {
|
*::after {
|
||||||
|
scroll-behavior: auto !important;
|
||||||
animation-duration: 0.01ms !important;
|
animation-duration: 0.01ms !important;
|
||||||
|
animation-iteration-count: 1 !important;
|
||||||
transition-duration: 0.01ms !important;
|
transition-duration: 0.01ms !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Keep the admin workspace in step with the class login/account variant. */
|
||||||
|
html[data-kc-theme-name="class"] {
|
||||||
|
--nexus-admin-void: #2868c7;
|
||||||
|
--nexus-admin-chrome: #3f7fd6;
|
||||||
|
--nexus-admin-panel: #ffffff;
|
||||||
|
--nexus-admin-canvas: #f7fbff;
|
||||||
|
--nexus-admin-canvas-strong: #e5f3ff;
|
||||||
|
--nexus-admin-signal: #f05a47;
|
||||||
|
--nexus-admin-signal-bright: #f6c54c;
|
||||||
|
--nexus-admin-indigo: #23966f;
|
||||||
|
--nexus-admin-mint: #f6c54c;
|
||||||
|
--nexus-admin-text: #18324a;
|
||||||
|
--nexus-admin-muted: #617387;
|
||||||
|
--nexus-admin-line: #c8dbe8;
|
||||||
|
--nexus-admin-line-strong: #9ebbd0;
|
||||||
|
--nexus-admin-danger: #c93636;
|
||||||
|
--nexus-admin-radius-sm: 2px;
|
||||||
|
--nexus-admin-radius-md: 4px;
|
||||||
|
--nexus-admin-shadow: 7px 7px 0 rgba(40, 104, 199, 0.1);
|
||||||
|
--pf-v5-global--primary-color--100: #3f7fd6;
|
||||||
|
--pf-v5-global--primary-color--200: #2868c7;
|
||||||
|
--pf-v5-global--link--Color: #2868c7;
|
||||||
|
--pf-v5-global--link--Color--hover: #174f9c;
|
||||||
|
--pf-v5-global--BackgroundColor--100: var(--nexus-admin-panel);
|
||||||
|
--pf-v5-global--BackgroundColor--150: #fbfdff;
|
||||||
|
--pf-v5-global--BackgroundColor--200: var(--nexus-admin-canvas);
|
||||||
|
--pf-v5-global--Color--100: var(--nexus-admin-text);
|
||||||
|
--pf-v5-global--Color--200: var(--nexus-admin-muted);
|
||||||
|
--pf-v5-global--BorderColor--100: var(--nexus-admin-line);
|
||||||
|
--pf-v5-global--BorderColor--200: var(--nexus-admin-line-strong);
|
||||||
|
--pf-v5-c-page__main-section--m-light--BackgroundColor: var(--nexus-admin-canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-kc-theme-name="class"].pf-v5-theme-dark {
|
||||||
|
--nexus-admin-void: #0d2742;
|
||||||
|
--nexus-admin-chrome: #123453;
|
||||||
|
--nexus-admin-panel: #0f2030;
|
||||||
|
--nexus-admin-canvas: #08131e;
|
||||||
|
--nexus-admin-canvas-strong: #173149;
|
||||||
|
--nexus-admin-signal: #ff7465;
|
||||||
|
--nexus-admin-signal-bright: #f2c45c;
|
||||||
|
--nexus-admin-indigo: #54c99d;
|
||||||
|
--nexus-admin-mint: #f2c45c;
|
||||||
|
--nexus-admin-text: #e7f1f9;
|
||||||
|
--nexus-admin-muted: #9ab0c2;
|
||||||
|
--nexus-admin-line: #355168;
|
||||||
|
--nexus-admin-line-strong: #58738a;
|
||||||
|
--nexus-admin-danger: #ff8585;
|
||||||
|
--nexus-admin-shadow: 7px 7px 0 #142a3e;
|
||||||
|
--pf-v5-global--primary-color--100: #6da8f6;
|
||||||
|
--pf-v5-global--primary-color--200: #91bdff;
|
||||||
|
--pf-v5-global--link--Color: #91bdff;
|
||||||
|
--pf-v5-global--link--Color--hover: #bdd7ff;
|
||||||
|
--pf-v5-global--BackgroundColor--150: #14293b;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-page__main {
|
||||||
|
background-image: linear-gradient(rgba(24, 50, 74, 0.035) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(24, 50, 74, 0.035) 1px, transparent 1px);
|
||||||
|
background-position: 24px 24px;
|
||||||
|
background-size: 24px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-masthead {
|
||||||
|
border-bottom-color: rgba(246, 197, 76, 0.75);
|
||||||
|
background: linear-gradient(90deg, rgba(255, 255, 255, 0.1), transparent 48%),
|
||||||
|
var(--nexus-admin-void);
|
||||||
|
box-shadow: 0 8px 0 rgba(63, 127, 214, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-masthead::after {
|
||||||
|
width: min(42vw, 38rem);
|
||||||
|
height: 4px;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
var(--nexus-admin-indigo) 0 34%,
|
||||||
|
var(--nexus-admin-signal-bright) 34% 67%,
|
||||||
|
var(--nexus-admin-signal) 67%
|
||||||
|
);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-page__sidebar,
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-page__sidebar-body {
|
||||||
|
background: linear-gradient(165deg, rgba(255, 255, 255, 0.08), transparent 42%),
|
||||||
|
var(--nexus-admin-chrome);
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-page__sidebar {
|
||||||
|
border-right-color: rgba(246, 197, 76, 0.65);
|
||||||
|
box-shadow: 8px 0 0 rgba(63, 127, 214, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-nav__link,
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-nav__section-title,
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-nav__link.pf-m-expandable {
|
||||||
|
color: rgba(255, 255, 255, 0.78);
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-nav__link:hover,
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-nav__link:focus,
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-nav__link.pf-m-current,
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-nav__item.pf-m-current > .pf-v5-c-nav__link {
|
||||||
|
color: #ffffff;
|
||||||
|
background: linear-gradient(90deg, rgba(246, 197, 76, 0.2), rgba(240, 90, 71, 0.08));
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-card,
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-modal-box,
|
||||||
|
html[data-kc-theme-name="class"] .pf-v5-c-empty-state {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user