mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
refactor(console): update error boundary styles per latest design
This commit is contained in:
parent
70d34c49c8
commit
b68e6a6235
7 changed files with 115 additions and 55 deletions
58
packages/console/src/components/AppError/index.module.scss
Normal file
58
packages/console/src/components/AppError/index.module.scss
Normal file
|
@ -0,0 +1,58 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background-color: var(--color-surface-1);
|
||||
color: var(--color-text);
|
||||
padding: _.unit(6);
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
|
||||
> * {
|
||||
margin-top: _.unit(6);
|
||||
}
|
||||
|
||||
img {
|
||||
height: 256px;
|
||||
width: 256px;
|
||||
margin-top: _.unit(30);
|
||||
}
|
||||
|
||||
label {
|
||||
font: var(--font-title-large);
|
||||
}
|
||||
|
||||
.summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: _.unit(4);
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
font: var(--font-body-medium);
|
||||
}
|
||||
|
||||
.expander {
|
||||
margin-left: _.unit(2);
|
||||
color: var(--color-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.details {
|
||||
width: 470px;
|
||||
background-color: var(--color-layer-1);
|
||||
border-radius: 16px;
|
||||
font: var(--font-body-medium);
|
||||
padding: _.unit(6);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
43
packages/console/src/components/AppError/index.tsx
Normal file
43
packages/console/src/components/AppError/index.tsx
Normal file
|
@ -0,0 +1,43 @@
|
|||
import React, { Fragment, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import ErrorImage from '@/assets/images/warning.svg';
|
||||
import { ArrowDown, ArrowUp } from '@/icons/Arrow';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
errorMessage?: string;
|
||||
callStack?: string;
|
||||
};
|
||||
|
||||
const AppError = ({ errorMessage, callStack }: Props) => {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const [isDetailsOpen, setIsDetailsOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<img src={ErrorImage} alt="oops" />
|
||||
<label>{t('errors.something_went_wrong')}</label>
|
||||
<div className={styles.summary}>
|
||||
<span>{errorMessage}</span>
|
||||
{callStack && (
|
||||
<>
|
||||
<span
|
||||
className={styles.expander}
|
||||
onClick={() => {
|
||||
setIsDetailsOpen(!isDetailsOpen);
|
||||
}}
|
||||
>
|
||||
{t('errors.more_details')}
|
||||
</span>
|
||||
{isDetailsOpen ? <ArrowUp /> : <ArrowDown />}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{callStack && isDetailsOpen && <div className={styles.details}>{callStack}</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppError;
|
|
@ -1,34 +0,0 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.container {
|
||||
overflow-y: auto;
|
||||
height: 100vh;
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--color-layer-1);
|
||||
color: var(--color-text);
|
||||
padding: _.unit(6);
|
||||
width: 858px;
|
||||
min-height: 100%;
|
||||
margin: 0 auto;
|
||||
|
||||
> *:not(:first-child) {
|
||||
margin-top: _.unit(6);
|
||||
}
|
||||
|
||||
img {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
img,
|
||||
h2 {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
details {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
import { conditional } from '@silverhand/essentials';
|
||||
import React, { Component, ReactNode } from 'react';
|
||||
import { TFunction, withTranslation } from 'react-i18next';
|
||||
|
||||
import ErrorImage from '@/assets/images/table-error.svg';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
import AppError from '../AppError';
|
||||
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
t: TFunction;
|
||||
};
|
||||
|
||||
type State = {
|
||||
|
@ -40,26 +36,15 @@ class ErrorBoundary extends Component<Props, State> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { children, t } = this.props;
|
||||
const { children } = this.props;
|
||||
const { callStack, errorMessage, hasError } = this.state;
|
||||
|
||||
if (hasError) {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.wrapper}>
|
||||
<img src={ErrorImage} alt="oops" />
|
||||
<h2>{t('admin_console.errors.something_went_wrong')}</h2>
|
||||
<details open>
|
||||
<summary>{errorMessage}</summary>
|
||||
{callStack}
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return <AppError errorMessage={errorMessage} callStack={callStack} />;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
}
|
||||
|
||||
export default withTranslation()(ErrorBoundary);
|
||||
export default ErrorBoundary;
|
||||
|
|
|
@ -10,7 +10,10 @@ export const ArrowDown = (props: SVGProps<SVGSVGElement>) => {
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path d="M12.71 15.5402L18.36 9.88023C18.4537 9.78726 18.5281 9.67666 18.5789 9.5548C18.6296 9.43294 18.6558 9.30224 18.6558 9.17023C18.6558 9.03821 18.6296 8.90751 18.5789 8.78565C18.5281 8.66379 18.4537 8.55319 18.36 8.46023C18.1726 8.27398 17.9191 8.16943 17.655 8.16943C17.3908 8.16943 17.1373 8.27398 16.95 8.46023L11.95 13.4102L6.99996 8.46023C6.8126 8.27398 6.55915 8.16943 6.29496 8.16943C6.03078 8.16943 5.77733 8.27398 5.58996 8.46023C5.49548 8.55284 5.42031 8.66329 5.36881 8.78516C5.31731 8.90704 5.29051 9.03792 5.28996 9.17023C5.29051 9.30253 5.31731 9.43342 5.36881 9.55529C5.42031 9.67717 5.49548 9.78761 5.58996 9.88023L11.24 15.5402C11.3336 15.6417 11.4473 15.7227 11.5738 15.7781C11.7003 15.8336 11.8369 15.8622 11.975 15.8622C12.1131 15.8622 12.2497 15.8336 12.3762 15.7781C12.5027 15.7227 12.6163 15.6417 12.71 15.5402Z" />
|
||||
<path
|
||||
d="M12.71 15.5402L18.36 9.88023C18.4537 9.78726 18.5281 9.67666 18.5789 9.5548C18.6296 9.43294 18.6558 9.30224 18.6558 9.17023C18.6558 9.03821 18.6296 8.90751 18.5789 8.78565C18.5281 8.66379 18.4537 8.55319 18.36 8.46023C18.1726 8.27398 17.9191 8.16943 17.655 8.16943C17.3908 8.16943 17.1373 8.27398 16.95 8.46023L11.95 13.4102L6.99996 8.46023C6.8126 8.27398 6.55915 8.16943 6.29496 8.16943C6.03078 8.16943 5.77733 8.27398 5.58996 8.46023C5.49548 8.55284 5.42031 8.66329 5.36881 8.78516C5.31731 8.90704 5.29051 9.03792 5.28996 9.17023C5.29051 9.30253 5.31731 9.43342 5.36881 9.55529C5.42031 9.67717 5.49548 9.78761 5.58996 9.88023L11.24 15.5402C11.3336 15.6417 11.4473 15.7227 11.5738 15.7781C11.7003 15.8336 11.8369 15.8622 11.975 15.8622C12.1131 15.8622 12.2497 15.8336 12.3762 15.7781C12.5027 15.7227 12.6163 15.6417 12.71 15.5402Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
@ -25,7 +28,10 @@ export const ArrowUp = (props: SVGProps<SVGSVGElement>) => {
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path d="M11.29 8.45977L5.64004 14.1198C5.54631 14.2127 5.47191 14.3233 5.42115 14.4452C5.37038 14.5671 5.34424 14.6978 5.34424 14.8298C5.34424 14.9618 5.37038 15.0925 5.42115 15.2144C5.47191 15.3362 5.54631 15.4468 5.64004 15.5398C5.8274 15.726 6.08085 15.8306 6.34504 15.8306C6.60922 15.8306 6.86267 15.726 7.05004 15.5398L12.05 10.5898L17 15.5398C17.1874 15.726 17.4409 15.8306 17.705 15.8306C17.9692 15.8306 18.2227 15.726 18.41 15.5398C18.5045 15.4472 18.5797 15.3367 18.6312 15.2148C18.6827 15.093 18.7095 14.9621 18.71 14.8298C18.7095 14.6975 18.6827 14.5666 18.6312 14.4447C18.5797 14.3228 18.5045 14.2124 18.41 14.1198L12.76 8.45977C12.6664 8.35827 12.5527 8.27726 12.4262 8.22185C12.2997 8.16645 12.1631 8.13784 12.025 8.13784C11.8869 8.13784 11.7503 8.16645 11.6238 8.22185C11.4973 8.27726 11.3837 8.35827 11.29 8.45977Z" />
|
||||
<path
|
||||
d="M11.29 8.45977L5.64004 14.1198C5.54631 14.2127 5.47191 14.3233 5.42115 14.4452C5.37038 14.5671 5.34424 14.6978 5.34424 14.8298C5.34424 14.9618 5.37038 15.0925 5.42115 15.2144C5.47191 15.3362 5.54631 15.4468 5.64004 15.5398C5.8274 15.726 6.08085 15.8306 6.34504 15.8306C6.60922 15.8306 6.86267 15.726 7.05004 15.5398L12.05 10.5898L17 15.5398C17.1874 15.726 17.4409 15.8306 17.705 15.8306C17.9692 15.8306 18.2227 15.726 18.41 15.5398C18.5045 15.4472 18.5797 15.3367 18.6312 15.2148C18.6827 15.093 18.7095 14.9621 18.71 14.8298C18.7095 14.6975 18.6827 14.5666 18.6312 14.4447C18.5797 14.3228 18.5045 14.2124 18.41 14.1198L12.76 8.45977C12.6664 8.35827 12.5527 8.27726 12.4262 8.22185C12.2997 8.16645 12.1631 8.13784 12.025 8.13784C11.8869 8.13784 11.7503 8.16645 11.6238 8.22185C11.4973 8.27726 11.3837 8.35827 11.29 8.45977Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -115,6 +115,7 @@ const translation = {
|
|||
invalid_uri_format: 'Invalid URI format',
|
||||
required_field_missing: 'Please enter {{field}}',
|
||||
required_field_missing_plural: 'You have to enter at least one {{field}}',
|
||||
more_details: 'More details',
|
||||
},
|
||||
tab_sections: {
|
||||
overview: 'Overview',
|
||||
|
|
|
@ -115,6 +115,7 @@ const translation = {
|
|||
invalid_uri_format: '无效的 URI 格式',
|
||||
required_field_missing: '请输入{{field}}',
|
||||
required_field_missing_plural: '{{field}}不能全部为空',
|
||||
more_details: '查看详情',
|
||||
},
|
||||
tab_sections: {
|
||||
overview: '概览',
|
||||
|
|
Loading…
Reference in a new issue