fix: hide preview chrome in source view (#1556)

* fix: hide preview chrome in source view

* fix: keep source-view edit controls
This commit is contained in:
Prantik Medhi 2026-05-13 16:42:00 +05:30 committed by GitHub
parent 660c5b88b4
commit 086be271d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 121 additions and 73 deletions

View file

@ -5121,6 +5121,7 @@ function HtmlViewer({
return t('fileViewer.deployLinkPreparingLabel');
};
const boardAvailable = mode === 'preview' && source !== null;
const showPreviewToolbarControls = mode === 'preview';
return (
<div className="viewer html-viewer">
@ -5152,7 +5153,7 @@ function HtmlViewer({
{t('fileViewer.source')}
</button>
</div>
{effectiveDeck ? (
{showPreviewToolbarControls && effectiveDeck ? (
<span
className="deck-nav"
role="group"
@ -5190,41 +5191,83 @@ function HtmlViewer({
) : null}
</div>
<div className="viewer-toolbar-actions">
<div className="palette-tweaks-anchor">
<button
type="button"
className={`viewer-action${selectedPalette || palettePopoverOpen ? ' active' : ''}`}
data-testid="palette-tweaks-toggle"
title="Tweaks"
aria-haspopup="dialog"
aria-expanded={palettePopoverOpen}
onClick={() => setPalettePopoverOpen((v) => !v)}
>
<Icon name="tweaks" size={13} />
<span>Tweaks</span>
{selectedPalette ? (
<span
className="palette-tweaks-badge"
aria-hidden
style={{
backgroundColor:
selectedPalette === 'coral' ? '#ff5a3c' :
selectedPalette === 'electric' ? '#7c3aed' :
selectedPalette === 'acid-forest' ? '#16a34a' :
selectedPalette === 'risograph' ? '#e11d48' :
'#0a0a0a',
}}
{showPreviewToolbarControls ? (
<>
<div className="palette-tweaks-anchor">
<button
type="button"
className={`viewer-action${selectedPalette || palettePopoverOpen ? ' active' : ''}`}
data-testid="palette-tweaks-toggle"
title="Tweaks"
aria-haspopup="dialog"
aria-expanded={palettePopoverOpen}
onClick={() => setPalettePopoverOpen((v) => !v)}
>
<Icon name="tweaks" size={13} />
<span>Tweaks</span>
{selectedPalette ? (
<span
className="palette-tweaks-badge"
aria-hidden
style={{
backgroundColor:
selectedPalette === 'coral' ? '#ff5a3c' :
selectedPalette === 'electric' ? '#7c3aed' :
selectedPalette === 'acid-forest' ? '#16a34a' :
selectedPalette === 'risograph' ? '#e11d48' :
'#0a0a0a',
}}
/>
) : null}
</button>
<PaletteTweaks
open={palettePopoverOpen}
selected={selectedPalette}
onChange={setSelectedPalette}
onPreview={setPreviewPalette}
onClose={() => setPalettePopoverOpen(false)}
/>
) : null}
</button>
<PaletteTweaks
open={palettePopoverOpen}
selected={selectedPalette}
onChange={setSelectedPalette}
onPreview={setPreviewPalette}
onClose={() => setPalettePopoverOpen(false)}
/>
</div>
</div>
<button
className={`viewer-action${drawOverlayOpen ? ' active' : ''}`}
type="button"
data-testid="draw-overlay-toggle"
title={t('fileViewer.draw')}
aria-pressed={drawOverlayOpen}
onClick={() => {
const next = !drawOverlayOpen;
if (!next) {
setDrawOverlayOpen(false);
return;
}
const activateDraw = () => {
setBoardMode(false);
clearBoardComposer();
setInspectMode(false);
setDrawOverlayMode('draw');
setMode('preview');
setDrawOverlayOpen(true);
};
if (manualEditMode) {
void exitManualEditModeAfterFlush().then((ok) => {
if (ok) activateDraw();
});
return;
}
activateDraw();
}}
>
<Icon name="draw" size={13} />
<span>{t('fileViewer.draw')}</span>
</button>
<span className="viewer-divider" aria-hidden />
<PreviewViewportControls
viewport={previewViewport}
onViewport={setPreviewViewport}
t={t}
/>
</>
) : null}
<button
className={`viewer-action${manualEditMode ? ' active' : ''}`}
type="button"
@ -5248,44 +5291,6 @@ function HtmlViewer({
<Icon name="edit" size={13} />
<span>{t('fileViewer.edit')}</span>
</button>
<button
className={`viewer-action${drawOverlayOpen ? ' active' : ''}`}
type="button"
data-testid="draw-overlay-toggle"
title={t('fileViewer.draw')}
aria-pressed={drawOverlayOpen}
onClick={() => {
const next = !drawOverlayOpen;
if (!next) {
setDrawOverlayOpen(false);
return;
}
const activateDraw = () => {
setBoardMode(false);
clearBoardComposer();
setInspectMode(false);
setDrawOverlayMode('draw');
setMode('preview');
setDrawOverlayOpen(true);
};
if (manualEditMode) {
void exitManualEditModeAfterFlush().then((ok) => {
if (ok) activateDraw();
});
return;
}
activateDraw();
}}
>
<Icon name="draw" size={13} />
<span>{t('fileViewer.draw')}</span>
</button>
<span className="viewer-divider" aria-hidden />
<PreviewViewportControls
viewport={previewViewport}
onViewport={setPreviewViewport}
t={t}
/>
<span className="viewer-divider" aria-hidden />
<button
type="button"

View file

@ -414,6 +414,49 @@ describe('FileViewer SVG artifacts', () => {
expect(markup).not.toContain('data-od-render-mode="url-load"');
});
it('hides preview-only toolbar controls when switching an HTML deck to source view', async () => {
const file = baseFile({
name: 'deck.html',
path: 'deck.html',
mime: 'text/html',
kind: 'html',
artifactManifest: {
version: 1,
kind: 'html',
title: 'Deck',
entry: 'deck.html',
renderer: 'html',
exports: ['html'],
},
});
const { container } = render(
<FileViewer
projectId="project-1"
file={file}
isDeck
liveHtml={'<html><body><section class="slide">one</section><section class="slide">two</section></body></html>'}
/>,
);
expect(container.querySelector('.deck-nav')).toBeTruthy();
expect(container.querySelector('.palette-tweaks-anchor')).toBeTruthy();
expect(container.querySelector('.viewer-viewport-switcher')).toBeTruthy();
fireEvent.click(screen.getByRole('button', { name: /^source$/i }));
await waitFor(() => {
expect(container.querySelector('.deck-nav')).toBeNull();
expect(container.querySelector('.palette-tweaks-anchor')).toBeNull();
expect(container.querySelector('.viewer-viewport-switcher')).toBeNull();
expect(screen.getByTestId('manual-edit-mode-toggle')).toBeTruthy();
expect(screen.queryByTestId('draw-overlay-toggle')).toBeNull();
expect(screen.queryByTestId('palette-tweaks-toggle')).toBeNull();
expect(screen.getByRole('button', { name: /zoom out/i })).toBeTruthy();
expect(screen.getByRole('button', { name: /zoom in/i })).toBeTruthy();
});
});
it('shows Cloudflare Pages as a deploy action without requiring a project name input', async () => {
const file = baseFile({
name: 'index.html',