Skip to content

fix: fall back to an available choice when the selected one is absent on the page (#169)#170

Merged
phonzammi merged 3 commits into
mainfrom
claude/inspiring-lamport-kqtk54
Jun 22, 2026
Merged

fix: fall back to an available choice when the selected one is absent on the page (#169)#170
phonzammi merged 3 commits into
mainfrom
claude/inspiring-lamport-kqtk54

Conversation

@brillout

Copy link
Copy Markdown
Owner

Fixes #169.

Root cause

A page can define a choice group with only a subset of the group's choices. For uiFramework (React/Vue/Solid), https://vike.dev/ClientOnly has all three, but https://vike.dev/bodyHtmlEnd only has React/Vue — so Solid is an empty choice there.

When Solid is selected on ClientOnly, it's persisted to localStorage (docpress:choice:uiFramework). Navigating to bodyHtmlEnd:

  • The hidden <select> that drives choice visibility via CSS still renders an <option value="Solid"> (the option list is the full config, not just the page's choices). With value="Solid" it gets :checked, so the CSS hides every real .choice and shows only the empty Solid one → no content.
  • The visible CustomSelect filters out empty choices and adds a hidden class when the selected choice is empty → no selector either.

Net result: nothing is shown.

Fix

Resolve the displayed choice to one that actually has content on the current page, via a small helper getAvailableChoice():

  1. the stored choice, if it's available on the page; otherwise
  2. the group's default, if available; otherwise
  3. the first available choice.

This is applied to the hidden <select> (drives content visibility), CustomSelect, and Tabs. The stored global preference is not overwritten — pages that do have Solid keep showing it.

To avoid a pre-hydration flash, the inline SSR script (initializeChoiceGroup) now marks empty <option>s with data-empty and only applies the stored choice when it has content on the page, keeping the server-rendered fallback otherwise. Stale choices (no longer in the config at all) are still cleaned up from localStorage.

Tests

  • Unit (getAvailableChoice.spec.ts): covers the fallback cases (default available, default empty, nothing empty, everything empty).
  • E2E (demo/testRun.ts + demo/pages/page-4): page-4 now defines uiFramework with only React/Vue. The test selects Solid (absent here), reloads, and asserts the content falls back to React instead of showing nothing.

Verified locally against the demo dev server with Playwright: the fix renders the fallback content, keeps the selector visible, preserves the Solid preference, and features (which has Solid) still renders Solid. Reverting the fix reproduces the blank page, confirming the test catches the regression. build, test:types, and test:units all pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BcbPYNNRXEBpDZEzzZwVkT


Generated by Claude Code

… on the page (#169)

A page can define a choice group with only a subset of the group's choices
(e.g. `bodyHtmlEnd` has `React`/`Vue` but not `Solid`). When a choice
persisted in localStorage (e.g. `Solid`, selected on another page) has no
content on the current page, the hidden `<select>` that drives CSS visibility
still matched its (empty) `<option>` — hiding every real choice and showing
the empty one — while the visible selector hid itself. Result: nothing shown.

Resolve the displayed choice to an available one (the stored choice if it has
content, else the group's default, else the first available choice) without
overwriting the stored global preference. The SSR `initializeChoiceGroup`
script now skips choices marked `data-empty`, keeping the server-rendered
fallback and avoiding a flash.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BcbPYNNRXEBpDZEzzZwVkT
claude and others added 2 commits June 22, 2026 13:55
Remove the e2e/unit test additions (and the demo page-4 reproduction) for
this edge-case quick fix, and trim comments down to the rationale the code
can't convey on its own.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BcbPYNNRXEBpDZEzzZwVkT
@phonzammi

Copy link
Copy Markdown
Collaborator

@brillout, LGTM ?

@brillout

Copy link
Copy Markdown
Owner Author

I didn't review the code in details, so as you wish. From my high-level perspective I think we can merge.

@phonzammi

Copy link
Copy Markdown
Collaborator

Alright, thanks. Merging now.

@phonzammi phonzammi merged commit afd0a81 into main Jun 22, 2026
2 checks passed
@phonzammi phonzammi deleted the claude/inspiring-lamport-kqtk54 branch June 22, 2026 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

+choices — nothing shown

3 participants