github graphql/graphiql graphiql@6.0.0-beta.0

latest releases: graphiql@6.0.0-beta.1, @graphiql/plugin-query-builder@1.0.0-beta.1, @graphiql/react@1.0.0-beta.1...
pre-release5 hours ago

Major Changes

  • #4416 9c153e2 Thanks @trevor-scheer! - @graphiql/plugin-explorer is removed. Its visual query-building UI is replaced by @graphiql/plugin-query-builder, which is default-installed in the graphiql meta-package, so the capability is available with no extra setup. If you installed and registered @graphiql/plugin-explorer yourself, drop the dependency and the plugins entry; if you relied on the default plugin set, there is nothing to change.

  • #4425 ff2e4ca Thanks @trevor-scheer! - Remove the composable GraphiQL.Toolbar and GraphiQL.Logo slots. Editor actions are now contributed through a plugin's sessionActions, and branding is customized through the brand prop passed to <GraphiQL> (or <TopBar> directly). GraphiQL.Footer is unchanged. See the migration guide for before/after examples.

  • #4228 Thanks @trevor-scheer! - A ground-up visual redesign for v6. A new OKLCH-based design-token system brings first-class light and dark themes, driven by a data-theme attribute on the GraphiQL container. The layout is rebuilt around a top bar (endpoint and Run action), a left activity rail for plugins, a resizable side panel, a slim status bar, a flattened editor workspace, and a Variables/Headers tab strip. Every built-in component and both Monaco editor themes are restyled to match, and the doc explorer and history panels are rebuilt on the new chrome.

    GraphQL syntax coloring is unified across the doc explorer, history, and query builder, with type names colored by category. The mapping is public API for retheming: the --type-scalar, --type-enum, --type-input, and --type-composite CSS tokens, plus the typeCategory helper exported from @graphiql/react.

    Custom CSS that overrides GraphiQL's internal class names may need updating; only the CSS custom properties (design tokens) are supported theming API. The build now targets the defaults browserslist preset, which covers the modern browsers the OKLCH color system requires. See the migration guide at docs/migration/graphiql-6.0.0.md. Refs #4219.

