Skip to content

Commit

Permalink
feat: parent framework theme detection
Browse files Browse the repository at this point in the history
  • Loading branch information
nolimits4web committed Sep 6, 2021
1 parent d670e1d commit 75f5acf
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 8 deletions.
13 changes: 11 additions & 2 deletions src/react/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { forwardRef, useImperativeHandle, useRef } from 'react';
import { cls } from '../shared/cls.js';
import { positionClass } from '../shared/position-class.js';
import { TailwindMobileProvider } from '../shared/TailwindMobileProvider.jsx';
import { useAutoTheme } from '../shared/use-auto-theme.js';

const App = forwardRef((props, ref) => {
const {
Expand Down Expand Up @@ -32,16 +33,24 @@ const App = forwardRef((props, ref) => {
...rest,
};

const currentTheme = useAutoTheme(theme);

const classes = cls(
theme === 'ios' ? `twm-ios` : 'twm-material',
currentTheme === 'ios' && `twm-ios`,
currentTheme === 'material' && 'twm-material',
'twm-app w-full h-full min-h-screen',
safeAreas && 'safe-areas',
positionClass('relative', className),
className
);

return (
<TailwindMobileProvider theme={theme} dark={dark} touchRipple={touchRipple}>
<TailwindMobileProvider
theme={currentTheme}
dark={dark}
touchRipple={touchRipple}
autoThemeDetection={false}
>
<Component ref={elRef} className={classes} {...attrs}>
{children}
</Component>
Expand Down
15 changes: 13 additions & 2 deletions src/react/shared/TailwindMobileProvider.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import React from 'react';
import { TailwindMobileContext } from './TailwindMobileContext.js';
import { useAutoTheme } from './use-auto-theme.js';

const TailwindMobileProvider = (props) => {
const { theme, dark, touchRipple = true, children } = props;
const {
theme,
dark,
touchRipple = true,
autoThemeDetection = true,
children,
} = props;

const currentTheme = useAutoTheme(theme, autoThemeDetection);

return (
<TailwindMobileContext.Provider value={{ theme, dark, touchRipple }}>
<TailwindMobileContext.Provider
value={{ theme: currentTheme, dark, touchRipple }}
>
{children}
</TailwindMobileContext.Provider>
);
Expand Down
32 changes: 32 additions & 0 deletions src/react/shared/use-auto-theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useState } from 'react';
import { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect.js';

export const useAutoTheme = (theme, autoThemeDetection = true) => {
const [themeState, setThemeState] = useState(theme);

/* eslint-disable no-restricted-globals */
useIsomorphicLayoutEffect(() => {
if (!autoThemeDetection) return;
if (theme === 'ios' || theme === 'material') {
if (themeState !== theme) setThemeState(theme);
} else if (
themeState === 'parent' &&
typeof window !== 'undefined' &&
typeof document !== 'undefined'
) {
const htmlEl = document.documentElement;
if (htmlEl) {
if (htmlEl.classList.contains('ios')) {
setThemeState('ios');
} else if (
htmlEl.classList.contains('md') ||
htmlEl.classList.contains('material')
) {
setThemeState('material');
}
}
}
}, [theme]);
/* eslint-enable no-restricted-globals */
return autoThemeDetection ? themeState : theme;
};
9 changes: 9 additions & 0 deletions src/react/shared/use-isomorphic-layout-effect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useEffect, useLayoutEffect } from 'react';

function useIsomorphicLayoutEffect(callback, deps) {
// eslint-disable-next-line
if (typeof window === 'undefined') return useEffect(callback, deps);
return useLayoutEffect(callback, deps);
}

export { useIsomorphicLayoutEffect };
4 changes: 2 additions & 2 deletions src/react/tailwind-mobile-react.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import * as React from 'react';
// PROVIDER
interface TailwindMobileProviderProps {
/**
* App theme
* App theme. If set to `'parent'` it will look for `ios` or `md` class on root `<html>` element, useful to use with parent framework like Framework7 or Ionic
*
* @default 'material'
*/
theme?: 'ios' | 'material';
theme?: 'ios' | 'material' | 'parent';
/**
* Include `dark:` variants (if dark theme is in use)
*
Expand Down
4 changes: 2 additions & 2 deletions src/types/App.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ interface Props {
*/
component?: string;
/**
* App theme
* App theme. If set to `'parent'` it will look for `ios` or `md` class on root `<html>` element, useful to use with parent framework like Framework7 or Ionic
*
* @default 'material'
*/
theme?: 'ios' | 'material';
theme?: 'ios' | 'material' | 'parent';
/**
* Include `dark:` variants (if dark theme is in use)
*
Expand Down

0 comments on commit 75f5acf

Please sign in to comment.