Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/tasty-3-5-0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@cube-dev/ui-kit': minor
---

Update Tasty to 3.5.0 (from 3.3.1). No changes were needed in the kit; two things matter to apps built on it.

**Injected CSS is garbage-collected again.** Once Tasty's render path became hook-free it stopped disposing the classes it injected, so their reference counts never fell back to zero and `gc()`, `cleanup()` and `tastyDebug.cleanup()` all read a non-zero count as "still in use". Nothing was ever evicted, and **a long-lived page accumulated injected rules for its entire lifetime** — the failure mode is a session that gets slower the longer it stays open, worst in a UI that mounts many short-lived styled subtrees (dialogs, popovers, table cells). What a style is worth keeping is now decided by the DOM: a sweep scans for the classes actually on the page, and only classes that are both absent from it and cold for longer than `gc.grace` (new, default 10s) beyond `gc.capacity` are deleted. Nothing is tracked per class while rendering, so collection costs nothing on the render path. `touch()` and the `StyleUsage` type are deprecated — both still exported, and `touch()`'s class-name argument is now ignored — and `tastyDebug` no longer reports `Unused: 0 classes` for a page holding hundreds of stale rules.

**Local `@keyframes` are content-addressed and owned by the classes that use them.** A `@keyframes` block written inside a styles object is emitted as `fade-<hash of its steps>` rather than `fade`, resolved identically by the client, the SSR collector and the RSC pass, and folded into the chunk's cache key. Two components that each author `animation: fade 1s` over _different_ steps therefore get two rules and two classes instead of one definition silently winning — which previously also let the server and the client disagree about which class to use. **If your own CSS or a test refers to a local keyframes name literally, it no longer resolves**; `keyframes()`-registered global animations are unaffected and keep their authored names. `holdKeyframes()` and `ownKeyframes()` come with it, re-exported from `@cube-dev/ui-kit`.

One 3.5.0 fix lands squarely on the kit as it now ships: since `Root` sets `batchInjection: true` and `Root`, `Portal` and `Overlay` each open a `TastyBatchProvider` window, a `tastyDebug` read taken inside one of those windows used to describe it as empty. Reads that reach into the registry rather than through an injector API now land the pending writes first, so debug output taken mid-commit is no longer blank.

Also in: styling overhead drops (from 3.4.0) — LRU cache reads are 1.79x faster in their steady-state shape, and a repeat SSR render of one component is 1.8x faster end to end now that `tasty()` factories memoize their chunk cache keys. A custom property declared with a whitespace-only value (`--brand-color: ;`) is skipped rather than read as an empty value, so it no longer auto-registers an `@property` off the strength of its name. Bundle: +1.21 kB on both the full import and a `{ Button }`-only import — matching deltas, which is what a change inside Tasty's always-included core looks like. Both stay inside budget, though `All` is now down to 1.40 kB of headroom, most of which the kit's own recent growth spent rather than this bump.
40 changes: 38 additions & 2 deletions .size-limit.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,37 @@ module.exports = [
}),
);
},
// Still 515 kB on `@tenphi/tasty` 3.3.1: 508.53 kB locally against 509.94 kB
// Still 515 kB on `@tenphi/tasty` 3.5.0: 513.60 kB against `main`'s
// 512.39 kB with both sides rebuilt here, i.e. +1.21 kB. The Button entry
// below moved by the same +1.21 kB, and matching deltas on both entries is
// the signature of a change inside Tasty's always-included core — here the
// DOM-scanning GC sweep that replaced the reference counting, keyframe
// ownership, content-addressed local `@keyframes` names, and the fuller
// `tastyDebug.summary()` accounting. 3.4.0 is pure performance (faster LRU
// reads, memoized chunk cache keys) and does not show up in either reading.
//
// That leaves only 1.40 kB, the thinnest this entry has been, and most of
// what ate it was not this bump: `main` had already climbed from 508.95 to
// 512.39 kB on its own (+3.44 kB of Board chrome, `tokens/resolve`,
// `useScheme`, TextInput `autoComplete` and the batched-injection wiring),
// leaving 2.61 kB before Tasty was touched. Left at 515 kB rather than
// rounded up: it fits, and the note further down wants the margin thin
// enough that real bloat still trips the budget. The NEXT change here
// almost certainly has to raise it — read the units note below first.
//
// Calibration worth keeping, against the macOS/Linux warning below: on the
// machine that measured this bump, the local reading matched CI EXACTLY on
// both entries. CI reported `main` at 500.38 KB and 118.96 KB binary, which
// is 512.39 kB and 121.81 kB decimal, and the local rebuild of the same
// commit read 512.39 kB and 121.81 kB. CI then measured this branch at
// 501.56 KB and 120.13 KB binary — 513.60 kB and 123.02 kB — matching the
// local readings above that the budgets were checked against. So the
// ~1.6 kB gap that warning describes did not apply here. Two entries on one
// machine do not retire the warning — still prefer CI's number — but a
// local reading is not automatically 1.6 kB light either, and assuming it
// is would have raised this budget for no reason.
//
// Before this: 515 kB on 3.3.1 too — 508.53 kB locally against 509.94 kB
// on 3.1.0 with both sides rebuilt here, i.e. -1.41 kB across the two
// releases. (508.95 kB after merging `main`'s cols x rows Board matrix,
// which is that feature's 0.42 kB and not the dependency's.) 3.2.0 added 0.69 kB for batched injection (the write queue and
Expand Down Expand Up @@ -146,7 +176,13 @@ module.exports = [
path: './dist/index.js',
webpack: true,
import: '{ Button }',
// Still 125 kB on `@tenphi/tasty` 3.3.1: 121.76 kB locally against 124.03 kB
// Still 125 kB on `@tenphi/tasty` 3.5.0: 123.02 kB against `main`'s
// 121.81 kB, both sides rebuilt here — +1.21 kB, matched by the same
// +1.21 kB on `All` above, so all of it is Tasty's always-included core and
// none of it ours. See that entry for what the release changed there, and
// for why a local reading was trusted here. 1.98 kB left.
//
// Before this: 125 kB on 3.3.1 too — 121.76 kB locally against 124.03 kB
// on 3.1.0, both sides rebuilt here — -2.27 kB, matched by the -1.41 kB on
// `All` above, so all of it is Tasty's always-included core and none of it
// ours. 3.2.0's batching cost this entry 0.68 kB; 3.3.0 then removed the
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
"@tabler/icons-react": "^3.31.0",
"@tanstack/react-virtual": "^3.13.12",
"@tenphi/glaze": "2.0.0",
"@tenphi/tasty": "^3.3.1",
"@tenphi/tasty": "^3.5.0",
"clipboard-copy": "^4.0.1",
"clsx": "^1.1.1",
"diff": "^8.0.3",
Expand Down
16 changes: 8 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading