Release 2026-08-07
- #9836: Add a preset switcher for global cookies that share a name. Instead of rendering one row per value (where toggling one toggled them all), same-named
x-scalar-cookiesnow collapse into a single row with a dropdown to switch between the predefined values — for example aCulturecookie withPLandEN. Only the selected value is sent, and the choice persists.
-
#9793: Expose
serverandcustomFetchin the ClientPluginbeforeRequesthook payload (both optional, additive) so plugins can resolve relative URLs and run network calls — e.g. a token refresh — through the host fetch without closing over external state. -
#9828: Bump shared build and runtime dependencies to their latest compatible versions (fuse.js, vite, vitest, tailwindcss, @vitejs/plugin-vue, @vue/test-utils, posthog-js, yaml, and the CSS injection plugin). The fuse.js 7.5.0 upgrade tightened generic inference, so the empty
new Fuse([])search instances now pass an explicitFuseDatatype argument. -
#9798: fix: header parameters with
x-disabled: false(e.g.x-scenario-id) now stay enabled while editingRequestTableRow'shandleUpdateRowunconditionally ranisDisabled.value = payload.isDisabled ?? false. WhenCodeInputLitefired@update:modelValuefor the name or value field it calledhandleUpdateRow({ name: v })with noisDisabled, which reset the row to enabled on every keystroke and overrode the correct initial state read fromx-disabled. It now only updatesisDisabledwhen it is explicitly present in the payload. -
#9804: Long file names in the multipart form no longer stretch the request table past its container. The name now truncates with an ellipsis, and hovering shows the full name.
-
#9839: Harden the API reference against untrusted OpenAPI documents:
- Link targets taken from the document (
info.license.url,info.termsOfService,info.contact.url,externalDocs.url,x-scalar-links) and the direct download link are now checked against an allow list of protocols, so a document can no longer render ajavascript:link that runs script when a reader clicks it. Unsafe values fall back to plain text. deepMerge(used by the exportedcreateEmptySpecification) no longer writes through the prototype chain, so a document can no longer add properties toObject.prototypevia__proto__,constructor, orprototype. Keys with those names are kept as plain data instead of being dropped, so a schema is still free to describe a property namedconstructor.customCsscan no longer close the injected<style>tag, which mattered during server rendering where the value lands in the HTML stream verbatim.- Added
rel="noopener noreferrer"to the remainingtarget="_blank"links.
Adds
isSafeUrlandsanitizeUrlto@scalar/helpers/url/is-safe-url. - Link targets taken from the document (
- #9835: Fix the published type declarations so they resolve under
moduleResolution: node16/nodenextagain. Since1.62.1the.d.tsfiles re-exported relative modules without a file extension (export { default } from './fastifyApiReference'), which ESM resolution rejects with TS2834 — so the plugin's types silently degraded toanyfor those consumers. The declarations are now emitted as a single self-containedindex.d.ts(matching the Next.js integration), which resolves under every module resolution setting.
- #9818: Fix multiple configurations reusing the first document during client-side navigation
-
#9828: Bump shared build and runtime dependencies to their latest compatible versions (fuse.js, vite, vitest, tailwindcss, @vitejs/plugin-vue, @vue/test-utils, posthog-js, yaml, and the CSS injection plugin). The fuse.js 7.5.0 upgrade tightened generic inference, so the empty
new Fuse([])search instances now pass an explicitFuseDatatype argument. -
#9837: Keep the selected server when the configuration is updated. Pushing a config update to a mounted reference (for example a refreshed auth token via
updateConfiguration) rebases the document in the store, which previously reset the server selector back to the first server. The user's selected server is now preserved across configuration updates. -
#9783: fix: resolve axe-core ARIA violations in the API reference sidebar and client tabs
Sidebar items used
aria-selectedon links/buttons (invalid for those roles) and the search trigger usedrole="search"on a button. Selected items now usearia-current="page", the search control is a plain named button, and the sidebar no longer sets an invalidrole="navigation"on<aside>(it keeps the default complementary landmark).Client library and SDK installation "More" comboboxes sat inside
role="tablist", which failsaria-required-children. They now sit beside the tablist. MCP install controls without a target URL render as buttons instead of emptya[href=""]links. -
#9791: Stop recursive schema rendering when a discriminator variant
allOfs back to its base type. The selected child now inherits the parent's discriminator context so the mapping is not re-inferred on every nest. -
#9830: Stop listing enum values twice for an array parameter whose
itemsis a$refto an enum schema. The values are now listed only in the array items card, which also shows the item schema's title and description. -
#9839: Harden the API reference against untrusted OpenAPI documents:
- Link targets taken from the document (
info.license.url,info.termsOfService,info.contact.url,externalDocs.url,x-scalar-links) and the direct download link are now checked against an allow list of protocols, so a document can no longer render ajavascript:link that runs script when a reader clicks it. Unsafe values fall back to plain text. deepMerge(used by the exportedcreateEmptySpecification) no longer writes through the prototype chain, so a document can no longer add properties toObject.prototypevia__proto__,constructor, orprototype. Keys with those names are kept as plain data instead of being dropped, so a schema is still free to describe a property namedconstructor.customCsscan no longer close the injected<style>tag, which mattered during server rendering where the value lands in the HTML stream verbatim.- Added
rel="noopener noreferrer"to the remainingtarget="_blank"links.
Adds
isSafeUrlandsanitizeUrlto@scalar/helpers/url/is-safe-url. - Link targets taken from the document (
-
#9829: Update Vue to 3.5.40. Vue 3.5.36 tightened
defineModeldefault validation, so models with array or object defaults now use the factory form (defineModel<T[]>({ default: () => [] })) as Vue already requires for regular props. Behaviour is unchanged. -
#9790: fix: keep dots in webhook navigation deep links
Webhook event names that use dots (for example
account_holder.created) had the dot dropped when building the navigation id, joining adjacent words intoaccount-holdercreated. Dots are now kept, producingaccount-holder.created.Old deep links using the dropped-dot slug are redirected to the new slug, so existing bookmarks keep resolving.
-
#9783: fix: resolve axe-core ARIA violations in the API reference sidebar and client tabs
Sidebar items used
aria-selectedon links/buttons (invalid for those roles) and the search trigger usedrole="search"on a button. Selected items now usearia-current="page", the search control is a plain named button, and the sidebar no longer sets an invalidrole="navigation"on<aside>(it keeps the default complementary landmark).Client library and SDK installation "More" comboboxes sat inside
role="tablist", which failsaria-required-children. They now sit beside the tablist. MCP install controls without a target URL render as buttons instead of emptya[href=""]links. -
#9842: fix: show tooltips whose trigger sits inside a modal
<dialog>A
<dialog>opened withshowModal()is promoted to the browser's top layer, which paints above the rest of the document no matter whatz-indexanything else carries. The tooltip element is a shared singleton parented to<body>, so it rendered behind the dialog and was invisible. It now moves into the dialog while it points at a target in there, and moves back to the body once it is hidden. -
#9844: Use the base surface for text inputs, text areas, and text input copy controls in light mode.
-
#9829: Update Vue to 3.5.40. Vue 3.5.36 tightened
defineModeldefault validation, so models with array or object defaults now use the factory form (defineModel<T[]>({ default: () => [] })) as Vue already requires for regular props. Behaviour is unchanged.
- #9793: Expose
serverandcustomFetchin the ClientPluginbeforeRequesthook payload (both optional, additive) so plugins can resolve relative URLs and run network calls — e.g. a token refresh — through the host fetch without closing over external state.
- #9827: Convert nullable
$refpatterns to the 3.1 null-union form when upgrading from OpenAPI 3.0 to 3.1
- #9684: Type the
defaultHttpClientconfig against the real client ids.targetKeyandclientKeywere plainstring, so there was no autocomplete and no error when the value was wrong — for example passing the display title'Fetch'instead of the client id'fetch', which silently did nothing. They are now typed to the actual targets and clients, in both the@scalar/typesand@scalar/schemasdefinitions.
- #9684: Type the
defaultHttpClientconfig against the real client ids.targetKeyandclientKeywere plainstring, so there was no autocomplete and no error when the value was wrong — for example passing the display title'Fetch'instead of the client id'fetch', which silently did nothing. They are now typed to the actual targets and clients, in both the@scalar/typesand@scalar/schemasdefinitions.
-
#9820: Cap concurrent external fetches while bundling a document, so documents that reference many external examples (
externalValue) or references do not open an unbounded number of connections on load -
#9826: fix: resolve relative request URLs against the current origin in
fetchRequestToHarA relative
proxyUrl(e.g./api/scalar-proxy) makesredirectToProxyreturn a relative URL, whichnew URL()could not parse, so every request threwTypeError: Invalid URLand never made it into history. -
#9819: Fall back to a schema-generated request body when a selected example only has an unresolved
externalValue, so the Test Request editor no longer shows an empty body -
#9790: fix: keep dots in webhook navigation deep links
Webhook event names that use dots (for example
account_holder.created) had the dot dropped when building the navigation id, joining adjacent words intoaccount-holdercreated. Dots are now kept, producingaccount-holder.created.Old deep links using the dropped-dot slug are redirected to the new slug, so existing bookmarks keep resolving.
2.14.4
2026-08-07
- Components [notification] add
progressandpauseOnHoveroptions (#24565 by @misakamayako)
- Directives stop repeat-click after mouseup (#24573 by @qp666)
- Components [input/select] prevent box-shadow noise (#24619 by @thlovey)
- Components [autocomplete] clear stale suggestions on refocus (#24621 by @ixyzorg)
- Components [popover] omit
gpuAccelerationdefault value (#24636 by @btea) - Components [table] stop mutating parent's filtered-value (#24594 by @SpanManX)
- Components [upload] stabilize file list reorder transitions (#24609 by @rzzf)
- Components [space] clone spacer vnode (#24647 by @rzzf)
- Components [date-picker] correct the input time format (#24574 by @xingyixiang)
- Components [scrollbar] update component on transition and animation end (#24508 by @prd-y-nguyen)
- Components [input] emit change event when toggling password visibility (#24342 by @guozi9999)
- Components [table] avoid null theadRef access after header unmount (#24668 by @btea)
- Components [loading] avoid innerHTML and children conflict (#24675 by @rzzf)
- Components normalize
*-classand*-styleprops (#24418 by @ZacharyBear) - Components [popover] replace attrs with props for better type inference (#24571 by @Jungzl)
Release 2026-08-07 11:10
Release 2026-08-07 11:10
- router: retain mounted UI during revalidation (#7992) (ea3a665d81) by @Sheraff
- @tanstack/react-router@1.170.22
- @tanstack/react-start@1.168.39
- @tanstack/react-start-client@1.168.20
- @tanstack/react-start-rsc@0.1.38
- @tanstack/react-start-server@1.167.27
- @tanstack/router-cli@1.167.25
- @tanstack/router-core@1.171.19
- @tanstack/router-generator@1.167.25
- @tanstack/router-plugin@1.168.27
- @tanstack/router-vite-plugin@1.167.27
- @tanstack/solid-router@1.170.22
- @tanstack/solid-start@1.168.38
- @tanstack/solid-start-client@1.168.20
- @tanstack/solid-start-server@1.167.27
- @tanstack/start-client-core@1.170.18
- @tanstack/start-plugin-core@1.171.30
- @tanstack/start-server-core@1.169.22
- @tanstack/start-static-server-functions@1.167.23
- @tanstack/start-storage-context@1.167.21
- @tanstack/vue-router@1.170.21
- @tanstack/vue-start@1.168.37
- @tanstack/vue-start-client@1.167.23
- @tanstack/vue-start-server@1.167.27
@tanstack/vue-start-server@1.167.27
- Updated dependencies [
ea3a665]:- @tanstack/router-core@1.171.19
- @tanstack/start-server-core@1.169.22
- @tanstack/vue-router@1.170.21
@tanstack/vue-start-client@1.167.23
- Updated dependencies [
ea3a665]:- @tanstack/router-core@1.171.19
- @tanstack/start-client-core@1.170.18
- @tanstack/vue-router@1.170.21
@tanstack/start-server-core@1.169.22
- Updated dependencies [
ea3a665]:- @tanstack/router-core@1.171.19
- @tanstack/start-client-core@1.170.18
- @tanstack/start-storage-context@1.167.21
@tanstack/vue-router@1.170.21
- Updated dependencies [
ea3a665]:- @tanstack/router-core@1.171.19
@tanstack/start-storage-context@1.167.21
- Updated dependencies [
ea3a665]:- @tanstack/router-core@1.171.19