Skip to content

GraphiQL v6 - #4228

Draft
trevor-scheer wants to merge 206 commits into
mainfrom
graphiql-6
Draft

trevor-scheer wants to merge 206 commits into
mainfrom
graphiql-6

Conversation

@trevor-scheer

@trevor-scheer trevor-scheer commented May 7, 2026 •

Copy link
Copy Markdown
Contributor

Tracking PR for the GraphiQL v6 redesign effort. This is the long-running integration branch that hosts work-in-progress against main.

Individual PRs target graphiql-6 and produce alpha releases via changesets pre-mode. When v6 is ready to ship, this branch will be merged into main.

See discussion #4219 for background and progress updates.

Closes #734 — the visual query builder ships in v6 as @graphiql/plugin-query-builder.

## Summary

- Swap the vestigial `graphiql-5` reference in
`.github/workflows/release.yml` for `graphiql-6` so the
changesets-action runs on pushes to the integration branch.
- Enter changesets pre-mode with the `alpha` tag so merges aggregate
into `6.0.0-alpha.N` prereleases.
- Add a changeset that seeds the alpha release line by bumping
`graphiql` to v6. No functional change — subsequent alphas accumulate
the redesign work.

## Test plan

- [ ] On merge: changesets-action opens a "Version Packages (alpha)" PR
bumping `graphiql` to `6.0.0-alpha.0`.
- [ ] Merging the version PR publishes `graphiql@6.0.0-alpha.0` to npm
with the `alpha` dist-tag.

Refs: #4219
@changeset-bot

changeset-bot Bot commented May 7, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 93c9f9c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
Name Type
@graphiql/react Major
@graphiql/plugin-history Major
graphiql Major
@graphiql/plugin-doc-explorer Major
graphql-language-service-server Major
@graphiql/plugin-collections Major
@graphiql/toolkit Major
@graphiql/plugin-query-builder Major
@graphiql/plugin-code-exporter Major
cm6-graphql Major
codemirror-graphql Major
graphql-language-service Major
graphql-language-service-cli Major
monaco-graphql Major
vscode-graphql Major
vscode-graphql-execution Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

The latest changes of this PR are not available as canary, since there are no linked changesets for this PR.

## Summary

- Introduce a new `packages/graphiql-react/src/style/tokens.css` with
the v6 OKLCH-based design token system. Both dark and light palettes
ship together.
- Light theme activates explicitly via `data-theme="light"` or
automatically via `prefers-color-scheme: light` when no theme is pinned.
Dark remains the default.
- Existing v5 HSL variables are unchanged; nothing in `@graphiql/react`
references the new tokens yet.
- Future PRs will restyle components to consume the new tokens and shim
the v5 variables.

Refs: #4219
## Summary

Storybook gives us a fast feedback loop for iterating on the look of the
app and individual components — flipping themes/density/font-size
without spinning up the full GraphiQL shell.

- Bootstrap Storybook 10 in `@graphiql/react`. Stories colocated as
`<component>.stories.tsx`; ships one starter (`Spinner`) to validate the
pipeline.
- A global decorator wraps every story in `.graphiql-container` with
`data-theme` / `data-density` / `data-font-size` attributes, toggleable
from the Storybook toolbar.
- Move `Uri`, `KeyMod`, `KeyCode`, and `Range` out of the `utility`
barrel into direct imports from `utility/monaco-ssr`. The barrel was
bundling two unrelated concerns — lightweight UI helpers (`cn`, `pick`,
etc.) and heavy Monaco re-exports — so any story reaching for `cn`
transitively pulled Monaco's ESM bundle, which doesn't initialize
cleanly inside Storybook's preview iframe. Splitting them keeps UI
primitives lightweight.

## Run locally

From the repo root:

```
yarn storybook         # dev server on http://localhost:6006
yarn build-storybook   # static build under packages/graphiql-react/storybook-static
```

Refs: #4219
## Summary

Component a11y is covered by Storybook + axe; this is the full-app
counterpart. `cypress-axe` runs axe at four checkpoints during a normal
session (initial render, after running a query, with the docs panel
open, with the history panel open) and gates PRs against a committed
baseline.

`cypress/.a11y-baseline.json` pins today's accepted violations —
color-contrast in several spots, a couple of nested-interactive cases,
link-in-text-block in the docs panel. CI fails on net-new only.

The spec lives alongside the existing Cypress suite, so it runs as part
of the normal `yarn e2e` flow. `cypress.config.ts` gets a small
`writeBaseline` Node task so the spec can persist baseline updates from
inside the browser.

## Refresh baseline

```
yarn workspace graphiql test:a11y:update
```

Refs: #4219
)

## Summary

