0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

feat(ui): init destop styling foundation (#787)

* feat(ui): init  destop styling foundation

init desktop styling

* fix(ui): cr fix

* style(ui): enable mobile and desktop global class

enable mobile and desktop global class
This commit is contained in:
simeng-li 2022-05-11 11:30:35 +08:00 committed by GitHub
parent 2b3061d06d
commit 5c02ec3bda
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 239 additions and 95 deletions

View file

@ -64,10 +64,21 @@
"extends": "@silverhand/react"
},
"stylelint": {
"extends": "@silverhand/eslint-config-react/.stylelintrc"
"extends": "@silverhand/eslint-config-react/.stylelintrc",
"rules": {
"selector-pseudo-class-no-unknown": [
true,
{
"ignorePseudoClasses": [
"global"
]
}
]
}
},
"prettier": "@silverhand/eslint-config/.prettierrc",
"dependencies": {
"react-device-detect": "^2.2.2",
"use-debounced-loader": "^0.1.1"
}
}

View file

@ -1,30 +1,61 @@
@use '@/scss/underscore' as _;
@use '@/scss/colors' as colors;
@use '@/scss/basic' as basic;
@use '@/scss/mobile' as mobile;
@use '@/scss/desktop' as desktop;
/* Foundation */
.light {
@include colors.light-theme;
}
.dark {
@include colors.dark-theme;
}
body {
@include colors.universal;
@include basic.fonts;
@include basic.layout;
background: var(--color-base);
color: var(--color-text);
font: var(--font-body);
}
.content {
position: absolute;
top: 0;
left: 0;
right: 0;
min-height: 100%;
background: var(--color-base);
@include _.flex_column;
background-color: var(--color-base);
}
main {
position: absolute;
inset: 0;
background: var(--color-surface);
color: var(--color-text);
font: var(--font-body);
@include _.flex_column;
}
/* Foundation */
:global(body.mobile) {
&.light {
@include mobile.colors-light-theme;
}
&.dark {
@include mobile.colors-dark-theme;
}
@include mobile.colors-universal;
@include mobile.fonts;
@include mobile.layout;
.content {
flex: 1;
align-self: stretch;
padding: _.unit(6) _.unit(5);
position: relative;
}
}
:global(body.desktop) {
&.light {
@include desktop.colors-light-theme;
}
&.dark {
@include desktop.colors-dark-theme;
}
@include desktop.colors-universal;
@include desktop.fonts;
@include desktop.layout;
.content {
width: 640px;
min-height: 640px;
position: relative;
padding: _.unit(6);
}
}

View file

