feat: upgrade to Tasty v3 and ESLint plugin v1 - #1275
Conversation
Points `@tenphi/tasty` at the v3 snapshot build and applies the migration, so the v3 release gets exercised against a real design system before it ships. Not for release — the dependency is a snapshot. Result: the full test suite passes (1139 tests) and the type-error count is unchanged from main (13, all pre-existing and unrelated to Tasty). Migration: - `getCssTextForNode` -> `getCSSTextForNode`. - `Props` is no longer exported by Tasty. It was never a Tasty concept, just `Record<string, any>`, but the UI Kit re-exported it publicly — so it is now declared in `src/props.ts` and still exported from the package root, leaving the UI Kit's own API unchanged. - `Text` declares its own `block` prop. It came from Tasty's `BaseProps`, which v3 dropped as unconsumed; the UI Kit does consume it, as a mod and in the `'ellipsis | block'` style branch. - `Title` declares its own `inline` prop, deprecated. Same origin, but genuinely dead: `TitleElement` has no `inline` mod and hardcodes `display: 'block'`, so forwarding it only risked an invalid DOM attribute. Kept on the type, no longer forwarded. No style values needed changing — v3's one-value-per-directional-group rule is not violated anywhere in the codebase. The ESLint plugin stays on ^0.11.2: its v3 canary cannot be published yet, since npm trusted publishing for that package rejects the snapshot workflow's token. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 2e4ca4e The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
📦 NPM canary releaseDeployed canary version 0.0.0-canary-b7acb99. |
🧪 Storybook is successfully deployed!
|
🏋️ Size limit report
Click here if you want to find out what is changed in this build |
Size check fails — and it is a real finding, not noiseI measured both sides locally rather than bumping the limit, because this is the number the release should be judged on.
So Tasty v3 costs a consumer roughly 3.4–3.8 kB gzipped, and it lands on an entry that had only 0.39 kB of headroom. The dominant contributor is dev-warning strings. v3 adds a fair amount of diagnostic prose — the directional-syntax warning, the handler-displacement warning, the chunk-conflict warning — and those live in modules that ship in every bundle. They cannot be stripped, because I have deliberately not raised
That is a call for the Tasty release, not for this PR, which is why I left the check red rather than papering over it. Everything else is green: Tests & lint pass, Build & canary release passes, CodeQL and Snyk pass, Storybook publishes. Type-error count is byte-identical to main (13, all pre-existing). |
Tasty v3 costs +3.77 kB on the Button entry (117.61 -> 121.38 kB gzipped). Its new dev diagnostics — directional syntax, handler displacement, chunk conflicts — ship in every bundle, because isDevEnv() is evaluated at runtime so a single build serves dev and production. That entry only had ~370 B of headroom, which the file's own comment had already flagged as likely to trip next. Raised to 123 kB rather than higher, keeping headroom small so real bloat still trips the budget. The All entry is unaffected (450.33 kB against 460 kB). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Limit bumped in 83a3ec7 —
Headroom stays deliberately small (~1.6 kB) so real bloat still trips the budget, matching the file's existing philosophy. The old comment on that entry had already called it — "only ~370 B of headroom, so this one is likely to trip next even though it passes today." Also merged main in, so this is up to date with #1276. The +3.77 kB is Tasty v3's new dev diagnostics, which ship in every bundle because Remaining checks are the two Chromatic gates, which need a human to accept or reject the visual diffs — build #3645, 916 stories. That is the last unverified thing about this migration: unit tests and typecheck both came back identical to main, so I would expect zero visual changes, but only Chromatic can confirm it. |
Styles.stories.tsx had `inset: '2x bottom 4x left'` — the positional form v3 removes. Now `'2x bottom, 4x left'`. Verified against the v3 runtime that the comma form reproduces what v2 rendered (`auto auto 16px 32px`); the old form now drops the `4x` and renders `auto auto 16px 16px`, so this was a real rendering change, not just a lint warning. The linter had missed it. Story files were effectively unchecked, because a Storybook story's `args.styles` matched none of the plugin's detection heuristics — the enclosing variable is named after the story and there is no Tasty call. Fixed in tenphi/eslint-plugin-tasty#38, which is what found this. Enabling story linting also surfaced 12 color tokens declared in `src/tasty-augment.d.ts` but absent from `tasty.config.ts`, which the plugin reads — so they were reported as unknown. Added, with a note to keep the two lists in sync. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
0.0.0-snapshot.33e181d -> 0.0.0-snapshot.cdc961c. Picks up two things the older snapshot predates: the `fade: true` typing fix, and main's #251 injector change (remove injected styles in text-injection mode), which is a runtime change this branch had not yet exercised. Unchanged against the older canary: 1139 tests pass, 13 type errors (all pre-existing), zero tasty lint errors. Sizes move by under 0.5 kB (450.33 -> 450.81 kB and 121.38 -> 121.79 kB), both inside their limits.
Both packages are released, so this moves off the canary snapshots onto real
versions: @tenphi/tasty ^3.0.0 and @tenphi/eslint-plugin-tasty ^1.0.0.
The changeset becomes a `minor` and drops the "not for release" caveat — the
branch was previously pinned to 0.0.0-snapshot builds purely to validate the
migration ahead of the release.
Verified against the released versions: 1139 tests pass, 13 type errors (all
pre-existing), zero tasty lint errors, and both size entries inside their limits
(450.81/460 kB and 121.79/123 kB).
Plugin v1 lints Storybook `args.styles` and `styles={{…}}` JSX props for the
first time, so story files are now covered — which is how the `inset` violation
this branch fixes was found in the first place.
|
Both packages are released, so this is off the canaries and onto real versions:
The changeset is now a Verified against the released versions:
One thing worth noting: plugin v1 lints Storybook |
It was committed into this PR by accident — swept in by a `git add -A` in the size-limit commit, which is unrelated to it — and the design it describes is no longer wanted. Removed entirely rather than untracked: nothing references it, and it was never meant to be part of the v3 upgrade.
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
Brings in the palette rework (#1277) and the DatePicker period pickers (#1279). Three conflicts, all in build config: - package.json: keeps `@tenphi/tasty` at `^3.0.0` (the point of this branch, now resolving to 3.0.1) and takes main's newer `@tenphi/glaze` 1.3.0. - .size-limit.cjs: the two increases stack. main had already gone 118 -> 119 kB for the ~400 B that tasty 2.11.0 -> 2.11.2 added; v3 costs a further ~3.8 kB. Re-measured on the merged tree at 121.79 kB and set to 123 kB rather than carrying either side's number forward. - pnpm-lock.yaml: regenerated. Verified against main's own baseline: the 13 type errors are byte-identical to `origin/main`'s, so the merge introduces no regressions. 1200 tests pass (main added 61), zero tasty lint errors, both size entries inside their limits (451.54/460 kB and 121.79/123 kB). Notably main's new palette and DatePicker code had never been built against v3, and needed no changes.
CI caught what my local check missed: the `All` entry is 460,161 B against a 460,000 B limit — over by 161 B. Raised to 462 kB, keeping headroom small. My earlier local measurement was wrong. `size-limit` bundles the built `./dist/index.js`; it does not build. I ran it after merging main without rebuilding, so I measured a pre-merge bundle and read 451.54 kB instead of the real 460.16 kB. Added a note in the config so the next person does not repeat it.
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
Use `display` instead: `<Text display="block">`, `<Title display="inline">`. Both were inherited from Tasty's `BaseProps` until v3 dropped them, at which point this branch re-declared them locally. `display` already covers the case on every Tasty component, so a bespoke boolean per component is redundant. `inline` on Title was already inert — destructured and discarded, with TitleElement hardcoding `display: 'block'`. Removing it changes nothing at runtime. `block` on Text was real: it drove a mod feeding the `'ellipsis | block'` display branch. That branch is now `ellipsis` alone, so `<Text ellipsis>` still renders as a block — pinned by a new test, since folding that branch is the part most likely to regress. Verified before removing that `display` works on both components, and after that the removed props are type errors while `display` is accepted. No internal usages existed to migrate.
@cube-dev/ui-kit is pre-1.0 (0.154.1), so a major changeset would have jumped it straight to 1.0.0. Breaking changes ride in minors until then. `changeset status` now reports a single minor bump and nothing at major.
Do not merge as-is —
@tenphi/tastypoints at a snapshot build. This exists to exercise the Tasty v3 release against a real design system before it ships, and to show what the migration actually costs.Upstream: tenphi/tasty#227 · tenphi/eslint-plugin-tasty#38
Result
No style values needed changing. v3's stricter directional syntax — a group naming directions takes one value, so
padding: '2x 4x top right'becomespadding: '2x top, 4x right'— is not violated anywhere in this codebase. I verified that by running the v3 ESLint plugin oversrc/, not by grepping.Migration
getCssTextForNode→getCSSTextForNode— test helpers and the ESLint-plugin probe. Mechanical.Propsis no longer exported by Tasty. It was never a Tasty concept, justRecord<string, any>. Worth flagging: the UI Kit re-exported it publicly, so this would have been a breaking change for our consumers. It is now declared insrc/props.tsand still exported from the package root, leaving our own API unchanged. 16 files repointed.Textdeclares its ownblockprop. It was inherited from Tasty'sBaseProps, which v3 dropped as an unconsumed prop — but the UI Kit does consume it, as a mod and in the'ellipsis | block'style branch. Declaring it locally preserves the behavior.Titledeclares its owninlineprop, deprecated. Same origin, but here the prop was genuinely dead:TitleElementhas noinlinemod and hardcodesdisplay: 'block', so forwarding it did nothing except risk an invalid DOM attribute. Kept on the type so the public prop surface is unchanged; no longer forwarded.Two things worth knowing
The ESLint plugin stays on
^0.11.2. Its v3 canary cannot be published: npm trusted publishing for@tenphi/eslint-plugin-tastyrejects the snapshot workflow's OIDC token with a 404 on the final PUT, after the build and provenance signing succeed. Addingenvironment: releaseto matchrelease.ymldid not fix it, so the allowed-workflow list on the npm package needs updating. Once that lands, this PR needs one line changed.The old plugin does not flag v3 code (it validates the v2 at-rule spellings, and v3's kebab-case keys fall through an unconditional accept), so lint is clean either way — it just isn't validating anything v3-specific yet.
This PR found a regression in the v3 ESLint plugin. An earlier version of
valid-directional-modifierreported 20 errors here, every one a false positive:verticalAlign: 'bottom',textAlign: 'left',transformOrigin: 'top center',transition: 'left 0.2s, top 0.2s'. Direction words are ordinary CSS values for a long tail of properties, so the rule's property gate turned out to be load-bearing. Fixed upstream, with all 20 cases added as regression tests. That is the payoff for testing on a real project rather than a fixture.🤖 Generated with Claude Code
Note
Medium Risk
Minor semver API change for
Text/Titleprops plus a major styling dependency bump and intentional bundle size increase; behavior is covered by new display tests but consumers must update usages.Overview
Upgrades
@tenphi/tastyto v3 and@tenphi/eslint-plugin-tastyto v1, with the mechanical renames (getCSSTextForNode) and a localPropstype insrc/props.tsso the package still re-exports it after Tasty dropped it.Breaking API cleanup: removes
blockonTextandinlineonTitlein favor ofdisplay;Textellipsis still forces block display. Docs anddisplay-prop.test.tsxcover the migration.Registers 12 color tokens in
tasty.config.ts(were only in augment types), fixes Storybookinsetto v3 comma syntax ('2x bottom, 4x left'), and raises size-limit budgets (~462 kB full / ~123 kB tree-shake) for Tasty v3’s larger bundle.Reviewed by Cursor Bugbot for commit 2e4ca4e. Bugbot is set up for automated code reviews on this repo. Configure here.