mirror of
https://github.com/logto-io/logto.git
synced 2025-03-24 22:41:28 -05:00
feat(console): modal layout (#419)
This commit is contained in:
parent
e9a3d7c434
commit
3e99ac172a
5 changed files with 120 additions and 73 deletions
packages/console/src
components/ModalLayout
pages/ApiResourceDetails/components/DeleteForm
scss
|
@ -0,0 +1,21 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 800px;
|
||||
padding: _.unit(8);
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
flex-shrink: 0;
|
||||
padding-top: _.unit(6);
|
||||
border-top: 1px solid var(--color-neutral-90);
|
||||
}
|
||||
}
|
40
packages/console/src/components/ModalLayout/index.tsx
Normal file
40
packages/console/src/components/ModalLayout/index.tsx
Normal file
|
@ -0,0 +1,40 @@
|
|||
import { AdminConsoleKey } from '@logto/phrases';
|
||||
import React, { ReactNode } from 'react';
|
||||
|
||||
import Close from '@/icons/Close';
|
||||
|
||||
import Card from '../Card';
|
||||
import CardTitle from '../CardTitle';
|
||||
import IconButton from '../IconButton';
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
title: AdminConsoleKey;
|
||||
subtitle?: AdminConsoleKey;
|
||||
children: ReactNode;
|
||||
footer?: ReactNode;
|
||||
onClose?: () => void;
|
||||
};
|
||||
|
||||
const ModalLayout = ({ title, subtitle, children, footer, onClose }: Props) => {
|
||||
return (
|
||||
<Card className={styles.container}>
|
||||
<div className={styles.header}>
|
||||
<CardTitle title={title} subtitle={subtitle} />
|
||||
{onClose && (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<Close />
|
||||
</IconButton>
|
||||
)}
|
||||
</div>
|
||||
<div>{children}</div>
|
||||
{footer && <div className={styles.footer}>{footer}</div>}
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModalLayout;
|
|
@ -1,27 +1,12 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.card {
|
||||
padding: _.unit(8);
|
||||
max-width: 800px;
|
||||
.content {
|
||||
padding: _.unit(6) 0;
|
||||
|
||||
> :not(:first-child) {
|
||||
margin-top: _.unit(6);
|
||||
}
|
||||
|
||||
.headline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.close {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.line {
|
||||
border-top: 1px solid var(--color-neutral-90);
|
||||
}
|
||||
|
||||
.description {
|
||||
font: var(--font-body-2);
|
||||
}
|
||||
|
@ -29,13 +14,13 @@
|
|||
.hightlight {
|
||||
color: var(--color-primary-50);
|
||||
}
|
||||
|
||||
.actions {
|
||||
text-align: right;
|
||||
|
||||
> :not(:first-child) {
|
||||
margin-left: _.unit(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
> :not(:first-child) {
|
||||
margin-left: _.unit(4);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,9 @@ import { Trans, useTranslation } from 'react-i18next';
|
|||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import Button from '@/components/Button';
|
||||
import Card from '@/components/Card';
|
||||
import CardTitle from '@/components/CardTitle';
|
||||
import IconButton from '@/components/IconButton';
|
||||
import ModalLayout from '@/components/ModalLayout';
|
||||
import TextInput from '@/components/TextInput';
|
||||
import useApi from '@/hooks/use-api';
|
||||
import Close from '@/icons/Close';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
|
@ -44,45 +41,44 @@ const DeleteForm = ({ id, name, onClose }: Props) => {
|
|||
};
|
||||
|
||||
return (
|
||||
// TODO LOG-1907: Modal
|
||||
<Card className={styles.card}>
|
||||
<div className={styles.headline}>
|
||||
<CardTitle title="api_resource_details.reminder" />
|
||||
<IconButton size="large" onClick={onClose}>
|
||||
<Close />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div className={styles.description}>
|
||||
<Trans
|
||||
t={t}
|
||||
i18nKey="api_resource_details.delete_description"
|
||||
values={{ name }}
|
||||
components={{ span: <span className={styles.hightlight} /> }}
|
||||
<ModalLayout
|
||||
title="api_resource_details.reminder"
|
||||
footer={
|
||||
<div className={styles.actions}>
|
||||
<Button
|
||||
type="outline"
|
||||
title="admin_console.api_resource_details.cancel"
|
||||
onClick={onClose}
|
||||
/>
|
||||
<Button
|
||||
disabled={inputMismatched || loading}
|
||||
type="danger"
|
||||
title="admin_console.api_resource_details.delete"
|
||||
onClick={handleDelete}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.description}>
|
||||
<Trans
|
||||
t={t}
|
||||
i18nKey="api_resource_details.delete_description"
|
||||
values={{ name }}
|
||||
components={{ span: <span className={styles.hightlight} /> }}
|
||||
/>
|
||||
</div>
|
||||
<TextInput
|
||||
value={inputName}
|
||||
placeholder={t('api_resource_details.enter_your_api_resource_name')}
|
||||
hasError={inputMismatched}
|
||||
onChange={(event) => {
|
||||
setInputName(event.currentTarget.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<TextInput
|
||||
value={inputName}
|
||||
placeholder={t('api_resource_details.enter_your_api_resource_name')}
|
||||
hasError={inputMismatched}
|
||||
onChange={(event) => {
|
||||
setInputName(event.currentTarget.value);
|
||||
}}
|
||||
/>
|
||||
<div className={styles.line} />
|
||||
<div className={styles.actions}>
|
||||
<Button
|
||||
type="outline"
|
||||
title="admin_console.api_resource_details.cancel"
|
||||
onClick={onClose}
|
||||
/>
|
||||
<Button
|
||||
disabled={inputMismatched || loading}
|
||||
type="danger"
|
||||
title="admin_console.api_resource_details.delete"
|
||||
onClick={handleDelete}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
</ModalLayout>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
.content {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
outline: none;
|
||||
}
|
||||
@use '@/scss/underscore' as _;
|
||||
|
||||
.overlay {
|
||||
position: fixed;
|
||||
background: rgba(0, 0, 0, 40%);
|
||||
inset: 0;
|
||||
overflow-y: auto;
|
||||
padding: _.unit(12) 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex: 0 0;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.fullScreen {
|
||||
|
|
Loading…
Add table
Reference in a new issue