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:
parent
a2cd983d97
commit
9fa13a24ae
4 changed files with 36 additions and 18 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue