0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-10 22:22:45 -05:00

Merge pull request #462 from logto-io/charles-log-2031-refactor-title-subtitle-styles

refactor(console): match design mockups by adjusting fonts, paddings, etc
This commit is contained in:
Charles Zhao 2022-03-30 11:57:36 +08:00 committed by GitHub
commit 34992a2116
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 215 additions and 154 deletions

View file

@ -3,7 +3,7 @@
.item {
padding: _.unit(2) _.unit(4);
list-style: none;
font: var(--font-body-2);
font: var(--font-body-medium);
cursor: pointer;
display: flex;
align-items: center;

View file

@ -13,7 +13,7 @@
.title {
padding: _.unit(5) _.unit(4) _.unit(2) _.unit(4);
font: var(--font-body-2);
font: var(--font-body-medium);
border-bottom: 1px solid var(--color-border);
}
}

View file

@ -1,20 +1,20 @@
@use '@/scss/underscore' as _;
.topbar {
flex: 0 0 66px;
flex: 0 0 64px;
width: 100%;
padding: _.unit(4) _.unit(6);
display: flex;
align-items: center;
img {
height: 30px;
height: 32px;
}
.line {
@include _.vertical-bar;
height: 24px;
margin: 0 _.unit(3);
height: 20px;
margin: 0 _.unit(5);
}
.text {

View file

@ -29,22 +29,3 @@
.dark {
@include colors.dark-theme;
}
$font-family: 'SF UI Text', 'SF Pro Display', sans-serif;
.web {
--font-title-large: 600 20px/28px #{$font-family};
--font-title-medium: 500 16px/24px #{$font-family};
--font-heading-small: 600 24px/32px #{$font-family};
--font-heading: 600 16px/24px #{$font-family};
--font-body: normal 16px/22px #{$font-family};
--font-body-1: normal 16px/24px #{$font-family};
--font-body-2: normal 14px/20px #{$font-family};
--font-small-text: normal 12px/16px #{$font-family};
--font-caption: normal 14px/20px #{$font-family};
--font-caption-bold: 600 14px/20px #{$font-family};
--font-button: 500 14px/20px #{$font-family};
--font-subhead-2: 500 14px/20px #{$font-family};
--font-label-large: 500 20px/32px #{$font-family};
--font-label-medium: 500 12px/16px #{$font-family};
}

View file

@ -6,7 +6,7 @@ import Sidebar from './components/Sidebar';
import Topbar from './components/Topbar';
import * as styles from './index.module.scss';
type Theme = 'light';
type Theme = 'light' | 'dark';
type Props = {
theme: Theme;
@ -17,11 +17,11 @@ const AppContent = ({ theme }: Props) => {
const href = useHref('/callback');
useEffect(() => {
const classes = [styles.web, styles[theme]].filter((value): value is string => Boolean(value));
document.body.classList.add(...classes);
const className = styles[theme] ?? '';
document.body.classList.add(className);
return () => {
document.body.classList.remove(...classes);
document.body.classList.remove(className);
};
}, [theme]);

View file

@ -6,8 +6,8 @@
border-radius: _.unit(2);
font: var(--font-button);
transition: background 0.2s ease-in-out;
@include _.text-ellipsis;
align-items: center;
white-space: nowrap;
&.withIcon {
display: inline-flex;
@ -144,6 +144,7 @@
&.plain {
background: none;
border-color: none;
font: var(--font-body-medium);
color: var(--color-primary);
&:disabled {

View file

@ -1,12 +1,47 @@
@use '@/scss/underscore' as _;
.title {
font: var(--font-heading-small);
color: var(--color-on-secondary-container);
}
.container {
overflow: hidden;
.subtitle {
margin-top: _.unit(1);
font: var(--font-body);
color: var(--color-component-caption);
.title {
color: var(--color-component-text);
@include _.text-ellipsis;
}
.subtitle {
margin-top: _.unit(1);
color: var(--color-component-caption);
@include _.text-ellipsis;
}
&.large {
.title {
font: var(--font-title-large);
}
.subtitle {
font: var(--font-body-medium);
}
}
&.medium {
.title {
font: var(--font-title-medium);
}
.subtitle {
font: var(--font-body-medium);
}
}
&.small {
.title {
font: var(--font-title-medium);
}
.subtitle {
font: var(--font-body-small);
margin-top: 0;
}
}
}

View file

@ -1,24 +1,31 @@
import { AdminConsoleKey } from '@logto/phrases';
import React from 'react';
import classNames from 'classnames';
import React, { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import DangerousRaw from '../DangerousRaw';
import * as styles from './index.module.scss';
type Props = {
title: AdminConsoleKey;
subtitle?: AdminConsoleKey;
title: AdminConsoleKey | ReactElement<typeof DangerousRaw>;
subtitle?: AdminConsoleKey | ReactElement<typeof DangerousRaw>;
size?: 'small' | 'medium' | 'large';
};
/**
* Always use this component to render CardTitle, with built-in i18n support.
*/
const CardTitle = ({ title, subtitle }: Props) => {
const CardTitle = ({ title, subtitle, size = 'large' }: Props) => {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
return (
<div>
<div className={styles.title}>{t(title)}</div>
{subtitle && <div className={styles.subtitle}>{t(subtitle)}</div>}
<div className={classNames(styles.container, styles[size])}>
<div className={styles.title}>{typeof title === 'string' ? t(title) : title}</div>
{subtitle && (
<div className={styles.subtitle}>
{typeof subtitle === 'string' ? t(subtitle) : subtitle}
</div>
)}
</div>
);
};

View file

@ -6,7 +6,7 @@
border-radius: _.unit(2);
background: var(--color-inverse-on-surface);
color: var(--color-on-secondary-container);
font: var(--font-caption);
font: var(--font-body-medium);
cursor: default;
.row {

View file

@ -12,12 +12,12 @@
margin-bottom: _.unit(1);
.title {
font: var(--font-caption-bold);
font: var(--font-subhead-2);
color: var(--color-component-text);
}
.required {
font: var(--font-body-2);
font: var(--font-body-medium);
color: var(--color-component-caption);
}
}

View file

@ -14,13 +14,13 @@
}
.title {
font: var(--font-body);
font: var(--font-body-medium);
color: var(--color-primary);
text-decoration: none;
}
.subtitle {
font: var(--font-small-text);
font: var(--font-body-small);
color: var(--color-outline);
}
}

View file

@ -1,5 +1,5 @@
.markdown {
font: var(--font-body-2);
font: var(--font-body-medium);
h1 {
font: var(--font-title-large);
@ -16,6 +16,6 @@
}
p {
font: var(--font-body-2);
font: var(--font-body-medium);
}
}

View file

@ -3,10 +3,7 @@
.radioGroup {
display: flex;
flex-wrap: wrap;
&:not(:first-child) {
margin-top: _.unit(3);
}
margin: 0 _.unit(-8) _.unit(-8) 0;
> .radio {
position: relative;
@ -60,7 +57,7 @@
}
.title {
font: var(--font-heading);
font: var(--font-subhead-2);
color: var(--color-component-text);
}

View file

@ -1,4 +1,12 @@
import React, { Children, cloneElement, forwardRef, isValidElement, ReactNode } from 'react';
import classNames from 'classnames';
import React, {
Children,
cloneElement,
forwardRef,
isValidElement,
LegacyRef,
ReactNode,
} from 'react';
import Radio, { Props as RadioProps } from './Radio';
import * as styles from './index.module.scss';
@ -7,33 +15,33 @@ type Props = {
name: string;
children: ReactNode;
value: string;
// https://github.com/yannickcr/eslint-plugin-react/issues/2856
// eslint-disable-next-line react/require-default-props
className?: string;
onChange?: (value: string) => void;
};
const RadioGroup = forwardRef<HTMLDivElement, Props>(
({ name, children, value, onChange }: Props, reference) => {
return (
<div ref={reference} className={styles.radioGroup}>
{Children.map(children, (child) => {
if (!isValidElement(child) || child.type !== Radio) {
return child;
}
const RadioGroup = (
{ name, children, value, className, onChange }: Props,
reference?: LegacyRef<HTMLDivElement>
) => {
return (
<div ref={reference} className={classNames(styles.radioGroup, className)}>
{Children.map(children, (child) => {
if (!isValidElement(child) || child.type !== Radio) {
return child;
}
return cloneElement<RadioProps>(child, {
name,
isChecked: value === child.props.value,
onClick: () => {
onChange?.(child.props.value);
},
tabIndex: 0,
});
})}
</div>
);
}
);
return cloneElement<RadioProps>(child, {
name,
isChecked: value === child.props.value,
onClick: () => {
onChange?.(child.props.value);
},
tabIndex: 0,
});
})}
</div>
);
};
export default RadioGroup;
export default forwardRef<HTMLDivElement, Props>(RadioGroup);
export { default as Radio } from './Radio';

View file

@ -1,7 +1,7 @@
@use '@/scss/underscore' as _;
.link {
font: var(--font-body-2);
font: var(--font-body-medium);
margin-right: _.unit(6);
padding-bottom: _.unit(1);

View file

@ -10,7 +10,7 @@
}
.content {
font: var(--font-body-2);
font: var(--font-body-medium);
color: var(--color-neutral-50);
margin-bottom: _.unit(2);
}

View file

@ -15,7 +15,7 @@
.content {
text-align: center;
font: var(--font-body-2);
font: var(--font-body-medium);
color: var(--color-neutral-50);
margin-bottom: _.unit(2);
}

View file

@ -2,7 +2,7 @@
.button {
display: inline-block;
font: var(--font-caption);
font: var(--font-body-medium);
color: var(--color-primary);
padding: _.unit(0.5) _.unit(1);
border-radius: _.unit(1);

View file

@ -9,7 +9,7 @@
border-radius: 6px;
border: 1px solid var(--color-component-border);
outline: 2px solid transparent;
font: var(--font-body-2);
font: var(--font-body-medium);
transition-property: outline, border;
transition-timing-function: ease-in-out;
transition-duration: 0.2s;

View file

@ -2,7 +2,7 @@
div.toast {
padding: _.unit(3) _.unit(4);
font: var(--font-body-2);
font: var(--font-body-medium);
color: var(--color-component-text);
box-shadow: var(--light-shadow-s1);
border-radius: _.unit(2);

View file

@ -8,7 +8,7 @@
color: #e0e3e3;
box-shadow: var(--light-shadow-s1);
padding: _.unit(2) _.unit(3);
font: var(--font-body);
font: var(--font-body-medium);
&::after {
content: '';

View file

@ -2,14 +2,14 @@ import React, { SVGProps } from 'react';
const Tick = (props: SVGProps<SVGSVGElement>) => (
<svg
width="16"
height="12"
viewBox="0 0 16 12"
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path d="M15.7016 0.216515C16.0686 0.531016 16.1016 1.07279 15.7755 1.42661L6.29399 11.7123C6.12531 11.8953 5.88353 12 5.62963 12C5.37573 12 5.13395 11.8953 4.96527 11.7123L0.224534 6.56946C-0.101615 6.21565 -0.0685652 5.67387 0.298352 5.35937C0.66527 5.04487 1.22711 5.07674 1.55326 5.43055L5.62963 9.85269L14.4467 0.287697C14.7729 -0.0661164 15.3347 -0.0979856 15.7016 0.216515Z" />
<path d="M15.5917 6.00822C15.5142 5.93011 15.4221 5.86811 15.3205 5.82581C15.219 5.7835 15.11 5.76172 15 5.76172C14.89 5.76172 14.7811 5.7835 14.6796 5.82581C14.578 5.86811 14.4858 5.93011 14.4084 6.00822L8.20004 12.2249L5.59171 9.60822C5.51127 9.53052 5.41632 9.46942 5.31227 9.42842C5.20823 9.38742 5.09713 9.36731 4.98531 9.36924C4.87349 9.37118 4.76315 9.39512 4.66058 9.4397C4.55802 9.48427 4.46524 9.54862 4.38754 9.62905C4.30984 9.70949 4.24875 9.80444 4.20774 9.90848C4.16674 10.0125 4.14663 10.1236 4.14856 10.2354C4.1505 10.3473 4.17444 10.4576 4.21902 10.5602C4.2636 10.6627 4.32794 10.7555 4.40837 10.8332L7.60837 14.0332C7.68584 14.1113 7.77801 14.1733 7.87956 14.2156C7.98111 14.2579 8.09003 14.2797 8.20004 14.2797C8.31005 14.2797 8.41897 14.2579 8.52052 14.2156C8.62207 14.1733 8.71424 14.1113 8.79171 14.0332L15.5917 7.23322C15.6763 7.15518 15.7438 7.06047 15.79 6.95506C15.8361 6.84964 15.86 6.7358 15.86 6.62072C15.86 6.50563 15.8361 6.3918 15.79 6.28638C15.7438 6.18096 15.6763 6.08625 15.5917 6.00822V6.00822Z" />
</svg>
);

View file

@ -6,7 +6,7 @@
}
.description {
font: var(--font-body-2);
font: var(--font-body-medium);
}
.hightlight {

View file

@ -6,7 +6,7 @@
}
.description {
font: var(--font-body-2);
font: var(--font-body-medium);
}
.hightlight {

View file

@ -1,7 +1,7 @@
@use '@/scss/underscore' as _;
.error {
font: var(--font-body-2);
font: var(--font-body-medium);
color: var(--color-error);
margin-top: _.unit(2);
}

View file

@ -6,29 +6,21 @@
background-color: var(--color-main-background);
height: 100vh;
.title {
font: var(--font-title-large);
color: var(--color-component-text);
}
.subtitle {
font: var(--font-body-1);
color: var(--color-component-caption);
}
.header {
display: flex;
align-items: center;
background-color: var(--color-on-primary);
height: 80px;
padding: 0 _.unit(17) 0 _.unit(5);
height: 64px;
padding: 0 _.unit(21) 0 _.unit(2);
.titleWrapper {
button {
margin-left: _.unit(4);
}
button + button {
margin-left: _.unit(4);
.separator {
@include _.vertical-bar;
height: 20px;
margin: 0 _.unit(5) 0 _.unit(4);
}
}
@ -43,21 +35,28 @@
.card {
width: 858px;
padding: _.unit(6) _.unit(8);
padding: _.unit(5) _.unit(6);
display: flex;
flex-direction: column;
scroll-margin: _.unit(6);
scroll-margin: _.unit(5);
&.selector {
display: block;
padding: _.unit(8);
margin-top: _.unit(4);
.title {
font: var(--font-title-large);
}
.subtitle {
font: var(--font-body-medium);
color: var(--color-component-text);
margin-top: _.unit(3);
}
.radioGroup {
margin-top: _.unit(6);
}
.radio {
border-radius: _.unit(2);
width: 240px;
@ -72,8 +71,7 @@
background: var(--color-neutral-variant-90);
border-radius: _.unit(2);
padding: 0 _.unit(4);
margin-top: 0;
font: var(--font-body-2);
font: var(--font-body-medium);
color: var(--color-component-text);
img {
@ -82,10 +80,6 @@
}
}
&.expanded {
padding: _.unit(8);
}
.cardHeader {
display: flex;
flex-direction: row;
@ -97,13 +91,15 @@
}
.index {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border-radius: 50%;
color: var(--color-primary);
background: var(--color-surface-5);
font: var(--font-label-large);
text-align: center;
font: var(--font-title-medium);
margin-right: _.unit(4);
&.active {

View file

@ -10,6 +10,8 @@ import highFive from '@/assets/images/high-five.svg';
import tada from '@/assets/images/tada.svg';
import Button from '@/components/Button';
import Card from '@/components/Card';
import CardTitle from '@/components/CardTitle';
import DangerousRaw from '@/components/DangerousRaw';
import IconButton from '@/components/IconButton';
import RadioGroup, { Radio } from '@/components/RadioGroup';
import Spacer from '@/components/Spacer';
@ -85,7 +87,12 @@ const GetStarted = ({ appName, onClose }: Props) => {
<div className={styles.title}>{t('applications.get_started.title')}</div>
<div className={styles.subtitle}>{t('applications.get_started.subtitle')}</div>
</div>
<RadioGroup name="libraryName" value={libraryName} onChange={setLibraryName}>
<RadioGroup
className={styles.radioGroup}
name="libraryName"
value={libraryName}
onChange={setLibraryName}
>
{Object.values(SupportedJavascriptLibraries).map((library) => (
<Radio key={library} className={styles.radio} title={library} value={library} />
))}
@ -123,10 +130,12 @@ const GetStarted = ({ appName, onClose }: Props) => {
<IconButton size="large" onClick={onClose}>
<Close />
</IconButton>
<div className={styles.titleWrapper}>
<div className={styles.title}>{appName}</div>
<div className={styles.subtitle}>{t('applications.get_started.header_description')}</div>
</div>
<div className={styles.separator} />
<CardTitle
size="small"
title={<DangerousRaw>{appName}</DangerousRaw>}
subtitle="applications.get_started.header_description"
/>
<Spacer />
<Button type="plain" size="small" title="general.skip" onClick={onClose} />
<Button
@ -151,11 +160,7 @@ const GetStarted = ({ appName, onClose }: Props) => {
// TODO: add more styles to markdown renderer
// TODO: render form and input fields in steps
return (
<Card
key={title}
ref={stepReferences[index]}
className={classNames(styles.card, isExpanded && styles.expanded)}
>
<Card key={title} ref={stepReferences[index]} className={styles.card}>
<div
className={styles.cardHeader}
onClick={() => {
@ -172,12 +177,13 @@ const GetStarted = ({ appName, onClose }: Props) => {
>
{isCompleted ? <Tick /> : index + 1}
</div>
<div>
<div className={styles.title}>{title}</div>
<div className={styles.subtitle}>{subtitle}</div>
</div>
<CardTitle
size="medium"
title={<DangerousRaw>{title}</DangerousRaw>}
subtitle={<DangerousRaw>{subtitle}</DangerousRaw>}
/>
<Spacer />
{isExpanded ? <ArrowUp /> : <ArrowDown />}
<IconButton>{isExpanded ? <ArrowUp /> : <ArrowDown />}</IconButton>
</div>
{isExpanded && (
<>

View file

@ -7,11 +7,11 @@
}
.subtitle {
font: var(--font-body-2);
font: var(--font-body-medium);
color: var(--color-component-text);
}
.description {
font: var(--font-caption);
font: var(--font-body-medium);
color: var(--color-component-caption);
}

View file

@ -16,12 +16,12 @@
}
.error {
font: var(--font-body-2);
font: var(--font-body-medium);
color: var(--color-error);
}
.description {
font: var(--font-body-2);
font: var(--font-body-medium);
color: var(--color-component-caption);
}

View file

@ -4,7 +4,7 @@
padding-top: _.unit(5);
.connector {
font: var(--font-body);
font: var(--font-body-medium);
width: 230px;
.logo {
@ -24,12 +24,12 @@
.connectorId {
margin-top: _.unit(2);
font: var(--font-body-2);
font: var(--font-body-medium);
color: var(--color-neutral-50);
}
.description {
font: var(--font-body-2);
font: var(--font-body-medium);
margin-top: _.unit(2);
height: 60px;
overflow: hidden;

View file

@ -31,7 +31,7 @@
.empty {
text-align: center;
font-size: var(--font-body-2);
font-size: var(--font-body-medium);
}
.emptyLine {

View file

@ -1,7 +1,7 @@
@use '@/scss/underscore' as _;
.content {
font: var(--font-body-2);
font: var(--font-body-medium);
.info {
margin-top: _.unit(6);

View file

@ -15,7 +15,7 @@
tr {
td {
padding: _.unit(2);
font: var(--font-body-2);
font: var(--font-body-medium);
&:first-child {
padding-left: _.unit(4);

View file

@ -0,0 +1,29 @@
$font-family:
-apple-system,
system-ui,
'BlinkMacSystemFont',
'Segoe UI',
'Roboto',
'Helvetica Neue',
'Helvetica',
'Arial',
sans-serif,
'Apple Color Emoji';
:root {
--font-headline-large: 600 32px/40px #{$font-family};
--font-headline-medium: 600 28px/36px #{$font-family};
--font-headline-small: 600 24px/32px #{$font-family};
--font-title-large: 600 20px/28px #{$font-family};
--font-title-medium: 600 16px/24px #{$font-family};
--font-title-small: 600 14px/20px #{$font-family};
--font-label-large: 500 14px/20px #{$font-family};
--font-label-medium: 500 12px/16px #{$font-family};
--font-label-small: 500 11px/16px #{$font-family};
--font-body-large: 400 16px/24px #{$font-family};
--font-body-medium: 400 14px/20px #{$font-family};
--font-body-small: 400 12px/16px #{$font-family};
--font-subhead-1: 500 16px/24px #{$font-family};
--font-subhead-2: 500 14px/20px #{$font-family};
--font-button: 500 14px/20px #{$font-family};
}

View file

@ -22,6 +22,6 @@
}
@mixin vertical-bar {
border: 1px solid #c4c7c7;
border-left: 1px solid var(--color-border);
width: 0;
}

View file

@ -1,4 +1,5 @@
@use '@/scss/underscore' as _;
@use '@/scss/fonts';
body {
margin: 0;

View file

@ -8,7 +8,7 @@
.content {
text-align: center;
font: var(--font-body);
font: var(--font-body-medium);
color: var(--color-font-primary);
}

View file

@ -3,7 +3,7 @@
.divider {
@include _.flex-row;
font: var(--font-body);
font: var(--font-body-medium);
color: var(--color-font-divider);
margin: _.unit(4) 0;
width: 100%;

View file

@ -12,7 +12,7 @@
.toast {
padding: _.unit(2) _.unit(4);
font: var(--font-body);
font: var(--font-body-medium);
color: var(--color-font-toast-text);
border-radius: _.unit(2);
max-width: none;