Skip to content

Commit 97e8032

Browse files
committed
Stabilize tabbed page layout
1 parent 1191d94 commit 97e8032

2 files changed

Lines changed: 14 additions & 4 deletions

File tree

apps/sim/lib/workspace-files/artifact-stylesheet.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,10 @@ export const SIM_ARTIFACT_STYLESHEET = `
208208
}
209209
210210
* { box-sizing: border-box; scrollbar-width: thin; }
211-
html { scroll-behavior: smooth; scroll-padding-top: 72px; }
211+
/* scrollbar-gutter keeps the centered column from shifting when content
212+
length toggles the viewport scrollbar (e.g. switching between a long and a
213+
short tab). */
214+
html { scroll-behavior: smooth; scroll-padding-top: 72px; scrollbar-gutter: stable; }
212215
@media (prefers-reduced-motion: reduce) {
213216
html { scroll-behavior: auto; }
214217
* { transition: none !important; animation: none !important; }
@@ -492,7 +495,10 @@ button.page-tab:hover { color: var(--text-body); }
492495
.art-cols > .rail { display: none; }
493496
@media (min-width: 800px) {
494497
.art-cols { grid-template-columns: minmax(0, 760px) fit-content(268px); justify-content: center; }
495-
.art-cols > .rail[data-rail="toc"] { display: block; position: sticky; top: 68px; align-self: start; max-height: calc(100vh - 6rem); overflow-y: auto; }
498+
/* Fixed width, not content-sized: in a tabbed doc the longest TOC entry
499+
differs per tab, and a column that resizes re-centers the whole grid on
500+
every switch. */
501+
.art-cols > .rail[data-rail="toc"] { display: block; position: sticky; top: 68px; align-self: start; max-height: calc(100vh - 6rem); overflow-y: auto; width: 268px; }
496502
}
497503
/* Rails scroll invisibly, like the docs — no scrollbar chrome beside the
498504
TOC; the absolutely-positioned clerk track SVGs also can't tip the box
@@ -901,7 +907,10 @@ export const SIM_ARTIFACT_SHELL = `<script>
901907
tocItems.appendChild(a)
902908
tocLinks.push(a)
903909
}
904-
right.style.display = headings.length === 0 ? 'none' : ''
910+
// In a tabbed doc an empty rail stays (its fixed column holds the grid
911+
// steady across switches); only an untabbed page drops it entirely.
912+
const tabbed = main.querySelector('[data-tab-panel]') !== null
913+
right.style.display = headings.length === 0 && !tabbed ? 'none' : ''
905914
refresh()
906915
}
907916
document.addEventListener('sim-tab-change', populateToc)

apps/sim/lib/workspace-files/page-tabs-rail.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/**
22
* @vitest-environment node
33
*/
4+
import { sleep } from '@sim/utils/helpers'
45
import { JSDOM } from 'jsdom'
56
import { describe, expect, it } from 'vitest'
67
import { renderSimPageDocument } from '@/lib/workspace-files/page-document'
@@ -40,7 +41,7 @@ const domOptions = {
4041
},
4142
}
4243

43-
const tick = () => new Promise((resolve) => setTimeout(resolve, 60))
44+
const tick = () => sleep(60)
4445

4546
describe('in-document tabs drive the on-this-page rail', () => {
4647
it('scopes the rail to the active tab and rebuilds it on switch', async () => {

0 commit comments

Comments
 (0)