Minor Changes

  • #4359 ac56840 Thanks @trevor-scheer! - New @graphiql/plugin-collections plugin for saving named operations into folder collections and reusing them later, default-installed in the graphiql meta-package so a Collections rail icon appears out of the box (passing the plugins prop opts out of the default set as before).

    • Collapsible tree UI with inline rename, hover-revealed row actions, and QRY/MUT/SUB pills (a MIX pill when a saved document holds more than one operation).
    • Save the current operation with ⌘S/Ctrl+S or the tab-strip Save button. An operation opened from a collection stays linked, so re-saving updates it in place; otherwise a "Save to collection" dialog opens. Clicking a saved item opens it in a new tab.
    • Reorder within and across collections by drag-and-drop or keyboard (focus a row's drag handle, Space to grab, arrow keys to move, Space to drop, Escape to cancel).
    • Copy a raw query or Share an importable envelope from any row; collection headers expose Share. Paste or drop a collections export anywhere in the pane to merge it in, or import/export JSON from the dialog. Imports reconcile by stable id, so re-importing updates in place and never duplicates; a conflict dialog lets you apply incoming changes, keep yours, or review each, and merge never deletes.
    • Pluggable persistence via the storage option (defaults to localStorage), plus readOnly, allowImportExport, and allowReplace for governed deployments.

    To support this without the core depending on any specific plugin, @graphiql/react gains a save API: registerSaveHandler(handler) (⌘S and the Save button fan out to every registered handler plus the onSaveQuery prop, and the dirty-state affordance only appears when at least one is registered), the onSaveQuery(tab) prop with markTabSaved(tabId) for deferred saves, and GraphiQLPlugin.sessionActions, an always-mounted plugin slot for toolbar buttons, dialogs, or behavior registration. The dirty-state dot means "a saved operation has unsaved edits" and survives a reload, so a tab that was never saved reads clean.

  • #4352 f8a9445 Thanks @trevor-scheer! - The active operation now follows the editor cursor. As you move the cursor between operations in a multi-operation document, operationName updates to the operation the cursor sits in, so the operation dropdown and operation-aware plugins all reflect where you are editing. Previously operationName only changed on run-at-cursor or via the operation dropdown.

    Two consequences if you embed GraphiQL: the onEditOperationName callback now fires when the cursor crosses into a different named operation, and a tab containing multiple operations shows the active operation name with a +N count of the others. Pinning an operation with the operationName prop still overrides cursor tracking.

    The Run button now offers an operation picker: in a document with multiple named operations, a dropdown on the Run button lets you choose which operation to run, and the menu marks which operation is currently active. The active operation still follows the editor cursor by default.

  • #4352 f8a9445 Thanks @trevor-scheer! - Add @graphiql/plugin-query-builder, a first-party visual query builder. It renders the schema's root types as a collapsible tree; checking a field adds it to the current operation and unchecking removes it, with the document parsed, mutated, and reprinted through the graphql package's AST utilities. Fields expose argument inputs (scalars, enums, lists, and input objects, including lists of input objects), scalar arguments can be promoted to variables, named fragments can be extracted from a field's selection and edited in place, and union/interface fields offer inline-fragment type-condition selectors.

    The query builder is default-installed in the graphiql meta-package, so it is available with no extra setup. It takes over from @graphiql/plugin-explorer.

  • #4321 03535ab Thanks @trevor-scheer! - Add a response pane header with real status, elapsed time, and response size from the active transport, a copy button, and a JSON / Tree / Table view toggle (the selection is persisted and restored on reload).

    • Tree renders the response JSON as a collapsible tree with type-colored values; top-level nodes expand by default and deeper levels start collapsed.
    • Table renders each list field as its own table captioned with its path (e.g. test.person.friends); sibling and aliased lists each get a table, nested objects and arrays show as shorthand summaries, non-list responses show an empty state, and rows get a bottom divider.
  • #4338 480afc1 Thanks @trevor-scheer! - Add a SettingsDialog with theme, density, font-size, and persist-headers controls, backed by a new useGraphiQLSettings() hook that persists preferences to localStorage and applies them to the GraphiQL container via data-* attributes. Density and font-size presets fill in concrete token values for the [data-density] and [data-font-size] blocks in tokens.css; Monaco editor font size, the status bar, and UI icon sizes follow the active font-size preset. The forcedTheme and showPersistHeadersSettings props continue to work, with forcedTheme hiding the theme control.

  • #4333 093cb10 Thanks @trevor-scheer! - Add a structured Transport API alongside the existing Fetcher. createTransport({...}) performs the GraphQL request and returns a TransportResponse carrying the real HTTP wire metadata (status, headers, timing, size) for queries, mutations, subscriptions, and incremental delivery, so the response pane can surface those values directly instead of fabricating them. That metadata is there even when the response body isn't valid JSON (an HTML error page from a proxy, a plain-text 401), so a broken response still shows its real status code instead of a generic error. <GraphiQL> accepts a new transport prop, mutually exclusive with fetcher at the type level.

    Transports support GET, POST, and the HTTP QUERY method per the GraphQL over HTTP spec. Pass method / supportedMethods to choose; GET encodes the query into the URL with no body, QUERY sends a JSON body but is safe and idempotent, and mutations are always sent over POST (or blocked when POST is unavailable). Transport exposes url, method, supportedMethods, and an optional setMethod, and the top bar shows the active method and endpoint with an inline switcher that cycles through the supported methods. Every request, incremental delivery on or off, sends application/graphql-response+json in its accept header alongside application/json, so spec-compliant servers don't fall back to legacy response semantics. Subscriptions require an explicit subscriptionClient satisfying a small SubscriptionClient contract: a single .subscribe(request, sink) method that graphql-ws and graphql-sse clients meet directly. The low-level simpleHttpTransport and multipartHttpTransport primitives also accept an optional method.

    TransportRequest carries extensions for GraphQL-over-HTTP extensions such as automatic persisted queries (encoded into the URL for GET, included in the JSON body for POST and QUERY), and signal, an AbortSignal that cancels an in-flight query or mutation. Stopping a running query or mutation aborts the request; stopping a subscription closes the underlying socket or SSE connection. TransportResponse.ok reflects both layers: the HTTP status and the absence of top-level GraphQL errors, so a 401 or 500 is never ok: true just because its body happens to parse as JSON with no errors.

    Plugins can observe and transform traffic through transport.onBeforeSend, transport.onResponse, and transport.onError, available via useGraphiQLPluginContext() (all three return a cleanup function; the transport field is undefined under the legacy fetcher path, so guard with optional chaining). onError fires when a request fails outright, such as a network error, so plugins can react to failures the same way they observe successful responses.

    createGraphiQLFetcher, the Fetcher type and its companions, and <GraphiQL fetcher={...}> are deprecated but continue to work unchanged. Consumers on the deprecated path see a one-time dismissible banner in the response pane pointing at docs/migration/graphiql-6.0.0.md rather than fabricated status/timing/size values. The CDN bundle exposes GraphiQL.createTransport and GraphiQL.createWsClient so script-tag consumers can adopt without a bundler.

Patch Changes

Don't miss a new graphiql release

NewReleases is sending notifications on new releases.