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: