From 4577e60fc22831cf8b50423ef58bc0e1e7bdb323 Mon Sep 17 00:00:00 2001 From: biss Date: Mon, 3 Aug 2026 11:09:19 +0800 Subject: [PATCH] admin --- package-lock.json | 26 + package.json | 1 + public/keycloak-theme/.gitignore | 3 + src/.gitignore | 244 ++++++++ src/account/KcAccountUi.tsx | 42 ++ src/account/KcContext.ts | 23 +- src/account/KcPage.tsx | 67 +-- src/account/KcPageStory.tsx | 38 -- src/account/Template.tsx | 124 ---- src/account/assets/logo.svg | 16 + src/account/i18n.ts | 30 - src/account/pages/Account.stories.tsx | 40 -- src/account/pages/Password.stories.tsx | 17 - src/account/theme.css | 780 +++++++------------------ vite.config.ts | 2 +- 15 files changed, 570 insertions(+), 883 deletions(-) create mode 100644 src/account/KcAccountUi.tsx delete mode 100644 src/account/KcPageStory.tsx delete mode 100644 src/account/Template.tsx create mode 100644 src/account/assets/logo.svg delete mode 100644 src/account/i18n.ts delete mode 100644 src/account/pages/Account.stories.tsx delete mode 100644 src/account/pages/Password.stories.tsx diff --git a/package-lock.json b/package-lock.json index 8d7ef03..1e7dfe9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@dagrejs/dagre": "^1.1.8", "@keycloak/keycloak-admin-client": "26.7.0", "@keycloakify/email-native": "~260007.0.0", + "@keycloakify/keycloak-account-ui": "~260700.0.3", "@keycloakify/keycloak-admin-ui": "~260700.0.2", "@keycloakify/keycloak-ui-shared": "~260700.0.2", "@patternfly/patternfly": "^5.4.2", @@ -1246,6 +1247,31 @@ "integrity": "sha512-hFUiOwwpc84eXPAct44G/pTBkYnDQF1jIObME+ZUrb7XidmFJ/TdH9q49LKpd9sIivSyOEJa1qLtrggP+c+BJw==", "license": "Apache-2.0" }, + "node_modules/@keycloakify/keycloak-account-ui": { + "version": "260700.0.3", + "resolved": "https://registry.npmjs.org/@keycloakify/keycloak-account-ui/-/keycloak-account-ui-260700.0.3.tgz", + "integrity": "sha512-K7jveFTb4BYYs33KI5VL+wF4H6/QSmQWT9NnqJsZbdIy7vnaFwZPUGRzJ2giQ9FHxGqG6R63W/mgmrnyzwdDUA==", + "license": "Apache-2.0", + "dependencies": { + "tsafe": "^1.8.5" + }, + "peerDependencies": { + "@keycloakify/keycloak-ui-shared": "~260700.0.2", + "@patternfly/patternfly": "^5.4.2", + "@patternfly/react-core": "^5.4.14", + "@patternfly/react-icons": "^5.4.2", + "@patternfly/react-table": "^5.4.16", + "@types/lodash-es": "^4.17.12", + "@types/react": "^18.3.18", + "i18next": "^25.7.3", + "i18next-fetch-backend": "^7.0.0", + "lodash-es": "^4.18.1", + "react": "^18.3.1", + "react-hook-form": "^7.70.0", + "react-i18next": "^16.5.1", + "react-router-dom": "^6.30.4" + } + }, "node_modules/@keycloakify/keycloak-admin-ui": { "version": "260700.0.2", "resolved": "https://registry.npmjs.org/@keycloakify/keycloak-admin-ui/-/keycloak-admin-ui-260700.0.2.tgz", diff --git a/package.json b/package.json index 7bb68a5..130aac3 100755 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "@keycloakify/keycloak-admin-ui": "~260700.0.2", + "@keycloakify/keycloak-account-ui": "~260700.0.3", "@dagrejs/dagre": "^1.1.8", "@keycloak/keycloak-admin-client": "26.7.0", "@keycloakify/keycloak-ui-shared": "~260700.0.2", diff --git a/public/keycloak-theme/.gitignore b/public/keycloak-theme/.gitignore index 399b983..a0c7acc 100644 --- a/public/keycloak-theme/.gitignore +++ b/public/keycloak-theme/.gitignore @@ -5,3 +5,6 @@ # === @keycloakify/keycloak-admin-ui v260700.0.2 === /admin/early-color-scheme.js + +# === @keycloakify/keycloak-account-ui v260700.0.3 === +/account/early-color-scheme.js diff --git a/src/.gitignore b/src/.gitignore index 985df64..3477cab 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,8 +1,12 @@ # This file is managed by Keycloakify, do not edit it manually. # === Owned files start === +# account/KcAccountUi.tsx +# account/KcContext.ts +# account/KcPage.tsx # admin/index.css # admin/KcAdminUi.tsx +# account/assets/logo.svg # admin/assets/logo.svg # admin/i18n/messages_en.properties # admin/i18n/messages_zh_Hans.properties @@ -831,3 +835,243 @@ /shared/keycloak-ui-shared/controls/table/ListEmptyState.tsx /shared/keycloak-ui-shared/controls/table/PaginatingTableToolbar.tsx /shared/keycloak-ui-shared/controls/table/TableToolbar.tsx + +# === @keycloakify/keycloak-account-ui v260700.0.3 === +/account/api.ts +/account/colorScheme.ts +/account/environment.ts +/account/i18n-type.ts +/account/i18next.d.ts +/account/index.ts +/account/routes.tsx +/account/account-security/AccountRow.tsx +/account/account-security/DeviceActivity.tsx +/account/account-security/LinkedAccounts.tsx +/account/account-security/LinkedAccountsToolbar.tsx +/account/account-security/SigningIn.tsx +/account/api/constants.ts +/account/api/methods.ts +/account/api/parse-links.ts +/account/api/parse-response.ts +/account/api/representations.ts +/account/api/request.ts +/account/applications/Applications.tsx +/account/assets/content.ts +/account/assets/favicon.svg +/account/content/ContentComponent.tsx +/account/content/fetchContent.ts +/account/groups/Groups.tsx +/account/i18n/i18n.ts +/account/i18n/index.ts +/account/i18n/messages_ar.properties +/account/i18n/messages_az.properties +/account/i18n/messages_ca.properties +/account/i18n/messages_cs.properties +/account/i18n/messages_da.properties +/account/i18n/messages_de.properties +/account/i18n/messages_el.properties +/account/i18n/messages_en.properties +/account/i18n/messages_es.properties +/account/i18n/messages_eu.properties +/account/i18n/messages_fa.properties +/account/i18n/messages_fi.properties +/account/i18n/messages_fr.properties +/account/i18n/messages_hr.properties +/account/i18n/messages_hu.properties +/account/i18n/messages_hy.properties +/account/i18n/messages_id.properties +/account/i18n/messages_it.properties +/account/i18n/messages_ja.properties +/account/i18n/messages_ka.properties +/account/i18n/messages_kk.properties +/account/i18n/messages_ky.properties +/account/i18n/messages_lt.properties +/account/i18n/messages_lv.properties +/account/i18n/messages_nl.properties +/account/i18n/messages_no.properties +/account/i18n/messages_pl.properties +/account/i18n/messages_pt_BR.properties +/account/i18n/messages_pt.properties +/account/i18n/messages_ro.properties +/account/i18n/messages_ru.properties +/account/i18n/messages_sk.properties +/account/i18n/messages_sl.properties +/account/i18n/messages_sv.properties +/account/i18n/messages_th.properties +/account/i18n/messages_tr.properties +/account/i18n/messages_uk.properties +/account/i18n/messages_vi.properties +/account/i18n/messages_zh_Hans.properties +/account/i18n/messages_zh_Hant.properties +/account/organizations/Organizations.tsx +/account/personal-info/PersonalInfo.tsx +/account/resources/EditTheResource.tsx +/account/resources/PermissionRequest.tsx +/account/resources/Resources.tsx +/account/resources/ResourcesTab.tsx +/account/resources/ResourceToolbar.tsx +/account/resources/SharedWith.tsx +/account/resources/ShareTheResource.tsx +/account/root/header.module.css +/account/root/Header.tsx +/account/root/PageNav.tsx +/account/root/Root.tsx +/account/utils/formatDate.ts +/account/utils/joinPath.ts +/account/utils/useAccountAlerts.ts +/account/utils/usePromise.ts +/account/verifiable-credentials/CredentialRow.tsx +/account/verifiable-credentials/IssuedCredentialsModal.tsx +/account/verifiable-credentials/UserAttributesDialog.tsx +/account/verifiable-credentials/VerifiableCredentials.tsx +/account/assets/passkeys/1password-dark.svg +/account/assets/passkeys/1password-light.svg +/account/assets/passkeys/acs-light.png +/account/assets/passkeys/aliasvault-light.svg +/account/assets/passkeys/allthenticator-light.png +/account/assets/passkeys/android-light.png +/account/assets/passkeys/apple-light.svg +/account/assets/passkeys/arculus-light.png +/account/assets/passkeys/atkey-light.png +/account/assets/passkeys/atkey1-light.png +/account/assets/passkeys/atkey2-light.png +/account/assets/passkeys/atkey4-light.png +/account/assets/passkeys/atlkey-light.png +/account/assets/passkeys/atos-light.png +/account/assets/passkeys/authenton1-light.png +/account/assets/passkeys/bitwarden-light.svg +/account/assets/passkeys/burp-light.svg +/account/assets/passkeys/cardos-light.png +/account/assets/passkeys/chipwon-light.png +/account/assets/passkeys/chrome-light.svg +/account/assets/passkeys/chunghwa-light.png +/account/assets/passkeys/crayonic-light.png +/account/assets/passkeys/cryptnox-light.png +/account/assets/passkeys/dapple-light.png +/account/assets/passkeys/dashlane-dark.svg +/account/assets/passkeys/dashlane-light.svg +/account/assets/passkeys/deepnet-light.png +/account/assets/passkeys/devolutions-light.svg +/account/assets/passkeys/edge-light.svg +/account/assets/passkeys/egomet-light.png +/account/assets/passkeys/ellipticsecure-light.png +/account/assets/passkeys/enpass-dark.svg +/account/assets/passkeys/enpass-light.svg +/account/assets/passkeys/ensurity-light.png +/account/assets/passkeys/ensurity1-light.png +/account/assets/passkeys/ensurity2-light.png +/account/assets/passkeys/ensurity3-light.png +/account/assets/passkeys/enterprise-light.svg +/account/assets/passkeys/ess-light.png +/account/assets/passkeys/ewbm-light.png +/account/assets/passkeys/excelsecu-light.png +/account/assets/passkeys/feitian-light.png +/account/assets/passkeys/fido-light.png +/account/assets/passkeys/fido1-light.png +/account/assets/passkeys/foongtone-light.png +/account/assets/passkeys/goldkey-light.png +/account/assets/passkeys/google-light.png +/account/assets/passkeys/google1-light.svg +/account/assets/passkeys/gotrust-light.png +/account/assets/passkeys/gstag-light.png +/account/assets/passkeys/heimlane-light.svg +/account/assets/passkeys/hid-light.png +/account/assets/passkeys/hideez-light.png +/account/assets/passkeys/hyper-light.png +/account/assets/passkeys/hyper1-light.png +/account/assets/passkeys/hypr-light.png +/account/assets/passkeys/icloud-dark.svg +/account/assets/passkeys/icloud-light.svg +/account/assets/passkeys/id-one-light.png +/account/assets/passkeys/ideem-light.png +/account/assets/passkeys/idemia-light.png +/account/assets/passkeys/idex-light.png +/account/assets/passkeys/idmelon-light.svg +/account/assets/passkeys/idmelon1-light.png +/account/assets/passkeys/iist-light.png +/account/assets/passkeys/initial-light.svg +/account/assets/passkeys/ipasswords-light.svg +/account/assets/passkeys/kaspersky-light.svg +/account/assets/passkeys/keepassdx-dark.svg +/account/assets/passkeys/keepassdx-light.svg +/account/assets/passkeys/keepassxc-dark.svg +/account/assets/passkeys/keepassxc-light.svg +/account/assets/passkeys/keeper-light.svg +/account/assets/passkeys/key-id-light.png +/account/assets/passkeys/keyvault-light.png +/account/assets/passkeys/keyxentic-light.png +/account/assets/passkeys/konai-light.png +/account/assets/passkeys/kqc-light.png +/account/assets/passkeys/lastpass-dark.svg +/account/assets/passkeys/lastpass-light.svg +/account/assets/passkeys/ledger-light.png +/account/assets/passkeys/logmeonce-dark.svg +/account/assets/passkeys/logmeonce-light.svg +/account/assets/passkeys/mettlesemi-light.png +/account/assets/passkeys/microsoft-light.svg +/account/assets/passkeys/neowave-light.png +/account/assets/passkeys/nitrokey-light.png +/account/assets/passkeys/nordpass-dark.svg +/account/assets/passkeys/nordpass-light.svg +/account/assets/passkeys/nxp-light.png +/account/assets/passkeys/nymi-light.png +/account/assets/passkeys/octatco-light.png +/account/assets/passkeys/onekey-light.png +/account/assets/passkeys/onespan-light.png +/account/assets/passkeys/onespan1-light.png +/account/assets/passkeys/onespan2-light.png +/account/assets/passkeys/onespan3-light.png +/account/assets/passkeys/onespan4-light.png +/account/assets/passkeys/onespan5-light.png +/account/assets/passkeys/onespan7-light.png +/account/assets/passkeys/onlykey-light.png +/account/assets/passkeys/opensk-light.png +/account/assets/passkeys/pone-light.png +/account/assets/passkeys/precision-light.png +/account/assets/passkeys/precision1-light.png +/account/assets/passkeys/precision2-light.png +/account/assets/passkeys/proton-light.svg +/account/assets/passkeys/pwsafe-light.svg +/account/assets/passkeys/rsa-light.png +/account/assets/passkeys/samsung-light.svg +/account/assets/passkeys/secora-light.png +/account/assets/passkeys/secora1-light.png +/account/assets/passkeys/securitag-light.png +/account/assets/passkeys/sentry-light.png +/account/assets/passkeys/sesame-light.svg +/account/assets/passkeys/shalo-light.png +/account/assets/passkeys/sherlocked-light.svg +/account/assets/passkeys/smartdisplayer-light.png +/account/assets/passkeys/solo-light.png +/account/assets/passkeys/starsign-light.png +/account/assets/passkeys/sticky-light.svg +/account/assets/passkeys/swissbit-light.png +/account/assets/passkeys/t-shield-light.png +/account/assets/passkeys/taglio-light.png +/account/assets/passkeys/thales-light.png +/account/assets/passkeys/thales1-dark.svg +/account/assets/passkeys/thales1-light.svg +/account/assets/passkeys/thales3-dark.svg +/account/assets/passkeys/thales3-light.svg +/account/assets/passkeys/thetis-light.png +/account/assets/passkeys/token-light.png +/account/assets/passkeys/token2-light.png +/account/assets/passkeys/toothpic-dark.svg +/account/assets/passkeys/toothpic-light.svg +/account/assets/passkeys/truu-light.png +/account/assets/passkeys/utrust-light.png +/account/assets/passkeys/valmido-light.png +/account/assets/passkeys/veridium-light.png +/account/assets/passkeys/verimark-light.png +/account/assets/passkeys/verimark1-light.png +/account/assets/passkeys/verocard-light.png +/account/assets/passkeys/vincss-light.png +/account/assets/passkeys/vivokey-light.png +/account/assets/passkeys/webcomm-light.png +/account/assets/passkeys/windows-light.svg +/account/assets/passkeys/winmagic-light.png +/account/assets/passkeys/yubikey-light.png +/account/assets/passkeys/zoho-light.svg +/account/assets/passkeys/ztpass-light.png +/account/components/datalist/EmptyRow.tsx +/account/components/page/Page.tsx diff --git a/src/account/KcAccountUi.tsx b/src/account/KcAccountUi.tsx new file mode 100644 index 0000000..da8a920 --- /dev/null +++ b/src/account/KcAccountUi.tsx @@ -0,0 +1,42 @@ +/** + * 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/KcAccountUi.tsx" --revert + */ + +import "@patternfly/patternfly/patternfly-addons.css"; +import "@patternfly/react-core/dist/styles/base.css"; +import "./theme.css"; + +import { useReducer, useEffect } from "react"; +import { startColorSchemeManagement } from "./colorScheme"; +import { KeycloakProvider } from "../shared/keycloak-ui-shared"; +import { environment } from "./environment"; +import { i18n } from "./i18n/i18n"; +import { Root } from "./root/Root"; +import { SessionExpirationWarningOverlay } from "../shared/SessionExpirationWarningOverlay"; + +document.title = "NEXUS / ID"; + +const prI18nInitialized = i18n.init(); +startColorSchemeManagement(); + +export default function KcAccountUi() { + const [isI18nInitialized, setI18nInitialized] = useReducer(() => true, false); + + useEffect(() => { + prI18nInitialized.then(() => setI18nInitialized()); + }, []); + + if (!isI18nInitialized) { + return null; + } + + return ( + + + + + ); +} diff --git a/src/account/KcContext.ts b/src/account/KcContext.ts index a043f25..77372f8 100644 --- a/src/account/KcContext.ts +++ b/src/account/KcContext.ts @@ -1,12 +1,17 @@ -/* eslint-disable @typescript-eslint/ban-types */ -import type { ExtendKcContext } from "keycloakify/account"; -import type { KcEnvName, ThemeName } from "../kc.gen"; +/** + * 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/KcContext.ts" --revert + */ -export type KcContextExtension = { - themeName: ThemeName; - properties: Record & {}; +import { type KcContextLike, createGetKcContext } from "@keycloakify/keycloak-account-ui"; +import type { KcEnvName } from "../kc.gen"; + +export type KcContext = KcContextLike & { + themeType: "account"; + themeName: string; + properties: Record; }; -export type KcContextExtensionPerPage = {}; - -export type KcContext = ExtendKcContext; +export const { getKcContext } = createGetKcContext(); diff --git a/src/account/KcPage.tsx b/src/account/KcPage.tsx index baf935a..6a78eee 100644 --- a/src/account/KcPage.tsx +++ b/src/account/KcPage.tsx @@ -1,47 +1,34 @@ -import { Suspense } from "react"; -import type { ClassKey } from "keycloakify/account"; +/** + * 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/KcPage.tsx" --revert + */ + +import { lazy } from "react"; +import { KcAccountUiLoader } from "@keycloakify/keycloak-account-ui"; import type { KcContext } from "./KcContext"; -import { useI18n } from "./i18n"; -import DefaultPage from "keycloakify/account/DefaultPage"; -import Template from "./Template"; -import "./theme.css"; +import { oidcEarlyInit } from "oidc-spa/entrypoint"; +import { browserRuntimeFreeze } from "oidc-spa/browser-runtime-freeze"; +import { DPoP } from "oidc-spa/DPoP"; + +const KcAccountUi = lazy(() => import("./KcAccountUi")); export default function KcPage(props: { kcContext: KcContext }) { const { kcContext } = props; - const { i18n } = useI18n({ kcContext }); + const { shouldLoadApp } = oidcEarlyInit({ + BASE_URL: kcContext.baseUrl.path, + sessionRestorationMethod: import.meta.env.DEV ? "full page redirect" : "auto", + securityDefenses: { + ...browserRuntimeFreeze({ excludes: ["fetch"] }), + ...DPoP({ mode: "auto" }) + } + }); - return ( - - {(() => { - switch (kcContext.pageId) { - default: - return ( - - ); - } - })()} - - ); + if (!shouldLoadApp) { + return null; + } + + return ; } - -const classes = { - kcHtmlClass: "nexus-account-html", - kcBodyClass: "nexus-account-body", - kcButtonClass: "nexus-account-button", - kcButtonPrimaryClass: "nexus-account-button--primary", - kcButtonDefaultClass: "nexus-account-button--default", - kcButtonLargeClass: "nexus-account-button--large", - kcFormClass: "nexus-account-form", - kcFormGroupClass: "nexus-account-field", - kcLabelClass: "nexus-account-label", - kcInputClass: "nexus-account-input", - kcInputWrapperClass: "nexus-account-input-wrapper", - kcInputErrorMessageClass: "nexus-account-field-error" -} satisfies { [key in ClassKey]?: string }; diff --git a/src/account/KcPageStory.tsx b/src/account/KcPageStory.tsx deleted file mode 100644 index c059547..0000000 --- a/src/account/KcPageStory.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import type { DeepPartial } from "keycloakify/tools/DeepPartial"; -import type { KcContext } from "./KcContext"; -import { createGetKcContextMock } from "keycloakify/account/KcContext"; -import type { KcContextExtension, KcContextExtensionPerPage } from "./KcContext"; -import KcPage from "./KcPage"; -import { themeNames, kcEnvDefaults } from "../kc.gen"; - -const kcContextExtension: KcContextExtension = { - themeName: themeNames[0], - properties: { - ...kcEnvDefaults - } -}; -const kcContextExtensionPerPage: KcContextExtensionPerPage = {}; - -export const { getKcContextMock } = createGetKcContextMock({ - kcContextExtension, - kcContextExtensionPerPage, - overrides: {}, - overridesPerPage: {} -}); - -export function createKcPageStory(params: { pageId: PageId }) { - const { pageId } = params; - - function KcPageStory(props: { kcContext?: DeepPartial> }) { - const { kcContext: overrides } = props; - - const kcContextMock = getKcContextMock({ - pageId, - overrides - }); - - return ; - } - - return { KcPageStory }; -} diff --git a/src/account/Template.tsx b/src/account/Template.tsx deleted file mode 100644 index 46f376d..0000000 --- a/src/account/Template.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import { useEffect } from "react"; -import { clsx } from "keycloakify/tools/clsx"; -import { kcSanitize } from "keycloakify/lib/kcSanitize"; -import { getKcClsx } from "keycloakify/account/lib/kcClsx"; -import { useSetClassName } from "keycloakify/tools/useSetClassName"; -import { useInitialize } from "keycloakify/account/Template.useInitialize"; -import type { TemplateProps } from "keycloakify/account/TemplateProps"; -import type { I18n } from "./i18n"; -import type { KcContext } from "./KcContext"; - -export default function Template(props: TemplateProps) { - const { kcContext, i18n, doUseDefaultCss, active, classes, children } = props; - const { kcClsx } = getKcClsx({ doUseDefaultCss, classes }); - const { msg, msgStr, currentLanguage, enabledLanguages } = i18n; - const { url, features, realm, message, referrer } = kcContext; - - useEffect(() => { - document.title = msgStr("accountManagementTitle"); - }, [msgStr]); - - useSetClassName({ qualifiedName: "html", className: kcClsx("kcHtmlClass") }); - useSetClassName({ qualifiedName: "body", className: kcClsx("kcBodyClass") }); - - const { isReadyToRender } = useInitialize({ kcContext, doUseDefaultCss }); - - if (!isReadyToRender) { - return null; - } - - const navigationItems = [ - { id: "account", href: url.accountUrl, label: msg("account"), visible: true }, - { id: "password", href: url.passwordUrl, label: msg("password"), visible: features.passwordUpdateSupported }, - { id: "totp", href: url.totpUrl, label: msg("authenticator"), visible: true }, - { id: "social", href: url.socialUrl, label: msg("federatedIdentity"), visible: features.identityFederation }, - { id: "sessions", href: url.sessionsUrl, label: msg("sessions"), visible: true }, - { id: "applications", href: url.applicationsUrl, label: msg("applications"), visible: true }, - { id: "log", href: url.logUrl, label: msg("log"), visible: features.log }, - { - id: "authorization", - href: url.resourceUrl, - label: msg("myResources"), - visible: realm.userManagedAccessAllowed && features.authorization - } - ].filter(item => item.visible); - - return ( -
-
- - N - - NEXUS / ID - - - -
- {msg("nexusIdentityControl")} - {msg("accountManagementTitle")} -
- - -
- -
- - -
- {message !== undefined && ( -
- - -
- )} -
{children}
-
-
-
- ); -} diff --git a/src/account/assets/logo.svg b/src/account/assets/logo.svg new file mode 100644 index 0000000..5a6a72d --- /dev/null +++ b/src/account/assets/logo.svg @@ -0,0 +1,16 @@ + + NEXUS ID + + + + + + + + + + + + NEXUS + / ID + diff --git a/src/account/i18n.ts b/src/account/i18n.ts deleted file mode 100644 index 499dafe..0000000 --- a/src/account/i18n.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { i18nBuilder } from "keycloakify/account"; -import type { ThemeName } from "../kc.gen"; - -/** @see: https://docs.keycloakify.dev/features/i18n */ -const { useI18n, ofTypeI18n } = i18nBuilder - .withThemeName() - .withCustomTranslations({ - en: { - accountManagementTitle: "Account Management", - myResources: "My Resources", - nexusIdentityControl: "IDENTITY CONTROL", - nexusAccountUtilities: "Account utilities", - nexusAccountMatrix: "ACCOUNT MATRIX", - nexusSecureSession: "SECURE SESSION" - }, - "zh-CN": { - accountManagementTitle: "账户管理", - myResources: "我的资源", - nexusIdentityControl: "身份控制", - nexusAccountUtilities: "账户操作", - nexusAccountMatrix: "账户矩阵", - nexusSecureSession: "安全会话" - } - }) - .build(); - -type I18n = typeof ofTypeI18n; - -export { useI18n, type I18n }; diff --git a/src/account/pages/Account.stories.tsx b/src/account/pages/Account.stories.tsx deleted file mode 100644 index 04fa8a0..0000000 --- a/src/account/pages/Account.stories.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; -import { createKcPageStory } from "../KcPageStory"; - -const { KcPageStory } = createKcPageStory({ pageId: "account.ftl" }); - -const meta = { - title: "account/account.ftl", - component: KcPageStory -} satisfies Meta; - -export default meta; - -type Story = StoryObj; - -export const Default: Story = { - render: () => -}; - -export const SimplifiedChinese: Story = { - render: () => ( - - ) -}; - -export const WithSuccessMessage: Story = { - render: () => ( - - ) -}; diff --git a/src/account/pages/Password.stories.tsx b/src/account/pages/Password.stories.tsx deleted file mode 100644 index ecd1b0e..0000000 --- a/src/account/pages/Password.stories.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; -import { createKcPageStory } from "../KcPageStory"; - -const { KcPageStory } = createKcPageStory({ pageId: "password.ftl" }); - -const meta = { - title: "account/password.ftl", - component: KcPageStory -} satisfies Meta; - -export default meta; - -type Story = StoryObj; - -export const Default: Story = { - render: () => -}; diff --git a/src/account/theme.css b/src/account/theme.css index 05c17e7..8fac4d2 100644 --- a/src/account/theme.css +++ b/src/account/theme.css @@ -1,633 +1,245 @@ -:root { - --nexus-account-void: #050713; - --nexus-account-chrome: #091020; - --nexus-account-panel: #0f172a; - --nexus-account-panel-raised: #141e34; - --nexus-account-ice: #63e6ff; - --nexus-account-violet: #8b7cff; - --nexus-account-text: #f4f7ff; - --nexus-account-muted: #95a2be; - --nexus-account-line: rgba(151, 172, 219, 0.18); - --nexus-account-success: #54e6a4; - --nexus-account-danger: #ff668f; - --nexus-account-display: "Bahnschrift SemiCondensed", "Arial Narrow", sans-serif; - --nexus-account-body-font: "Segoe UI Variable", "Segoe UI", sans-serif; - --nexus-account-mono: "Cascadia Code", Consolas, monospace; +:root, +.pf-v5-theme-dark { + --nexus-account-void: #070b16; + --nexus-account-chrome: #0b1120; + --nexus-account-panel: #ffffff; + --nexus-account-canvas: #f3f6fb; + --nexus-account-ice: #2dc7e5; + --nexus-account-violet: #7569f2; + --nexus-account-text: #172033; + --nexus-account-muted: #63708a; + --nexus-account-line: #dce3ef; + --pf-v5-global--primary-color--100: #007f9b; + --pf-v5-global--primary-color--200: #00677e; + --pf-v5-global--link--Color: #00758d; + --pf-v5-global--link--Color--hover: #004f62; + --pf-v5-global--BackgroundColor--100: var(--nexus-account-panel); + --pf-v5-global--BackgroundColor--150: #f8fafc; + --pf-v5-global--BackgroundColor--200: var(--nexus-account-canvas); + --pf-v5-global--Color--100: var(--nexus-account-text); + --pf-v5-global--Color--200: var(--nexus-account-muted); + --pf-v5-global--BorderColor--100: var(--nexus-account-line); + --pf-v5-global--BorderColor--200: #c9d3e2; + color-scheme: light; } -.nexus-account-html, -.nexus-account-body, +html, +body, #root { min-height: 100%; } -.nexus-account-body { - min-height: 100vh; - margin: 0; +body { color: var(--nexus-account-text); - background: var(--nexus-account-void); - font-family: var(--nexus-account-body-font); - font-size: 15px; - line-height: 1.5; + background: var(--nexus-account-canvas); + font-family: "Segoe UI Variable", "Segoe UI", sans-serif; } -.nexus-account-body *, -.nexus-account-body *::before, -.nexus-account-body *::after { - box-sizing: border-box; +.pf-v5-c-page, +.pf-v5-c-page__main, +.pf-v5-c-page__main-section, +.pf-v5-c-page__main-section.pf-m-light { + background-color: var(--nexus-account-canvas); } -.nexus-account-body button, -.nexus-account-body input, -.nexus-account-body select, -.nexus-account-body textarea { - font: inherit; -} - -.nexus-account-body a { - color: #a9eefe; - text-decoration: none; -} - -.nexus-account-body a:hover { - color: #ffffff; -} - -.nexus-account-shell { - min-height: 100vh; - background: radial-gradient( - circle at 10% 60%, - rgba(99, 230, 255, 0.07), - transparent 29rem - ), - radial-gradient(circle at 88% 15%, rgba(139, 124, 255, 0.07), transparent 27rem), - linear-gradient(rgba(127, 155, 207, 0.028) 1px, transparent 1px), - linear-gradient(90deg, rgba(127, 155, 207, 0.028) 1px, transparent 1px), - var(--nexus-account-void); - background-size: - auto, - auto, - 52px 52px, - 52px 52px, - auto; -} - -.nexus-account-header { - position: sticky; - z-index: 20; - top: 0; - display: grid; - min-height: 76px; - align-items: center; - grid-template-columns: 260px 1fr auto; - gap: 28px; - padding: 0 clamp(22px, 4vw, 58px); - border-bottom: 1px solid var(--nexus-account-line); - background: rgba(6, 10, 23, 0.88); - backdrop-filter: blur(18px); -} - -.nexus-account-brand { - display: flex; - align-items: center; - gap: 12px; - color: var(--nexus-account-text) !important; - font-family: var(--nexus-account-display); - font-size: 0.92rem; - font-weight: 650; - letter-spacing: 0.18em; -} - -.nexus-account-brand b { - color: var(--nexus-account-muted); - font-weight: 400; -} - -.nexus-account-brand__mark { +.pf-v5-c-page__main { position: relative; - display: grid; - width: 28px; - height: 28px; - place-items: center; - color: var(--nexus-account-ice); - font-size: 0.75rem; + isolation: isolate; + background-image: linear-gradient(rgba(32, 62, 104, 0.028) 1px, transparent 1px), + linear-gradient(90deg, rgba(32, 62, 104, 0.028) 1px, transparent 1px); + background-size: 44px 44px; } -.nexus-account-brand__mark::before { - position: absolute; - inset: 3px; - border: 1px solid rgba(99, 230, 255, 0.52); - box-shadow: - inset 0 0 14px rgba(99, 230, 255, 0.1), - 0 0 16px rgba(99, 230, 255, 0.08); +.pf-v5-c-page__main::before, +.pf-v5-c-page__main::after { + position: fixed; + z-index: -1; + right: -12rem; + bottom: -15rem; + width: 34rem; + height: 34rem; + border: 1px solid rgba(45, 199, 229, 0.11); + border-radius: 50%; + content: ""; + pointer-events: none; +} + +.pf-v5-c-page__main::after { + right: -4rem; + bottom: -7rem; + width: 18rem; + height: 18rem; + border-color: rgba(117, 105, 242, 0.12); + box-shadow: 0 0 80px rgba(45, 199, 229, 0.06); +} + +.pf-v5-c-masthead { + min-height: 68px; + border-bottom: 1px solid rgba(99, 230, 255, 0.18); + background: linear-gradient(90deg, rgba(99, 230, 255, 0.04), transparent 38%), + var(--nexus-account-void); + box-shadow: 0 8px 28px rgba(5, 9, 21, 0.18); +} + +img.keycloak__pageheader_brand { + width: 190px; + height: 42px; + object-fit: contain; + object-position: left center; +} + +.pf-v5-c-masthead .pf-v5-c-button.pf-m-link { + color: #b9c5da; +} + +.pf-v5-c-page__sidebar, +.pf-v5-c-page__sidebar-body { + border-right: 1px solid rgba(117, 105, 242, 0.16); + color: #d8e2f5; + background: radial-gradient(circle at 18% 88%, rgba(99, 230, 255, 0.08), transparent 14rem), + var(--nexus-account-chrome); +} + +.pf-v5-c-page__sidebar-body::before { + display: block; + width: 3.5rem; + height: 1px; + margin: 1.5rem 1.25rem 0.8rem; + background: linear-gradient(90deg, var(--nexus-account-ice), transparent); + box-shadow: 0.8rem 0.35rem 0 -0.12rem var(--nexus-account-violet); + content: ""; +} + +.pf-v5-c-nav__link, +.pf-v5-c-nav__section-title, +.pf-v5-c-nav__link.pf-m-expandable { + color: #9daac3; +} + +.pf-v5-c-nav__link { + border-radius: 2px; + font-size: 0.88rem; +} + +.pf-v5-c-nav__link:hover, +.pf-v5-c-nav__link:focus { + color: #ffffff; + background: rgba(99, 230, 255, 0.06); +} + +.pf-v5-c-nav__link.pf-m-current, +.pf-v5-c-nav__item.pf-m-current > .pf-v5-c-nav__link { + color: #ffffff; + background: linear-gradient(90deg, rgba(99, 230, 255, 0.15), rgba(117, 105, 242, 0.08)); + box-shadow: inset 2px 0 var(--nexus-account-ice); +} + +.pf-v5-c-nav__link.pf-m-current::after { + border-color: transparent; +} + +.pf-v5-c-page__main-section:first-child { + border-bottom: 1px solid rgba(220, 227, 239, 0.8); + background: rgba(255, 255, 255, 0.78); + backdrop-filter: blur(12px); +} + +.pf-v5-c-page__main-section + .pf-v5-c-page__main-section { + background: transparent; +} + +.pf-v5-c-card, +.pf-v5-c-data-list, +.pf-v5-c-modal-box, +.pf-v5-c-drawer__panel, +.pf-v5-c-menu { + border: 1px solid var(--nexus-account-line); + border-radius: 3px; + background: var(--nexus-account-panel); + box-shadow: 0 15px 42px rgba(27, 43, 72, 0.08); +} + +.pf-v5-c-title, +.pf-v5-c-content h1, +.pf-v5-c-content h2, +.pf-v5-c-page__main-title { + color: var(--nexus-account-text); + font-family: "Bahnschrift SemiCondensed", "Arial Narrow", sans-serif; + letter-spacing: -0.018em; +} + +.pf-v5-c-title.pf-m-2xl::before { + display: inline-block; + width: 0.45rem; + height: 0.45rem; + margin: 0 0.75rem 0.18rem 0; + background: linear-gradient(135deg, var(--nexus-account-ice), var(--nexus-account-violet)); content: ""; transform: rotate(45deg); } -.nexus-account-header__realm { - display: flex; - align-items: baseline; - gap: 10px; - min-width: 0; -} - -.nexus-account-header__realm span, -.nexus-account-sidebar__label, -.nexus-account-sidebar__status { - color: var(--nexus-account-muted); - font-family: var(--nexus-account-mono); - font-size: 0.63rem; - letter-spacing: 0.15em; -} - -.nexus-account-header__realm strong { - overflow: hidden; - color: #dce6fb; - font-size: 0.82rem; - font-weight: 550; - text-overflow: ellipsis; - white-space: nowrap; -} - -.nexus-account-utility { - display: flex; - align-items: center; - gap: 18px; - font-size: 0.78rem; -} - -.nexus-account-language { - position: relative; -} - -.nexus-account-language summary { - color: var(--nexus-account-muted); - cursor: pointer; - list-style: none; -} - -.nexus-account-language ul { - position: absolute; - top: calc(100% + 12px); - right: 0; - min-width: 150px; - max-height: 320px; - overflow: auto; - margin: 0; - padding: 7px; - border: 1px solid var(--nexus-account-line); - background: var(--nexus-account-panel-raised); - box-shadow: 0 18px 45px rgba(0, 0, 0, 0.38); - list-style: none; -} - -.nexus-account-language li a { - display: block; - padding: 7px 9px; -} - -.nexus-account-signout { - padding: 8px 12px; - border: 1px solid var(--nexus-account-line); +.pf-v5-c-button { border-radius: 2px; + font-weight: 620; } -.nexus-account-layout { - display: grid; - min-height: calc(100vh - 76px); - grid-template-columns: 280px minmax(0, 1fr); +.pf-v5-c-button.pf-m-primary { + color: #ffffff; + background: linear-gradient(105deg, #007f9b, #087f91 58%, #655bd7); + box-shadow: 0 6px 18px rgba(0, 127, 155, 0.16); } -.nexus-account-sidebar { - position: relative; - display: flex; - min-height: calc(100vh - 76px); - overflow: hidden; - flex-direction: column; - padding: 40px 28px 28px clamp(24px, 4vw, 58px); - border-right: 1px solid var(--nexus-account-line); - background: rgba(8, 13, 28, 0.78); +.pf-v5-c-button.pf-m-primary:hover { + filter: brightness(1.08); } -.nexus-account-orbit { - position: absolute; - right: -130px; - bottom: -100px; - width: 330px; - height: 330px; - border: 1px solid rgba(99, 230, 255, 0.1); - border-radius: 50%; - pointer-events: none; -} - -.nexus-account-orbit::before, -.nexus-account-orbit::after { - position: absolute; - border: 1px dashed rgba(139, 124, 255, 0.13); - border-radius: 50%; - content: ""; -} - -.nexus-account-orbit::before { - inset: 18%; -} - -.nexus-account-orbit::after { - inset: 36%; -} - -.nexus-account-orbit span { - position: absolute; - top: 37%; - left: -4px; - width: 8px; - height: 8px; - border-radius: 50%; - background: var(--nexus-account-ice); - box-shadow: 0 0 15px var(--nexus-account-ice); -} - -.nexus-account-sidebar__label { - margin: 0 0 22px; - color: var(--nexus-account-ice); -} - -.nexus-account-sidebar nav, -.nexus-account-sidebar nav ul { - position: relative; - z-index: 1; - margin: 0; - padding: 0; - list-style: none; -} - -.nexus-account-sidebar li { - margin-bottom: 5px; -} - -.nexus-account-sidebar li a { - display: flex; - align-items: center; - gap: 12px; - padding: 11px 12px; - border: 1px solid transparent; +.pf-v5-c-form-control, +.pf-v5-c-select__toggle, +.pf-v5-c-menu-toggle { border-radius: 2px; - color: var(--nexus-account-muted); - font-size: 0.84rem; - transition: 150ms ease; + border-color: #c9d3e2; + background: #ffffff; + box-shadow: none; } -.nexus-account-sidebar li a:hover { - border-color: var(--nexus-account-line); - color: var(--nexus-account-text); - background: rgba(99, 230, 255, 0.04); +.pf-v5-c-form-control:focus-within, +.pf-v5-c-menu-toggle:focus { + border-color: #008eaa; + box-shadow: 0 0 0 3px rgba(45, 199, 229, 0.12); } -.nexus-account-sidebar li.active a { - border-color: rgba(99, 230, 255, 0.24); - color: var(--nexus-account-text); - background: linear-gradient( - 90deg, - rgba(99, 230, 255, 0.11), - rgba(139, 124, 255, 0.04) - ); -} - -.nexus-account-nav__signal { - width: 5px; - height: 5px; - border-radius: 50%; - background: #52617e; -} - -.nexus-account-sidebar li.active .nexus-account-nav__signal { - background: var(--nexus-account-ice); - box-shadow: 0 0 9px var(--nexus-account-ice); -} - -.nexus-account-sidebar__status { - position: relative; - z-index: 1; - margin-top: auto; - padding-top: 18px; - border-top: 1px solid var(--nexus-account-line); -} - -.nexus-account-sidebar__status span { - display: inline-block; - width: 5px; - height: 5px; - margin-right: 8px; - border-radius: 50%; - background: var(--nexus-account-success); - box-shadow: 0 0 8px var(--nexus-account-success); -} - -.nexus-account-content { - min-width: 0; - padding: clamp(28px, 5vw, 70px); -} - -.nexus-account-panel { - width: min(100%, 1080px); - min-height: 420px; - padding: clamp(28px, 4vw, 52px); - border: 1px solid var(--nexus-account-line); - border-radius: 3px; - background: linear-gradient(145deg, rgba(18, 27, 49, 0.94), rgba(10, 16, 32, 0.92)); - box-shadow: - 0 28px 80px rgba(0, 0, 0, 0.28), - inset 0 1px rgba(255, 255, 255, 0.03); -} - -.nexus-account-panel > .row:first-child { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 20px; - margin-bottom: 34px; -} - -.nexus-account-panel h2 { - margin: 0; - color: var(--nexus-account-text); - font-family: var(--nexus-account-display); - font-size: clamp(2rem, 3vw, 2.7rem); - font-weight: 520; - letter-spacing: -0.035em; - line-height: 1.05; -} - -.nexus-account-panel h2::after { - display: block; - width: 46px; - height: 2px; - margin-top: 17px; - background: linear-gradient( - 90deg, - var(--nexus-account-ice), - var(--nexus-account-violet) - ); - content: ""; -} - -.nexus-account-panel .subtitle { - color: var(--nexus-account-muted); - font-family: var(--nexus-account-mono); - font-size: 0.66rem; - letter-spacing: 0.08em; -} - -.nexus-account-panel .required { - color: var(--nexus-account-danger); -} - -.nexus-account-form, -.nexus-account-panel .form-horizontal { - width: 100%; -} - -.nexus-account-field, -.nexus-account-panel .form-group { - display: grid; - align-items: center; - grid-template-columns: minmax(120px, 180px) minmax(0, 1fr); - gap: 18px; - margin-bottom: 20px; -} - -.nexus-account-label, -.nexus-account-panel .control-label { - color: #bdc8df; - font-size: 0.8rem; - font-weight: 600; -} - -.nexus-account-input, -.nexus-account-panel .form-control { - width: 100%; - min-height: 46px; - padding: 10px 14px; - border: 1px solid rgba(151, 172, 219, 0.24); - border-radius: 2px; - color: var(--nexus-account-text); - outline: 0; - background: rgba(4, 8, 21, 0.68); - transition: 150ms ease; -} - -.nexus-account-input:focus, -.nexus-account-panel .form-control:focus { +.pf-v5-c-tabs__link::after { border-color: var(--nexus-account-ice); - box-shadow: 0 0 0 3px rgba(99, 230, 255, 0.08); } -.nexus-account-input:disabled, -.nexus-account-panel .form-control:disabled { - color: #6f7b96; - background: rgba(5, 8, 18, 0.5); -} - -.nexus-account-button, -.nexus-account-panel .btn { - display: inline-flex; - min-height: 42px; - align-items: center; - justify-content: center; - margin: 0 8px 8px 0; - padding: 9px 18px; - border: 1px solid var(--nexus-account-line); +.pf-v5-c-label { border-radius: 2px; - color: var(--nexus-account-text); - background: rgba(18, 27, 49, 0.9); - cursor: pointer; - font-size: 0.82rem; - font-weight: 650; } -.nexus-account-button--primary { - border-color: transparent; - color: #06111c; - background: linear-gradient(105deg, var(--nexus-account-ice), #8cf0ec 52%, #a8a1ff); +:focus-visible { + outline: 2px solid var(--nexus-account-ice) !important; + outline-offset: 2px; } -.nexus-account-panel .submit { - grid-column: 2; - margin-top: 10px; -} - -.nexus-account-panel table { - width: 100%; - border-collapse: collapse; - color: #dce4f5; - font-size: 0.82rem; -} - -.nexus-account-panel th, -.nexus-account-panel td { - padding: 13px 14px; - border: 1px solid var(--nexus-account-line); - text-align: left; - vertical-align: top; -} - -.nexus-account-panel th { - color: var(--nexus-account-muted); - background: rgba(5, 9, 21, 0.7); - font-family: var(--nexus-account-mono); - font-size: 0.65rem; - letter-spacing: 0.06em; - text-transform: uppercase; -} - -.nexus-account-panel tr:nth-child(even) td { - background: rgba(255, 255, 255, 0.018); -} - -.nexus-account-alert { - display: flex; - width: min(100%, 1080px); - align-items: flex-start; - gap: 11px; - margin-bottom: 18px; - padding: 14px 16px; - border: 1px solid rgba(99, 230, 255, 0.25); - color: #dce6f8; - background: rgba(99, 230, 255, 0.06); - font-size: 0.82rem; -} - -.nexus-account-alert--error { - border-color: rgba(255, 102, 143, 0.32); - background: rgba(255, 102, 143, 0.07); -} - -.nexus-account-alert__signal { - width: 7px; - height: 7px; - flex: 0 0 auto; - margin-top: 6px; - border-radius: 50%; - background: var(--nexus-account-ice); - box-shadow: 0 0 8px currentColor; -} - -.nexus-account-alert--error .nexus-account-alert__signal { - color: var(--nexus-account-danger); - background: currentColor; -} - -.nexus-account-field-error, -.nexus-account-panel .has-error { - color: #ff93ae; -} - -.nexus-account-body :focus-visible { - outline: 2px solid var(--nexus-account-ice); - outline-offset: 3px; -} - -@media (max-width: 900px) { - .nexus-account-header { - grid-template-columns: 1fr auto; +@media (max-width: 768px) { + .pf-v5-c-masthead { + min-height: 58px; } - .nexus-account-header__realm { - display: none; + img.keycloak__pageheader_brand { + width: 158px; + height: 36px; } - .nexus-account-layout { - grid-template-columns: 1fr; - grid-template-rows: auto 1fr; - } - - .nexus-account-sidebar { - min-height: auto; - padding: 18px 20px; - border-right: 0; - border-bottom: 1px solid var(--nexus-account-line); - } - - .nexus-account-sidebar__label, - .nexus-account-sidebar__status, - .nexus-account-orbit { - display: none; - } - - .nexus-account-sidebar ul { - display: flex; - overflow-x: auto; - gap: 6px; - padding-bottom: 4px !important; - scrollbar-width: none; - } - - .nexus-account-sidebar ul::-webkit-scrollbar { - display: none; - } - - .nexus-account-sidebar li { - flex: 0 0 auto; - margin: 0; - } - - .nexus-account-content { - padding: 24px 20px 40px; - } -} - -@media (max-width: 600px) { - .nexus-account-header { - min-height: 66px; - padding: 0 16px; - } - - .nexus-account-brand { - font-size: 0.78rem; - } - - .nexus-account-utility > a:not(.nexus-account-signout), - .nexus-account-language { - display: none; - } - - .nexus-account-layout { - min-height: calc(100vh - 66px); - } - - .nexus-account-content { - padding: 18px 12px 32px; - } - - .nexus-account-panel { - padding: 26px 20px; - } - - .nexus-account-panel > .row:first-child { - align-items: flex-start; - flex-direction: column; - gap: 14px; - } - - .nexus-account-field, - .nexus-account-panel .form-group { - grid-template-columns: 1fr; - gap: 8px; - } - - .nexus-account-panel .submit { - grid-column: 1; - } - - .nexus-account-panel { - overflow-x: auto; + .pf-v5-c-page__sidebar-body::before { + margin-top: 1rem; } } @media (prefers-reduced-motion: reduce) { - .nexus-account-body *, - .nexus-account-body *::before, - .nexus-account-body *::after { + *, + *::before, + *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } diff --git a/vite.config.ts b/vite.config.ts index fec821c..ebb3883 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,7 +7,7 @@ export default defineConfig({ plugins: [ react(), keycloakify({ - accountThemeImplementation: "Multi-Page" + accountThemeImplementation: "Single-Page" }) ] });