0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-30 20:33:54 -05:00

feat(ui): implement Confirm Modal (#449)

* feat(ui): implement Confirm Modal

add Confirm Modal

* fix(ui): remove lock file

remove lock filee

* fix(ui): confirmModal CR fix

confirmModal CR fix
This commit is contained in:
simeng-li 2022-03-28 09:36:39 +08:00 committed by GitHub
parent 14ac317358
commit b99c11e211
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 123 additions and 14 deletions

View file

@ -5,6 +5,8 @@ const translation = {
skip: 'Skip',
next: 'Next',
retry: 'Try again',
confirm: 'Confirm',
cancel: 'Cancel',
},
sign_in: {
action: 'Sign In',

View file

@ -7,6 +7,8 @@ const translation = {
skip: '跳过',
next: '下一步',
retry: '重试',
confirm: '确认',
cancel: '取消',
},
sign_in: {
action: '登录',

View file

@ -25,6 +25,7 @@
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-i18next": "^11.15.4",
"react-modal": "^3.14.4",
"react-phone-number-input": "^3.1.46",
"react-router-dom": "^5.2.0"
},
@ -40,6 +41,7 @@
"@types/jest": "^27.4.0",
"@types/react": "^17.0.14",
"@types/react-dom": "^17.0.9",
"@types/react-modal": "^3.13.1",
"@types/react-router-dom": "^5.3.2",
"eslint": "^8.10.0",
"identity-obj-proxy": "^3.0.0",

View file

@ -68,7 +68,7 @@ $font-family: 'PingFang SC', 'SF Pro Text', sans-serif;
--color-secondary-background-active: #{$color-neutral-10};
--color-secondary-background-disabled: #{$color-neutral-10};
--color-border: #{$color-neutral-100};
--color-border-active: #{$color-neutral-70};
--color-border-secondary: #{$color-neutral-70};
--color-border-disabled: #{$color-neutral-30};
--color-control-background: #{$color-neutral-10};
--color-control-focus: #{$color-primary-tint-60};
@ -84,7 +84,7 @@ $font-family: 'PingFang SC', 'SF Pro Text', sans-serif;
--color-font-divider: #bbb;
--color-font-button-text: #{$color-neutral-0};
--color-font-button-text-active: #{rgba($color-neutral-0, 0.4)};
--color-font-secondary-active: #{$color-neutral-70};
--color-font-secondary-dialog: #{$color-neutral-70};
--color-font-secondary-disabled: #{rgba($color-neutral-100, 0.4)};
--color-font-link: #{$color-primary};
--color-font-link-secondary: #{$color-neutral-70};
@ -108,6 +108,7 @@ $font-family: 'PingFang SC', 'SF Pro Text', sans-serif;
--font-heading-2-bold: 600 18px/22px #{$font-family};
--font-control: 500 18px/20px #{$font-family};
--font-button-text: 600 20px/24px #{$font-family};
--font-button-text-small: 500 18px/22px #{$font-family};
--font-body: 400 16px/20px #{$font-family};
--font-body-bold: 600 16px/20px #{$font-family};
--font-body-small: 400 14px/18px #{$font-family};

View file

@ -5,7 +5,7 @@
flex-direction: row;
justify-content: center;
align-items: center;
padding: _.unit(3) _.unit(10);
padding: _.unit(3);
border-radius: _.unit(2);
font: var(--font-button-text);
transition: var(--transition-default-control);
@ -19,20 +19,19 @@
border: none;
background: var(--color-primary);
color: var(--color-font-button-text);
&:active {
background: linear-gradient(0deg, rgba(0, 0, 0, 16%), rgba(0, 0, 0, 16%)), var(--color-primary);
color: var(--color-font-button-text-active);
}
}
.secondary {
border: _.border(var(--color-border));
background: var(--color-background);
color: var(--color-font-primary);
}
&:active {
border: _.border(var(--color-border-active));
color: var(--color-font-secondary-active);
.small {
font: var(--font-button-text-small);
&.secondary {
border: _.border(var(--color-border-secondary));
color: var(--color-font-secondary-dialog);
}
}

View file

@ -1,13 +1,14 @@
import classNames from 'classnames';
import React from 'react';
import React, { ReactNode } from 'react';
import * as styles from './index.module.scss';
export type Props = {
htmlType?: 'button' | 'submit' | 'reset';
size?: 'large' | 'small';
isDisabled?: boolean;
className?: string;
children: string; // TODO: make it i18nKey with optional params
children: ReactNode; // TODO: make it i18nKey with optional params
type?: 'primary' | 'secondary';
onClick?: React.MouseEventHandler;
};
@ -15,6 +16,7 @@ export type Props = {
const Button = ({
htmlType = 'button',
type = 'primary',
size = 'large',
isDisabled,
className,
children,
@ -22,7 +24,7 @@ const Button = ({
}: Props) => (
<button
disabled={isDisabled}
className={classNames(styles.button, styles[type], className)}
className={classNames(styles.button, styles[type], styles[size], className)}
type={htmlType}
onClick={onClick}
>

View file

@ -0,0 +1,27 @@
@use '@/scss/underscore' as _;
.container {
background: var(--color-background);
padding: _.unit(6);
border-radius: _.unit(2);
}
.content {
text-align: center;
font: var(--font-body);
color: var(--color-font-primary);
}
.footer {
@include _.flex_row;
margin-top: _.unit(6);
justify-content: space-between;
> * {
flex: 1;
}
> button:first-child {
margin-right: _.unit(2);
}
}

View file

@ -0,0 +1,56 @@
import { I18nKey } from '@logto/phrases';
import classNames from 'classnames';
import React, { ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
import ReactModal from 'react-modal';
import Button from '@/components/Button';
import * as modalStyles from '@/scss/modal.module.scss';
import * as styles from './index.module.scss';
type Props = {
classname?: string;
isOpen?: boolean;
children: ReactNode;
cancelText?: I18nKey;
confirmText?: I18nKey;
onConfirm?: () => void;
onClose: () => void;
};
const ConfirmModal = ({
classname,
isOpen = false,
children,
cancelText = 'general.cancel',
confirmText = 'general.confirm',
onConfirm,
onClose,
}: Props) => {
const { t } = useTranslation();
return (
<ReactModal
role="dialog"
isOpen={isOpen}
className={classNames(modalStyles.modal, classname)}
overlayClassName={modalStyles.overlay}
parentSelector={() => document.querySelector('main') ?? document.body}
>
<div className={styles.container}>
<div className={styles.content}>{children}</div>
<div className={styles.footer}>
<Button type="secondary" size="small" onClick={onClose}>
{t(cancelText)}
</Button>
<Button size="small" onClick={onConfirm ?? onClose}>
{t(confirmText)}
</Button>
</div>
</div>
</ReactModal>
);
};
export default ConfirmModal;

View file

@ -0,0 +1,14 @@
.modal {
position: absolute;
left: 40px;
right: 40px;
top: 50%;
transform: translate(0, -50%);
outline: none;
}
.overlay {
position: fixed;
background: rgba(0, 0, 0, 16%);
inset: 0;
}

View file

@ -283,6 +283,7 @@ importers:
'@types/jest': ^27.4.0
'@types/react': ^17.0.14
'@types/react-dom': ^17.0.9
'@types/react-modal': ^3.13.1
'@types/react-router-dom': ^5.3.2
classnames: ^2.3.1
eslint: ^8.10.0
@ -301,6 +302,7 @@ importers:
react: ^17.0.2
react-dom: ^17.0.2
react-i18next: ^11.15.4
react-modal: ^3.14.4
react-phone-number-input: ^3.1.46
react-router-dom: ^5.2.0
stylelint: ^13.13.1
@ -317,6 +319,7 @@ importers:
react: 17.0.2
react-dom: 17.0.2_react@17.0.2
react-i18next: 11.15.4_3fb644aa30122a07f960d67fa51d6dc1
react-modal: 3.14.4_react-dom@17.0.2+react@17.0.2
react-phone-number-input: 3.1.46_react-dom@17.0.2+react@17.0.2
react-router-dom: 5.3.0_react@17.0.2
devDependencies:
@ -331,6 +334,7 @@ importers:
'@types/jest': 27.4.0
'@types/react': 17.0.37
'@types/react-dom': 17.0.11
'@types/react-modal': 3.13.1
'@types/react-router-dom': 5.3.2
eslint: 8.10.0
identity-obj-proxy: 3.0.0