Tabs without `defaultValue`: with the panels before the list, the server selects the first tab and renders no panel
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- typescript
Research direction
The Tabs server render order lives in the core tabs behavior exercised by checkServer from @ui-sdk/core/testing, and the Solid adapter @ui-sdk/solid/tabs shows the rendered output. Start by reproducing the panels-first case with checkServer(tabs, {}, panelsFirst) and compare it with the list-first markup. Done means the server HTML selects a tab and renders its panel regardless of order, or the docs state that server-rendered Tabs need value or defaultValue.
Written by the indexing model from the issue text.
Description
What happens
Without value or defaultValue, Tabs selects "the first enabled tab". On the server, that
depends on render order. With the list before the panels the server HTML is right (first tab
selected, its panel rendered). With the panels before the list (a bottom tab bar, a phone layout)
the panels render before any tab has registered, so none of them is selected: the server HTML has
the first tab selected and no panel. The client renders the panel at hydration (no hydration
warning), so the page shows an empty content area until the bundle runs.
checkServer already says why: it reports both orders without a default as reading options.
Minimal reproduction
Core only, no framework, with @ui-sdk/core/testing:
import { tabs } from '@ui-sdk/core/tabs'
import { checkServer } from '@ui-sdk/core/testing'
const panelsFirst =
'<root><panel value="a">PA</panel><panel value="b">PB</panel><list><tab value="a">A</tab><tab value="b">B</tab></list></root>'
checkServer(tabs, {}, panelsFirst)
// throws: checkServer found 4 problems:
// - `panel` "a" reads option `value`
// - `panel` "b" reads option `value`
// - `tab` "a" reads option `value`
// - `tab` "b" reads option `value`
checkServer(tabs, { defaultValue: 'b' }, panelsFirst)
// <div data-slot="tabs"><div data-slot="tabs-panel" role="tabpanel" … data-selected>PB</div>
// <div data-slot="tabs-list" role="tablist">…aria-selected="true" data-selected>B</button></div></div>
The list-first markup without a default throws the same four problems. Rendered through
@ui-sdk/solid/tabs on the server (Solid 2 renderToString, then hydrate), panels first and no
default:
<div data-slot="tabs">
<div data-slot="tabs-list" role="tablist" aria-label="Sections">
<button
data-slot="tabs-tab"
role="tab"
…
aria-selected="true"
data-selected
>
A
</button>
<button data-slot="tabs-tab" role="tab" … aria-selected="false">B</button>
<span data-slot="tabs-indicator" role="presentation"></span>
</div>
</div>
No tabpanel at all; after hydration panel A is there. Reproduced twice with checkServer and
on two server renders.
Versions
@ui-sdk/core0.1.0-beta.1,@ui-sdk/solid0.1.0-beta.1, Solid 2.0.0-rc.21
Expected behavior
Either the server resolves "the first enabled tab" independent of render order (the panels could
be rendered once the tabs are known, or the first panel could stand in), or the docs say that a
server-rendered Tabs needs value or defaultValue, as Server Rendering already says for ids
("render order matters"). Today only checkServer hints at it.
Reproduced on @ui-sdk/core / @ui-sdk/solid 0.1.0-beta.2.
- Dominant language
- TypeScript
- Stars
- 4.4k
- Forks
- 122
- Avg merge
- 3h 12m
- Merged PRs (30d)
- 437
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from vercel-labs/ui
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
vercel-labs/ui#540 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
vercel-labs/ui#525 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
vercel-labs/ui#521 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
vercel-labs/ui#515 ·
Maintainers usually reply within 1 day
-
`checkPattern('checkbox')` on a `CheckboxGroup` reports the group's own hidden form input as unnamedOpen
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
vercel-labs/ui#512 ·
Maintainers usually reply within 1 day
Similar issues
-
area: web
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
inabagumi/shinju-date#6823 ·
Maintainers usually reply within 1 day
-
accepted ai-dev ai-implementing
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
livesport/homer#218 · 1 comment ·
Maintainers usually reply within 1 day
-
normalizePropName strips `#` characters from Figma property names instead of only the `#id` suffixOpen
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
figma/code-connect#419 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day