Skip to content

Commit db14744

Browse files
committed
feat: hide editor title bar when embedded in iframe (#368)
1 parent 84747bd commit db14744

3 files changed

Lines changed: 304 additions & 437 deletions

File tree

app/components/editor/index.tsx

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { loadingOverlay } from '@/app/components/editor/plugins/LoadingOverlayEx
3131
import { extractPageContent } from '@/app/utils/contentExtractor';
3232
import { formatEngineResults, ResultsMap } from '@/app/utils/resultFormatter';
3333
import { casbinLinter, createPolicyLinter, requestLinter } from '@/app/utils/casbinLinter';
34+
import { isInsideIframe } from '@/app/utils/iframeDetector';
3435
import { useLang } from '@/app/context/LangContext';
3536
import { useAutoCarousel } from '@/app/context/AutoCarouselContext';
3637
import type { EngineType } from '@/app/config/engineConfig';
@@ -69,6 +70,11 @@ export const EditorScreen = () => {
6970
const skipNextEffectRef = useRef(false);
7071
const sidePanelChatRef = useRef<{ openDrawer: (message: string) => void } | null>(null);
7172
const policyViewRef = useRef<any | null>(null);
73+
74+
// Memoize iframe detection since it doesn't change during the session
75+
const isIframe = useMemo(() => {
76+
return isInsideIframe();
77+
}, []);
7278
const { setupEnforceContextData, setupHandleEnforceContextChange } = useSetupEnforceContext({
7379
onChange: setEnforceContextDataPersistent,
7480
data: enforceContextData,
@@ -256,32 +262,34 @@ export const EditorScreen = () => {
256262
return (
257263
<div className="flex flex-col h-full w-full overflow-hidden">
258264
<Toaster position="top-center" />
259-
{/* Header with Casbin logo and Policy Editor text */}
260-
<div
261-
className={clsx(
262-
'flex items-center gap-3 px-4 py-2 border-b border-border',
263-
theme === 'dark' ? 'bg-slate-900' : 'bg-white',
264-
)}
265-
>
266-
<img
267-
src="https://cdn.casbin.org/img/casbin_logo_1024x256.png"
268-
alt="Casbin Logo"
269-
className="h-8 w-auto"
270-
/>
271-
<span className={clsx('text-xl font-semibold', textClass)}>{t('Policy Editor')}</span>
272-
<a
273-
href="/gallery"
265+
{/* Header with Casbin logo and Policy Editor text - hidden when inside iframe */}
266+
{!isIframe && (
267+
<div
274268
className={clsx(
275-
'ml-auto px-4 py-2 rounded-lg font-medium transition-all duration-200',
276-
'bg-primary text-primary-foreground',
277-
'hover:bg-primary/90 shadow-sm hover:shadow-md',
278-
'flex items-center gap-2',
269+
'flex items-center gap-3 px-4 py-2 border-b border-border',
270+
theme === 'dark' ? 'bg-slate-900' : 'bg-white',
279271
)}
280272
>
281-
<img src="/modelGallery.svg" alt="Model Gallery" className={clsx('w-5 h-5', iconFilterClass)} />
282-
<span>{t('Model Gallery')}</span>
283-
</a>
284-
</div>
273+
<img
274+
src="https://cdn.casbin.org/img/casbin_logo_1024x256.png"
275+
alt="Casbin Logo"
276+
className="h-8 w-auto"
277+
/>
278+
<span className={clsx('text-xl font-semibold', textClass)}>{t('Policy Editor')}</span>
279+
<a
280+
href="/gallery"
281+
className={clsx(
282+
'ml-auto px-4 py-2 rounded-lg font-medium transition-all duration-200',
283+
'bg-primary text-primary-foreground',
284+
'hover:bg-primary/90 shadow-sm hover:shadow-md',
285+
'flex items-center gap-2',
286+
)}
287+
>
288+
<img src="/modelGallery.svg" alt="Model Gallery" className={clsx('w-5 h-5', iconFilterClass)} />
289+
<span>{t('Model Gallery')}</span>
290+
</a>
291+
</div>
292+
)}
285293
{/* Main content area */}
286294
<div className="flex flex-col sm:flex-row flex-1 overflow-hidden">
287295
{/* Mobile sidebar toggle - shown only on mobile when showCustomConfig is true */}

app/utils/iframeDetector.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2024 The casbin Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* Detects if the current window is running inside an iframe
17+
* @returns {boolean} true if the window is inside an iframe, false otherwise
18+
*/
19+
export const isInsideIframe = (): boolean => {
20+
// Check if we're in a browser environment
21+
if (typeof window === 'undefined') {
22+
return false;
23+
}
24+
25+
try {
26+
return window.self !== window.top;
27+
} catch (e) {
28+
// If we get a cross-origin error accessing window.top, we're in an iframe
29+
// Cross-origin errors occur when iframe is from a different domain
30+
return true;
31+
}
32+
};

0 commit comments

Comments
 (0)