-
Notifications
You must be signed in to change notification settings - Fork 426
Dashboard tabset: second tab has inverted row/column layout orientation #14222
Description
I have:
- searched the issue tracker for similar issues
- installed the latest version of Quarto CLI
- formatted my issue following the Bug Reports guide
Bug description
When a dashboard tabset contains tabs with nested #### Column and ##### Row layout headings, all even-positioned tabs (2nd, 4th, 6th...) render with inverted grid orientation (rows become columns, columns become rows). Odd-positioned tabs render correctly.
Steps to reproduce
---
title: "Second tab has inverted layout orientation"
format: dashboard
---
## Row {.tabset}
### Tab A
#### Column
##### Row
::: {.card title="Card 1"}
Should be side-by-side with Card 2
:::
::: {.card title="Card 2"}
Should be side-by-side with Card 1
:::
### Tab B
#### Column
##### Row
::: {.card title="Card 1"}
Should be side-by-side with Card 2 **BUT IS STACKED**
:::
::: {.card title="Card 2"}
Should be side-by-side with Card 1 **BUT IS STACKED**
:::
### Tab C
#### Column
##### Row
::: {.card title="Card 1"}
Should be side-by-side with Card 2
:::
::: {.card title="Card 2"}
Should be side-by-side with Card 1
:::Actual behavior
- Tab A: Cards are side-by-side (correct)
- Tab B: Cards are stacked vertically (wrong - layout is inverted)
- Tab C: Cards are side-by-side (correct)
Inspecting the HTML shows Tab B has grid-template-rows where Tab A and C have grid-template-columns, and vice versa for nested elements.
Expected behavior
All three tabs should render identically with cards side-by-side.
Possible root cause analysis
(I updated this as Claude had a few hypotheses before this conclusion we got to after we found a temp workaround of adding new dummy tabs which are hidden)
The bug is in the dashboard Lua filters. Two pieces of global mutable state persist across tab processing:
lastLevelinmain.lua(~line 7683) - tracks the last heading level seencurrentOrientationinlayout.lua(line 123) - tracks current layout orientation
The orientation logic in main.lua (~lines 8087-8097) rotates orientation when a new heading level is encountered:
local toOrientation = dashboard.layout.currentOrientation()
if level ~= lastLevel then
lastLevel = level
toOrientation = dashboard.layout.rotatedOrientation()
endAnd orientContents mutates currentOrientation as a side effect.
When processing tabs with nested #### Column (level 4) and ##### Row (level 5):
-
Tab A:
#### Columnis level 4 (new), rotates.##### Rowis level 5 (new), rotates again. After processing,lastLevel=5. -
Tab B:
#### Columnis level 4, butlastLevelis still 5 from Tab A. Since 4 ≠ 5, it rotates when it shouldn't. Then##### Rowis level 5, same as the newlastLevel, so it doesn't rotate when it should. Result: inverted layout. -
Tab C: Same pattern as Tab B, but the double-wrong rotations happen to cancel out and produce the correct layout.
This affects all even-positioned tabs (2, 4, 6...), not just the second one.
The fix should reset lastLevel before processing each tab's contents, so each tab starts fresh rather than inheriting state from the previous sibling.
Your environment
IDE: Positron 2025.02.0-149
OS: Ubuntu 24.04.4 LTS
Quarto check output
Quarto 1.9.35
[✓] Checking versions of quarto binary dependencies...
Pandoc version 3.8.3: OK
Dart Sass version 1.87.0: OK
Deno version 2.4.5: OK
Typst version 0.14.2: OK
[✓] Checking Quarto installation......OK
Version: 1.9.35
Path: /opt/quarto/bin
[✓] Checking R installation...........OK
Version: 4.5.2
knitr: 1.51
rmarkdown: 2.30