mirror of
https://github.com/logto-io/logto.git
synced 2025-03-31 22:51:25 -05:00
feat(console): link button component (#527)
This commit is contained in:
parent
72aa2f53e6
commit
06ea931d64
13 changed files with 100 additions and 63 deletions
|
@ -1,14 +0,0 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.button {
|
||||
padding-left: 0;
|
||||
|
||||
.body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> *:not(:first-child) {
|
||||
margin-left: _.unit(1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import classNames from 'classnames';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import * as buttonStyles from '@/components/TextButton/index.module.scss';
|
||||
|
||||
import Back from './Back';
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
to: string;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
const BackLink = ({ to, children }: Props) => (
|
||||
<Link to={to} className={classNames(buttonStyles.button, styles.button)}>
|
||||
<div className={styles.body}>
|
||||
<Back />
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
|
||||
export default BackLink;
|
27
packages/console/src/components/LinkButton/index.module.scss
Normal file
27
packages/console/src/components/LinkButton/index.module.scss
Normal file
|
@ -0,0 +1,27 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.linkButton {
|
||||
background: none;
|
||||
border-color: none;
|
||||
font: var(--font-body-medium);
|
||||
color: var(--color-primary);
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
> *:not(:first-child) {
|
||||
margin-left: _.unit(1);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: var(--color-primary-30);
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--color-primary-80);
|
||||
}
|
||||
}
|
28
packages/console/src/components/LinkButton/index.tsx
Normal file
28
packages/console/src/components/LinkButton/index.tsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { I18nKey } from '@logto/phrases';
|
||||
import classNames from 'classnames';
|
||||
import React, { ReactElement, ReactNode } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import DangerousRaw from '../DangerousRaw';
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
to: string;
|
||||
title: I18nKey | ReactElement<typeof DangerousRaw>;
|
||||
icon?: ReactNode;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const LinkButton = ({ to, title, icon, className }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Link to={to} className={classNames(styles.linkButton, className)}>
|
||||
{icon}
|
||||
{typeof title === 'string' ? <span>{t(title)}</span> : title}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default LinkButton;
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
|
||||
const Back = () => {
|
||||
return (
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="20" height="20" viewBox="0 -2 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.3566 13.6562L4.69995 7.99958L10.3566 2.34292L11.3 3.28558L6.58528 7.99958L11.3 12.7136L10.3566 13.6562Z" />
|
||||
</svg>
|
||||
);
|
|
@ -1,12 +1,7 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.backButton {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> *:not(:first-child) {
|
||||
margin-left: _.unit(1);
|
||||
}
|
||||
.backLink {
|
||||
margin: _.unit(1) 0 0 _.unit(1);
|
||||
}
|
||||
|
||||
.header {
|
||||
|
|
|
@ -8,16 +8,17 @@ import { useLocation, useParams } from 'react-router-dom';
|
|||
import useSWR from 'swr';
|
||||
|
||||
import ActionMenu, { ActionMenuItem } from '@/components/ActionMenu';
|
||||
import BackLink from '@/components/BackLink';
|
||||
import Button from '@/components/Button';
|
||||
import Card from '@/components/Card';
|
||||
import CopyToClipboard from '@/components/CopyToClipboard';
|
||||
import Drawer from '@/components/Drawer';
|
||||
import FormField from '@/components/FormField';
|
||||
import ImagePlaceholder from '@/components/ImagePlaceholder';
|
||||
import LinkButton from '@/components/LinkButton';
|
||||
import TabNav, { TabNavLink } from '@/components/TabNav';
|
||||
import TextInput from '@/components/TextInput';
|
||||
import useApi, { RequestError } from '@/hooks/use-api';
|
||||
import Back from '@/icons/Back';
|
||||
import Delete from '@/icons/Delete';
|
||||
import More from '@/icons/More';
|
||||
import * as detailsStyles from '@/scss/details.module.scss';
|
||||
|
@ -74,8 +75,12 @@ const ApiResourceDetails = () => {
|
|||
|
||||
return (
|
||||
<div className={detailsStyles.container}>
|
||||
<BackLink to="/api-resources">{t('api_resource_details.back_to_api_resources')}</BackLink>
|
||||
|
||||
<LinkButton
|
||||
to="/api-resources"
|
||||
icon={<Back />}
|
||||
title="admin_console.api_resource_details.back_to_api_resources"
|
||||
className={styles.backLink}
|
||||
/>
|
||||
{isLoading && <div>loading</div>}
|
||||
{error && <div>{`error occurred: ${error.body.message}`}</div>}
|
||||
{data && (
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.backLink {
|
||||
margin: _.unit(1) 0 0 _.unit(1);
|
||||
}
|
||||
|
||||
.body {
|
||||
padding-bottom: 0;
|
||||
|
||||
|
|
|
@ -8,18 +8,19 @@ import { useLocation, useParams } from 'react-router-dom';
|
|||
import useSWR from 'swr';
|
||||
|
||||
import ActionMenu, { ActionMenuItem } from '@/components/ActionMenu';
|
||||
import BackLink from '@/components/BackLink';
|
||||
import Button from '@/components/Button';
|
||||
import Card from '@/components/Card';
|
||||
import CopyToClipboard from '@/components/CopyToClipboard';
|
||||
import Drawer from '@/components/Drawer';
|
||||
import FormField from '@/components/FormField';
|
||||
import ImagePlaceholder from '@/components/ImagePlaceholder';
|
||||
import LinkButton from '@/components/LinkButton';
|
||||
import MultiTextInput from '@/components/MultiTextInput';
|
||||
import { convertRhfErrorMessage, createValidatorForRhf } from '@/components/MultiTextInput/utils';
|
||||
import TabNav, { TabNavLink } from '@/components/TabNav';
|
||||
import TextInput from '@/components/TextInput';
|
||||
import useApi, { RequestError } from '@/hooks/use-api';
|
||||
import Back from '@/icons/Back';
|
||||
import Delete from '@/icons/Delete';
|
||||
import More from '@/icons/More';
|
||||
import * as detailsStyles from '@/scss/details.module.scss';
|
||||
|
@ -182,7 +183,12 @@ const ApplicationDetails = () => {
|
|||
|
||||
return (
|
||||
<div className={detailsStyles.container}>
|
||||
<BackLink to="/applications">{t('application_details.back_to_applications')}</BackLink>
|
||||
<LinkButton
|
||||
to="/applications"
|
||||
icon={<Back />}
|
||||
title="admin_console.application_details.back_to_applications"
|
||||
className={styles.backLink}
|
||||
/>
|
||||
{isLoading && <div>loading</div>}
|
||||
{error && <div>{`error occurred: ${error.body.message}`}</div>}
|
||||
{data && oidcConfig && (
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.backLink {
|
||||
margin: _.unit(1) 0 0 _.unit(1);
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: _.unit(8);
|
||||
display: flex;
|
||||
|
|
|
@ -6,17 +6,18 @@ import { useNavigate, useParams } from 'react-router-dom';
|
|||
import useSWR from 'swr';
|
||||
|
||||
import ActionMenu, { ActionMenuItem } from '@/components/ActionMenu';
|
||||
import BackLink from '@/components/BackLink';
|
||||
import Button from '@/components/Button';
|
||||
import Card from '@/components/Card';
|
||||
import CodeEditor from '@/components/CodeEditor';
|
||||
import Drawer from '@/components/Drawer';
|
||||
import ImagePlaceholder from '@/components/ImagePlaceholder';
|
||||
import LinkButton from '@/components/LinkButton';
|
||||
import Markdown from '@/components/Markdown';
|
||||
import Status from '@/components/Status';
|
||||
import TabNav, { TabNavLink } from '@/components/TabNav';
|
||||
import UnnamedTrans from '@/components/UnnamedTrans';
|
||||
import useApi, { RequestError } from '@/hooks/use-api';
|
||||
import Back from '@/icons/Back';
|
||||
import Delete from '@/icons/Delete';
|
||||
import More from '@/icons/More';
|
||||
import Reset from '@/icons/Reset';
|
||||
|
@ -97,7 +98,12 @@ const ConnectorDetails = () => {
|
|||
|
||||
return (
|
||||
<div className={detailsStyles.container}>
|
||||
<BackLink to="/connectors">{t('connector_details.back_to_connectors')}</BackLink>
|
||||
<LinkButton
|
||||
to="/connectors"
|
||||
icon={<Back />}
|
||||
title="admin_console.connector_details.back_to_connectors"
|
||||
className={styles.backLink}
|
||||
/>
|
||||
{isLoading && <div>loading</div>}
|
||||
{error && <div>{`error occurred: ${error.body.message}`}</div>}
|
||||
{data && (
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
@use '@/scss/underscore' as _;
|
||||
|
||||
.backButton {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> *:not(:first-child) {
|
||||
margin-left: _.unit(1);
|
||||
}
|
||||
.backLink {
|
||||
margin: _.unit(1) 0 0 _.unit(1);
|
||||
}
|
||||
|
||||
.header {
|
||||
|
|
|
@ -9,16 +9,17 @@ import { useParams } from 'react-router-dom';
|
|||
import useSWR from 'swr';
|
||||
|
||||
import ActionMenu, { ActionMenuItem } from '@/components/ActionMenu';
|
||||
import BackLink from '@/components/BackLink';
|
||||
import Button from '@/components/Button';
|
||||
import Card from '@/components/Card';
|
||||
import CodeEditor from '@/components/CodeEditor';
|
||||
import CopyToClipboard from '@/components/CopyToClipboard';
|
||||
import FormField from '@/components/FormField';
|
||||
import ImagePlaceholder from '@/components/ImagePlaceholder';
|
||||
import LinkButton from '@/components/LinkButton';
|
||||
import TabNav, { TabNavLink } from '@/components/TabNav';
|
||||
import TextInput from '@/components/TextInput';
|
||||
import useApi, { RequestError } from '@/hooks/use-api';
|
||||
import Back from '@/icons/Back';
|
||||
import Delete from '@/icons/Delete';
|
||||
import More from '@/icons/More';
|
||||
import Reset from '@/icons/Reset';
|
||||
|
@ -101,8 +102,12 @@ const UserDetails = () => {
|
|||
|
||||
return (
|
||||
<div className={detailsStyles.container}>
|
||||
<BackLink to="/users">{t('user_details.back_to_users')}</BackLink>
|
||||
|
||||
<LinkButton
|
||||
to="/users"
|
||||
icon={<Back />}
|
||||
title="admin_console.user_details.back_to_users"
|
||||
className={styles.backLink}
|
||||
/>
|
||||
{isLoading && <div>loading</div>}
|
||||
{error && <div>{`error occurred: ${error.body.message}`}</div>}
|
||||
{id && data && (
|
||||
|
|
Loading…
Add table
Reference in a new issue