diff --git a/packages/console/package.json b/packages/console/package.json
index df99c94b7..324dd7fa3 100644
--- a/packages/console/package.json
+++ b/packages/console/package.json
@@ -26,6 +26,7 @@
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-i18next": "^11.15.4",
+ "react-modal": "^3.14.4",
"react-router-dom": "^6.2.2",
"swr": "^1.2.2"
},
@@ -39,6 +40,7 @@
"@types/lodash.kebabcase": "^4.1.6",
"@types/react": "^17.0.14",
"@types/react-dom": "^17.0.9",
+ "@types/react-modal": "^3.13.1",
"eslint": "^8.10.0",
"lint-staged": "^11.1.1",
"parcel": "^2.3.1",
diff --git a/packages/console/src/components/AppContent/index.module.scss b/packages/console/src/components/AppContent/index.module.scss
index 116f89113..2ec2cb045 100644
--- a/packages/console/src/components/AppContent/index.module.scss
+++ b/packages/console/src/components/AppContent/index.module.scss
@@ -1,9 +1,6 @@
.app {
position: absolute;
- left: 0;
- top: 0;
- bottom: 0;
- right: 0;
+ inset: 0;
display: flex;
flex-direction: column;
}
diff --git a/packages/console/src/components/AppContent/index.tsx b/packages/console/src/components/AppContent/index.tsx
index ba24055e8..5fe800617 100644
--- a/packages/console/src/components/AppContent/index.tsx
+++ b/packages/console/src/components/AppContent/index.tsx
@@ -1,5 +1,4 @@
-import classNames from 'classnames';
-import React, { ReactNode } from 'react';
+import React, { ReactNode, useEffect } from 'react';
import * as styles from './index.module.scss';
@@ -11,7 +10,16 @@ type Props = {
};
const AppContent = ({ children, theme }: Props) => {
- return
{children}
;
+ useEffect(() => {
+ const classes = [styles.web, styles[theme]].filter((value): value is string => Boolean(value));
+ document.body.classList.add(...classes);
+
+ return () => {
+ document.body.classList.remove(...classes);
+ };
+ }, [theme]);
+
+ return {children}
;
};
export default AppContent;
diff --git a/packages/console/src/components/Card/index.tsx b/packages/console/src/components/Card/index.tsx
index 58594e067..88c103d23 100644
--- a/packages/console/src/components/Card/index.tsx
+++ b/packages/console/src/components/Card/index.tsx
@@ -1,13 +1,15 @@
+import classNames from 'classnames';
import React, { ReactNode } from 'react';
import * as styles from './index.module.scss';
type Props = {
children: ReactNode;
+ className?: string;
};
-const Card = ({ children }: Props) => {
- return {children}
;
+const Card = ({ children, className }: Props) => {
+ return {children}
;
};
export default Card;
diff --git a/packages/console/src/pages/Applications/components/Create/index.module.scss b/packages/console/src/pages/Applications/components/Create/index.module.scss
new file mode 100644
index 000000000..df3124c93
--- /dev/null
+++ b/packages/console/src/pages/Applications/components/Create/index.module.scss
@@ -0,0 +1,18 @@
+@use '@/scss/underscore' as _;
+
+.card {
+ padding: _.unit(8);
+}
+
+.headline {
+ display: flex;
+ justify-content: space-between;
+
+ > *:not(:first-child) {
+ margin-left: _.unit(3);
+ }
+
+ > svg {
+ cursor: pointer;
+ }
+}
diff --git a/packages/console/src/pages/Applications/components/Create/index.tsx b/packages/console/src/pages/Applications/components/Create/index.tsx
new file mode 100644
index 000000000..88af325c3
--- /dev/null
+++ b/packages/console/src/pages/Applications/components/Create/index.tsx
@@ -0,0 +1,32 @@
+import React, { SVGProps } from 'react';
+
+import Card from '@/components/Card';
+import CardTitle from '@/components/CardTitle';
+
+import * as styles from './index.module.scss';
+
+const Close = (props: SVGProps) => (
+
+);
+
+type Props = {
+ onClose?: () => void;
+};
+
+const Create = ({ onClose }: Props) => {
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default Create;
diff --git a/packages/console/src/pages/Applications/index.tsx b/packages/console/src/pages/Applications/index.tsx
index 671305431..f7f7428b5 100644
--- a/packages/console/src/pages/Applications/index.tsx
+++ b/packages/console/src/pages/Applications/index.tsx
@@ -1,6 +1,7 @@
import { Application } from '@logto/schemas';
-import React from 'react';
+import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
+import Modal from 'react-modal';
import useSWR from 'swr';
import Button from '@/components/Button';
@@ -9,12 +10,15 @@ import CardTitle from '@/components/CardTitle';
import CopyToClipboard from '@/components/CopyToClipboard';
import ImagePlaceholder from '@/components/ImagePlaceholder';
import ItemPreview from '@/components/ItemPreview';
+import * as modalStyles from '@/scss/modal.module.scss';
import { RequestError } from '@/swr';
import { applicationTypeI18nKey } from '@/types/applications';
+import Create from './components/Create';
import * as styles from './index.module.scss';
const Applications = () => {
+ const [isCreateFormOpen, setIsCreateFormOpen] = useState(false);
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const { data, error } = useSWR('/api/applications');
const isLoading = !data && !error;
@@ -23,7 +27,23 @@ const Applications = () => {
-
+
diff --git a/packages/console/src/scss/modal.module.scss b/packages/console/src/scss/modal.module.scss
new file mode 100644
index 000000000..83e44bf69
--- /dev/null
+++ b/packages/console/src/scss/modal.module.scss
@@ -0,0 +1,13 @@
+.content {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translateX(-50%) translateY(-50%);
+ outline: none;
+}
+
+.overlay {
+ position: fixed;
+ background: rgba(0, 0, 0, 40%);
+ inset: 0;
+}
diff --git a/packages/ui/src/components/AppContent/index.module.scss b/packages/ui/src/components/AppContent/index.module.scss
index 604eb2dae..17bc48658 100644
--- a/packages/ui/src/components/AppContent/index.module.scss
+++ b/packages/ui/src/components/AppContent/index.module.scss
@@ -1,9 +1,6 @@
.content {
position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
+ inset: 0;
background: var(--color-background);
color: var(--color-body);
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 413cfd9f7..aa8ab66cd 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -32,6 +32,7 @@ importers:
'@types/lodash.kebabcase': ^4.1.6
'@types/react': ^17.0.14
'@types/react-dom': ^17.0.9
+ '@types/react-modal': ^3.13.1
classnames: ^2.3.1
eslint: ^8.10.0
i18next: ^21.6.12
@@ -45,6 +46,7 @@ importers:
react: ^17.0.2
react-dom: ^17.0.2
react-i18next: ^11.15.4
+ react-modal: ^3.14.4
react-router-dom: ^6.2.2
stylelint: ^13.13.1
swr: ^1.2.2
@@ -60,6 +62,7 @@ importers:
react: 17.0.2
react-dom: 17.0.2_react@17.0.2
react-i18next: 11.15.4_2c37a602a29bb6bd53f3de707a8cfcc5
+ react-modal: 3.14.4_react-dom@17.0.2+react@17.0.2
react-router-dom: 6.2.2_react-dom@17.0.2+react@17.0.2
swr: 1.2.2_react@17.0.2
devDependencies:
@@ -72,6 +75,7 @@ importers:
'@types/lodash.kebabcase': 4.1.6
'@types/react': 17.0.37
'@types/react-dom': 17.0.11
+ '@types/react-modal': 3.13.1
eslint: 8.10.0
lint-staged: 11.2.6
parcel: 2.3.1_postcss@8.4.6
@@ -3566,6 +3570,12 @@ packages:
'@types/react': 17.0.37
dev: true
+ /@types/react-modal/3.13.1:
+ resolution: {integrity: sha512-iY/gPvTDIy6Z+37l+ibmrY+GTV4KQTHcCyR5FIytm182RQS69G5ps4PH2FxtC7bAQ2QRHXMevsBgck7IQruHNg==}
+ dependencies:
+ '@types/react': 17.0.37
+ dev: true
+
/@types/react-router-dom/5.3.2:
resolution: {integrity: sha512-ELEYRUie2czuJzaZ5+ziIp9Hhw+juEw8b7C11YNA4QdLCVbQ3qLi2l4aq8XnlqM7V31LZX8dxUuFUCrzHm6sqQ==}
dependencies:
@@ -6004,6 +6014,10 @@ packages:
clone-regexp: 2.2.0
dev: true
+ /exenv/1.2.2:
+ resolution: {integrity: sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=}
+ dev: false
+
/exit/0.1.2:
resolution: {integrity: sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=}
engines: {node: '>= 0.8.0'}
@@ -11251,6 +11265,25 @@ packages:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
dev: true
+ /react-lifecycles-compat/3.0.4:
+ resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==}
+ dev: false
+
+ /react-modal/3.14.4_react-dom@17.0.2+react@17.0.2:
+ resolution: {integrity: sha512-8surmulejafYCH9wfUmFyj4UfbSJwjcgbS9gf3oOItu4Hwd6ivJyVBETI0yHRhpJKCLZMUtnhzk76wXTsNL6Qg==}
+ engines: {node: '>=8'}
+ peerDependencies:
+ react: ^0.14.0 || ^15.0.0 || ^16 || ^17
+ react-dom: ^0.14.0 || ^15.0.0 || ^16 || ^17
+ dependencies:
+ exenv: 1.2.2
+ prop-types: 15.8.1
+ react: 17.0.2
+ react-dom: 17.0.2_react@17.0.2
+ react-lifecycles-compat: 3.0.4
+ warning: 4.0.3
+ dev: false
+
/react-refresh/0.9.0:
resolution: {integrity: sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==}
engines: {node: '>=0.10.0'}
@@ -13245,6 +13278,12 @@ packages:
makeerror: 1.0.12
dev: true
+ /warning/4.0.3:
+ resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
/wcwidth/1.0.1:
resolution: {integrity: sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=}
dependencies: