astro-vscode@2.17.4
- #18692
ad77e9eThanks @Princesseuh! - Republishes the extension to the VS Code Marketplace and Open VSX, which were missed in the previous release
Release 2026-11-10
-
#10871: Add schema-aware file controls for multipart/mixed and multipart/related parts, preserving part order and encodings. Restrict multipart/form-data uploads to file fields when a request body schema is available.
Honor binary encoding content types on multipart fields and share file-schema detection with example generation, including nullable, composed, and typeless file placeholders.
-
#10731: Support OpenID Connect flow defaults, including client ID, selected scopes, and PKCE, after discovery. Prefer a sole configured flow while retaining other discovered flows. Add typed OpenID Connect authentication configuration for .NET.
- #10892: Allow defaultHttpClient to select custom code samples with targetKey: 'custom'.
- #10891: Support optional display labels for SDK installation tabs while retaining language-based selection and icons.
- #10902: Render self-contained Avro, RAML, and Protobuf schemas as native field and type documentation, retaining copyable source for unsupported schemas.
-
#10890: Add an Elixir language icon and show it on Elixir SDK installation tabs.
-
#10936: Mark hosting waitlist sign-ups from the developer tools Deploy card with an
osscontact property. -
#10898: Preserve browser-native plugin URL imports when bundling API Reference with Next.js Turbopack.
-
#10908: Expose
Scalar.releaseUnusedStyles()in the standalone bundle to release orphaned CSS without mounting a temporary reference or changing body theme classes. Preserve styles owned by active references and restore detached styles on the next mount. -
#10873: Display the API description version verbatim without adding a
vprefix, so commit hashes and other version identifiers remain accurate. -
#10874: Automatically group deep-object query parameters with expandable fields in a collapsed row.
Keep expanded fields open during navigation within a group, and mark flattened fields as required only when every ancestor is required.
-
#10949: Show response header examples, including media type examples and OpenAPI 3.2 cookie examples, with explicit examples taking precedence over schema examples. Preserve this precedence through composed schemas and fall back to media type examples when header examples have no usable values.
Keep external example URLs visible and preserve line breaks in displayed string examples. Across all schemas, array-level examples take precedence over item examples.
Preserve
x-exampleandx-exampleson OpenAPI 2.0 response headers during upgrades.
- #10894: Substitute explicitly mapped reader credentials into custom code samples with default masking, public field opt-outs, and real values on copy.
- #10893: Allow custom code samples to use separate picker headings with an optional
groupfield.
-
#10949: Show response header examples, including media type examples and OpenAPI 3.2 cookie examples, with explicit examples taking precedence over schema examples. Preserve this precedence through composed schemas and fall back to media type examples when header examples have no usable values.
Keep external example URLs visible and preserve line breaks in displayed string examples. Across all schemas, array-level examples take precedence over item examples.
Preserve
x-exampleandx-exampleson OpenAPI 2.0 response headers during upgrades. -
#10902: Render self-contained Avro, RAML, and Protobuf schemas as native field and type documentation, retaining copyable source for unsupported schemas.
- #10894: Substitute explicitly mapped reader credentials into custom code samples with default masking, public field opt-outs, and real values on copy.
- #10890: Add an Elixir language icon and show it on Elixir SDK installation tabs.
- #10897: Resolve proxy references within their schema resource using the shared bundle resolver, and expose resolved targets to lifecycle hooks for scope-aware transformations.
- #10904: Share confined document loading between Markdown converters and include HTTP status codes in load errors.
- #10935: feat(release-notes): add a per-product
maxHighlightsoption (1 to 20, default 5) that sets how many highlights a generated note may carry. The limit is stated in the default system prompt, enforced when the response is validated, and passed to custom system prompts, and the default output token budget grows with it.
- #10900: Upgrade the CLI to Commander 15 and require Node.js 22.12.0 or later.
- #10894: Substitute explicitly mapped reader credentials into custom code samples with default masking, public field opt-outs, and real values on copy.
- #10892: Allow defaultHttpClient to select custom code samples with targetKey: 'custom'.
- #10891: Support optional display labels for SDK installation tabs while retaining language-based selection and icons.
- #10893: Allow custom code samples to use separate picker headings with an optional
groupfield.
- #10894: Substitute explicitly mapped reader credentials into custom code samples with default masking, public field opt-outs, and real values on copy.
- #10892: Allow defaultHttpClient to select custom code samples with targetKey: 'custom'.
- #10891: Support optional display labels for SDK installation tabs while retaining language-based selection and icons.
- #10731: Support OpenID Connect flow defaults, including client ID, selected scopes, and PKCE, after discovery. Prefer a sole configured flow while retaining other discovered flows. Add typed OpenID Connect authentication configuration for .NET.
- #10893: Allow custom code samples to use separate picker headings with an optional
groupfield.
-
#10871: Add schema-aware file controls for multipart/mixed and multipart/related parts, preserving part order and encodings. Restrict multipart/form-data uploads to file fields when a request body schema is available.
Honor binary encoding content types on multipart fields and share file-schema detection with example generation, including nullable, composed, and typeless file placeholders.
-
#10894: Substitute explicitly mapped reader credentials into custom code samples with default masking, public field opt-outs, and real values on copy.
-
#10871: Add schema-aware file controls for multipart/mixed and multipart/related parts, preserving part order and encodings. Restrict multipart/form-data uploads to file fields when a request body schema is available.
Honor binary encoding content types on multipart fields and share file-schema detection with example generation, including nullable, composed, and typeless file placeholders.
-
#10891: Support optional display labels for SDK installation tabs while retaining language-based selection and icons.
-
#10731: Support OpenID Connect flow defaults, including client ID, selected scopes, and PKCE, after discovery. Prefer a sole configured flow while retaining other discovered flows. Add typed OpenID Connect authentication configuration for .NET.
-
#10893: Allow custom code samples to use separate picker headings with an optional
groupfield.
-
#10928: Fill the discriminator property with the selected variant's mapping value in generated examples.
-
#10813: fix: keep the required properties of an object that the example depth cap truncates, so a deeply nested mock response no longer serves
{}where its schema requires keys, including keys required throughallOfmembers or the selectedoneOf/anyOfvariantPreserve explicit values equal to the depth marker and exclude requirements from unselected union branches.
Keep required primitive compositions on the normal traversal and collect discriminator requirements from the branch rendered after depth truncation.
Reuse evaluated discriminator values for required-property collection and keep inferred tuple arrays empty past the depth cap.
Preserve shared requirements and required primitive values through dynamic references, including requirements declared in dynamically referenced composition members.
Collect requirements separately when composition branches reuse a shared template under different dynamic bindings.
Exclude requirements from composition members omitted by the request or response mode.
-
#10938: fix: merge array items whose
allOfdescribes an object withouttype: objecton the first member into one example instead of one partial object per member -
#10955: fix: respect array length bounds when generating schema examples
Preserve cycle detection for selected array branches, pad unrestricted annotated items, and prefer a contains sample when no item constraints are declared.
-
#10908: Load Scalar only on API reference routes and destroy its instances when leaving, preventing standalone styles from affecting other Docusaurus pages.
The CDN bundle is no longer injected on every page. Sites using
window.Scalar.createApiReferenceoutside an API reference route must load the bundle explicitly. Upgrade pinned CDN bundles to a release withScalar.releaseUnusedStylesfor cleanup when navigation interrupts loading.
- #10879: Omit response URLs and redact saved credentials from response headers and bodies before sending request tool output to the chat model.
- #10876: Require approval before executing any AI-generated API request, including GET requests that can send stored credentials or data.
- #10878: Validate AI request paths and require a usable selected server before attaching stored credentials or sending a request.
- #10904: Block private-network document requests by default and require an explicit basePath for local files. Apply the same permissions to external references, with an opt-in for trusted private-network inputs.
- #10904: Share confined document loading between Markdown converters and include HTTP status codes in load errors.
- #10923: Update the bundled mdast-util-to-hast to 13.2.1 to fix CVE-2025-66400 (unsanitized class attribute).
- #10894: Substitute explicitly mapped reader credentials into custom code samples with default masking, public field opt-outs, and real values on copy.
- #10882: Skip proxying requests whose origin matches the proxy origin to avoid an unnecessary forwarding hop.
- #10880: Preserve empty upstream response headers when restoring headers for scripts, request history, and agent results.
- #10951: Use shortest round-trip decimal values consistently for multipleOf checks, including large JSON integers and positive exponents. Fast-path safe integers and share keyword registration across validators.
- #10951: Validate decimal
multipleOfconstraints with exact decimal arithmetic, accepting values such as19.99and1000000.19formultipleOf: 0.01while rejecting nonmultiples without a floating-point tolerance. - #10959: Reduce repeated schema compilation in decimal validation tests to avoid CI timeouts.
-
#10951: Use shortest round-trip decimal values consistently for multipleOf checks, including large JSON integers and positive exponents. Fast-path safe integers and share keyword registration across validators.
-
#10951: Validate decimal
multipleOfconstraints with exact decimal arithmetic, accepting values such as19.99and1000000.19formultipleOf: 0.01while rejecting nonmultiples without a floating-point tolerance. -
#10813: fix: keep the required properties of an object that the example depth cap truncates, so a deeply nested mock response no longer serves
{}where its schema requires keys, including keys required throughallOfmembers or the selectedoneOf/anyOfvariantPreserve explicit values equal to the depth marker and exclude requirements from unselected union branches.
Keep required primitive compositions on the normal traversal and collect discriminator requirements from the branch rendered after depth truncation.
Reuse evaluated discriminator values for required-property collection and keep inferred tuple arrays empty past the depth cap.
Preserve shared requirements and required primitive values through dynamic references, including requirements declared in dynamically referenced composition members.
Collect requirements separately when composition branches reuse a shared template under different dynamic bindings.
Exclude requirements from composition members omitted by the request or response mode.
-
#10950: Ignore declared Content-Length, Content-Encoding, and Content-Type response headers so generated bodies remain readable and empty responses do not inherit a declared content type.
Ignore other transport-managed headers, including Transfer-Encoding and Trailer. Skip and warn about malformed declared header names and values instead of failing the response.
-
#10938: fix: merge array items whose
allOfdescribes an object withouttype: objecton the first member into one example instead of one partial object per member -
#10940: Route path segments that mix parameters with literal text, such as
{id}.json,{id}:cancelandv{version}, only to requests that carry the literal text, and pass their parameters to request validation,x-handlerandx-variable. -
#10930: Accept request bodies that leave out required
readOnlyproperties during request validation. -
#10875: Keep mock store collections and item IDs isolated from inherited host properties, and validate keys passed through the script sandbox.
-
#10898: Preserve path parameters when generating OpenAPI descriptions from Next.js handlers with asynchronous params, and mark path parameters as required.
Infer missing path parameters from route paths when handlers use named parameter aliases or generated Next.js RouteContext types.
- #10904: Share confined document loading between Markdown converters and include HTTP status codes in load errors.
- #10921: Isolate declaration compatibility tests from ambient workspace types.
-
#10736: Exclude benchmark fixtures from published build output.
-
#10925: Keep
type: fileinside Swagger 2.0 example data when upgrading to OpenAPI 3.0. Continue converting file schemas in reusable responses and parameters named like data keywords. Preserve example and default data on schemas and reusable parameters whose names match schema-map keywords. Continue upgrading response headers whose names match data keywords. Limit Swagger-specific data guards to the 2.0 upgrade so OpenAPI 3.0 request bodies and callbacks namedx-examplestill upgrade. Preserve example payloads on reusable objects namedheaders. -
#10948: Convert Swagger 2.0 discriminator strings to Discriminator Objects so upgrades preserve the discriminating property name.
Preserve x-ms-discriminator-value and x-discriminator-value aliases from allOf subtypes in discriminator mappings, including inherited subtypes, without replacing authored mappings.
-
#10949: Show response header examples, including media type examples and OpenAPI 3.2 cookie examples, with explicit examples taking precedence over schema examples. Preserve this precedence through composed schemas and fall back to media type examples when header examples have no usable values.
Keep external example URLs visible and preserve line breaks in displayed string examples. Across all schemas, array-level examples take precedence over item examples.
Preserve
x-exampleandx-exampleson OpenAPI 2.0 response headers during upgrades. -
#10920: Prefer operation-level
producesover the globalproduceswhen upgrading Swagger 2.0 response content.
- #10942: Keep application/x-www-form-urlencoded bodies in the ofetch and undici snippets, preserve the order of repeated, empty and prototype-named fields in the fetch, Go, F#, Julia and Clojure snippets, and escape apostrophes in the PHP cURL body.
- #10925: Stabilize the color-picker edit-position regression test by completing syntax parsing after document changes.
- @scalar/api-reference@1.78.0
- #10731: Support OpenID Connect flow defaults, including client ID, selected scopes, and PKCE, after discovery. Prefer a sole configured flow while retaining other discovered flows. Add typed OpenID Connect authentication configuration for .NET.
- @scalar/api-reference@1.78.0
- #10731: Support OpenID Connect flow defaults, including client ID, selected scopes, and PKCE, after discovery. Prefer a sole configured flow while retaining other discovered flows. Add typed OpenID Connect authentication configuration for .NET.
- @scalar/api-reference@1.78.0
- #10731: Support OpenID Connect flow defaults, including client ID, selected scopes, and PKCE, after discovery. Prefer a sole configured flow while retaining other discovered flows. Add typed OpenID Connect authentication configuration for .NET.
- @scalar/api-reference@1.78.0
- #10731: Support OpenID Connect flow defaults, including client ID, selected scopes, and PKCE, after discovery. Prefer a sole configured flow while retaining other discovered flows. Add typed OpenID Connect authentication configuration for .NET.
- #10731: Support OpenID Connect flow defaults, including client ID, selected scopes, and PKCE, after discovery. Prefer a sole configured flow while retaining other discovered flows. Add typed OpenID Connect authentication configuration for .NET.
- #10934: Keep embedded API descriptions inside the API reference configuration script and escape the Django Ninja page title.
- #10934: Keep embedded API descriptions inside the API reference configuration script and escape the Django Ninja page title.
- #10905: Configure a separate agent key for each Galaxy and Petstore API description.
- #10903: Upgrade Monaco Editor and YAML support, migrate language APIs, and use Vite-managed workers in web and desktop editors.
- @scalar/api-reference@1.78.0
- @scalar/api-reference@1.78.0
- @scalar/api-reference@1.78.0
v3.33.1
- Deleting a text selection that spans the whole document no longer leaves the deleted text's marks active, so text typed into the emptied editor is no longer bold, linked or otherwise marked.
- The first
goToNextResult()orgoToPreviousResult()after a new search now selects the highlighted first result instead of skipping it.
yCursorPluginnow publishes alastSelectionawareness field with each collaborative field's latest selection and whether its editor is focused. Unlikecursor, it stays after the editor loses focus, so other clients can still read the selection.lastSelectionis now reserved and can't be used as the cursor field.
v2.3.2
HMR now handles code-splitting changes more reliably, reducing unnecessary full-page reloads when chunks are added or rearranged. Newly required chunks are loaded before HMR accept callbacks run, and changes to async chunk dependencies no longer cause unnecessary update propagation.
The experimental rule.as option lets a matched resource use a different path for subsequent rule matching while preserving the original resource for file reading and loaders. For example, as: '[resource-path].txt' lets later .txt rules also process example.source.js. (#15917)
// rspack.config.mjs
export default {
module: {
rules: [
{
test: /\.source\.js$/,
type: 'asset/source',
as: '[resource-path].txt',
},
{ test: /\.txt$/, use: './text-loader.js' },
],
},
};
Here, example.source.js matches the later .txt rule as example.source.js.txt; text-loader.js still receives the contents of the original file.
Rspack can now bypass side-effect-free modules that only forward exports with export *, connecting directly to the underlying module.
Mark the package as side-effect-free in package.json:
{
"sideEffects": false
}
// src/value.js
export const value = 42;
// src/passthrough.js
export * from './value.js';
// src/index.js
export * from './passthrough.js';
With optimization.sideEffects enabled (the default in production), the export * connection from index.js can now go directly to value.js, skipping passthrough.js.
- feat(sri): support hashLoading: "lazy" in SubresourceIntegrityPlugin by @sd2k in https://github.com/web-infra-dev/rspack/pull/16374
- feat: add output.environment.topLevelAwait and await async ESM entries by @hai-x in https://github.com/web-infra-dev/rspack/pull/16386
- feat: support externals.byLayer by @stormslowly in https://github.com/web-infra-dev/rspack/pull/16307
- feat(css): Add opt-in runtime public paths for injected styles by @scttcper in https://github.com/web-infra-dev/rspack/pull/15705
- feat: add experimental rule.as by @intellild in https://github.com/web-infra-dev/rspack/pull/15917
- feat(tree-shaking): prune dynamic imports from unused exports by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/15449
- feat: skip side-effect-free
export *passthrough modules by @hai-x in https://github.com/web-infra-dev/rspack/pull/16472
- perf: use memchr SIMD scans and drop winnow by @intellild in https://github.com/web-infra-dev/rspack/pull/16424
- perf(sources): box the replacement name by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/15878
- perf: lazily create existing loader dependency sets by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16449
- perf: lazily materialize package.json metadata by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/16469
- perf(core): trim runtime spec sets on creation by @guru-irl in https://github.com/web-infra-dev/rspack/pull/16478
- perf(sources): share source map text with BytesStr by @SyMind in https://github.com/web-infra-dev/rspack/pull/16468
- perf(core): free the previous compilation's assets during a rebuild by @guru-irl in https://github.com/web-infra-dev/rspack/pull/16479
- perf(sources): compact noSources maps only when retained by @SyMind in https://github.com/web-infra-dev/rspack/pull/16536
- perf: reduce source map memory during asset generation and content hashing by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/16470
- fix(core): keep property access when inlining an export reached through a re-export by @flex-mookeun in https://github.com/web-infra-dev/rspack/pull/16310
- fix(core): keep the full hash stable across rebuilds without HMR by @guru-irl in https://github.com/web-infra-dev/rspack/pull/16280
- fix(runtime): avoid coercion collisions in chunk ID matchers by @intellild in https://github.com/web-infra-dev/rspack/pull/16423
- fix(devtool): map bootstrap and startup sources by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/16426
- fix: keep receiver exports for calls on unprovided members by @hai-x in https://github.com/web-infra-dev/rspack/pull/16418
- fix: restore side-effect imports after package metadata changes by @ahabhgk in https://github.com/web-infra-dev/rspack/pull/16435
- fix(cache): reuse completed builds for external and generated modules by @ahabhgk in https://github.com/web-infra-dev/rspack/pull/16429
- fix(core): fold chunk hashes into the full hash in chunk id order by @guru-irl in https://github.com/web-infra-dev/rspack/pull/16293
- fix: keep initializers of unused top-level using declarations by @hai-x in https://github.com/web-infra-dev/rspack/pull/16437
- fix(watcher): preserve concrete paths in native watcher events by @stormslowly in https://github.com/web-infra-dev/rspack/pull/16411
- fix(stats): report each runtime module's own size and chunks by @guru-irl in https://github.com/web-infra-dev/rspack/pull/16076
- fix(hmr): complete new entry chunk dependencies by @JSerFeng in https://github.com/web-infra-dev/rspack/pull/15955
- fix: isolate entry declarations from runtime tables by @ahabhgk in https://github.com/web-infra-dev/rspack/pull/16497
- fix: preserve module namespace key order for mixed exports by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/16491
- fix(watcher): separate filesystem accuracy from cache by @stormslowly in https://github.com/web-infra-dev/rspack/pull/16512
- fix(watcher): align rename events with watchpack by @stormslowly in https://github.com/web-infra-dev/rspack/pull/16460
- fix: skip cyclic star re-exports when resolving a binding by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/16496
- fix: preserve lone surrogates during constant evaluation by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/16494
- fix(watcher): pass SystemTime to mtime_accuracy by @hai-x in https://github.com/web-infra-dev/rspack/pull/16526
- fix(resolver): support UTF-8 BOM in tsconfig files by @stormslowly in https://github.com/web-infra-dev/rspack/pull/16518
- fix: evaluate
x in nsto true whenxis a re-exported namespace by @hai-x in https://github.com/web-infra-dev/rspack/pull/16509 - fix: preserve negative zero in exports and use JavaScript number strings in constant evaluation by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/16527
- fix(mf): keep the whole requiredVersion range in mf-manifest.json by @arnaud-zg in https://github.com/web-infra-dev/rspack/pull/16402
- fix(core): distinguish fatal module errors from loader diagnostics by @ahabhgk in https://github.com/web-infra-dev/rspack/pull/16538
- fix(css): scope counter styles and implicit grid lines by @intellild in https://github.com/web-infra-dev/rspack/pull/16520
- fix(hmr): invalidate cached chunks when version tags change by @JSerFeng in https://github.com/web-infra-dev/rspack/pull/16548
- fix(watcher): account for directory mtime accuracy by @stormslowly in https://github.com/web-infra-dev/rspack/pull/16531
- fix(mf): read provided shared fields directly in manifests by @ahabhgk in https://github.com/web-infra-dev/rspack/pull/16533
- fix(resolver): report circular tsconfig extends instead of crashing by @stormslowly in https://github.com/web-infra-dev/rspack/pull/16513
- fix(hmr): load async groups through their last chunk by @JSerFeng in https://github.com/web-infra-dev/rspack/pull/16328
- fix(resolver): reload PnP manifest from cached path by @stormslowly in https://github.com/web-infra-dev/rspack/pull/16543
- refactor(binding): rely on napi-rs for module retention by @SyMind in https://github.com/web-infra-dev/rspack/pull/16431
- refactor: remove unused exports_definitions hook from ConcatenatedModule by @hai-x in https://github.com/web-infra-dev/rspack/pull/16434
- refactor(binding): implement module classes in JavaScript by @SyMind in https://github.com/web-infra-dev/rspack/pull/16436
- docs: clarify split chunks sizing and cache group examples by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16409
- docs: clarify split chunks counting and troubleshooting by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16412
- docs: explain entry dependencies and shared runtime by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16413
- docs: standardize Rspack runtime terminology by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16427
- docs: clarify Lightning CSS minimizer options and examples by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16417
- docs: add Nitro to community integrations by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16428
- docs: introduce rspack-chain for configuration customization by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16430
- docs: illustrate runtime chunk initialization by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16414
- docs: add compilation dependency tracking examples by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16415
- docs: add entrypoints manifest example by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16416
- docs: refresh Rspack and Rstack introduction by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16455
- docs: clarify stats asset metadata by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16461
- docs: redirect moved pages on Cloudflare Pages by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16465
- docs(website): simplify Rspress configuration by @SoonIter in https://github.com/web-infra-dev/rspack/pull/16522
- docs: expand community plugin list by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16524
- docs: expand community loader list by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16528
- docs: clarify chunk ID assignment when chunkIds is false by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/16523
- docs: use a WebMCP prompt in the Rspack 2.3 announcement by @SoonIter in https://github.com/web-infra-dev/rspack/pull/16553
- test(cache): validate persistent cache hits in config and normal cases by @ahabhgk in https://github.com/web-infra-dev/rspack/pull/16397
- test: exclude external re-export case from cache reuse checks by @SyMind in https://github.com/web-infra-dev/rspack/pull/16425
- ci: use trunk baseline for branch-based PR stacks by @ScriptedAlchemy in https://github.com/web-infra-dev/rspack/pull/16201
- chore(deps): update napi by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/16230
- chore(deps): update dependency tiny-emitter to v2.1.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/16440
- test: exclude container tree shaking for configCases cache test by @ahabhgk in https://github.com/web-infra-dev/rspack/pull/16450
- chore(deps): upgrade SWC crates and browserslist-rs by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16458
- chore(deps): update dependency rsbuild-plugin-google-analytics to v1.1.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/16438
- chore(deps): update dependency coffee-loader to v5 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/16441
- chore(deps): update patch npm dependencies by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/16476
- chore(deps): update dependency mermaid to ^12.3.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/16480
- chore: use Rspress built-in Shiki transformers by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/16489
- chore(deps): update dependency playwright to v1.65.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/16481
- chore(ci): use mini runner for ecosystem ci dispatcher by @stormslowly in https://github.com/web-infra-dev/rspack/pull/14471
- test(watcher): stabilize nested context removal case by @stormslowly in https://github.com/web-infra-dev/rspack/pull/16519
- chore(deps): update Rslib to 1.0.6 by @SoonIter in https://github.com/web-infra-dev/rspack/pull/16471
- chore(deps): update dependency sass-loader to ^17.1.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/16498
- chore(deps): update rust crate tokio to 1.54.1 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/16502
- chore(deps): update dependency jsdom to v31 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/16504
- chore(deps): bump swc-next to 0.6.1 by @CPunisher in https://github.com/web-infra-dev/rspack/pull/16525
- chore: bump
swc_corefrom 84.0.1 to 84.0.2 by @CPunisher in https://github.com/web-infra-dev/rspack/pull/16547 - test(stats): cover shared issuers in child compilations by @stormslowly in https://github.com/web-infra-dev/rspack/pull/16456
- chore(deps): update dependency execa to v10 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/16503
- test: wait for both watchers to finish the initial batch in rename cases by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/16530
- test(watcher): validate burst aggregation against event timing by @stormslowly in https://github.com/web-infra-dev/rspack/pull/16544
- test: stabilize cache restoration watch test by @ahabhgk in https://github.com/web-infra-dev/rspack/pull/16555
- @sd2k made their first contribution in https://github.com/web-infra-dev/rspack/pull/16374
- @scttcper made their first contribution in https://github.com/web-infra-dev/rspack/pull/15705
- @arnaud-zg made their first contribution in https://github.com/web-infra-dev/rspack/pull/16402
Full Changelog: https://github.com/web-infra-dev/rspack/compare/v2.3.1...v2.3.2
v0.7.12
Astryx 0.7.12 — all @astryxdesign/* packages ship at this version.
OLD_VERSION=0.7.11 # replace with the Core version your project uses today
npm install @astryxdesign/core@0.7.12 @astryxdesign/cli@0.7.12 # plus every other @astryxdesign/* package you use, at 0.7.12
npx @astryxdesign/cli upgrade --from "$OLD_VERSION" --apply --path .
-
BottomSheet: at rest, a sheet's content starts below the grab bar whatever its
padding, so the first line is no longer drawn through the bar's fade. The block-start inset is never less than the bar's height (--spacing-6): the band under the bar is not padding a child escapes, so a loneSectionstarts below the bar too; scrolled content still passes beneath it. A sheet at the default padding starts its content 8 px lower, one withpadding={0}starts it below the bar, and one whose only child is aSectionstarts that Section 24 px lower and grows by the same amount. Core's ownpadding={0}sheets (the touch date and time pickers, the DropdownMenu and ContextMenu sheets, and the PowerSearch and Tokenizer sheets) no longer reserve that band themselves, so the pickers, PowerSearch and Tokenizer look the same and a menu's first row sits 8 px lower. The CLI'stable-filterandtable-inboxpage templates drop their own band too, so it is not doubled. (#8558)Also released in
@astryxdesign/cli. -
ChatLayout keeps its composer on top of the software keyboard where the visual viewport shrinks for it, instead of leaving it underneath until the browser scrolls the whole page. In Chrome on Android the dock rides Gboard's measured slides up and down, in step with the keyboard. In Safari on iOS (in the browser and as a home-screen app) and in Firefox for Android, it moves above the keyboard once the browser reports it. Where a page sets
interactive-widget=resizes-content, Chrome shrinks the page for the keyboard itself and the composer stays above it without moving. A conversation at its newest message stays there, and the rest of the transcript can still be scrolled above the composer. On a touch screen, in a top-level page, every way into the composer's text (a tap, the keyboard's previous and next buttons, Tab, the input'sfocus()) reaches it without the page scrolling; under a mouse or inside an iframe the browser's own focus applies. In a top-level page on a touch screen, the composer's wrapper (without the scroll-to-bottom button) is a group with no name. When the keyboard's Done ends typing, focus rests there (it is no tab stop), so the next tap or Tab starts from the composer; it shows the focus ring after keyboard input only. A tap that focuses the composer still raises its click once. Under a mouse or inside an iframe, the wrapper is a plain container. Under Reduce Motion the composer never travels with Gboard: it cross-fades to its place above the keyboard. Under a mouse, with no software keyboard, nothing changes. The browser-support guide's section on the on-screen keyboard covers ChatLayout's composer. (#8176)Also released in
@astryxdesign/cli. -
Kbdshowsmetaas ⌘ on Apple platforms, where it showed "META". (#10528) -
Kbdshowsctrl,altandshiftas text ("Ctrl", "Alt", "Shift") off Apple platforms and before hydration, andmetaas "Win" off Apple platforms and before hydration, instead of Apple's ⌃ ⌥ ⇧ symbols and "META". Apple platforms keep the symbols, and spoken names are unchanged. The text comes from the catalog, so other locales can translate it. (#10524) -
A
LayoutPanelthat takes auseResizableregion in itsresizableprop slides closed and open from the edge facing itsResizeHandlewhen the region collapses or opens, under every pointer, with the content beside it moving on the same motion: throughcollapse(),expand(), Enter, a double-click, the grow arrow, a controlledisCollapsed, or a lift past the collapse threshold. A drag that reopens the panel follows the pointer, and Reduce Motion is honored. A hand-builtResizablePropsobject does not slide. No prop or option is added. (#9989) -
On a phone or tablet, drag a Lightbox photo down to close the viewer, as in the iOS Photos viewer. The photo follows your finger and shrinks a little as you pull, while the backdrop fades and the controls fade faster. The backdrop fades without its blur, which comes back once it is at rest. Let go moving down, however short the pull, and the photo carries on down as the viewer closes. Flick it back up, or bring it back to where you started, and it springs back into place. A zoomed photo still pans when you drag it; the drag to close starts from the fitted size. Videos are unchanged. (#8215) The viewer's controls now sit in their own layers, which fade together during the drag.
-
A Lightbox gallery now pages the way the iOS Photos viewer does. On a phone or tablet, drag or flick between items: the row follows your finger, and the release lands on the next or previous item, one at most. A gap of 40 px separates the items while they move. A zoomed photo pans with your finger until it reaches its edge; a new drag from that edge moves to the next item. A photo you leave zoomed returns to its fitted size once the gallery rests. Under a finger, the previous and next buttons and the arrow keys slide to the item instead of swapping it in place. (#8197) Each item's caption moves with its item, right under its photo.
onIndexChangealso reports a swipe.Lightbox now loads its touch code with it, as Toast and Slider do. Its import grows from 51.4 KB to 99.6 KB gzip with the zoom and paging beneath, mostly shared touch modules that a page loads once; Lightbox's own code adds 14.1 KB minified.
-
ListtakesanimatedLayout, the handle fromuseAnimatedLayout({containerRef}), andListItemtakesitemKey, the row's identity. With the handle, when rows are inserted, removed or reordered, an inserted row enters, a removed row (a swiped one with its action showing) collapses in place, and a row that crosses rows moving the other way rides above them with the surface color behind it, as an iOS table's opaque cell does. The rows after a change and the content after the list, up to the handle's container, glide to their new places. All of it runs on one shared motion and starts together, under every pointer; under Reduce Motion nothing travels. A row without anitemKeychanges at once, and without the handle the whole list does. (#8106) -
While a reorderable
Listrow is in reorder mode, a hint anchored to its handle, in the keyboard hint's layer and theme roles, shows the moves and Done. Each is a button that does what its key does and leaves the focus on the handle, so a row can be reordered by taps alone: the handle, the moves, then Done. (#8139) -
createReorderable({onReorder, isReorderable})makes a collection's reorder behavior, andListtakes it asreorderable: eachListItemwith anitemKeygets a reorder handle at its end, and each committed move callsonReorder({key, to})once, with the row's key and its index after the move. On a touch screen a finger held still on a handle picks up its row the way an iOS table's reorder control does (a flick on it still scrolls): the row stays in its place, dimmed, while a copy of it follows the finger and an accent line marks where it would land; the other rows stay still, the page scrolls near the edges, and on release the rows rearrange, gliding to their new places. A pen held on a handle picks up its row the same way where the primary pointer is coarse. A mouse, or a pen where the primary pointer is fine, drags a handle at once with the same copy and line, and rows take their places without motion; a cancelled drag puts everything back at once. Without a drag, a click, Space or Enter on a handle turns on reorder mode for its row: the insertion line marks the row's place, each arrow key moves it a place at once, announced with its place and neighbours, and Escape or another activation ends the mode, keeping the moves. The object'sstart(key)enters the same mode from the app's own UI, such as a row's context menu. A List withoutreorderableloads none of the reorder code. (#8139) -
A
ResizeHandlethat any pointer pulls past the maximum, or under the minimum, of a region whose pane aLayoutPanelrenders now moves the handle with resistance, at most about 8 px past the limit and over the content beside it, while the panes keep their sizes, and the handle springs back to the limit after the lift. A panel sized by the region'ssizealone stops at the limit. A collapsible region no longer collapses mid-drag: only the lift collapses it, when the pointer is pastcollapsedSize, or released fast enough to come to rest past it, and aLayoutPanel's pane slides shut on a spring from the release velocity. Any other lift under the minimum returns to the minimum. A pointer that grabs the handle again catches it where it shows. Arrow keys still stop at the limit. Reduce Motion lands both at once. (#10292) -
Tables can window fixed-height flat data: pass
useTableRowsVirtualization({rowHeight, initialViewportHeight})toTable.virtualization. Table keeps the complete data and row identity, mounts only the rows in its viewport plus a few overscan rows, keeps native table semantics with full-table row positions, keeps the focused row mounted, and falls back to rendering every row for content or geometry it cannot window. Tables that do not opt in are unchanged. (#8280)Also released in
@astryxdesign/cli. -
useTableRowsVirtualization'sviewportHeightis renamedinitialViewportHeightbefore the hook's first stable release. It only sizes the first window, on the server and before the viewport is measured; it no longer sets the Table's height. A windowed Table scrolls inside the height its parent gives it, so give the parent a height.rowHeightis unchanged. (#10894) -
Table plugins can now read where a row sits. Table passes each body row and cell transform an immutable
TableRowContext(the row's key, its zero-basedlogicalIndexin the complete data, the row and header counts, and the row model). It passes the scroll-wrapper transform aTableRenderContextwith a stableviewportreference. A plugin declaresrowModel: 'flat'when its body transforms keep one row per data item.useTableSelectionanduseTableStickyColumnsdeclare it.useTableRowIndex()without options now numbers rows from the context (passingdatastill numbers from that array), and rows that move re-render only for plugins that read the index. Read context values during the transform; a later read from a callback warns in development. The CLI's numbered-rows block no longer passesdata. (#10171)Also released in
@astryxdesign/cli. -
Windowed tables stay windowed with row selection and row numbers. A windowed row-number column widens to fit its last number before that row mounts, at the table's font and density, and pinned columns after it move with it. (#10658)
-
Under the touch presentation, ToggleButtonGroup tracks a finger's or a pen's press across its toggles, like a menu. Press a toggle and slide across the others: the highlight follows, and only the toggle you lift on changes. Lifting outside the group changes nothing. A mouse press is unchanged: it acts as a native toggle's, on the toggle it began on. With a finger, a toggle the group tracks keeps its 44 px target, now drawn by the group. A toggle without a value keeps its own press, and the keyboard is unchanged. Before, each toggle tracked only its own press, and sliding off it changed nothing. An enabled ToggleButtonGroup root is position: relative under a coarse pointer, so absolutely positioned children anchor to the group. With a fine primary pointer, the group is unchanged. (#8660)
-
Under a coarse primary pointer, expanding a
TreeListrow glides the rows below it to their new places on the shared layout glide while its children fade in on the same timing, so the tree moves as one. A collapse fades the children out as the rows below glide up, and the chevron turns on that timing. The rows used to appear and leave in a single frame. Without ananimatedLayouthandle the motion stays inside the tree, so content after the tree takes its place at once, and the tree clips its bottom edge while it moves so no row paints over that content; pass a handle for it to glide too. The guide lines beside a group now show and hide with its rows. With reduced motion on and a finger, the children fade in where they land. With a mouse the rows still change at once. Under every pointer, a guide line now ends at the last row it joins instead of running on beside an expanded last row's children. (#8088) -
BaseTypeahead takes
menu, which chooses what its anchored menu shows while Astryx keeps the layer: its position, top layer, outside press, Escape, focus return and ARIA.{role: 'listbox', render}places information such as a header or a key hint around the result list, and anything a person acts on stays a result, so the arrow keys reach it (a control outside the list warns in development).{role: 'dialog', label, render}shows content that takes focus in a dialog named bylabel; closing it returns focus to the element focused when it opened, or to the input. A newhandleRefexposesopen()andclose(), andonOpenChangereports each change; there is no controlled open state. Callingopen()fromonChangekeeps the menu open, so a pick can switch the list to a dialog on the same layer. Typeahead forwardsmenuandhandleRef. (#10544)
-
a month position past the end of a Gregorian-aligned calendar's year constrains to that year's last month in calendarMonthFromYearMonth and useCalendarDays, instead of returning a NaN CalendarMonth and laying out the next year's January (#10461)
-
Declare renderer-owned DOM boundaries so decorator overlays mount outside managed content without changing safe inline hosting. RichTextEditor also mirrors its
dirprop onto the wrapper around the editable surface, so the editing surface and its content blocks, the placeholder, UI rendered throughplugins, and relocated overlays followdir; the editing surface previously kept the surrounding direction. (#7633)Also released in
@astryxdesign/richtext. -
On Android, text follows the reader's system font scale in every theme with no setup, in browsers that report
env(preferred-text-scale)(verified on Chromium and on Chrome stable). The rootThemereadsenv(preferred-text-scale)and scales every font size by it, as it already follows Dynamic Type on iPhone. Before, the system font scale reached Astryx text only when the page added<meta name="text-scale" content="scale">. A page withcontent="scale"keeps working as it did: its root font size carries the scale, and the rootThemeadds none. Browsers without either see no change.astryx docs typography/type-scaledescribes it. (#10727)Also released in
@astryxdesign/cli. -
Motion: in WebKit on Linux, the last frame of an
animatedLayoutchange shows where each motion ends once a frame has drawn the motion near its end. Under load, that frame, and every frame of a long task over its end, could show a glide, an exit's fade or an indicator's turn part of the way through: a collapsingTreeListdrew the rows below 44 px back, its leaving rows half faded and its chevron mid-turn. A long task that starts before that frame, or a motion near its end only at its last keyframe, can still show it. At normal speed the motion is unchanged. (#10663) -
Motion: a Switch's value change mid-travel keeps the thumb's running speed. A rebase toward the new rest shifts the curve whole. (#10369)
-
Avatar: initials are drawn as generated content with empty alternative text instead of text, so axe's Label in Name check (
label-content-name-mismatch) no longer flags a link or button avatar that shows initials. The accessible name, the name tooltip and the initials' appearance are unchanged. (#10816) -
Under reduced motion, a
BottomSheetthat a finger's swipe dismisses fades out where the finger left it. Before, it jumped back to its open position in one frame and faded from there. With motion, the next open after such a swipe rises from below the screen again, instead of starting where the finger left the sheet. (#10925) -
BottomSheet: a drag reads its release velocity from Core's velocity tracker, on each event's own timestamp, also when a touch drag starts on the sheet's content. The release depends on the last two moves, so a move that reaches the page late earlier in a flick no longer slows the flick. A hold weighs on the first move after it, as iOS's filter does. Two rules differ from iOS: a finger that holds still for more than 40 ms before the lift releases nothing in motion, and a release needs two moves. (#10463)
-
A stacked
BottomSheetwhose close waits in a suspended transition takes over the dim when the sheet beneath it closes, so the page behind it stays dimmed. (#10776) -
BottomSheet: an open sheet that renders again no longer reads the viewport height. It keeps the viewport height that its
resizelistener reads, so a tap that renders the sheet again forces no style recalculation or layout in React's commit. The sheet's height, reserve and detents are unchanged. (#10363) -
Button: disabled buttons no longer render the native
disabledattribute. They stay focusable in keyboard tab order, keep focus when they become disabled while focused (a link Button, which becomes a<button>when disabled, still moves focus), and exposearia-disabled="true". All activation paths (mouse clicks, Enter, Space) and clickAction/onClick callbacks remain blocked without losing focus to the document body. A disabled named submit Button withholds its name sonew FormData(form, submitter)omits its value. A ButtonGroup whose members are all disabled (whether on the group or individually) keeps its one Tab stop instead of dropping out of the Tab order or giving every member its own stop, and Carousel's hidden scroll buttons are never Tab stops. Tests that asserttoBeDisabled()or:disabledshould query[aria-disabled="true"]instead. (#7906) -
A labelled
Buttongrows with its label when the text size grows: its height is its size, or one line of its label when that is taller, so the label stays inside the button. At the default text size Buttons render exactly as before, a caller'sheightstill applies, and icon-only buttons keep their fixed square. (#10588) -
Calendarday buttons grow with their numbers when the person's text size grows, such as a larger browser default font size. Their size is now a minimum, so a day's number stays inside its own tap target and a tap no longer lands on the day below. At the default text size nothing changes. (#10596) -
Under snap paging (
hasSnap={useSnapPaging()}), Carousel's edge buttons andhandleRef'sscrollNext,scrollPrevandscrollTomove the row through the paging, also from rest. A touch that catches such a move now leaves the row on a page, as a flick's settle does. On iOS a still touch used to stop the browser's smooth scroll between two items. (#10384) -
Under snap paging (
hasSnap={useSnapPaging()}), Carousel's edge scroll buttons and edge fades follow the row as it moves. They change in the frame where it leaves an edge. A flick used to leave them as they were until the settle ended and the row went back to native scrolling, so the start button came back about half a second after the row had visibly left the start. (#10359) -
ChatComposerInput: composing with an input method (for example Japanese or Chinese) right after picking a mention, inserting a token, or inserting text after a token now commits only the composed text. The composer places its caret inside the trailing text, not on an element boundary, so the first raw letter of the composition is no longer committed. Right after a mention pick, one Backspace now removes the mention with its space, and no stray line break is left. (#6423)
-
ChatLayout's scroll-to-bottom button now appears when
scrollRefnames the document's scroller and the reader scrolls the page up. The stream scroll also stops following there, so a streaming reply no longer pulls that reader back to the newest message. (#10779) -
ChatLayout with a
scrollRefnow rests the newest message above the fixed composer dock at the scroll's end. The message area's end padding holds the dock's height and follows it as the composer grows. (#10676) -
useChatStreamScroll'sscrollToMessagenow puts the message at the top of the viewport when the scroller is the page itself. It landed off by the page's own scroll. (#10781) -
CommandPalette stays open with no results when a search or bootstrap request rejects (#10675)
-
A Table, or a List with
edge="bleed", that is the first or last child of a rounded Card or Dialog that holds no other Table or bleeding List deeper inside now rounds with the corner it reaches, so the table's focus ring stays whole at the container's corners instead of being cut off. A bleeding List with a header rounds only its last row. Every other corner stays square: standalone, inside a square container or a wrapper element, between other content, at the top of a BottomSheet (below its grab bar), or while another Table or bleeding List sits deeper in the same container. (#10586) -
CodeBlock's "Failed to copy value to clipboard." announcement now uses the assertive live region instead of the polite one, as status announcements require for errors, so screen readers report a failed copy right away. A successful copy is still announced politely. (#10448)
-
A swizzled
Outline(or another copy that carries Core's Markdown plugin protocol) now type-checks against the package's Markdown plugins:MarkdownPluginEntryandMarkdownTransformcarry their node type on a shared, versioned key instead of a module-local symbol, so the package's and the copy's types match. The member exists only in types; runtime trust and claim checks are unchanged. No API changes. (#10641) -
A swizzled copy and the package now agree on the animated-layout handle, code-language values and snap paging. A handle from
useAnimatedLayoutpassed to a swizzledAppShell,List,Table,TreeList,CollapsibleorSideNavno longer throws when the layout changes, and those copies type-check: each brand is read through a registered, versioned key at runtime, and the types carry one optional brand member that is never present. No API changes. (#10576) -
Core registers every React context, and the English its components register, under a versioned key, so two copies of Core's modules on one page share them: a provider from one copy reaches consumers from the other, a layer boundary from either resets the layer-scoped contexts of both, and a component from either shows its English. A copy built against another version of a context keeps its own. No API changes. (#10233)
-
A swizzled component that carries Core's touch code, such as a swizzled
SwitchorSlider, now joins the package's gesture host, window input listeners, click guard, layer input holds and moving-element hit testing for the page instead of keeping a second set, so the copy and package components do not both claim the same touches. No API changes. (#10599) -
A swizzled
List,TransferListorListInputand the package now agree on acreateReorderableobject: its reorder machinery is read through a registered, versioned key. Before, a swizzledListfound no machinery on an object from the package and showed no reorder handles. No API changes. (#10741) -
A
DateInputorDateTimeInputwithpresentation="bottom-sheet"no longer causes a hydration mismatch when the server and the browser are on different dates. The closed sheet's calendar now renders right after hydration, once the browser's today is known. (#10400) -
Dialog: under React StrictMode, a
Dialogwith aDialogHeaderthat is first mounted open and then removed while open (rendered only while open) now returns focus to the element that opened it, instead of leaving focus on the page body. The opener is captured only on the closed-to-open edge. (#5642) -
Dialog: aDialogHeadertitle now takes focus only after the dialog is modal, also when the header mounts in the render that opens the dialog. When no other control asks for focus, initial focus now starts on the title in every browser. Before, a header with a start control, and any header in Firefox, started on the first control. (#10408) -
Drawer: a non-modal drawer (hasScrim={false}) that unmounts while it is open, for example one rendered only while open ({isEditing && <Drawer isOpen …>}) or removed with the rest of a view, now returns focus to the control that opened it instead of dropping it to the page. A modal drawer already did. (#9672) -
DropdownMenu: a finger's hold-slide-lift no longer flashes the focus outline on the menu button. When a held press opens the menu, the button takes focus first, so focus can return to it when the menu closes; that focus now shows the outline only after keyboard input. A keyboard open and close still show the outline on the button. (#10079)
-
Dialog, CommandPalette, BottomSheet, Lightbox, Drawer, MobileNav, Popover: Tab no longer escapes a modal through a radio group. The browser gives a same-name group of native radios one Tab stop: its checked radio, or, when none is checked, its first moving forward and its last moving backward. The focus region now finds its first and last stops the same way. Before, Tab from a group's checked radio left the modal for the browser's toolbar when the group ended the modal and that radio was not last in it, and Shift+Tab did the same when a group started it. Reported by @duytbp. (#10304)
-
Gestures: a finger's lift is read on the clock its moves came on. In WebKit on Linux, a page pointerup listener that runs long no longer makes a fast flick read as a resting finger, or a tap lifted in time read as a long press. (#10583)
-
HoverCardanduseHoverCardno longer open on keyboard focus of the trigger whileisOpen={false}is passed. The controlledfalsealready refused hover, but tabbing onto the trigger opened the card and reportedonOpenChange(true)against the owner's state; focus now takes the same refusal as hover. (#10181) -
HoverCard: a labelled card no longer puts
aria-haspopup="dialog"on a role-less trigger, such as text or a<time>. Such a trigger names the open card througharia-controlsonly; a button or link trigger still getsaria-haspopupandaria-expanded. (#10733) -
A
HoverCardrendered into another document, such as an iframe or a Picture-in-Picture window, now closes when Escape is pressed there, and Escape from inside the card returns focus to its trigger. Moving focus from the trigger into such a card also keeps it open. Before, the card read only the page's document, so Escape in the other document never closed it. The card now also ranks on the shared dismissal stack by its trigger's place, so a card whose trigger sits inside a focus-trap container takes Escape before that container, as the topmost layer. (#9592) -
HoverCardandTooltip: a controlledisOpen={true}(orisDefaultOpen) no longer strands the layer in the viewport corner when its trigger mounts with no layout box yet, for example inside aDialogthat has not calledshowModal()yet. (#5398)Dialogmounts its children before it opens (isOpengatesshowModal(), not rendering), so aHoverCardorTooltipinside one with a controlledisOpen={true}runs its show effect while the trigger sits in a still non-modal<dialog>and has no box. A trigger with no box is not a valid CSS anchor: the popover resolves to its fallback position in the viewport corner, and unlike a live layout change that resolution is not revisited once the trigger later gets a box.Layer'sshow()now opens immediately when the trigger already has a layout box (an empty one, such as a ContextMenu's cursor anchor, counts), so a menu or popover still opens in the same task as the press that asked for it. Only a trigger with no layout box (display: none, or inside a<dialog>that is not showing) waits: first for it to get a layout box and for its dialog to show, then for any running animation on the document timeline that ends on its own, on the trigger or an ancestor, to finish, so the layer anchors to the trigger's settled position and not to a mid-transition one. Paused, infinite, and scroll- or view-driven animations are not waited on.The box wait is driven by signals and polls nothing: a
ResizeObserverfor a trigger that gains a layout box, anIntersectionObserverfor a purelydisplay: inlinetrigger (such as the wrapper<span>of a text-only trigger), which aResizeObservernever delivers an entry for, and the enclosing dialog'sopenattribute andtoggleevent. A dialog counts as showing when it is open or shown as a popover, so triggers inside a non-modalDrawerstill open their layers. The wait has no time limit and ends when the trigger gets a box inside a showing dialog or the open is cancelled (a latershow()orhide(), or unmount). If the trigger element is replaced while waiting, the wait restarts on the new one, and a trigger that unmounts for good stops observing. Without a layout engine to wait on (noResizeObserveror no Web Animations API, as in jsdom) the layer opens immediately.A transient
nullthen same-element call on the trigger ref, as a combined ref utility makes when a handler changes identity, no longer removes and re-adds the element'sanchor-name, which could also leave an open layer stranded in the corner. -
Layers with an entrance input hold: a finger or pen that was already down when a light-dismissing layer opened, and lifts while it enters, now lifts through the hold's shield onto what is under it in WebKit, so the layer dismisses as it already did in Chromium. The shield leaves a small opening at each such press until it lifts. New presses during the entrance are still held. (#10398)
-
Layer: a light-dismissible layer that opens from a right click's
contextmenuevent stays open when that same press is released. Before, the release counted as a press outside, so a DropdownMenu opened throughisMenuOpenfrom a right click closed at once. A later press outside still dismisses the layer. (#10128) -
A popover taller than the room on both sides of its trigger keeps its top when the keyboard shortens it. The field being typed into stays under the caret. It used to jump below the trigger as the keyboard arrived, and back as it went. (#10497)
-
Once the keyboard caps a layer such as a popover, a scroll a person starts in it afterwards is no longer undone. On a busy page, the layer could scroll back to the focused field just after. A later keyboard change still brings the field being typed into back into view. (#10457)
-
A Tooltip, including a Slider's value bubble, no longer jumps to another side of its trigger in the middle of a scroll. Before, when a scroll carried the trigger toward the edge, the layer runtime took the Tooltip out of rendering for one forced layout so the browser would choose its position again, and it did this again on later frames of the scroll. Now the Tooltip has one fallback list from the start, and no option in it covers the trigger: it tries the opposite side first, then beside the trigger, then a side sized to the room. During a scroll, the Tooltip keeps its side: it is not checked or placed afresh until the scroll stops. In the first frame painted after the scroll stops (at
scrollend, or 150 ms after the lastscrollevent where the browser has noscrollend), it is checked once and moves to the side with room if it needs to. At a show, a remount or a size change it is checked as before. (#10439) -
A Tooltip's content scrolls by CSS alone, and nothing watches its trigger move. A Tooltip now has
overflow-y: autofrom its first frame, with no overscroll containment. It scrolls only while its content overflows, so a wheel over a Tooltip that fits still scrolls the page. Once a tall Tooltip has scrolled to its end, the next wheel moves on to the page, where before the page held. A Tooltip is now always a scroll container, soposition: stickyandscroll(nearest)timelines inside its content resolve against the Tooltip. The layer runtime no longer reads the Tooltip's scroll size after its trigger moves, and it no longer observes a trigger that moves without resizing. (#10472) -
A swizzled
LayerProvidernow shows the package's toasts: the viewport the package'sToastregisters renders in a copied provider's outlet, and the package's provider renders a copy's. Before, each copy kept its own registry, so toasts added under a swizzled provider never showed. The registry lives under a registered, versioned key. No API changes. (#10800) -
Layout: afalse,true, or empty-string slot, such asfalsefromisOpen && <LayoutPanel />, now counts as empty. The neighbouring regions move out to the layout edge, the same as when the slot is omitted, and withcontentWidtha closed side panel no longer stops the content area at the content-width frame. The docs now listchildrenandref, show how to hide a region, and say that landmark roles go on the region components. (#10500) -
LayoutContent: the edge away from a single start panel now takes the Layout-edge inset, sopadding={0}on the Layout makes it full bleed, and withcontentWidthits children end one Layout-edge inset inside the content-width frame, as they do without panels. Each edge now publishes the padding it applies, so a full-bleed child such as a Table lines up beside an end panel and under a header without a divider. A Layout nested under a header or footer without a divider keeps its own content spacing instead of taking the outer collapse. (#10516) -
A
Layoutwith nocontentWidthno longer caps itsLayoutHeaderandLayoutFooterat the viewport's width. In a frame wider than the viewport, such as a scrolling canvas or a wide embed, their content now spans the frame like the rest of the Layout. (#10715) -
LayoutFooter: adata-dividerattribute passed by the caller no longer replaces the divider state the footer reflects, so the content above a footer without a divider keeps its collapsed spacing, and a footer with a divider keeps its spacing above the line. The docs now listpaddingandref, and say that an unsethasDividerfollows the Layout'sdefaultHasDividers. (#10674) -
LayoutHeader: adata-dividerattribute passed by the caller no longer replaces the divider state the header reflects, so the content below a header without a divider keeps its collapsed spacing, and a header with a divider keeps its spacing below the line. The docs now listpaddingandref, and say that an unsethasDividerfollows the Layout'sdefaultHasDividers. (#10686) -
LayoutPanel: on an edge that takes the Layout's own inset, the panel now tells its children the padding it applies there. Children that read their container's padding, such as a full-bleedDivider,Table, orTabList, or a nestedLayout, now follow the panel's outer edge whenever the Layout'spaddingdiffers from the inner inset. Before, they used the inner inset: withpadding={6}a full-bleedDividerstopped 8px short of the edge, and withpadding={0}it ran 16px past it. The docs now say which edgehasDividerdraws on, that the Layout'sdefaultHasDividersdoes not apply, and thatpadding={0}is full bleed, and they listref. (#10774) -
Lightbox: a screen reader now hears the viewer's own messages while it is open. Moving to another item ("Mountain lake, 2 of 4") and zooming in or out are announced inside the open viewer; before, they went to the page behind the modal viewer, where a screen reader does not read them. The0key now returns a zoomed photo to its fitted size. The docs list the0key, and no longer say that the lightbox is only for images. (#10775) -
Lightbox's drag to close now plays at the theme's tempo, like the viewer's other motion. At the default tempo it plays exactly as before. (#10630)
-
An open Lightbox shows the nearest item when
indexordefaultIndexis NaN or a fraction between the first and last item. A fraction rounds to the nearest item, and NaN shows the first item. Before, the viewer rendered nothing for those values. (#10632) -
A reorderable
Listin its own scroll box keeps the dragged row under the pointer when a wheel during a mouse or pen drag scrolls the page, as a wheel at the box's end does. The wheel scrolls as before. (#10742) -
Markdown: each paragraph, heading, quote and list item lays out in the direction of its own text. A Hebrew or Arabic paragraph in a left-to-right page now starts on the right, and an English paragraph in a right-to-left page starts on the left. A block with no letters, such as digits, punctuation or an image, takes the page's direction from the
InternationalizationProvider, also inside a quote or list item that reads the other way. Lists, code blocks and tables keep the direction around them too, and the text in each table cell reads in its own direction. A numbered item that reads against its list shows its number beside its own text, and a table cell that reads against its table keeps the table's column lines and any explicit column alignment. A task list now keeps to the same prose width as other lists. (#10293) -
Menus: the arrow keys, Home, End and type-ahead now reach a disabled row in
DropdownMenu, its sub-menus,MoreMenu,ContextMenuandNavHeadingMenu, so a keyboard or screen-reader user finds the row and its description. The row takes focus, is announced as disabled, and Enter, Space or a click on it still does nothing and leaves the menu open. Opening a menu from the keyboard still lands on an enabled row. (#10160) -
DropdownMenu: a held mouse dragged from the trigger onto a row keeps that row lit. On a loaded page the menu's open focus could land after the drag reached the row and take the highlight back to the menu container until the pointer moved again. (#10590)
-
DropdownMenu: a menu that a mouse press opens stays open when that press is released quickly away from the trigger, or after the trigger moved away under the pointer. Before, the browser's light dismiss read that release as a press outside and closed the menu at once. A press released after the settle time outside the menu still closes it, and a later press outside dismisses it. (#10689)
-
Under a finger, the month and year wheels behind the calendar title in the DateInput and DateTimeInput bottom sheets now behave like the iOS date picker's: (#8209)
- Turning a wheel moves a chosen date to the new month and keeps its day, so October 15 becomes May 15. A day the month lacks becomes its last day, the result stays within
minandmax, and DateTimeInput keeps the time. A date thatdateConstraintsrefuses is not chosen; the calendar still moves. - With no date chosen, the wheels only move the calendar.
With a mouse, the wheels still move only the calendar.
- Turning a wheel moves a chosen date to the new month and keeps its day, so October 15 becomes May 15. A day the month lacks becomes its last day, the result stays within
-
Motion: elements that start moving from rest in the same frame now start at one time. Before, each element took its own reading of the clock in that frame, so items starting together, such as a carousel's pages as they settle, could start apart by as long as the frame callbacks between them ran. (#10584)
-
Motion: a spring retarget that the browser commits late, behind a busy main thread, now starts at that frame, from where the element is on screen. Before, it kept the clock of the call, so the element jumped to where the new curve had got to: 42 px back in one frame for a retarget behind a 200 ms block. Motion calls made in one callback now share one clock, so the children of a pager line up after a retarget. A retarget made inside a page's own frame or ResizeObserver callback now shows its new curve one frame later. (#10607)
-
MultiSelector: opening the closed list never highlights a disabled option. ArrowDown, Enter, Space and a press highlight the first enabled option in the order the list opens in, and ArrowUp the last, so Enter no longer lands on an option it cannot toggle. A list with search still highlights nothing when a press or Enter opens it. (#10820)
-
Carousel paging: a finger or a pen that lands on a row still settling after a swipe no longer reaches the item under it: no press highlight and no click, as on iOS. A mouse click is unchanged. (#10370)
-
Carousel paging: a finger or a pen that lands on the row during an edge button's move now stops it at the touch, as on iOS, instead of letting it run on for about 85 ms. The item under the finger still takes the tap. A mouse is unchanged. (#10545)
-
A page that a swipe releases now settles at the theme's
tempo, as the rest of its motion does: in aCarouselgivenhasSnap={useSnapPaging()}, and in aLightboxgallery. At the default tempo the settle is unchanged. (#8197) -
Pagination's ellipsis grows with a larger text size, as its page buttons now do throughButton. Its size is now a minimum height, so the "…" stays inside its own box. At the default text size nothing changes. (#10567) -
Paginationwraps its row when its controls don't fit, as at a larger text size on a phone, instead of scrolling the page sideways and pushing Next off-screen. Previous stays first and Next stays last. Beside other content in a flex row, Pagination can now shrink to its widest control and wrap at the default text size too, where it held one line before; give itflexShrink: 0throughxstyleto keep one line there. (#10552) -
parseColoranswersnullforconstructorand__proto__(in any case), as for any unknown name, instead of a truthy empty RGBA that made composed callers such as chartcolors.alphareturnrgba(NaN, NaN, NaN, …)(or#NANNANNANat full opacity) instead of the original string (#10468) -
A closed
Popover, and anyusePopovercomposition, no longer leaves a hiddenrole="dialog"with its label in the DOM. The surface stays mounted but carries the dialog role, name andaria-modalonly while open, so[role="dialog"]selectors and tests that include hidden elements find no dialog that is not on screen. The accessibility tree already omitted the hidden surface. Reopening restores them. (#10487) -
A dialog Popover starts focus on its first enabled tab stop. It skips a disabled control, lets an element that holds
tabindex="-1"yield to a later tab stop, and starts on its labelled surface when every control is disabled. Before, a DateInput or DateTimeInput calendar whose range starts in the shown month opened on the disabled Previous month button. Now it opens on Next month, or, in a one-month range, on the selected day, else today, else the first enabled day. Disabled controls stay reachable by Tab. (#10503) -
Under a finger, Popover's growth shows its content from its first frame. The growth starts at opacity 0.001 rather than 0: Chromium skips drawing a layer at exactly 0, so the first frames of a growth from 0 showed the popover without its content. No 8-bit pixel differs from transparent at 0.001. (#10757)
-
In PowerSearch's phone sheet, a date range is now picked on a calendar inside the sheet, instead of a calendar popover opening over it. The desktop editor popover is unchanged. (#10618)
-
PowerSearch's phone sheet now edits single and multiple choices with the standard RadioList and CheckboxList at their usual spacing, instead of its own 48 px rows, and its Operator radios put the radio at the start of the row, as every RadioList does. The choices use the shared touch band, so their touch targets are smaller than before. End, Home and Enter no longer pick a choice; the arrow keys and Space work as in any RadioList or CheckboxList. Adds a "Sheet presentation · realistic config" story that covers every value type. The desktop editor popover is unchanged. (#10608)
-
PowerSearch: a filter token's field and operator now come from one catalog message (@astryx.powersearch.token.fieldOperator, "{field}: {operator}" in English), and its full text, which also names its remove button and editor, joins that label and the value with another (@astryx.powersearch.token.labelValue, "{label} {value}"). A locale can reorder the parts and change the punctuation.PowerSearchTokenuses the same message. English tokens read as before, except that a filter with no operator text no longer shows a trailing colon. (#10437) -
Press feedback: a
pointerupthat carries nopointerId, such as a bare event a test helper or drag script dispatches, no longer throwsCannot read properties of null (reading 'live')when no press is held. It is ignored, aspointercancelalready does. (#10695) -
Inside a scroll view, a pressable's highlight now comes 150 ms after the touch, even when a busy page handles the touch late. Before, the wait started when the page handled the touch, so the highlight came late by that delay. This covers every pressable, and SegmentedControl, Switch, Slider and
usePressTrackercontrols, in a scroll view. (#10260) -
A theme duration token written with
calc()now times a press's release as the browser resolves it. Before, the release clock fell back to 175 ms while the fade played the token's value. (#10069) -
Two loads of Core's scroll-lock modules on one page now share one page scroll lock: closing the overlay that opened first no longer unlocks the page while the other overlay is still open. Text-selection locks, which a swizzled copy carries, are shared the same way, so a copy's release no longer restores a selection lock the package still holds. No API changes. (#10822)
-
useScrollableArea: an ancestor's inline
stylechange measures the scroll area again only when it changes the axis mapping or the boxes' existence (direction,writing-mode,display,visibility,content-visibility); a size change still reaches it through the resize observers. A BottomSheet writes its transform, and its scrim's custom property, on every input sample of a drag, and each write forced a full measurement (its computed-style reads and the scroll geometry) in the next frame, a style recalculation and a layout on every frame of the drag. (#10034) -
getContentPropsfromuseScrollableAreanow applies a caller'sxstyleinstead of leaking it to the DOM. (#6314) A viewport that lost overflow while focused drops its leftovertabindexas soon as it is blurred, and a focused viewport in another document keeps focus when it loses overflow.ScrollableArea's viewport also sheds the obsolete-webkit-overflow-scrollingand initial-value scrollbar declarations. -
Selector: when the options move or reload while the list is open, the highlight stays on its option instead of naming whatever option now sits at its old position. If its option leaves, the highlight moves to the next remaining enabled option after it, or the previous one when none remains after it, and with none left nothing is highlighted. (#10818)
-
SelectoranduseCombobox: opening a closed list starts on the selected option, as the WAI-ARIA listbox pattern asks, and never on a disabled option. Before, ArrowDown and ArrowUp opened on the first or last option even when it was disabled, and ArrowDown then Enter changed "Hard" to the first option. Now opening highlights the selected option when it is enabled. Otherwise ArrowUp opens on the last enabled option and ArrowDown, a press, Enter or Space on the first; with no enabled option nothing is highlighted. A search list opened by a press, Enter or typing still highlights nothing.MultiSelectoris unchanged. (#8868) -
A Selector whose trigger sits near the bottom of the screen now opens its list on screen. The selected-item overlay's clamp did not count the layer's viewport gutter, so near the bottom edge the browser flipped the list below the viewport and its last options could not be reached. (#10697)
-
In a searchable
SelectororMultiSelector, typing now clears the highlight, so Enter never picks an option you did not highlight. Before, the highlight kept its old position, which could point at a different option of the filtered list or at nothing. ArrowDown then starts at the first row: the first enabled match inSelector, and Select all or the create row when shown inMultiSelector. (#8871) -
Selector with
hasSearch: a required field no longer putsaria-requiredon its trigger, a button where the attribute is not allowed. The search field carries it while the list is open, and the closed trigger still announces "Required", through the field label or, when the label shows no marker, through its description. (#10878) -
SideNavno longer adds space below afooterwhen it has nofooterIconsand no built-in collapse button. The sidebar rendered an empty footer row there, and the gap of the sticky bottom area added space after the footer. The row now renders only when it holds the collapse button orfooterIcons, as the drawer already does. (#10721) -
Navigation rows grow with a larger text size. The shared nav item styles (
navItemStyles, used bySideNavItemand byTopNavItemand the mega menu in the mobile drawer) now take their size as a minimum height instead of a fixed one, so above 200% text a row's label no longer overlaps the next row, and its end content (such as a countBadge) stays inside the row. Collapsed rail rows keep their fixed square. At the default text size, TopNav drawer menu and mega menu rows with a description now fit their text instead of overlapping the next row; other rows are unchanged. A callerheighton these styles no longer brings a row below its size; overrideminHeightinstead. (#10550) -
Carousel snap paging: a stop that sits within half a step of the row's end is part of the last page, so a flick, a wheel or a key never rests a pixel short of the end, and a step back from the end moves a full step. (#10591)
-
Carousel paging: a row that narrows while a finger holds it now rests where the row ends, instead of short of its end by as much as it narrowed. (#10425)
-
Carousel paging: while the paging holds a row, the pager measures its pages and travel from the row's layout, as at rest. (#10860)
-
A
Stepkeeps its ownaria-currentover a caller's. Before, anaria-currentpassed to aStepreplaced the reflected value, so a step that was not in progress could be marked current and the in-progress step could losearia-current="step". Now only the in-progress step carriesaria-current="step", whatever the caller passes. No API changes. (#10640) -
Under a mouse, a key that cannot scroll a DateInput, TimeInput or DateTimeInput wheel, as Tab, no longer ends the wheel's key step. On a busy page, Tab right after an arrow key could commit the row the wheel was leaving. (#10924)
-
Table's column settings plugin keeps its active columns in state. When the table re-renders on its own after a render React discards, such as a suspended transition, it shows the committed columns. (#10911)
-
Table: three of its keyboard tab stops draw the theme's focus ring instead of the browser's default: the scroll wrapper once the table scrolls inline, and the tree plugin's row expander and expand-all toggle. A theme's--focus-outline-*tokens now reach them. The scroll wrapper's ring sits inside its box, clear of a bordered Card's border, so a Card no longer cuts off its edges (a Card's rounded corners still trim the ring's square corners); atdensity="compact"the tree toggles' ring sits inside the toggle, so the row does not clip it. The row-expansion, grouped-rows and filter buttons are unchanged. (#8873) -
Table: a row expansion panel with
panelVariant="muted"now paints its wash on its cell, so with ananimatedLayouthandle the wash slides in with the panel's content. On iOS Safari the panel's edge trailed the rows gliding below it for a few frames; now they stay together. At rest the panel looks the same. (#10403) -
A Table column-resize handle now announces its column's rendered width from the first render after layout, and its announced range always holds that width, also when the layout renders a column past its maximum or minimum width. Before, until a column was first resized, its handle announced the column's minimum width, so a screen reader read the wrong width. (#10593)
-
A Table column-resize handle on a column with no maximum width now announces a maximum at or above its value, so a screen reader no longer reads the width past ARIA's default maximum of 100. It uses the window's width as the stand-in maximum, as an unbounded Resizable region does, and announces its value in words, for example "133 pixels". A column with
maxWidthis unchanged. (#10577) -
A Table plugin's
transformScrollWrapperclassName now reaches the table's scroll container beside the wrapper's own class; before, the wrapper replaced it. (#10702) -
TableTree rows no longer carry
aria-expanded, which is valid on a row only in a treegrid. Each row's expand and collapse button still exposes its expanded state, and rows keeparia-levelfor their depth. (#10538) -
A swizzled
Tablenow honorsvirtualizationfrom the package'suseTableRowsVirtualization, and the packageTablehonors a capability from a swizzled copy. Before, each copy recognized only its own capability, so a swizzled Table rendered every row and its code failed to type-check. The capability is read through a registered, versioned key, and its type carries one required brand member that is never present at runtime, so only the hook makes a capability. Avirtualizationvalue the hook did not make now gets its own development warning. No API changes. (#10798) -
TabListtabs, including aTabMenutab, grow with a larger text size. Their size now sets a minimum height instead of a fixed one, so at 200% text and above a tab label is no longer clipped. At the default text size nothing changes. (#10534) -
TextInput, TextArea, NumberInput, DateInput, DateRangeInput, DateTimeInput, TimeInput, Tokenizer, Typeahead, PowerSearch, ChatComposer and RichTextEditor: when the primary pointer is coarse (a phone or tablet), the focus look shows at once, with no fade, so a tapped field repaints once while the keyboard rises. With a fine primary pointer, such as a mouse, a click and the Tab key keep the fade. ChatComposer's focus depth also shows at once under reduced motion, as the other fields' focus look already does. (#10611)
Also released in
@astryxdesign/richtext. -
TextInput: the clear button now runs
changeActionwith the empty value and shows the optimistic empty value and busy state, as typing does. The clear goes through the input's own change handler, soonChangeandchangeActionreceive a real change event (before,onChangereceivednullas its event andchangeActiondid not run),onChangeruns first, and itspreventDefault()cancels the Action. (#6425) -
A truncated Text or Heading mounts its tooltip on the first hover, tap or focus, not as soon as it renders, so a long table or list of truncated cells mounts no closed tooltip layers at load. The hover delay, the tap and the focus rules are the tooltip's own: a touch that becomes a scroll opens nothing, and a tap outside closes it. No visual change. (#10290)
-
Theming: a theme's
:activeoverride now follows the touch press model. With a mouse it still paints on:active. Under a finger it paints only while Astryx believes the press, so a themed control no longer flashes the theme's press color on the touch itself or while the page scrolls. (#10420) -
In Safari on iPhone, text follows the reader's text size (Dynamic Type) in every theme, branded included. Where the browser exposes that size through
font: -apple-system-body, as Safari on iPhone does, the theme's font sizes scale with the size the reader picked in Settings (Display & Text Size, then Larger Text), each size on the curve of the iOS text style it plays: body text like Body,heading-1like Title 1, display text like Large Title, with every role kept in order. A semantic size a theme fixes at a length, such as the 0.75rem supporting text of Butter, Stone and Y2K, scales on the curve of the step it reads by default. At the default size every font size is the theme's own; the family, spacing, line-height ratios and the root font size never change, text inputs keep their 16px floor on iOS, and browsers without the keyword see no change. There is no option, prop or document attribute: the rootThemereads the reader's size from a hidden element.astryx docs typography/type-scaledescribes it. (#10416)Also released in
@astryxdesign/cli. -
Themekeeps its runtime-injected CSS in the document until the last mountedThemeusing that theme unmounts. Before, theThemethat injected the CSS first owned the shared<style>tags, so unmounting it (a nestedThemearound a dialog that mounted first, for example) stripped the component overrides and prose defaults from every otherThemestill using that theme. Built themes, which import their CSS as a file, are unaffected. (#10178) -
TimeInputshows the stepped time after an arrow-key adjustment made while a typed draft is pending, and leaving the field keeps that step. Before, the text typed before pressing ArrowUp or ArrowDown stayed in the box while the committed value and the screen-reader announcement had moved on, and blurring re-parsed that stale text and committed it over the step, silently undoing it. (#10179) -
Timestamp exposes its details popup on the focusable time element. (#6298)
-
Toast: the viewport is each toast's only announcement owner. While an open modal hosts a top-layer viewport (the default), it announces each toast through that modal's own live regions, so a toast shown over a Dialog is announced once. Elsewhere it announces through the shared channel. A viewport rendered in place announces through
useAnnounce, which delivers inside an enclosing Astryx modal. The toast card is no longer a live region inside a viewport, including while a modal hosts it. (#7871) -
Tokenizer forwards
cancelto itssearchSource, so a newer search, closing the menu or the sheet, focus leaving the field, or unmounting cancels the consumer's in-flight search (for example, to abort its request). Previously the inline field wrapped the source to filter selected items and droppedcancel, and the bottom-sheet presentation never called it. (#8777) -
A
ToolbarwithcenterContentwraps its row when its lanes don't fit, as at a larger text size on a phone, instead of letting the center title spill over the buttons beside it and past the screen's edge. The end lane, and the center lane when it does not fit beside the start lane, move to a following line. The center sits at the toolbar's middle as before while each side lane fits in half of the width it leaves. In a narrow container, a centerTabListnow shows all its tabs and the row wraps, and its tabs scroll only when they are wider than the toolbar. (#10563) -
A controlled
Tooltipheld closed (isOpen={false}) no longer opens on keyboard focus or a click into a text-field trigger. It reports that focus asonOpenChange(true)and shows nothing, so the caller decides, the same way Escape on a held-open tooltip reportsonOpenChange(false)without hiding. Before, focus opened a held-closed tooltip anyway, and Escape could not close it.useTooltipreports the same focus throughonShowunderisOpen={false}. (#10490) -
on a touch screen, keys typed into a text field no longer make the focus a closing dialog returns to a Tooltip or HoverCard trigger open its layer; Tab, Escape and arrow keys still count as keyboard input.
useTouchTrigger'sisTouchInteraction()from@astryxdesign/core/Layerstays true in that case too. A field in an iframe or Picture-in-Picture window is not read as a text-entry field, so typing there still opens the tooltip as before. (#10639) -
A disabled
TopNavItemnow keeps its Tab stop, in both the bar and the drawer. Before, it rendered withtabIndex={-1}, so Tab skipped it and keyboard and screen-reader users could not reach it. Now it is a focusablelinkthat exposesaria-disabled="true", while a click, Enter or Space still runs noonClickoronKeyDown, does not navigate, and does not close the mobile drawer. No API changes. (#9208) -
TopNav's heading can now shrink, so a heading wider than the whole bar ends in an ellipsis instead of running off the bar and scrolling the page sideways.
TopNavHeadingkeeps its logo whole, and independently linked lines wrap and keep their longest word; a plain line beside them still keeps its full width. (#9551) -
TopNavwraps its bar when its regions don't fit one row, as at a larger text size, instead of letting the end content (such as buttons) cover the navigation items. The end content moves to a second line. While the regions fit, the bar and its centered content look as before. (#10571) -
DateInput's touch sheet keeps keyboard focus when the month reaches the end of the range, by an arrow press or a swipe, while a month arrow holds focus. That arrow hides there, so focus now moves first to the other month arrow, or to the month-and-year button when both arrows hide. Before, focus fell to the page. (#10231)
-
Toast: the
useToastfallback warning and its server-rendering error no longer tell you to wrap the app in<AppShell>. AppShell provides no layer context, so that advice left the warning in place. They now name only<LayerProvider>, which removes it. (#10875) -
With a mouse or trackpad, a date or time sheet's wheel no longer turns back to the row a key step is leaving. A key step commits its row at once and then scrolls there. On a busy page or a slow device the scroll could draw no frame for longer than the wheel's quiet period, or the browser could end it part-way, and the wheel took that pause for rest: it committed the row under the band and turned back there. A rest before the step's row is reached now finishes the scroll instead. A scroll a person makes still rests where it stops. (#10610)
-
Closing a Popover or DropdownMenu with Escape, or a DropdownMenu with a pick or a press on its trigger, runs one layout again, not two. A closed trigger stops being a CSS anchor, and these closes took the trigger's anchor name away after the hide's own layout, so the browser laid out once more. Our hide now drops the name before its layout, unless the layer's closed state keeps it shown to fade out. A close the browser runs itself, such as a light dismiss, still drops the name at its toggle event. A layer that fades out keeps the name until its fade ends. (#10346)
-
Popover, DropdownMenu and its submenus, Selector, ComplexSelector, PowerSearch and Breadcrumbs' menu play their entrance on the surface inside the layer, not on the anchored layer. Chromium laid the anchored layer out again on every frame of its 150 ms entrance, two to four times per frame, whenever the page had other frame work. The entrance looks the same.
layerAnimationsis unchanged; its docs now say to apply it to the surface. Applied to the layer, it still plays as before. (#10561) -
While a Tooltip or another anchored layer plays its entrance, most reads of the layer's box write no styles. Before, each read during the entrance overrode the layer's transform, read the box and put the transform back, so the browser recomputed style and layout twice in that frame (measured in Chromium: 8 style writes, 2 style recalculations and 2 layouts per read). Now a read on the middle frames of an entrance takes the entrance transform out of one box read by calculation, and gets the same box. The read that shows the layer and any read while its entrance is pending, a read whose box does not yet carry the entrance (in Chromium, a layer at a fallback position), the last frames of an entrance, a layer under a CSS
zoomother than 1, and atranslategiven as a percentage still use the override, as before. Placement, the entrance animation and the keyboard cap do not change. (#10240) -
Motion: a Switch at rest holds no compositing layer under a coarse pointer. Its colour fade and its lift's shadow take a layer only while they move. (#10542)
-
Motion: the motions that one callback starts on elements that came in the same task read their stylesheets'
will-changein one style pass, after the callback. Before, each element forced a style pass of its own: eight for a list whose eight rows glide together. (#10728) -
Under a finger, Popover plays its growth on the surface inside the layer, not on the anchored layer. Chromium restyles the growth's animations twice as they start and once as they end, and each restyle laid the anchored layer out twice, its backdrop included. Under load those layouts landed inside the growth. The popover looks the same. (#10717)
-
Under snap paging, a Carousel's release bakes the settle's keyframes once, not once per item, and plays the settle only on the items that can show. With 9 items the release takes about a third less main-thread time, and with 30 items about two thirds less. (#10568)
-
useTableRowIndex builds its number column once per plugin, so a parent re-render no longer re-renders every row of a table that shows row numbers. (#10654)
-
Truncating Text and Heading take a newly mounted element's first measurement from the shared resize observer's first notification, after the browser's own layout, instead of forcing a layout pass after each commit. Pages and windowed tables that mount many truncating texts commit faster; the tooltip behaves as before. (#10668)
-
The source header of
Layout/containerCorners.stylex.ts(shipped in the package) now says that the--container-corner-*variables Card and Dialog set are inastryx.css, undocumented, and read only by Table and List; it had said they stay out of public API. (#10701) -
Hook docs for
useCalendarConstraints, soastryx hook useCalendarConstraintsandastryx searchreturn it, and auseCalendarConstraints — Hotel Booking Rangeexample block: a booking range picker that enforces min/max dates, disables closed Mondays, and caps reservations at 7 nights once check-in is selected. Copy it withastryx template useCalendarConstraintsHookUsage <path>. (#10151)Also released in
@astryxdesign/cli. -
Hook docs for
useCalendarNavigation, soastryx hook useCalendarNavigationandastryx searchreturn it, and auseCalendarNavigation — Month Pagerexample block: a month-by-month calendar with Previous/Next controls, localized month-year header, and cross-month arrow key navigation usingpendingFocus. Copy it withastryx template useCalendarNavigationHookUsage <path>. (#10154)Also released in
@astryxdesign/cli. -
Hook docs for
useLinkify, soastryx hook useLinkifyandastryx searchreturn it, and auseLinkify — Links in a Comment Threadexample block: plain-text comments where the URL and email become Links and a custom#123issue-reference pattern shows the patterns option, while a comment without matches stays plain. (#9969)Also released in
@astryxdesign/cli. -
Add usePowerSearchConfig hook docs and a filtered directory table example block (#10660)
Also released in
@astryxdesign/cli. -
Add useTableColumnSettingsState hook docs and a column visibility picker example block (#10652)
Also released in
@astryxdesign/cli. -
HoverCard: a trigger inside SVG
<foreignObject>cannot be a CSS anchor in Chromium, so its card opens at the viewport corner. The docs now say so and show the fix: render the trigger in an HTML layer positioned over the SVG node. (#10908) -
LayoutPanel's JSDoc example wraps its Layout in aCardinstead ofLayoutContainer, a component Astryx does not have. (#10716) -
ChatLayout's guidance explains how a reply gets one right edge: Markdown prose keeps its 680px measure while code blocks and tables span the message column, so pass
contentWidth="100%"to the reply's Markdown. Markdown's default measure is unchanged. (#6608) -
useClickableContainer documents a pressable surface without Card chrome: the hook on the surface,
usePressFeedbackwithinteractionOverlayStyles.backgroundColorfor the hover tint and touch press, a visually hidden<button>or<a>as the named control, andfocusOutlineStyles.focusWithinfor the shared focus ring that ClickableCard draws. ClickableCard's docs point chrome-free use to it. (#10880) -
The
collapsible,collapsedSize,isCollapsedandonCollapseChangedescriptions in the Resizable anduseResizabledocs name what collapses a region, a lift or a key step under the collapsed size rather than a drag alone, and what reports a collapse change. (#10635) -
Section's docs show how to center it: set
marginInlineStartandmarginInlineEndto'auto'inxstyle. (#10207) -
SegmentedControl: the label contrast guidance says the track is translucent, so label contrast depends on the background behind the control, and asks you to check the labels on every background it sits on, including a custom page color. (#10882)
-
SideNavCollapseButton's docs now list every key its
collapsibleprop takes: the whole controlled config SideNav gets, not onlyisCollapsedandonCollapsedChange. (#10282) -
The
Skeletonradiusprop's description no longer says4is 16px.4maps to the same container radius as3(12px), so the two values draw the same corners. No behavior change. (#10750) -
Tab's docs show how to give a tab help text: anchor a
Tooltipon theTabthrough its ref, so the description lands on the tab, and put a decorative infoIconinendContent.endContentis documented as non-interactive: a button, link, orInfoTipinside it would nest a control inside the tab's button. (#10734)Also released in
@astryxdesign/cli. -
Tab's docs show how to run the selected indicator edge to edge in one strip: a nested
Themethat takes the app's color mode, extends the app's theme and setsinsetInline: '0'on thetab-indicatortarget, so other TabLists keep the default indicator. The override is best effort across releases. (#10814) -
TableSelectionToolbardocuments how to select every row that matches a query across server pages with today's API: the app keeps "every matching row minus exclusions" and passes the toolbar its own count and label. In this mode the toolbar'sselectedKeysholds only the loaded rows. (#10271) -
The Tailwind guide (
astryx docs styling-libraries/tailwind) adds a recipe for an app that already uses Tailwind: keep the app's own@import "tailwindcss", put the@layerline above it, and add the Astryx stylesheets after it. It explains why the@layerline must come before the Tailwind import: below it, the Astryx reset outranks every utility class, and nothing reports it. The Core README's Next.js + Tailwind section points to it. (#10532)Also released in
@astryxdesign/cli.
-
Internal: a ChatComposerInput source comment that restated the code is removed. No change to behavior or output. (#10811)
-
Internal: Core's internal touch entry re-exports the action-group tracking hook, which gains a no-paint option and press callbacks for Lab's TabBar. A tab-bar string joins Core's message catalog. Apps import nothing new. (#9699)
-
Internal: the undocumented
@astryxdesign/core/internal/reorderentry also gives Lab'sListInputList's reorder session for rows that are not ListItems:useListReorderScopeandListReorderScope.Listruns its own rows' session through the same session hooks, so its callers see no change. A ListInput string joins Core's message catalog. Internal entries are outside the public API and its compatibility promise. (#8163) -
Internal: the undocumented
@astryxdesign/core/internal/reorderentry lets Lab'sTransferListandTransferListSelectorreorder through acreateReorderableobject:adaptReorderableruns the owner's engine with the collection's own moves, and the owner'sstart(key)still finds the collection's list. ExistingListcallers are unchanged. Internal entries are outside the public API and its compatibility promise. (#8143) -
Internal: Core's internal touch entry re-exports its scroll test for Lab's TabBar. Apps import nothing new. (#10791)
-
Internal: per-instance warning deduplication and temporary focus targets each have one shared owner in Core. Resizable, Dialog and TabList dedupe their development warnings through it, and Chat's Done button parks focus through it. Warning text and focus behavior are unchanged; apps import nothing new. (#10655)
-
Internal: the More tab's label, a tab-bar string, joins Core's message catalog for Lab's TabBar. Apps import nothing new. (#10791)
-
Internal: Core's internal finger-scroll reader can answer for a past time on the page's clock, for Lab's NavigationStack scroll edge. Apps import nothing new. (#10540)
-
Internal: the undocumented
@astryxdesign/core/internal/line-clampentry gives Lab'sLineClampCore's focusable selector, the shared mutation observer and its flush, and the shared truncation tooltip. The shared mutation observer now passes each registration the records that reached it, and existing callers ignore them, so their behaviour is unchanged. Internal entries are outside the public API and its compatibility promise. (#4259) -
Internal: the layer's outside-press watch can follow chosen pointer types, close as a press that starts outside begins to pan (on either axis, at core's pan threshold) or when the browser takes it, and judge a press inside a closed shadow root, which the document sees as its host. No component passes these options yet, so every watch keeps today's behavior. Not exported from the package entry point. (#9814)
-
Internal: Popover keeps its chosen presentation (the sheet or the anchored layer, the touch grow or the pointer entrance) from the open until its close settles through the layer runtime's one presentation hold (Layer/presentationHold.ts). No behavior change. (#8587)
-
Internal: one owner module now turns the browser's scroll anchoring off on a container whose position a component owns.
useChatStreamScrolluses it while it follows the end, with the same behaviour as before, and the undocumented@astryxdesign/core/internal/scroll-anchoringentry gives its writer to Lab. Internal entries are outside the public API and its compatibility promise. (#10173) -
Internal: Selector and MultiSelector keep the presentation an opening chose, and a closing sheet mounted until its focus handoff, through the layer runtime's presentation hold (Layer/presentationHold.ts). No behavior change. (#8591)
-
Internal: Core's shared-realm module gains helpers for state that the package and a swizzled copy share (state, maps, stores, brands and sequences). No API or behavior changes. (#10817)
-
Timer's tick pipeline, format ladder, cadence switch, and resource cleanup were audited with no behavior defect found. Two previously untested guards are now pinned: the wait for a distant future
startTimeis capped at the 32-bitsetTimeoutceiling, and an unknownformatvalue coerces toelapsed. The Default story now asserts in a real browser that the display advances on its own. (#6609)
- In
RichTextEditor, Tab and Shift+Tab in a code block indent and outdent every line the selection touches, by the indent the block already uses (a tab when one of its lines starts with a tab, otherwise the fewest leading spaces of any indented line, kept between 2 and 8, otherwise 2 spaces). The selection stays on the same characters and each press is one undo step. Tab used to put a tab character in place of the selection, and Shift+Tab did the same. Escape then Tab still moves focus out of the editor. (#8579)
-
RichTextEditorAutoLinkPluginno longer turns a URL inside a code block into a link. A URL typed or pasted into a code block, or one in an imported fence, now stays code. Before, the link nested inside the code block, and the exported Markdown fence lost it. (#10664) -
In
RichTextEditor, pasting rich content into a code block inserts plain text: the plain text on the clipboard, or, when there is none, each pasted block as one line of its text. Headings, lists, tables, and formatting used to land inside the code block, where the Markdown export wrote them as plain lines of the fence, so the document read back differently from what the editor showed. (#8580) -
A link inside a disabled
RichTextEditorno longer navigates, shows no pointer cursor, and is not a tab stop. Before, a disabled editor's links acted as live links: a click or Enter opened them, and Tab stopped on each one. (#10679)
-
RichTextView,RichTextEditorToolbarandRichTextEditorAutoLinkPlugineach ship a doc file, soastryx component,astryx discoverand the docs list their props, defaults and usage. (#10407)Also released in
@astryxdesign/cli. -
A source comment in the editor theme now says that core
Markdowngives each block the direction of its own text, while the editor keeps blocks in the surface's direction. (#10293) -
RichTextEditor documents how to switch between reading and editing in place without reflow: set the field's inset and border outside the reading width with
xstyle, so every paragraph keeps its line count across the switch. A standalone editor keeps its form width. (#10429)
-
astryx discoverlists the Lab DialogHeroHeaderShowcase template from@astryxdesign/lab. (#10109) -
astryx discoverlists the Lab DialogHeroHeader component from@astryxdesign/lab. (#10108) -
astryxlists acreate…factory documented as a hook, such ascreateReorderable, with the hooks. (#8139) -
astryx docsalso opens a docs-tree node by its bare name, or by a route that drops the prefix its name repeats, when exactly one node matches:astryx docs tokens-colorandastryx docs tokens/colorboth opentokens/tokens-color. Two or more nodes answering one name still fail with the suggestions they always listed, and an experimental doc still opens only by its marked route. (#10387) -
astryx docs --depth <levels>now names the docs below each namespace on the topic list, by the route that opens them, so one read learns every route instead of one read per namespace. Without--depththe list is unchanged, and the JSON keeps its shape: the newchildrensit inside eachmeta.namespacesentry. (#10393) -
The official-packages discovery list now includes the Lab
LineClampcomponent, soastryxcan find and describe it. (#4259) -
Replace the theme showcase's custom layout, text and icon styling with Astryx components. The embedded preview paints the theme's body behind card-token surfaces instead of a surface-colored card band. The new standalone top-navigation shell uses the theme's surface canvas; the embedded view stays shell-free. Make demo inputs, cart feedback, inventory filters and chat respond locally, with clearable filters and no payment submission. Keep the template id, gallery visibility and demo content. (#10404)
-
Comments, a codemod note and the grouped-table template's sample data no longer use internal-format identifiers. (#10958)
-
astryx swizzle --listno longer lists Core's shared folders (animator,gestures,i18n,internal,keyboard,motion,privateAttributes,__tests__) as components. A copy ofgesturesimports@astryxdesign/core/motion, which the core package does not export. (#10185) -
astryx componentprints a theme warning as one line: control and format characters in the configuredastryx.themevalue or the generated theme record print as�, so a newline or an escape sequence in a checkout cannot rewrite the terminal. (#10764) -
astryx docs <topic>reads a topic authored as.doc.tsfrom an installed integration on every supported Node, and from a linked integration below Node 22.18. Topic and docs-tree files now load.tsthrough the same TypeScript loader as component docs, where a plain import failed undernode_modules("Stripping types is currently unsupported") and below Node 22.18 ("Unknown file extension .ts").astryx searchalso reads an installed.doc.tscomponent doc, so it finds the component by its keywords, shows its description, and lists a family's members..doc.mjstopics load as before. (#10763) -
A long-running process that calls the CLI's API, such as a docs site's search route, now reads an edited CommonJS
.doc.jsfile again in docs, search and template reads. It read the doc as first loaded. (#10760) -
A command that reads a project module again after changing it, such as
astryx integration addchecking the manifest it just wrote, now reads the change for an ES module.jsfile in a package without a"type"field. It read the module as first loaded. (#10745) -
Icon sets:
integration checknow accepts a generated declaration file (*.generated.d.ts) whose long type arguments a formatter such as Prettier re-wrapped. Before, the re-wrapped line made the check reporticon_generated_types_mismatchand fail. A changed declaration still fails the check. The experimental icon commands are unchanged. (#10898) -
astryx build: when an idea names a family only after its head ("a saml for a login") and the family's base template matches no other word, the variant that outranks the base now stays the start (login-sso, notlogin), so adding page templates no longer flips such ideas to the base. Ideas that name the family in their head ("saml login") start as before. (#10431) -
astryx experimental renderno longer dies silently with exit 139 when Node itself crashes while it renders a page. The page now renders in a separate process, so a crash (a crash signal, or a crash status on Windows) ends only that process, and the render fails withERR_RENDER_FAILEDand a message that names the Node version and path; a signal that stops it names them too. That process ends when the CLI ends, so a page that never finishes does not outlive a stopped CLI. Some Node builds crash inIntl.Segmenter, which components such as Avatar use to split text: on such a build the render runs the page once more withoutIntl.Segmenterand adds anode-crashwarning that names the Node build and says the output may differ slightly (a joined emoji, a flag, or a letter with a separate accent mark in initials), so pages with Avatar render again. (#10915) -
astryx searchputs the results that fit the whole query higher. The first result stays the same. At the default limit, and at any limit of 10 or more, the set of results stays the same. A smaller--limitshows the top of the new order, so it can show a different result. Below the first result, inside each group of equally strong matches, a result whose docs fit the query much worse than the others in its group moves after them. A result whose name spells two or more of the query's words never moves down; it can still move up. The fit uses the same word-meaning weightsastryx builduses to pick blocks, so a new component or template is placed from its own docs. A query that is an entry's whole name keeps its answer. (#10926) -
Every import in an
astryx swizzlecopy now names a file the copy holds or a path the owner package exports. Before, the copy sent every import that left the component folder to the package's folder entry, which does not export the internal helpers most components use, soButton,Dialog,Tableand about 100 other copies failed to type-check or bundle. Now the copy imports what the package exports from the package, carries every internal module it needs beside it in the package's folder layout, and copies the nested folders it imports (such asTable'splugins/). Test helpers and notes are no longer copied. A helper an earlier swizzle wrote is reused when it is the same and is never replaced by a copy that carries it, even with--overwrite: a different one stays, and the new copy writes its own under a version-suffixed name. Swizzling the component whose folder holds that helper treats it as one of that component's own files, which--overwritereplaces. A private attribute owner module and the style modules it imports are the exception, as before: a changed copy fails the command without--overwriteand is replaced with it. Fixes #3506. (#10197) -
A swizzled component whose source imports another Astryx package's internal module, such as a Lab component that uses Core's gesture primitives, no longer imports that private path, except a StyleX module that package exports, which the copy keeps importing by that path because its identity is its path. Swizzle carries every other such module, and what it reaches, into the copy under a folder named after its package (for example
components/astryx/core/internal/touch.ts); that package's public names are still imported from the package. (#10595) -
astryx swizzlereports the npm packages a copy imports, such asd3-scalefor a chart, with the version range the owner package declares, so the copy builds once you install them. Theswizzle.copyreceipt lists them independencies, and the text output names them to install. Node's built-in modules and the owner package itself are not listed. (#10502) -
astryx swizzlewrites anastryx-swizzle.jsonmarker into an output folder it owns (one the copy creates, an empty one, or one it marked before), naming each package the folder's copies came from and its version.@astryxdesign/build's Babel, PostCSS and Vite integrations, andwithAstryx()under webpack, compile the copies under that folder belowastryx-theme, so a theme's component overrides reach a swizzled component as they reach the package component. For a folder that already holds other files it writes no marker and says what it found and how to add the marker by hand; theswizzle.copyreceipt reports this in a new optionalmarkerfield. Under Turbopack and with the stock StyleX plugins, a copy's styles still land above the theme. The marker is not listed among the copy's files. (#10483)Also released in
@astryxdesign/build. -
The
table-filtertemplate's link-style header actions setminHeight: 0with their auto height, so no minimum holds them taller than their text. (#10588) -
astryx template <name>puts the template a typo slips from first in its suggestions: a name one or two slips away (a letter added, dropped or changed, or two letters swapped, as inAppShellCotnentOnlyordasbhoard) ranks just below the templates that carry every typed word. The suggestion list is never longer than before. (#10712)
-
A new
Course Detailpage template: a long-form sales page for a single offering in two columns — the long read (a preview poster with a fact row, an about block with skill chips, a module syllabus whose sections collapse module by module, an instructor card, reviews with a scored-aspects panel, and a FAQ) beside a sticky enroll rail (the price with a compare-at, a self-paced or cohort start picker, and a weekly-pace slider that computes a finish date). Copy it withastryx template course-detail <path>. (#9753) -
The File Explorer page template scrolls its columns with
StackItemandHStackisScrollableinstead of custom overflow and flex styles, and names each column after the folder it lists while the column scrolls. Its chevrons now mirror in right-to-left, and a detail pane scrolled to its end keeps its bottom padding. (#10421) -
A
useInteractiveRole — One Tile, Four Rolesexample block for the existing hook docs: a polymorphic Tile rendered four ways — href link, onClick button, Popover-trigger context button, inert content — showing the resolution order in one place. (#9972) -
Fix the
useStreamingText — Streaming Responseexample block: it passedisStreamingasfalse, so the streaming reveal it exists to show never ran. The block is now a chat-style reply card with a Regenerate button that streams the response in bursts — the hook reveals it steadily while streaming and snaps to the full text when it ends. (#9975) -
The grouped table page template groups its rows with
useTableGroupedRowsinstead of hand-rendered header rows and a hand-writtencolgroup. Its columns now have headers, each group's toggle is a button that reports whether its group is expanded, and the row menu's Move to project arrow mirrors in right-to-left. (#10423) -
The
useInputStatusIcon — Coupon Code Statusexample block's field appliesinputWrapperStyles.textField. A field copied from it now shows its focus look at once when the primary pointer is coarse, as Core's text fields do. (#10649)
-
Internal: doctor.mjs and template.mjs are formatted with Prettier. No change to any command's output. (#10988)
-
Internal: the icon-set export reader reuses the shared top-level helper, and a source comment on look refreshes is shorter. No change to any command's output. (#10449)
-
Internal: the doc importers import each doc file through one small module that the CLI's own test project loads natively, so its tests no longer time out on a busy machine. No change to any command's output. (#10740)
-
Gothic: accent text and accent icons stay readable on a light media surface. They used Gothic's light accent there, near-white on a light band (1.14:1); now they follow the surface's dark accent (18.7:1 against a white surface). The CLI's Gothic theme template carries the same change. (#10852)
Also released in
@astryxdesign/cli(templates). -
Neutral: an unselected SegmentedControl label meets 4.5:1 in dark mode on AppShell's surface. The track is translucent, so it lightens the surface under the label:
#9e9e9eon#3c3c3cmeasured 4.11:1. The label now takesneutral.dark[80](6.46:1), the same lift Neutral already gives secondary text on its selected rows and pills. Light mode is unchanged, and the CLI's Neutral theme template matches. (#10881)Also released in
@astryxdesign/cli(templates). -
Matcha: light-mode secondary text is slightly darker (Neutral Light 30), so it meets 4.5:1 on the body (5.11:1, was 3.83:1), the surface and the card. (#10932) [fix] Y2K: light-mode secondary text is slightly darker (Neutral Light 35), so it meets 4.5:1 on the Periwinkle body (5.14:1, was 4.25:1). The CLI's Matcha and Y2K theme templates match.
Also released in
@astryxdesign/cli(templates). -
The Butter, Stone and Y2K themes set supporting text (
--text-supporting-size) in rem instead of a fixed 12px, so it grows when a reader raises the browser's default font size, like the rest of the text. At the default size it is still 12px. The CLI's copies of these themes match. (#10320)Also released in
@astryxdesign/cli(templates).
- A swizzled copy can now compile as Astryx source in the Babel, PostCSS, and Vite integrations. Every module under a folder that holds an
astryx-swizzle.jsonmarker gets the library class prefix and lands in@layer astryx-base, belowastryx-theme, so a theme's component overrides reach it.astryx swizzledoes not write the marker yet: add the file to the swizzle output folder. Under webpack,withAstryx()rebuilds a cached copy when its marker appears or disappears. Turbopack builds do not read the marker yet. No API changes. (#10334)
-
Butter's buttons take inline padding only and use
Button's own block padding. Their height is unchanged. (#10588) -
Theme packages publish the declarations of their
./theme.cssexport. The export pointedtypesattheme.css.d.ts, which the package didn't ship, so TypeScript found no types forimport '@astryxdesign/theme-<name>/theme.css'. The export is unchanged; the file is now published. (#10903)Also released in
@astryxdesign/theme-chocolate,@astryxdesign/theme-gothic,@astryxdesign/theme-matcha,@astryxdesign/theme-neutral,@astryxdesign/theme-stone,@astryxdesign/theme-y2k. -
Theme packages declare
"type": "module", so bundlers and Node read the./builtentry as the ES module it is. Before, it was an ES module in a.jsfile in a package without atype, which tools that follow the package'styperead as CommonJS. Every export subpath stays the same. The CommonJS build of the source entry is nowdist/source.cjsbehind the samerequirecondition, with its own CommonJS declarations (dist/source.d.cts), so TypeScript types each condition in the format it loads. As before,require('…/built')loads an ES module, so it needs a Node version withrequire(esm)(22.12 or later). Deep imports that reach pastexportsintodist/change too:dist/source.jsis nowdist/source.cjs, and arequireofdist/<theme>.jsgets an ES module (require(esm), Node 22.12 or later). (#10876)Also released in
@astryxdesign/theme-chocolate,@astryxdesign/theme-gothic,@astryxdesign/theme-matcha,@astryxdesign/theme-neutral,@astryxdesign/theme-stone,@astryxdesign/theme-y2k.
- If your bundler lowers CSS
light-dark(), media surfaces in themes other than Gothic may lose their color overrides, which can make accent text low contrast. This will be fixed in the next stable release. Gothic does not have this issue in v0.7.12.
Thanks to everyone who contributed to this release:
@aashish254 @AKnassa @bhamodi @cixzhang @duytbp @emilyhorsman @ernestt @freddymeta @Geervan @harjothkhara @HelloOjasMutreja @humbertovirtudes @hurrymaplelad @imdreamrunner @jiunshinn @josephfarina @LetMeSleep8h @ManoharPaturi @mego1123 @parinith-web @potatowagon @rubyycheung @thecodebasedot @utkarshpatwa393-sys @Varshavia @vittoriobusatta @vjeux @WeAreResilience
Full Changelog: https://github.com/meta/astryx/compare/v0.7.11...v0.7.12
engine.io-client@6.6.8
- types: avoid MapIterator in generated typings (#5568) (b8b6ef0)
- honor Max-Age=0 and unparseable expiry attributes (#5585) (303a765)
- keep '=' characters in query values (#5574) (238db10)
- match cookie attribute names case-insensitively (#5589) (294ad42)
- @lazerg made their first contribution in https://github.com/socketio/socket.io/pull/5568
- @simpleqt made their first contribution in https://github.com/socketio/socket.io/pull/5585
- @NgoQuocViet2001 made their first contribution in https://github.com/socketio/socket.io/pull/5574
- @yxshee made their first contribution in https://github.com/socketio/socket.io/pull/5589
Thanks a lot to them!
ws@~8.21.0(no change)
v2.0.0-beta.3
The third beta of Leaflet 2.0 makes chained view changes like setView(c).setZoom(z) or panTo(c).panBy(o) end where you'd expect, makes adding and removing event listeners up to hundreds of times faster on busy maps, and validates coordinates so bad data fails where it's created instead of somewhere deep in rendering. It also brings a round of keyboard and screen reader fixes for markers, popups and controls, along with over 15 bug fixes.
- Make adding and removing event listeners constant-time: adding 50,000 markers with popups to a map takes 0.5 s instead of 15.6 s, and
on,off,onceandfireare faster in the common small cases too (#10537, #6914, #6923) - Position tooltips without measuring them, so maps with many permanent tooltips zoom without a forced layout per tooltip (#6948)
- Construct
Pointobjects ~40% faster, and the array and object forms ofPointandLatLng5–15% faster (#10550)
- Make view changes compose regardless of call order and timing:
setView(c)thensetZoom(z)(or the reverse) keeps both,panTo(c).panBy(o)ends atc + o, andzoomIn()calls during a zoom animation add up (#10549, #2609, #2915, #7766 by @Falke-Design) - Validate
PointandLatLngcoordinates, accepting numbers and numeric strings, and makePoint.validate()andLatLng.validate()match exactly what the constructors accept, so they can filter data (#10550, #7765 and #7767 by @johnd0e, #8214 by @Falke-Design) - Allow dragging the map during a zoom animation instead of treating the drag as a click (#8201)
- Let shift-drag pan the map and drag markers when box zoom is disabled (#2772, #6233, #7088)
- Honor
coords.zinTileLayer#getTileUrl, so it can build URLs for zoom levels other than the current one (#8849, #9201 by @yohanboniface) - Style
<button>and otherrole="button"elements inleaflet-barcontrols like links (#9462, @someonewithpc) - Support numeric strings and a partly automatic size like
[100, 'auto']iniconSize(#9253) - Add a
getEvents()hook to controls, like the one on layers: the map listeners it returns are added and removed with the control (#10229)
- Bring a focused marker to the front whatever
riseOnHoveris set to, so it's never hidden under its neighbors (#10536, #8078) - Return focus to the marker whenever its popup closes with focus inside it, not only on Escape (#10536, #8115)
- Set
aria-expandedandaria-controlson keyboard-accessible markers with a popup (#10536, #7527) - Move focus into a popup opened from a marker with the keyboard, and keep focus on a marker activated by a screen reader (#8113, #8114)
- Keep focus on a control after clicking it instead of moving it to the map (#7947)
- Make Space activate the zoom, layers and fullscreen buttons and the popup close button (#7369)
- Open tooltips only on keyboard focus, so a tooltip no longer appears when the window regains focus or a popup closes (#9150)
- Translate the default marker
alttext with thetranslatemap option (#10542 by @nfreear, #10541) - Raise the attribution and scale contrast to pass WCAG AA, with solid backgrounds and underlined links under
prefers-contrast: more(#6742, #7538, #10536)
- Fix tiles flickering during fractional zoom animations past a layer's
maxZoom(#8300, #8311 by @sbquinlan) - Fix polygons disappearing when
weightis a string (#6072, #7432) - Fix tooltip positions in right-to-left containers (#7201, #7782)
- Fix the expanded layers list sometimes being covered by other controls (#7944)
- Fix a dragged marker's
autoPanpanning pastmaxBounds(#10539 by @A350xt, #6219) - Fix
DocumentFragmentpopup and tooltip content being empty after the first open (#10540 by @A350xt, #3922) - Fix
setIconkeeping the size, anchor,bgPosandcrossOriginof the previous icon when the new one doesn't set them (#10538 by @b84330808) - Fix
fitBoundsandgetBoundsZoomzooming all the way in when the padding is larger than the map (#10544 by @jayhemnani9910) - Fix
overlaps()onBoundsandLatLngBoundsreturningtruefor a point or line inside the other bounds (#10547 by @xunguangzlj-cloud) - Fix a layer with a
NaNminZoomormaxZoombreaking the map's zoom limits (#10548 by @xunguangzlj-cloud, #8354) - Fix
togglePopup()andtoggleTooltip()throwing on a layer that isn't on the map (#10551 by @Enesuygurs) - Fix listeners added during
firebeing called by that samefire, a regression from 1.x (#10537) - Fix
setViewwithworldCopyJumpleaving the map outside the main world copy when it doesn't animate (#10549) - Fix
getCenter()returning a center snapped to whole pixels right after the map is created
- Mark the text that the
translateoption translates with a "Translatable" badge in the reference (#10546 by @Falke-Design) - Document the
flyToandpinchflags ofmoveandzoomevents (#9775), and how to stop control events from reaching the map (#10299)
LatLngandPointthrowInvalid LatLng object/Invalid Point objectfor coordinates that aren't numbers or numeric strings.null,''and booleans used to become0or1, and missing coordinates ({lat: 50}) gaveNaN. A non-numeric altitude throws too, andnullaltitude means no altitude instead of0.Pointconverts numeric strings to numbers instead of keeping them (#10550)- A non-numeric
radiuson a circle or circle marker throws, and a numeric string is converted to a number zoomIn(),zoomOut(),setZoom(),panTo()andpanBy()build on the view a running animation is heading to: two quickzoomIn()calls (or clicks on the zoom button) zoom in two levels.panByduring a zoom animation waits for it to end (#10549)riseOnHoveronly controls hover: focused markers always come to the front (#10536)- The attribution and scale controls have black text on a 90% white background, and attribution links are a darker blue (#6742, #7538)
Control#_refocusOnMapis gone.ZoomControl,ScaleControlandAttributionControladd their map listeners throughgetEvents(), andZoomControlandScaleControlno longer have anonRemovemethodTileLayer#_getZoomForUrltakes the tile zoom as an argument
cherry-markdown-vscode-plugin@0.4.0
-
feat(vscodePlugin): 统一上传配置、支持 PicGo multipart,并为重要行为变化提供一次性更新说明
- 上传配置按当前文档所属文件夹、工作区、用户、默认值的顺序读取。上传器地址和认证头整体取自同一层,避免项目地址混入全局认证信息。
- 配置无效时阻止上传并提示修正,不静默切换上传目标。
- 重要行为变化会显示一次性更新说明通知,可查看随插件打包的本地说明或打开上传设置,也可从命令面板重新查看。通知按重要变更标识记录,普通 patch、关闭通知和重载窗口不会重复提示;首次上线无法可靠区分新装和升级,因此首次启用都会提示一次。
- 仅记录扩展内部通知状态,不迁移用户设置,上传时的配置错误提醒继续保留。
CustomUploader.format支持binary和multipart,省略时仍使用原有的binary行为。- PicGo 2.4.0+ 用户可设置
ImageUploadMode=remote、format=multipart、fieldName=files继续上传;插件直接发送文件内容,自动生成表单边界和长度,不根据地址猜测协议,也不在失败后切换路线。 - 停止使用旧
UploadType、PicGoServer选择上传方式和地址,不提供旧路径列表或剪贴板协议适配。 - 仅有旧配置时,上传提醒会说明本地、Base64、远程三种新模式,并提供 PicGo 配置示例,可打开设置或配置说明;此过渡提醒计划在下一个 major 版本移除。不会自动修改或清理用户已有设置。
- 受限模式只允许用户级上传设置;用户可通过 VS Code 原生工作区信任界面授权,再使用项目配置。预览显示当前上传目标和配置来源。
- 原有手动主题继续保存在扩展状态中,不再自动读取或迁移已移除的旧主题设置。 @RSS1102(#1943)(
59de6c1)
-
feat(vscodePlugin): 支持跟随 VS Code 主题并在预览中搜索 @RSS1102(#1938)(
37e4600)
@cherry-markdown/milkdown@0.0.2
- feat: 优化链接浮层,支持直接打开、复制、编辑和取消链接,外观跟随 Cherry 主题。支持使用 Alt+F10 进入链接操作条,同时保留编辑器原有的 Tab 行为。调整链接编辑表单样式;取消链接可一次撤销,滚动或调整窗口时保留未保存的表单内容。 @RSS1102(#1929)(
44f6e87) - fix(milkdown): 同步 Cherry 的 URL 协议校验,阻止通过字符实体编码绕过危险协议检查 @RSS1102(#1947)(
372b561) - Updated dependencies [
1be27df,2318517,1e76861,8112362,b2cc414,464480b]:- cherry-markdown@0.11.13