0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-27 21:39:16 -05:00

feat(ui): add darkmode logo (#880)

* feat(ui): add darkmode logo

add darkmode logo

* fix(ui): cr fix

cr fix
This commit is contained in:
simeng-li 2022-05-19 14:21:14 +08:00 committed by GitHub
parent a2cd983d97
commit 9fa13a24ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 18 deletions

View file

@ -1,15 +1,17 @@
import { useState, useMemo, createContext } from 'react'; import { useState, useMemo, createContext } from 'react';
import { isMobile } from 'react-device-detect'; import { isMobile } from 'react-device-detect';
import { SignInExperienceSettings, Platform } from '@/types'; import { SignInExperienceSettings, Platform, Theme } from '@/types';
type Context = { type Context = {
theme: Theme;
toast: string; toast: string;
loading: boolean; loading: boolean;
platform: Platform; platform: Platform;
termsAgreement: boolean; termsAgreement: boolean;
showTermsModal: boolean; showTermsModal: boolean;
experienceSettings: SignInExperienceSettings | undefined; experienceSettings: SignInExperienceSettings | undefined;
setTheme: (theme: Theme) => void;
setToast: (message: string) => void; setToast: (message: string) => void;
setLoading: (loading: boolean) => void; setLoading: (loading: boolean) => void;
setPlatform: (platform: Platform) => void; setPlatform: (platform: Platform) => void;
@ -24,11 +26,13 @@ const noop = () => {
export const PageContext = createContext<Context>({ export const PageContext = createContext<Context>({
toast: '', toast: '',
theme: 'light',
loading: false, loading: false,
platform: isMobile ? 'mobile' : 'web', platform: isMobile ? 'mobile' : 'web',
termsAgreement: false, termsAgreement: false,
showTermsModal: false, showTermsModal: false,
experienceSettings: undefined, experienceSettings: undefined,
setTheme: noop,
setToast: noop, setToast: noop,
setLoading: noop, setLoading: noop,
setPlatform: noop, setPlatform: noop,
@ -40,6 +44,7 @@ export const PageContext = createContext<Context>({
const usePageContext = () => { const usePageContext = () => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [toast, setToast] = useState(''); const [toast, setToast] = useState('');
const [theme, setTheme] = useState<Theme>('light');
const [platform, setPlatform] = useState<Platform>(isMobile ? 'mobile' : 'web'); const [platform, setPlatform] = useState<Platform>(isMobile ? 'mobile' : 'web');
const [experienceSettings, setExperienceSettings] = useState<SignInExperienceSettings>(); const [experienceSettings, setExperienceSettings] = useState<SignInExperienceSettings>();
const [termsAgreement, setTermsAgreement] = useState(false); const [termsAgreement, setTermsAgreement] = useState(false);
@ -47,12 +52,14 @@ const usePageContext = () => {
const context = useMemo( const context = useMemo(
() => ({ () => ({
theme,
toast, toast,
loading, loading,
platform, platform,
termsAgreement, termsAgreement,
showTermsModal, showTermsModal,
experienceSettings, experienceSettings,
setTheme,
setLoading, setLoading,
setToast, setToast,
setPlatform, setPlatform,
@ -60,7 +67,7 @@ const usePageContext = () => {
setShowTermsModal, setShowTermsModal,
setExperienceSettings, setExperienceSettings,
}), }),
[experienceSettings, loading, platform, showTermsModal, termsAgreement, toast] [experienceSettings, loading, platform, showTermsModal, termsAgreement, theme, toast]
); );
return { return {

View file

@ -1,21 +1,24 @@
import { AppearanceMode } from '@logto/schemas'; import { AppearanceMode } from '@logto/schemas';
import { useState, useEffect, useContext } from 'react'; import { useEffect, useContext } from 'react';
import { Theme } from '@/types';
import { PageContext } from './use-page-context'; import { PageContext } from './use-page-context';
export type Theme = 'dark' | 'light';
const darkThemeWatchMedia = window.matchMedia('(prefers-color-scheme: dark)'); const darkThemeWatchMedia = window.matchMedia('(prefers-color-scheme: dark)');
const getThemeBySystemConfiguration = (): Theme => (darkThemeWatchMedia.matches ? 'dark' : 'light'); const getThemeBySystemConfiguration = (): Theme => (darkThemeWatchMedia.matches ? 'dark' : 'light');
export default function useTheme(mode: AppearanceMode = AppearanceMode.SyncWithSystem): Theme { export default function useTheme(mode: AppearanceMode = AppearanceMode.SyncWithSystem): Theme {
const { experienceSettings } = useContext(PageContext); const { experienceSettings, theme, setTheme } = useContext(PageContext);
const [theme, setTheme] = useState<Theme>(
mode === AppearanceMode.SyncWithSystem ? 'light' : mode
);
useEffect(() => { useEffect(() => {
if (mode !== AppearanceMode.SyncWithSystem || !experienceSettings?.branding.isDarkModeEnabled) { if (mode !== AppearanceMode.SyncWithSystem) {
setTheme(mode);
return;
}
if (!experienceSettings?.branding.isDarkModeEnabled) {
return; return;
} }
@ -30,7 +33,7 @@ export default function useTheme(mode: AppearanceMode = AppearanceMode.SyncWithS
return () => { return () => {
darkThemeWatchMedia.removeEventListener('change', changeTheme); darkThemeWatchMedia.removeEventListener('change', changeTheme);
}; };
}, [experienceSettings, mode]); }, [experienceSettings, mode, setTheme]);
return theme; return theme;
} }

View file

@ -9,22 +9,28 @@ import * as styles from './index.module.scss';
import { PrimarySection, SecondarySection, CreateAccountLink } from './registry'; import { PrimarySection, SecondarySection, CreateAccountLink } from './registry';
const SignIn = () => { const SignIn = () => {
const { experienceSettings } = useContext(PageContext); const { experienceSettings, theme } = useContext(PageContext);
const { slogan, logoUrl = '', style } = experienceSettings?.branding ?? {};
if (!experienceSettings) {
return null;
}
const { slogan, logoUrl, darkLogoUrl, style } = experienceSettings.branding;
const logo = theme === 'light' ? logoUrl : darkLogoUrl ?? logoUrl;
return ( return (
<div className={classNames(styles.wrapper)}> <div className={classNames(styles.wrapper)}>
<BrandingHeader <BrandingHeader
className={styles.header} className={styles.header}
headline={style === BrandingStyle.Logo_Slogan ? slogan : undefined} headline={style === BrandingStyle.Logo_Slogan ? slogan : undefined}
logo={logoUrl} logo={logo}
/> />
<PrimarySection signInMethod={experienceSettings?.primarySignInMethod} /> <PrimarySection signInMethod={experienceSettings.primarySignInMethod} />
<SecondarySection <SecondarySection
primarySignInMethod={experienceSettings?.primarySignInMethod} primarySignInMethod={experienceSettings.primarySignInMethod}
secondarySignInMethods={experienceSettings?.secondarySignInMethods} secondarySignInMethods={experienceSettings.secondarySignInMethods}
/> />
<CreateAccountLink primarySignInMethod={experienceSettings?.primarySignInMethod} /> <CreateAccountLink primarySignInMethod={experienceSettings.primarySignInMethod} />
</div> </div>
); );
}; };

View file

@ -16,6 +16,8 @@ export enum SearchParameters {
export type Platform = 'web' | 'mobile'; export type Platform = 'web' | 'mobile';
export type Theme = 'dark' | 'light';
export interface ConnectorData extends ConnectorMetadata { export interface ConnectorData extends ConnectorMetadata {
id: string; id: string;
} }