0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-04 02:01:58 -05:00

Cleaned up Frame components

refs https://github.com/TryGhost/Team/issues/1858
This commit is contained in:
Simon Backx 2022-08-31 14:52:49 +02:00
parent 02a514f17c
commit bcb23bc9dc
3 changed files with 67 additions and 60 deletions

View file

@ -1,4 +1,4 @@
import Frame from './components/Frame';
import {CommentsFrame} from './components/Frame';
import React from 'react';
import {isSyncAction, ActionHandler, SyncActionHandler} from './actions';
import {createPopupNotification} from './utils/helpers';
@ -18,14 +18,6 @@ function AuthFrame({adminUrl, onLoad}) {
);
}
function CommentsBoxContainer({done, appVersion}) {
return (
<Frame title="comments-box">
<CommentsBox done={done} />
</Frame>
);
}
function SentryErrorBoundary({dsn, children}) {
// todo: add Sentry.ErrorBoundary wrapper if Sentry is enabled
return (
@ -309,7 +301,9 @@ export default class App extends React.Component {
return (
<SentryErrorBoundary dsn={this.props.sentryDsn}>
<AppContext.Provider value={this.getContextFromState()}>
<CommentsBoxContainer done={done} />
<CommentsFrame>
<CommentsBox done={done} />
</CommentsFrame>
<AuthFrame adminUrl={this.props.adminUrl} onLoad={this.initAdminAuth.bind(this)}/>
<PopupModal />
</AppContext.Provider>

View file

@ -2,32 +2,73 @@ import React, {useContext, useState} from 'react';
import AppContext from '../AppContext';
import IFrame from './IFrame';
const Frame = ({
children,
type,
...props
}) => {
/**
* Loads all the CSS styles inside an iFrame. Only shows the visible content as soon as the CSS file with the tailwind classes has loaded.
*/
const TailwindFrame = ({children, onResize, style, title}) => {
const {stylesUrl} = useContext(AppContext);
const [cssLoaded, setCssLoaded] = useState(!stylesUrl);
const styles = `
const initialStyles = `
body, html {
overflow: hidden;
}
`;
// We have two types of frames:
// - A full width + content fitted height one
// - A fixed positioned one for modals
/**
* @type {'dynamic'|'fixed'}
*/
type = type ?? 'dynamic';
const onLoadCSS = () => {
setCssLoaded(true);
};
// For now we don't listen for type changes, we could consider adding useEffect, but that won't be used
const defaultStyle = type === 'dynamic' ? {
const head = (
<>
{stylesUrl ? <link rel="stylesheet" href={stylesUrl} onLoad={onLoadCSS} /> : null}
<style dangerouslySetInnerHTML={{__html: initialStyles}} />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
</>
);
// For now we're using <NewFrame> because using a functional component with portal caused some weird issues with modals
return (
<IFrame head={head} style={style} onResize={onResize} title={title}>
{cssLoaded && children}
</IFrame>
);
};
/**
* This iframe has the same height as it contents and mimics a shadow DOM component
*/
const ResizableFrame = ({children, style, title}) => {
const [iframeStyle, setIframeStyle] = useState(style);
const onResize = (iframeRoot) => {
setIframeStyle((current) => {
return {
...current,
height: `${iframeRoot.scrollHeight}px`
};
});
};
return (
<TailwindFrame style={iframeStyle} onResize={onResize} title={title}>
{children}
</TailwindFrame>
);
};
export const CommentsFrame = ({children}) => {
const style = {
width: '100%',
height: '400px'
} : {
};
return (
<ResizableFrame style={style} title="comments-frame">
{children}
</ResizableFrame>
);
};
export const PopupFrame = ({children}) => {
const style = {
zIndex: '3999999',
position: 'fixed',
left: '0',
@ -37,37 +78,9 @@ const Frame = ({
overflow: 'hidden'
};
const [iframeStyle, setIframeStyle] = useState(defaultStyle);
const onResize = (iframeRoot) => {
setIframeStyle((current) => {
return {
...current,
height: `${iframeRoot.scrollHeight}px`
};
});
};
const [cssLoaded, setCssLoaded] = useState(!stylesUrl);
const onLoadCSS = () => {
setCssLoaded(true);
};
const head = (
<>
{stylesUrl ? <link rel="stylesheet" href={stylesUrl} onLoad={onLoadCSS} /> : null}
<style dangerouslySetInnerHTML={{__html: styles}} />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
</>
);
// For now we're using <NewFrame> because using a functional component with portal caused some weird issues with modals
return (
<IFrame {...props} head={head} style={iframeStyle} onResize={type === 'dynamic' ? onResize : null}>
{cssLoaded && children}
</IFrame>
<TailwindFrame style={style} title="popup-frame">
{children}
</TailwindFrame>
);
};
export default Frame;

View file

@ -1,6 +1,6 @@
import React, {useContext, useEffect} from 'react';
import {Transition} from '@headlessui/react';
import Frame from '../Frame';
import {PopupFrame} from '../Frame';
import AppContext from '../../AppContext';
const GenericDialog = (props) => {
@ -29,7 +29,7 @@ const GenericDialog = (props) => {
return (
<Transition show={props.show} appear={true}>
<Frame type="fixed">
<PopupFrame>
<div>
<Transition.Child
enter="transition duration-200 linear"
@ -53,7 +53,7 @@ const GenericDialog = (props) => {
</div>
</Transition.Child>
</div>
</Frame>
</PopupFrame>
</Transition>
);
};