@ -1,5 +1,6 @@
import classNames from 'classnames';
import { conditionalString } from '@silverhand/essentials';
import React, { ReactNode, useEffect, useCallback, useContext } from 'react';
import { isMobile } from 'react-device-detect';
import { useDebouncedLoader } from 'use-debounced-loader';
import LoadingLayer from '@/components/LoadingLayer';
@ -24,14 +25,17 @@ const AppContent = ({ children }: Props) => {
}, [setToast]);
useEffect(() => {
document.body.classList.remove(styles.light ?? '');
document.body.classList.remove(styles.dark ?? '');
document.body.classList.add(styles[theme] ?? '');
document.body.classList.remove(conditionalString(styles.light), conditionalString(styles.dark));
document.body.classList.add(conditionalString(styles[theme]));
}, [theme]);
useEffect(() => {
document.body.classList.add(isMobile ? 'mobile' : 'desktop');
}, []);
return (
<main className={classNames(styles.content, styles[theme])}>
{children}
<main>
<div className={styles.content}>{children}</div>
<Toast message={toast} isVisible={Boolean(toast)} callback={hideToast} />
{debouncedLoading && <LoadingLayer />}
</main>

View file

@ -30,7 +30,6 @@
/* stylelint-disable selector-class-pattern */
/* stylelint-disable-next-line selector-pseudo-class-no-unknown */
:global {
.ReactModal__Content[role='popup'] {
transform: translateY(100%);

View file

@ -10,7 +10,7 @@
svg {
position: absolute;
left: _.unit(4);
left: _.unit(-2);
top: 50%;
transform: translateY(-50%);
fill: var(--color-text);

View file

@ -2,9 +2,9 @@
.wrapper {
@include _.page-wrapper;
position: absolute;
inset: 0;
@include _.full-page;
@include _.flex-column;
justify-content: flex-start;
}
.connector {

View file

@ -1,7 +1,9 @@
@use '@/scss/underscore' as _;
.wrapper {
@include _.page-wrapper;
@include _.full-page;
@include _.flex-column;
justify-content: flex-start;
.header {
margin-top: _.unit(30);

View file

@ -1,14 +1,14 @@
@use '@/scss/underscore' as _;
.container {
position: absolute;
inset: 0;
.wrapper {
@include _.full-page;
@include _.flex-column;
align-items: stretch;
.wrapper {
.container {
flex: 1;
@include _.page-wrapper;
@include _.flex-column;
justify-content: flex-start;
}
.icon {

View file

@ -18,9 +18,9 @@ const ErrorPage = ({ title = 'description.not_found', message }: Props) => {
const navigate = useNavigate();
return (
<div className={styles.container}>
<div className={styles.wrapper}>
<NavBar />
<div className={styles.wrapper}>
<div className={styles.container}>
<ErrorIcon className={styles.icon} />
<div className={styles.title}>{t(title)}</div>
{message && <div className={styles.message}>{message}</div>}

View file

@ -1,8 +1,11 @@
@use '@/scss/underscore' as _;
.wrapper {
@include _.page-wrapper;
padding-top: _.unit(2);
@include _.full-page;
}
.container {
margin-top: _.unit(2);
}
.title {

View file

@ -43,14 +43,14 @@ const Passcode = () => {
}
return (
<>
<div className={styles.wrapper}>
<NavBar />
<div className={styles.wrapper}>
<div className={styles.container}>
<div className={styles.title}>{t('action.enter_passcode')}</div>
<div className={styles.detail}>{t('description.enter_passcode', { address: target })}</div>
<PasscodeValidation type={type} method={method} target={target} />
</div>
</>
</div>
);
};

View file

@ -1,8 +1,11 @@
@use '@/scss/underscore' as _;
.wrapper {
@include _.page-wrapper;
padding-top: _.unit(2);
@include _.full-page;
}
.container {
margin-top: _.unit(2);
}

View file

@ -34,13 +34,13 @@ const Register = () => {
}
return (
<>
<div className={styles.wrapper}>
<NavBar />
<div className={styles.wrapper}>
<div className={styles.container}>
<div className={styles.title}>{t('action.create_account')}</div>
{registerForm}
</div>
</>
</div>
);
};

View file

@ -1,8 +1,11 @@
@use '@/scss/underscore' as _;
.wrapper {
@include _.page-wrapper;
padding-top: _.unit(2);
@include _.full-page;
}
.container {
margin-top: _.unit(2);
}

View file

@ -34,13 +34,13 @@ const SecondarySignIn = () => {
}
return (
<>
<div className={styles.wrapper}>
<NavBar />
<div className={styles.wrapper}>
<div className={styles.container}>
<div className={styles.title}>{t('action.sign_in')}</div>
{signInForm}
</div>
</>
</div>
);
};

View file

@ -1,7 +1,9 @@
@use '@/scss/underscore' as _;
.wrapper {
@include _.page-wrapper;
@include _.full-page;
@include _.flex-column;
justify-content: flex-start;
.header {
margin: _.unit(8);

View file

@ -1,5 +1,9 @@
@use '@/scss/underscore' as _;
.wrapper {
@include _.page-wrapper;
@include _.full-page;
}
.container {
margin-top: _.unit(2);
}

View file

@ -20,12 +20,12 @@ const SocialRegister = () => {
}
return (
<>
<div className={styles.wrapper}>
<NavBar title={t('description.bind_account_title')} />
<div className={styles.wrapper}>
<div className={styles.container}>
<SocialCreateAccount connectorId={connector} />
</div>
</>
</div>
);
};

View file

@ -1,22 +0,0 @@
/* Foundation */
$font-family: -apple-system,
system-ui,
'BlinkMacSystemFont',
'Segoe UI',
'Roboto',
'Helvetica Neue',
'Helvetica',
'Arial',
sans-serif;
@mixin fonts {
--font-title: 600 32px/40px #{$font-family};
--font-body-bold: 500 16px/20px #{$font-family};
--font-body: 400 16px/20px #{$font-family};
--font-body-small: 500 14px/18px #{$font-family};
--font-caption: 400 14px/18px #{$font-family};
}
@mixin layout {
--radius: 8px;
}

View file

@ -0,0 +1,63 @@
/* Foundation */
$font-family: -apple-system,
system-ui,
'BlinkMacSystemFont',
'Segoe UI',
'Roboto',
'Helvetica Neue',
'Helvetica',
'Arial',
sans-serif;
@mixin colors-light-theme {
--color-surface: #ecebf6;
--color-base: #fff;
// legacy bellow
--color-text: #191c1d;
--color-icon: #747778;
--color-caption: #747778;
--color-outline: #78767f;
--color-border: #e0e3e3;
--color-disabled: #c4c7c7;
--color-primary: #5d34f2;
--color-layer: #eff1f1;
--color-error: #ba1b1b;
--color-toast: rgba(25, 28, 29, 80%);
--color-overlay: rgba(25, 28, 29, 16%);
--color-dialogue: #fff;
}
@mixin colors-dark-theme {
--color-surface: #25272b;
--color-base: #2a2c32;
// legacy bellow
--color-text: #f7f8f8;
--color-icon: #a9acac;
--color-caption: #a9acac;
--color-outline: #928f9a;
--color-border: #444748;
--color-disabled: #5c5f60;
--color-primary: #7958ff;
--color-layer: linear-gradient(0deg, rgba(202, 190, 255, 14%), rgba(202, 190, 255, 14%)), linear-gradient(0deg, rgba(196, 199, 199, 2%), rgba(196, 199, 199, 2%)), #191c1d;
--color-error: #dd3730;
--color-toast: rgba(247, 248, 248, 80%);
--color-overlay: rgba(25, 28, 29, 40%);
--color-dialogue: linear-gradient(0deg, rgba(202, 190, 255, 8%), rgba(202, 190, 255, 8%)), linear-gradient(0deg, rgba(196, 199, 199, 2%), rgba(196, 199, 199, 2%)), #191c1d;
}
@mixin colors-universal {
--color-primary-button-text: #fff;
}
@mixin fonts {
--font-title: 600 32px/40px #{$font-family};
--font-body-bold: 500 16px/20px #{$font-family};
--font-body: 400 16px/20px #{$font-family};
--font-body-small: 500 14px/18px #{$font-family};
--font-caption: 400 14px/18px #{$font-family};
}
@mixin layout {
--radius: 8px;
}

View file

@ -1,4 +1,15 @@
@mixin light-theme {
/* Foundation */
$font-family: -apple-system,
system-ui,
'BlinkMacSystemFont',
'Segoe UI',
'Roboto',
'Helvetica Neue',
'Helvetica',
'Arial',
sans-serif;
@mixin colors-light-theme {
--color-text: #191c1d;
--color-icon: #747778;
--color-caption: #747778;
@ -11,10 +22,11 @@
--color-toast: rgba(25, 28, 29, 80%);
--color-overlay: rgba(25, 28, 29, 16%);
--color-base: #fff;
--color-surface: #fff;
--color-dialogue: #fff;
}
@mixin dark-theme {
@mixin colors-dark-theme {
--color-text: #f7f8f8;
--color-icon: #a9acac;
--color-caption: #a9acac;
@ -27,9 +39,23 @@
--color-toast: rgba(247, 248, 248, 80%);
--color-overlay: rgba(25, 28, 29, 40%);
--color-base: #191c1d;
--color-surface: #191c1d;
--color-dialogue: linear-gradient(0deg, rgba(202, 190, 255, 8%), rgba(202, 190, 255, 8%)), linear-gradient(0deg, rgba(196, 199, 199, 2%), rgba(196, 199, 199, 2%)), #191c1d;
}
@mixin universal {
@mixin colors-universal {
--color-primary-button-text: #fff;
}
@mixin fonts {
--font-title: 600 32px/40px #{$font-family};
--font-body-bold: 500 16px/20px #{$font-family};
--font-body: 400 16px/20px #{$font-family};
--font-body-small: 500 14px/18px #{$font-family};
--font-caption: 400 14px/18px #{$font-family};
}
@mixin layout {
--radius: 8px;
}

View file

@ -29,11 +29,9 @@
color: var(--color-text);
}
@mixin page-wrapper {
position: relative;
padding: unit(6) unit(5);
@include flex-column;
justify-content: flex-start;
@mixin full-page {
flex: 1;
align-self: stretch;
}
@mixin container-width {

View file

@ -864,6 +864,7 @@ importers:
postcss-modules: ^4.3.0
prettier: ^2.3.2
react: ^17.0.2
react-device-detect: ^2.2.2
react-dom: ^17.0.2
react-i18next: ^11.15.4
react-modal: ^3.14.4
@ -875,6 +876,7 @@ importers:
typescript: ^4.6.2
use-debounced-loader: ^0.1.1
dependencies:
react-device-detect: 2.2.2_sfoxds7t5ydpegc3knd667wn6m
use-debounced-loader: 0.1.1_react@17.0.2
devDependencies:
'@logto/jest-config': link:../jest-config
@ -16755,6 +16757,17 @@ packages:
- webpack
dev: true
/react-device-detect/2.2.2_sfoxds7t5ydpegc3knd667wn6m:
resolution: {integrity: sha512-zSN1gIAztUekp5qUT/ybHwQ9fmOqVT1psxpSlTn1pe0CO+fnJHKRLOWWac5nKxOxvOpD/w84hk1I+EydrJp7SA==}
peerDependencies:
react: '>= 0.14.0'
react-dom: '>= 0.14.0'
dependencies:
react: 17.0.2
react-dom: 17.0.2_react@17.0.2
ua-parser-js: 1.0.2
dev: false
/react-dnd-html5-backend/16.0.0:
resolution: {integrity: sha512-be3lKEbbT8FQcoTjFlQ4ZXG/NVrFNJu9W0INc5rm/5EFQpHCkz+xpbB2U8j9uh5Bvk7AsJyQrZznEut0hrNPIA==}
dependencies:
@ -19530,6 +19543,10 @@ packages:
resolution: {integrity: sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==}
dev: true
/ua-parser-js/1.0.2:
resolution: {integrity: sha512-00y/AXhx0/SsnI51fTc0rLRmafiGOM4/O+ny10Ps7f+j/b8p/ZY11ytMgznXkOVo4GQ+KwQG5UQLkLGirsACRg==}
dev: false
/uglify-js/3.15.3:
resolution: {integrity: sha512-6iCVm2omGJbsu3JWac+p6kUiOpg3wFO2f8lIXjfEb8RrmLjzog1wTPMmwKB7swfzzqxj9YM+sGUM++u1qN4qJg==}
engines: {node: '>=0.8.0'}