Component-level a11y for v6. `@storybook/addon-a11y` surfaces axe
results next to each story while you're working on it;
`@storybook/addon-vitest` folds those same checks into the existing
Vitest suite so they run as part of `yarn test` in CI.

The model is per-story `parameters.a11y.test`:

- `'error'` (default) — axe violations fail the test
- `'todo'` — warn only, for stories with known issues we plan to fix
- `'off'` — skip a11y for the story

`vitest.config.mts` is split into two projects:

- `unit` — existing jsdom suite, unchanged behavior
- `storybook` — Vitest browser mode (Playwright Chromium), picks up
`.stories.*` files

The PR CI workflow gets one new step: `yarn playwright install
--with-deps chromium` ahead of `yarn test`.

## Run locally

```
yarn workspace @graphiql/react test                       # both projects
yarn workspace @graphiql/react vitest run --project=unit  # unit only
yarn workspace @graphiql/react vitest run --project=storybook
```

The Storybook a11y panel surfaces the same axe results live during `yarn
workspace @graphiql/react storybook`.

Refs: #4219
## Summary

- Migrate `Button`, `UnStyledButton`, `ToolbarButton`, and
`ExecuteButton` CSS to v6 OKLCH tokens.
- Add `variant?: 'default' | 'primary'` to `Button`; `primary` renders
the Run-button style.
- Switch `:focus` to `:focus-visible` on interactive states so the focus
ring no longer fires on mouse click. Aligns with [MDN
`:focus-visible`](https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible)
and WCAG 2.4.7 (Focus Visible).
- Import `clsx` directly in `button` and `toolbar-button`, following the
leaf-module pattern from #4272. A follow-up PR will convert remaining
callers and remove the `cn` re-export.
- Add Storybook stories: `Primitives/Button` (Default, Primary, Success,
Error, Disabled) and `Primitives/ToolbarButton` (Default).

## Test plan

- [x] Open Storybook `Primitives/Button` and verify each variant matches
the design.
- [x] Tab into the buttons, then mouse-click them. Focus ring appears on
Tab only, not on click.
- [x] Open `Primitives/ToolbarButton`. Hover the icon button; a v6
tooltip appears.
- [x] Run `yarn dev:graphiql`. The Run button and toolbar buttons match
the new design.

