Skip to content

Commit 05d1383

Browse files
committed
feat: add fullscreen mode to Go component
Adds a fullscreen toggle button that expands the component preview to fill the viewport while keeping all chrome (tabs, footer). Pressing Escape or clicking the button again exits fullscreen. Includes iOS Safari safe area support and smooth enter animation.
1 parent 4970d0e commit 05d1383

File tree

3 files changed

+107
-2
lines changed

3 files changed

+107
-2
lines changed

src/example-preview/components/index.module.scss

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,40 @@
237237
}
238238
}
239239

240+
.box-fullscreen {
241+
position: fixed;
242+
top: 0;
243+
left: 0;
244+
right: 0;
245+
bottom: 0;
246+
z-index: 9999;
247+
height: 100vh;
248+
height: 100dvh;
249+
width: 100vw;
250+
border-radius: 0;
251+
border: none;
252+
padding:
253+
env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px)
254+
env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
255+
animation: fullscreen-enter 0.15s ease-out;
256+
257+
@media (max-width: 600px) {
258+
height: 100vh;
259+
height: 100dvh;
260+
}
261+
}
262+
263+
@keyframes fullscreen-enter {
264+
from {
265+
opacity: 0.9;
266+
transform: scale(0.98);
267+
}
268+
to {
269+
opacity: 1;
270+
transform: scale(1);
271+
}
272+
}
273+
240274
.code-view-comp {
241275
display: flex;
242276
align-items: center;

src/example-preview/components/index.tsx

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { SwitchSchema } from './switch-schema';
2828
import { PreviewImg } from './preview-img';
2929
import { ResizableContainer } from './resizable';
3030

31-
import { IconGithub, IconCopyLink } from '../utils/icon';
31+
import { IconGithub, IconCopyLink, IconFullscreen, IconExitFullscreen } from '../utils/icon';
3232
import { tabScrollToTop } from '../utils/tool';
3333
import { useTreeController } from '../hooks/use-tree-controller';
3434
import type { SchemaOptionsData } from '../hooks/use-switch-schema';
@@ -143,10 +143,30 @@ export const ExampleContent: FC<ExampleContentProps> = ({
143143
};
144144
}, [previewImage, currentEntry, defaultWebPreviewFile]);
145145
const [tmpCurrentFileName, setTmpCurrentFileName] = useState('');
146+
const [isFullscreen, setIsFullscreen] = useState(false);
146147
const defaultI18n = (key: string) => DEFAULT_I18N[key] || key;
147148
const t = useI18nHook ? useI18nHook() : defaultI18n;
148149
const lang = useLangHook ? useLangHook() : 'en';
149150

151+
useEffect(() => {
152+
if (isFullscreen) {
153+
const originalOverflow = document.body.style.overflow;
154+
document.body.style.overflow = 'hidden';
155+
156+
const handleEscape = (e: KeyboardEvent) => {
157+
if (e.key === 'Escape') {
158+
setIsFullscreen(false);
159+
}
160+
};
161+
document.addEventListener('keydown', handleEscape);
162+
163+
return () => {
164+
document.body.style.overflow = originalOverflow;
165+
document.removeEventListener('keydown', handleEscape);
166+
};
167+
}
168+
}, [isFullscreen]);
169+
150170
const getContainer = () => containerRef.current as HTMLDivElement;
151171
const onFileSelect = (v: string) => {
152172
setShowFileTree(false);
@@ -163,7 +183,7 @@ export const ExampleContent: FC<ExampleContentProps> = ({
163183

164184
const showCodeTab = entryData && entryData?.length > 1;
165185
return (
166-
<div className={s.box}>
186+
<div className={`${s.box} ${isFullscreen ? s['box-fullscreen'] : ''}`}>
167187
<div className={s.container} ref={containerRef}>
168188
<div className={s.content}>
169189
<div className={s['code-wrap']}>
@@ -415,6 +435,23 @@ export const ExampleContent: FC<ExampleContentProps> = ({
415435
);
416436
}}
417437
/>
438+
<Button
439+
theme="borderless"
440+
icon={
441+
isFullscreen ? (
442+
<IconExitFullscreen
443+
style={{ color: 'var(--semi-color-text-2)' }}
444+
/>
445+
) : (
446+
<IconFullscreen
447+
style={{ color: 'var(--semi-color-text-2)' }}
448+
/>
449+
)
450+
}
451+
type="tertiary"
452+
size="small"
453+
onClick={() => setIsFullscreen((v) => !v)}
454+
/>
418455
{rightFooter}
419456
</Space>
420457
</div>

src/example-preview/utils/icon.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,40 @@ export function IconGithub(props: SVGProps<SVGSVGElement>) {
3939
);
4040
}
4141

42+
export function IconFullscreen(props: SVGProps<SVGSVGElement>) {
43+
return (
44+
<svg
45+
xmlns="http://www.w3.org/2000/svg"
46+
viewBox="0 0 24 24"
47+
width="1em"
48+
height="1em"
49+
{...props}
50+
>
51+
<path
52+
fill="currentColor"
53+
d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"
54+
/>
55+
</svg>
56+
);
57+
}
58+
59+
export function IconExitFullscreen(props: SVGProps<SVGSVGElement>) {
60+
return (
61+
<svg
62+
xmlns="http://www.w3.org/2000/svg"
63+
viewBox="0 0 24 24"
64+
width="1em"
65+
height="1em"
66+
{...props}
67+
>
68+
<path
69+
fill="currentColor"
70+
d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"
71+
/>
72+
</svg>
73+
);
74+
}
75+
4276
export function IconCopyLink(props: SVGProps<SVGSVGElement>) {
4377
return (
4478
<svg

0 commit comments

Comments
 (0)