Skip to content

Solid v2 - #4

Merged
odama626 merged 26 commits into
mainfrom
solid-v2
Sep 22, 2026
Merged

odama626 merged 26 commits into
mainfrom
solid-v2

Conversation

@odama626

Copy link
Copy Markdown
Member

No description provided.

Toolchain moves to @solidjs/vite-plugin, @solidjs/web and
@solidjs/testing-library 1.0.0-beta.3, with jsxImportSource pointing at
@solidjs/web. solid-js is pinned to 2.0.0-rc.8: rc.9 is inside pnpm's
minimumReleaseAge cutoff and fails the lockfile policy check.

Tests move off the directives to the ref factories, validateRef folds into
validate, and createEffect takes its two-argument form.

All 86 collect; 52 pass. The 34 failures share one cause: solid 2 defers
store writes, where solid 1 applied them in the same tick as the event.
Verified directly - after a blur the store reads undefined synchronously
and holds the message a moment later. The bare no-await assertions were
written as canaries for exactly this and have now fired.
Solid 2 batches store writes, so nothing observable lands in the same tick
as the event that caused it. The action helpers now dispatch and then let
the scheduler drain, and every call site awaits them.

73 of 86 pass. The remainder split three ways: seven where an event
handler does not fire in tests that call submit from onClick, two store
proxy differences between solid 1 and 2, and two submission-signal tests
whose shape batching has changed.
Adds a migration guide covering what changed and why: directives to ref
factories, validators taking an accessor, validateRef folding into
validate, batched store writes, deleted keys, and @solidjs/web as a peer.
Quick start is rewritten against the new api.

Demos are ordinary components again. The v2 site and the v2 library both
run solid 2, so there is no second runtime to isolate and the iframe is
gone. Two of them: one submitting through formSubmit, one calling submit()
from an inline-arrow onClick, which is the shape that never fires under
jsdom. Both render on the quick start page for checking in a browser.
The imperative demo held its selection in a plain variable, so choosing a
plan re-rendered nothing and there was no way to tell a click had landed.
It uses a signal now, marks the pressed button, and logs each step, so a
failure says which half broke rather than just sitting there.

Code blocks go through shiki, using its sync engine so rendering stays
synchronous for the prerender. Both themes are emitted as css variables
and app.scss swaps them on data-color-scheme, so code follows the rest of
the page.

The v2 landing page pointed at a demo that does not exist; it now shows
the submit one.
versions.json lost its root entry, so the runtime manifest fetch resolved
to "undefinedversions.json" and 404d. The fetch is guarded, so the
switcher fell back to its compiled list rather than breaking, but the
published list was never read.
Replaces the bespoke markdown layer with the setup the studio site uses.
Pages are .mdx under routes/, so a demo is an ordinary import written
inline. Deleted: MarkdownPage, its parse(), the :::demo::: grammar, the
Demo registry, the per-page .tsx route shims and the content/ directory.

The piece that mattered is jsxImportSource: '@solidjs/web'. Without it MDX
emits React's pragma, solid never compiles the JSX, and every page renders
an empty shell with no error. elementAttributeNameCase: 'html' matters too,
since solid takes html attribute names.

The provider maps each tag onto a concrete component written as JSX, so
the compiler emits a static template per tag. A Dynamic-based version
builds but diverges from the server render during hydration.

Shiki moves to @shikijs/rehype, and frontmatter now comes through
remark-mdx-frontmatter as real exports.
Three tests for the outcomes: validation refusing, a clean run, and the
callback returning errors. Two existing tests that asserted the old void
return are updated.

The api reference and migration guide describe the boolean, and the
imperative demo states its outcome instead of leaving it to be inferred
from a missing log line.
@sparkstone/css picks its scheme from prefers-color-scheme and lets
[data-color-scheme] override it. The shiki rules only covered the
attribute, so os dark mode with no explicit choice left code blocks on the
light theme against a dark page.