Refs: #4219
trevor-scheer and others added 30 commits October 1, 2026 14:15
The optional-features list links to `#custom-save-handlers`, but that
section was replaced by [Saving with your own
plugin](https://github.com/graphql/graphiql/blob/d3f2e0ff74e4a2b3c39d590c4e431fca1ccada79/docs/migration/graphiql-6.0.0.md#saving-with-your-own-plugin).
It also still describes host and plugin save hooks.

Point the link at the existing section and describe the single
registered custom save handler.
The license check follows the root `cspell` range through current
registry metadata, where a newly published dictionary now reports WTFPL.
The lockfile still installs the earlier MIT-licensed dictionary, so this
unrelated registry change is failing the v6 PR checks.

`cspell` is only used for linting. Moving it to `devDependencies` keeps
the installed version and the CI spell check the same, while the license
check's existing `dev: false` setting continues to check the published
workspace packages without scanning this development tool.
The v6 packages still build with
`babel-plugin-react-compiler@19.1.0-rc.3` and publish a dependency on
the matching prerelease runtime. This replaces both with the stable
`1.0.0` release before v6 is finalized.

The build continues to target React 18, and each compiled published
package keeps `react-compiler-runtime` as a direct dependency. This
follows [React's guidance for compiled libraries that support React
18](https://react.dev/reference/react-compiler/compiling-libraries). The
version change also covers the E2E app's compiler so its build uses the
same release as the published packages.
The v6 branch still builds with a July 2026 `@typescript/native-preview`
release. TypeScript 7.0.2 is now stable and ships its native compiler as
`tsc`.

This replaces the preview with a TypeScript 7 npm alias and updates the
build scripts to use `tsc`. TypeScript 7 doesn't yet expose a stable
programmatic API, so packages that use `svelte2tsx`, declaration
bundlers, or other API consumers continue to install TypeScript 5
directly. That includes packages which previously inherited TypeScript 5
from the workspace root. [TypeScript's migration
guidance](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/#running-side-by-side-with-typescript-60)
describes the side-by-side arrangement.
The v6 packages already advertise GraphQL 17 in their peer ranges, but
most of the workspace still develops against GraphQL 16. The existing
[PR
job](https://github.com/graphql/graphiql/blob/7a85b593/.github/workflows/pr.yml#L86-L105)
exercises only four language-service test files with GraphQL 17, so we
aren't building the UI and toolkit against that advertised major.

This uses GraphQL 17 for the published packages and browser E2E app,
updates `graphql-ws` to a version whose peer range includes 17, and runs
the full build and test suite under GraphQL 16 in a compatibility job.
It also reads GraphQL 17's new SDL default representation when
generating variable JSON schemas and resolves one declaration format
consistently across project references. The first commit handles source
compatibility, the second changes the development baseline and CI job,
and the third limits the declaration-resolution setting to the four
affected packages.

This is stacked on #4624, which provides the stable TypeScript 7
compiler needed for this build. A few older packages (`graphql-helix`,
`graphql-config`, `subscriptions-transport-ws`, and
`graphiql-code-exporter`) still declare peer ranges ending before
GraphQL 17. The E2E server already used GraphQL 17 before this PR.
The language server uses `@astrojs/compiler` to parse Astro frontmatter
before finding GraphQL tags. This updates it from 2 to 4.

While checking the existing Astro fixture, I found that the reported
query line was one line early: the parser disabled positions even though
the range mapper reads the frontmatter position. This lets the compiler
provide positions and asserts the query's source line in that fixture.
`@graphiql/react` uses Motion's `Reorder` components for tabs. This
updates `framer-motion` to v14 and records the dependency change in the
v6 release notes. [Motion's upgrade
guide](https://motion.dev/docs/react-upgrade-guide) reports no breaking
React API changes in v14; its peer range still covers React 18 and 19.
The three published packages using `clsx` now depend on v2. Their named
`clsx` imports stay the same, and the old v1 copy drops from the
lockfile.
`pnpm/action-setup@v4` uses the deprecated Node 20 action runtime. This
updates every workflow reference to v6, which uses Node 24.
Several user-facing dialogs provide a title but no `Dialog.Description`.
Radix reports this during tests, and assistive technology receives no
concise explanation of what each dialog is for.

This adds screen-reader descriptions to Settings and the collection form
dialogs. The conflict and destructive replacement dialogs already had
visible explanatory text, so this makes that text the Radix description
rather than duplicating it. The generic portal tests now include the
description required by the dialog contract as well.
The GraphiQL 6 test and build logs currently include a line for every
Zustand mock creation, Monaco worker request, and successful React
Compiler transform. The language service CLI test also prints the three
error stacks that it intentionally triggers, while the execute button
stories pass GraphQL ASTs through Storybook args and produce
cyclic-value warnings.

This removes the routine messages while preserving React Compiler skip
and failure reporting. The CLI test now stubs and asserts each expected
stderr write and failure exit independently. The execute button stories
parse their operations inside `render`, leaving their serializable args
available to Storybook controls without passing cyclic AST location data
through the args channel.

The first commit removes the unconditional logs. The second commit keeps
intentionally failing test output and cyclic story data out of the logs.
Since v3, the `graphql-language-service` package has exposed a `graphql`
executable that only prints a migration notice directing users to
`graphql-language-service-cli`:
https://github.com/graphql/graphiql/blob/c1fe2ca802fb39fc37e662c5f85cd83ab13a2b7b/packages/graphql-language-service/src/temp-bin.ts#L10-L34

The workspace manifest points that executable at build output, so pnpm
tries to link `dist/temp-bin.js` before it exists and reports a
missing-bin warning for every workspace consumer during installation.
This removes the deprecated `bin` entry and its warning-only source as
part of the v6 major release. The README migration note remains and
still directs CLI users to `graphql-language-service-cli` and
`graphql-lsp`.

To verify the install behavior, run `pnpm install --frozen-lockfile` in
a fresh checkout. To inspect the published contents after building, run
`npm pack --dry-run --json` from `packages/graphql-language-service`;
neither the package metadata nor file list should contain the old
executable.
Downstream jobs restore the build job’s Turbo cache, but Cypress
currently runs a full build and then invokes `pnpm e2e`, which requests
the GraphiQL build again. Lint also waits for and runs the build even
though `oxlint` only reads source files, and each Turbo invocation
replays cached task output.

This has Cypress materialize only the `graphiql-e2e...` build graph once
before calling the package-level E2E runner, lets lint run independently
without Turbo, and uses `--output-logs=new-only` for Turbo-backed
workflow commands. The canary job still materializes the full build
output before publishing.
The repo runs Vitest 4 while Vite is already on 8. This updates Vitest
and its browser, worker, and canvas helpers to versions that support
Vitest 5. The Storybook Vitest addon moves to 10.6.1 because 10.6.0 only
accepts Vitest 4 as a peer.

The first local parallel test run passed its assertions but hit an
intermittent Monaco mock worker teardown error; a focused run and a
second full run completed without it. No published package dependency or
API changes.
Cypress 16 deprecates its bundled Electron browser, but our E2E scripts
still default to Electron and CI carries an Electron-only GPU
workaround.

This runs source, built, interactive, and accessibility Cypress commands
in Chrome, removes the GPU workaround, and updates `cypress-real-events`
to 1.15.1 (the release whose peer range includes Cypress 16).

The latest `cypress-axe` package still only declares support through
Cypress 15. Upstream merged [Cypress 16
support](component-driven/cypress-axe#193), but
[its release pipeline is currently blocking
publication](component-driven/cypress-axe#194),
so this leaves 1.7.0 in place instead of pinning Cypress backward or
depending on an unreleased commit.
Vite 8 currently warns for SVGs transformed by `vite-plugin-svgr` 4
because the plugin calls the deprecated `transformWithEsbuild` API.
Vitest also warns while loading the two ESM configuration files that
still refer to the CommonJS-only `__dirname` global.

This updates both SVG plugin consumers to 5.2.0, whose Rolldown path
uses `transformWithOxc`, and resolves both test aliases relative to
`import.meta.dirname`. I kept the other dependency deprecations and peer
compatibility warnings out of this change.
`@types/dotenv` is a deprecated stub package; `dotenv@10.0.0` already
declares its own `types/index.d.ts`. `sane@2.0.0` is also deprecated and
remained in `codemirror-graphql` after the watch script that imported it
was removed in 2021:
5f49f27

This removes both development dependencies and prunes their orphaned
lockfile entries. In particular, removing `sane` drops its old Watchman,
`fsevents@1`, and micromatch dependency tree. Neither change affects
published runtime dependencies, so there is no changeset.
The GraphQL 16 compatibility install reports peer failures from two
direct dependencies of `example-graphiql-webpack`: `ajv-formats`
receives AJV 6 instead of its AJV 8 peer, and `worker-loader@2` only
supports Webpack 3 and 4 while the example uses Webpack 5.

Neither package is imported or configured. `worker-loader` is left over
from the example’s Webpack 4 setup, and `ajv-formats` was added as a
speculative `copy-webpack-plugin` workaround. Removing both declarations
also prunes the obsolete Webpack 4 loader dependency chain from the
lockfile.
Fresh installs currently warn about three deprecated Babel proposal
plugins and `@babel/polyfill`. The proposal syntax has been part of the
language for years, and Babel maintains equivalent transform plugins for
these configurations.

This replaces the proposal plugins with their transform equivalents in
the root and both Webpack example configurations. It also removes the
unused root `@babel/polyfill` dependency and stops loading it from
`graphql-language-service-cli`. The CLI already compiles to ES2018, and
its `yargs` dependency requires Node 10 or newer, where the Promise and
async runtime features used by the compiled output are native. Adding
`core-js` and `regenerator-runtime` to every CLI invocation would not
provide a required compatibility path.

The lockfile no longer contains `@babel/polyfill`, its `core-js` 2
dependency, or the superseded proposal plugins. The first commit is the
mechanical plugin migration; the second removes the CLI polyfill and
includes its patch changeset.
`@graphiql/toolkit` installs deprecated `subscriptions-transport-ws`
only so two tests can construct or mock its client. The runtime
compatibility path is already structural: it calls
`legacyWsClient.request(...)` and subscribes to the returned observable
without importing the package:
https://github.com/graphql/graphiql/blob/c1fe2ca802fb39fc37e662c5f85cd83ab13a2b7b/packages/graphiql-toolkit/src/create-fetcher/lib.ts#L299-L311

This replaces the package fixtures with structural clients and exercises
the legacy observable through request, subscription, result delivery,
completion, and unsubscribe. Removing the package also exposed that its
declarations had implicitly supplied Node types used by toolkit source
and tests, so this declares `@types/node` directly and includes it in
the toolkit TypeScript configuration.

The public `legacyWsClient` option, implementation, and documentation
remain unchanged. This is development/test dependency cleanup, so there
is no changeset.
`eslint-plugin-react-hooks` is loaded as an Oxlint JS plugin, but pnpm
also auto-installs its ESLint peer and the lockfile still selects the
unsupported ESLint 9 release. This emits a deprecation warning during
the GraphQL 16 compatibility install even though the plugin supports
ESLint 10.

This constrains that auto-installed peer with a workspace override and
refreshes the lockfile to ESLint 10. Keeping the constraint as an
override avoids representing ESLint as a tool the repository invokes
directly. A peer dependency rule would only hide the warning while
leaving the unsupported package installed.

This branch was successfully deployed

1 active deployment
deploy — 93c9f9c5 Deployed Oct 23, 2026 by trevor-scheer via Release #1693
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.

Visual query builder from Graphql schema

1 participant