diff --git a/packages/console/src/components/TenantEnvTag/index.module.scss b/packages/console/src/components/TenantEnvTag/index.module.scss
index d4330e7b7..d841d832a 100644
--- a/packages/console/src/components/TenantEnvTag/index.module.scss
+++ b/packages/console/src/components/TenantEnvTag/index.module.scss
@@ -1,15 +1,11 @@
@use '@/scss/underscore' as _;
.tag {
- display: flex;
- align-items: center;
+ display: inline-block;
+ vertical-align: middle;
padding: 0 _.unit(1.5);
border-radius: _.unit(1);
- height: 18px;
-
- .text {
- font: var(--font-label-3);
- }
+ font: var(--font-label-3);
&.development {
background: var(--color-env-tag-development);
@@ -22,4 +18,8 @@
&.production {
background: var(--color-env-tag-production);
}
+
+ &.large {
+ font: var(--font-label-1);
+ }
}
diff --git a/packages/console/src/components/TenantEnvTag/index.tsx b/packages/console/src/components/TenantEnvTag/index.tsx
index 4bcfabbea..194046065 100644
--- a/packages/console/src/components/TenantEnvTag/index.tsx
+++ b/packages/console/src/components/TenantEnvTag/index.tsx
@@ -9,24 +9,34 @@ import * as styles from './index.module.scss';
type Props = {
tag: TenantTag;
className?: string;
+ isAbbreviated?: boolean;
+ size?: 'default' | 'large';
};
type TenantTagMap = {
[key in TenantTag]: AdminConsoleKey;
};
-export const tenantTagMap = Object.freeze({
+export const tenantAbbreviatedTagNameMap = Object.freeze({
[TenantTag.Development]: 'tenants.settings.environment_tag_development',
+ // Todo @xiaoyijun Remove staging tag before release
[TenantTag.Staging]: 'tenants.settings.environment_tag_staging',
[TenantTag.Production]: 'tenants.settings.environment_tag_production',
}) satisfies TenantTagMap;
-function TenantEnvTag({ tag, className }: Props) {
+const tenantTagNameMap = Object.freeze({
+ [TenantTag.Development]: 'tenants.full_env_tag.development',
+ // Todo @xiaoyijun Remove staging tag before release
+ [TenantTag.Staging]: 'tenants.settings.environment_tag_staging',
+ [TenantTag.Production]: 'tenants.full_env_tag.production',
+}) satisfies TenantTagMap;
+
+function TenantEnvTag({ tag, className, isAbbreviated = true, size = 'default' }: Props) {
+ const phrasesMap = isAbbreviated ? tenantAbbreviatedTagNameMap : tenantTagNameMap;
+
return (
-
-
-
-
+
+
);
}
diff --git a/packages/console/src/components/Topbar/TenantSelector/index.module.scss b/packages/console/src/components/Topbar/TenantSelector/index.module.scss
index 3b1a36a88..f06ff2128 100644
--- a/packages/console/src/components/Topbar/TenantSelector/index.module.scss
+++ b/packages/console/src/components/Topbar/TenantSelector/index.module.scss
@@ -36,7 +36,6 @@ $dropdown-item-height: 40px;
}
.tag {
- font: var(--font-body-3);
margin-right: _.unit(2);
}
diff --git a/packages/console/src/consts/external-links.ts b/packages/console/src/consts/external-links.ts
index 4635d965e..206784eec 100644
--- a/packages/console/src/consts/external-links.ts
+++ b/packages/console/src/consts/external-links.ts
@@ -10,3 +10,4 @@ export const reservationLink = buildUrl('https://calendly.com/logto/30min', {
// Note: month format is YYYY-MM
month: new Date().toISOString().slice(0, 7),
});
+export const trustAndSecurityLink = 'https://logto.io/trust-and-security';
diff --git a/packages/console/src/pages/TenantSettings/TenantBasicSettings/DeleteModal/index.tsx b/packages/console/src/pages/TenantSettings/TenantBasicSettings/DeleteModal/index.tsx
index bb9325bda..25eea9431 100644
--- a/packages/console/src/pages/TenantSettings/TenantBasicSettings/DeleteModal/index.tsx
+++ b/packages/console/src/pages/TenantSettings/TenantBasicSettings/DeleteModal/index.tsx
@@ -2,7 +2,7 @@ import classNames from 'classnames';
import { useTranslation, Trans } from 'react-i18next';
import { type TenantResponse } from '@/cloud/types/router';
-import { tenantTagMap } from '@/components/TenantEnvTag';
+import { tenantAbbreviatedTagNameMap } from '@/components/TenantEnvTag';
import { contactEmailLink } from '@/consts';
import DeleteConfirmModal from '@/ds-components/DeleteConfirmModal';
import TextLink from '@/ds-components/TextLink';
@@ -38,7 +38,7 @@ function DeleteModal({ isOpen, isLoading, onClose, onDelete, tenant }: Props) {
}}>
{t('tenants.delete_modal.description_line1', {
name,
- tag: t(tenantTagMap[tag], {}), // Referred to the use in DynamicT component.
+ tag: t(tenantAbbreviatedTagNameMap[tag], {}), // Referred to the use in DynamicT component.
})}
diff --git a/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantEnvironment/index.module.scss b/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantEnvironment/index.module.scss
new file mode 100644
index 000000000..16c55b315
--- /dev/null
+++ b/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantEnvironment/index.module.scss
@@ -0,0 +1,13 @@
+@use '@/scss/underscore' as _;
+
+.container {
+ padding: _.unit(5.5) _.unit(6);
+ border: 1px solid var(--color-divider);
+ border-radius: 12px;
+}
+
+.description {
+ margin-top: _.unit(2);
+ font: var(--font-body-2);
+ color: var(--color-text-secondary);
+}
diff --git a/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantEnvironment/index.tsx b/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantEnvironment/index.tsx
new file mode 100644
index 000000000..36774ddc2
--- /dev/null
+++ b/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantEnvironment/index.tsx
@@ -0,0 +1,37 @@
+import { TenantTag } from '@logto/schemas/lib/models/tenants.js';
+import { Trans, useTranslation } from 'react-i18next';
+
+import TenantEnvTag from '@/components/TenantEnvTag';
+import TextLink from '@/ds-components/TextLink';
+
+import * as styles from './index.module.scss';
+
+type Props = {
+ tag: TenantTag;
+};
+
+function TenantEnvironment({ tag }: Props) {
+ const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
+
+ return (
+
+
+
+ ,
+ }}
+ >
+ {t(
+ tag === TenantTag.Development
+ ? 'tenants.settings.development_description'
+ : 'tenants.create_modal.production_description'
+ )}
+
+
+
+ );
+}
+
+export default TenantEnvironment;
diff --git a/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantRegion/index.module.scss b/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantRegion/index.module.scss
new file mode 100644
index 000000000..cc064d53f
--- /dev/null
+++ b/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantRegion/index.module.scss
@@ -0,0 +1,21 @@
+@use '@/scss/underscore' as _;
+
+.container {
+ padding: _.unit(5.5) _.unit(6);
+ border: 1px solid var(--color-divider);
+ border-radius: 12px;
+}
+
+.region {
+ font: var(--font-label-1);
+
+ .icon {
+ margin-right: _.unit(2);
+ }
+}
+
+.regionTip {
+ font: var(--font-body-2);
+ color: var(--color-text-secondary);
+ margin-top: _.unit(2);
+}
diff --git a/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantRegion/index.tsx b/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantRegion/index.tsx
new file mode 100644
index 000000000..16e7576e2
--- /dev/null
+++ b/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/TenantRegion/index.tsx
@@ -0,0 +1,29 @@
+import { Trans, useTranslation } from 'react-i18next';
+
+import { trustAndSecurityLink } from '@/consts';
+import TextLink from '@/ds-components/TextLink';
+
+import * as styles from './index.module.scss';
+
+function TenantRegion() {
+ const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
+
+ return (
+
+
+ 🇪🇺EU
+
+
+ ,
+ }}
+ >
+ {t('tenants.settings.tenant_region_tip', { region: 'EU' })}
+
+
+
+ );
+}
+
+export default TenantRegion;
diff --git a/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/index.tsx b/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/index.tsx
index 000f88a6f..eec7f1a24 100644
--- a/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/index.tsx
+++ b/packages/console/src/pages/TenantSettings/TenantBasicSettings/ProfileForm/index.tsx
@@ -4,6 +4,7 @@ import { Controller, useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import FormCard from '@/components/FormCard';
+import { isDevFeaturesEnabled } from '@/consts/env';
import CopyToClipboard from '@/ds-components/CopyToClipboard';
import FormField from '@/ds-components/FormField';
import RadioGroup, { Radio } from '@/ds-components/RadioGroup';
@@ -11,6 +12,8 @@ import TextInput from '@/ds-components/TextInput';
import { type TenantSettingsForm } from '../types.js';
+import TenantEnvironment from './TenantEnvironment/index.js';
+import TenantRegion from './TenantRegion/index.js';
import * as styles from './index.module.scss';
type Props = {
@@ -41,6 +44,7 @@ function ProfileForm({ currentTenantId }: Props) {
control,
register,
formState: { errors },
+ getValues,
} = useFormContext
();
return (
@@ -54,22 +58,34 @@ function ProfileForm({ currentTenantId }: Props) {
error={Boolean(errors.profile?.name)}
/>
-
- (
-
- {tagOptions.map(({ value: optionValue, title }) => (
-
- ))}
-
- )}
- />
-
- {t('tenants.settings.environment_tag_description')}
-
-
+ {isDevFeaturesEnabled && (
+
+
+
+ )}
+ {!isDevFeaturesEnabled && (
+
+ (
+
+ {tagOptions.map(({ value: optionValue, title }) => (
+
+ ))}
+
+ )}
+ />
+
+ {t('tenants.settings.environment_tag_description')}
+
+
+ )}
+ {isDevFeaturesEnabled && (
+
+
+
+ )}
);
}