Both rules now, with :root:not([data-color-scheme='light']) inside the
media query so an explicit light choice still wins.
Pulls in @sparkstone/css/classless/kobalte, which keys on kobalte's own
state attributes, and points the switcher's parts at the classes it
styles: btn on the trigger, dropdown-content on the content, menu on the
listbox, menu-item on each option.

The hand-written .docs-version-placeholder rule is gone, and the
pre-hydration fallback wears the same btn classes as the trigger so the
swap is not visible.
The imperative submit demo used bare buttons and a signal; it uses
kobalte's SegmentedControl with the segmented classes now, which is what
that control is for and what the kobalte layer styles.

Three demos on pages that had none: an async availability check with real
latency behind a cheap length check, server errors coming back as both a
field error and a form-level one, and a cross-field password match read
through getFieldValue rather than a signal.

No build output: run pnpm build:all after merging.
The library is 2.0.0 and targets Solid 2; its peers move to rc.9, which is
the release the tree runs on. The changelog records every breaking change
and says plainly that Solid 1 projects should stay on 1.x.

versions.json makes v2 current, so the root redirect goes to /v2/. v1 is
frozen and is not rebuilt, but its site now pins ^1.6.1 from npm instead of
following the workspace, so an accidental build:all cannot build its demos
against 2.x.

The v2 docs and the readme now describe the v2 api. Code moves from the
directives to the ref factories. The child components guide is rewritten,
since it documented validateRef, which no longer exists. Troubleshooting
drops the two directive sections for the failures people actually hit on
v2: mismatched solid releases breaking event handlers, and errors arriving
a flush later. The api reference gives the real signatures, and submit is
documented as returning a boolean.

One claim is corrected rather than converted: the docs said the validator
accessor is read when a field is checked. It is read once, at
registration, so they now say that and show where to put a condition that
has to change while the form is open.

No build output: run pnpm build after merging.
Two tests switch a conditional rule on and off after the field mounts.
Both fail against the current library, which reads the accessor once
during registration, and both pass when the read moves to check time.
They were checked in both directions before committing, so they fail for
that reason and no other.

Signal writes are batched in Solid 2 as well as store writes, so each test
lets its signal flush before the blur that reads it; without that, the
switched-on case fails even with the fix in place.

Also fixes the two submission-signal tests. They failed on an effect
callback returning seen.push(...), which is a length rather than a
cleanup. The [isSubmitting, isSubmitted] sequence they assert is intact
under Solid 2: [false, false], then [true, false] while the callback runs,
then [false, true].
All three were test problems rather than library bugs.

The remount test set a signal false then true in the same tick. Solid 2
batches those into no change, so Show never unmounted and the element was
the same one. It flushes between the two writes now.

The no-owner test called validate(input), the v1 directive signature. In
v2 validate is a ref factory, so that passed the input as the accessor and
never registered anything; submit then had no fields and ran the callback.
It calls validate()(input).

The constructor test asserted that key is dropped, which was Solid 1.9.15
behaviour. Solid 2 stores it as an ordinary key, so the expectation
follows, and the test is renamed to say what it now checks.
Mirrors the workflows in the css repo. Continuous Releases publishes each
push and pull request to pkg.pr.new; Docs Preview deploys each pull
request's docs to its own surge.sh domain, comments the link, and tears it
down on close.

Three differences from the css repo, each commented in place:

- Continuous Releases runs the test suite before publishing, since this
  library has one.
- The docs build is pnpm --dir website build; the root build is the
  library only.
- The site is built for /solid-validation/, so the surge deploy nests the
  build one directory down and adds a root page that forwards to it.

pnpm is pinned through packageManager, and pkg-pr-new and surge are dev
dependencies so CI runs them from the lockfile. The lockfile is not in
this commit: run pnpm install and commit it before these workflows can
run with --frozen-lockfile.
@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

📚 Docs preview removed: the pull request was closed.

@odama626
odama626 merged commit 444a094 into main Sep 22, 2026
4 of 5 checks passed
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.

1 participant