Conversation
Scorched-earth removal of the entire v3 toolchain ahead of the v4 rewrite (see docs/v4-vision.md): Emotion 10 + onno-react components, babel, webpack 4, Storybook 5, CircleCI, and all associated config. The repo is reset to a clean slate for a framework-agnostic Tailwind v4 + tailwind-variants library. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Establish the v4 toolchain (see docs/v4-vision.md), ESM-only and framework-agnostic: - Bun 1.3 as package manager, test runner, and script runner - tsdown (Rolldown/oxc) as the library bundler — ESM-only, neutral platform - Biome 2 for lint + format in a single pass (CSS excluded; Tailwind v4 at-rules are hand-maintained) - TypeScript 6 (bundler resolution, verbatimModuleSyntax, strict + noUncheckedIndexedAccess) - Changesets for releases (public access, baseBranch master) - tailwind-variants 3 runtime dep; tailwindcss 4 peer - mise pins bun/node; publint wired via the validate script Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The v3 theme.ts is re-expressed as a Tailwind v4 @theme/@utility/@custom-variant stylesheet — the single source of truth for brand tokens. Validated end-to-end against the tailwindcss 4.3 compiler (116/117 candidate classes resolve; the lone 'miss' is the no-output `peer` marker). - ADD brand colors, fonts, fluid type (clamp, with paired line-height/tracking), raw leading/tracking scales, max-widths, namespaced easings - fluid spacing as a custom --space-fluid-* namespace driving functional @Utility families (p/px/py/m/mb/gap/...-fluid-*), exposing the full 0-6 scale - breakpoints ADDED namespaced (mojo-md/mojo-lg) so stock md:/lg: are untouched - z-stack as named @Utility (v4 has no --z-index-* namespace) - schemes via [data-scheme] runtime vars + @theme inline + @custom-variant - reset residue beyond Preflight only (th text-align, replaced-element max-width) - body-sm clamp corrected from the v3 source's invalid `+ -0.07vw` Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- src/tv.ts: brand-configured createTV() that teaches tailwind-merge about the custom scales (fluid type via the font-size group, fluid spacing across all padding/margin/gap groups via a fluid-step validator, brand max-w/w, z-stack) so recipe defaults and consumer className overrides dedupe predictably. Verified: every custom utility collapses to the override value. - src/tokens.ts: typed JS mirror of theme.css tokens (colors, schemes, fonts, fluid type/space scales, breakpoints, easings, zStack) for JS consumers. - add tailwind-merge as a direct dependency (tailwind-variants v3 peer) so consumers get predictable merging zero-config. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
flex, grid, gridSystem, autoGrid, wrap, section — the v3 layout components as tailwind-variants recipes. gridSystem/autoGrid keep their FIXED 24/48px gutters (gap-6/gap-12, not fluid) to preserve v3 behavior; responsiveness is hand-coded mojo-md: prefixes (responsiveVariants is gone in Tailwind v4). All emitted classes verified against the compiler. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
text, listItem, textLink. text maps size 0-5 to the fluid type scale (line-height and tracking ride on the paired theme tokens) plus the per-size bottom margin. listItem and textLink extend text via tv `extend`. textLink's underline is a currentColor gradient wipe; the v3 opacity:0 default (invisible link) is dropped as a bug. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
button, textInput, image, scheme. button is slotted (root + sliding shine) and fixes the v3 invalid `background-color: dark`. textInput is a JS-free floating label via the CSS peer + :placeholder-shown pattern, fixing the v3 always-0 label opacity. scheme applies the semantic bg/fg tokens that follow [data-scheme], replacing the v3 SchemeProvider React context. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- src/index.ts re-exports every recipe (+ its VariantProps), the brand tv/cn/cx authoring helpers, and the design tokens. - wire publint (--strict) + attw (esm-only profile) into the validate script. Verified end-to-end: tsdown build emits clean ESM + per-recipe .d.ts + a shared tv chunk + copied theme.css; publint passes; attw is green for ESM/bundler resolution; runtime smoke test resolves the barrel and subpath imports. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tailwind-variants always exposes a `base` slot; naming the primary slot `root`
left an empty `base` alongside it. Rename button/text-input's primary slot to
`base` so the returned slots are exactly { base, shine } / { base, input, label }.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- tokens.test.ts: pin zStack/colors/schemes/breakpoints against brand values - tv.test.ts: assert consumer className overrides win for every custom scale - recipes.test.ts: pin key recipe outputs (defaults, fixed gutters, CSS-driven float, fixed v3 bugs) + a 'no recipe class is purged' guard that compiles every class every recipe emits against the real theme - theme.test.ts: assert fluid utilities, paired type tokens, semantic scheme tokens, and brand+stock breakpoints all compile via the tailwindcss 4 API - tw-compile.ts: shared in-memory Tailwind compile helper 21 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- ci.yml: on push/PR, bun install + 'bun run check' (biome/tsc/test) + 'bun run validate' (tsdown build + publint + attw) - release.yml: Changesets action on master to open release PRs / publish to npm with provenance (OIDC id-token) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- README: framework-agnostic positioning, install, the REQUIRED @source step, React + Vue usage, schemes, the stock-Tailwind divergences, font-licensing note - AGENTS.md: architecture, toolchain, layout, commands, and the invariants (recipes return strings, static class strings only, no purged classes, mojo-md/lg prefixes, base slot, tokens in two homes) for agents/contributors Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v4: framework-agnostic Tailwind + tailwind-variants rewrite
A complete, breaking rewrite of
@mojotech/mojo-ui. It stops being a React + Emotion + onno-react component library and becomes a framework-agnostic design system: a Tailwind v4 theme plustailwind-variantsrecipes that returnclassNamestrings. The same recipe powers a React, Vue, or Svelte component the consumer writes and owns — no runtime, no framework lock-in, SSR/RSC-safe.Full design + migration cheat sheet:
docs/v4-vision.md.Highlights
master.)src/recipes/*.ts, 12 recipes (button,text,gridSystem,textInput, …), each exporting atv()recipe + itsVariantProps.theme.css— every v3 token re-expressed as Tailwind v4@theme/@utility/@custom-variant: fluid clamp type (with paired line-height/tracking), fluid*-fluid-*spacing scale, brand colors,mojo-md/mojo-lgbreakpoints (stocksm/md/lg/xl/2xluntouched), named z-stack, anddata-schemecolor schemes.AGENTS.mddocuments architecture, invariants, and how to add a recipe/token.Bugs fixed from v3
background-color: darkliteral → routed through theme colors.opacity: 0always (never visible) → CSSpeer+:placeholder-shownfloat, no JS.body-smclamp had invalid+ -0.07vwmath → corrected.Validated end-to-end (not assumed)
@utilitysyntax and every recipe class were checked against the real Tailwind 4.3 compiler — a test compiles every class every recipe emits (151 classes) so nothing silently purges.twMergeconfig proven: consumerclassNameoverrides win for every custom scale.bun run check(Biome + tsc + 21 tests) andbun run validate(tsdown build +publint"All good" +attw🟢 ESM/bundler) both pass.LICENSE + README + dist/only (ESM +.d.ts+theme.css), 54 kB.Deferred to follow-ups
Docs catalog (Storybook replacement),
examples/apps, the migration codemod, and@font-facefiles (Adobe Fonts licensing foraltis-mojoregular). Nothing is published — that's a Changesets call.Test plan
bun install --frozen-lockfilebun run check— 21 passbun run validate— publint + attw clean🤖 Generated with Claude Code