feat(frontend): land Tamagui toolchain, swap ProgressBar off Radix (#580) - #701
Closed
gaidheal1 wants to merge 4 commits into
Closed
feat(frontend): land Tamagui toolchain, swap ProgressBar off Radix (#580)#701gaidheal1 wants to merge 4 commits into
gaidheal1 wants to merge 4 commits into
Conversation
) First real (non-PoC) landing of the Tamagui toolchain decided in #591 for the RN/Expo migration (#578), and the first sub-issue of #578 to ship: ProgressBar (#580) moves off @radix-ui/react-progress onto Tamagui's own Progress primitive (a genuine fork of Radix's, not a runtime wrapper around it - confirmed by reading @tamagui/progress's source and package.json before writing this). Toolchain, wired as permanent config rather than PoC scaffolding: - tamagui, @tamagui/core, @tamagui/config, @tamagui/vite-plugin, react-native-web added; @radix-ui/react-progress removed. - Pinned to the exact Tamagui version (2.6.0) the epic's PoC findings (#629, #583) are based on, rather than drifting to latest - avoids re-litigating verified findings against an untested version. (Latest, 2.7.1, also requires TamaguiProvider's new `defaultTheme` prop, which 2.6.0's types don't - another reason to stay pinned for now.) - tamagui.config.ts: @tamagui/config's default preset with breakpoints aligned to the app's own SCSS scale (sm/md/mdUp), per #629's findings. - vite.config.ts: @tamagui/vite-plugin's compiler wired in alongside (not replacing) the existing maplibre-gl static-copy workaround. - <TamaguiProvider> mounted at the app root (main.tsx) and as a Storybook global decorator, so future Tamagui-based stories don't each need their own wrap. ProgressBar.tsx: swapped Progress.Root for Tamagui's Progress with `unstyled` set, so ProgressBar.module.scss stays the sole source of visual truth - same role Radix's bare Progress.Root played. The fill stays a plain styled <div>, not Progress's own Indicator, matching the original's design (Radix's Indicator was never used either) and avoiding Indicator's transform-based positioning model, which doesn't match this component's percent-width fill. Found and fixed a real bug along the way, not just a test artifact: Map.tsx renders tooltip content (including ProgressBar, via #673's village-progress tooltip) into a second, independent React root (createRoot(host), for imperative position-tracking) that doesn't inherit main.tsx's <TamaguiProvider> context - React context follows the component tree, not DOM nesting. Without re-providing it at that second root, tapping a village marker would throw in production, not just in tests. Fixed by wrapping that root's render in its own <TamaguiProvider>. Verified: 448/448 unit tests pass (incl. Map.test.tsx, updated to wrap renders in TamaguiProvider), tsc --noEmit clean, lint unchanged from development's pre-existing 14 problems, production build succeeds. Bundle delta on the index chunk: +431 kB raw / +121 kB gzip (measured directly, both branches built with the same toolchain) - a bit above #629's PoC estimate (+383/+102), expected since this lands a real component on top of the fixed provider cost, not just the provider. Not verified: Storybook's browser-mode a11y suite (`vitest --project storybook`) - this sandbox lacks the chrome-headless-shell binary that provider needs, confirmed pre-existing by reproducing the same failure on unmodified development. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019tw1wbEwrW3EiTspfBt4RP
) First real (non-PoC) landing of the Tamagui toolchain decided in #591 for the RN/Expo migration (#578), and the first sub-issue of #578 to ship: ProgressBar (#580) moves off @radix-ui/react-progress onto Tamagui's own Progress primitive (a genuine fork of Radix's, not a runtime wrapper around it - confirmed by reading @tamagui/progress's source and package.json before writing this). Toolchain, wired as permanent config rather than PoC scaffolding: - tamagui, @tamagui/core, @tamagui/config, @tamagui/vite-plugin, react-native-web added; @radix-ui/react-progress removed. - Pinned to the exact Tamagui version (2.6.0) the epic's PoC findings (#629, #583) are based on, rather than drifting to latest - avoids re-litigating verified findings against an untested version. (Latest, 2.7.1, also requires TamaguiProvider's new `defaultTheme` prop, which 2.6.0's types don't - another reason to stay pinned for now.) - tamagui.config.ts: @tamagui/config's default preset with breakpoints aligned to the app's own SCSS scale (sm/md/mdUp), per #629's findings. - vite.config.ts: @tamagui/vite-plugin's compiler wired in alongside (not replacing) the existing maplibre-gl static-copy workaround. - <TamaguiProvider> mounted at the app root (main.tsx) and as a Storybook global decorator, so future Tamagui-based stories don't each need their own wrap. ProgressBar.tsx: swapped Progress.Root for Tamagui's Progress with `unstyled` set, so ProgressBar.module.scss stays the sole source of visual truth - same role Radix's bare Progress.Root played. The fill stays a plain styled <div>, not Progress's own Indicator, matching the original's design (Radix's Indicator was never used either) and avoiding Indicator's transform-based positioning model, which doesn't match this component's percent-width fill. Found and fixed a real bug along the way, not just a test artifact: Map.tsx renders tooltip content (including ProgressBar, via #673's village-progress tooltip) into a second, independent React root (createRoot(host), for imperative position-tracking) that doesn't inherit main.tsx's <TamaguiProvider> context - React context follows the component tree, not DOM nesting. Without re-providing it at that second root, tapping a village marker would throw in production, not just in tests. Fixed by wrapping that root's render in its own <TamaguiProvider>. Verified: 448/448 unit tests pass (incl. Map.test.tsx, updated to wrap renders in TamaguiProvider), tsc --noEmit clean, lint unchanged from development's pre-existing 14 problems, production build succeeds. Bundle delta on the index chunk: +431 kB raw / +121 kB gzip (measured directly, both branches built with the same toolchain) - a bit above component on top of the fixed provider cost, not just the provider. Not verified: Storybook's browser-mode a11y suite (`vitest --project storybook`) - this sandbox lacks the chrome-headless-shell binary that provider needs, confirmed pre-existing by reproducing the same failure on unmodified development. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019tw1wbEwrW3EiTspfBt4RP
….com/progressrpg/ProgressRPG into claude/issue-580-progressbar-tamagui # Conflicts: # frontend/.storybook/preview.tsx # frontend/package-lock.json # frontend/package.json # frontend/src/components/Map/Map.test.tsx # frontend/src/components/ProgressBar/ProgressBar.test.tsx # frontend/src/components/ProgressBar/ProgressBar.tsx
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.
Summary
First real (non-PoC) landing of the Tamagui toolchain decided in #591 for the RN/Expo migration (#578), and the first sub-issue of #578 to ship: closes #580.
ProgressBarmoves off@radix-ui/react-progressonto Tamagui's ownProgressprimitive — confirmed by reading@tamagui/progress's source that it's a genuine fork of Radix's Progress, not a runtime wrapper around it, so this actually satisfies "no@radix-ui/react-progressimport remains," not just an import rename.Toolchain (wired as permanent config, not PoC scaffolding)
tamagui,@tamagui/core,@tamagui/config,@tamagui/vite-plugin,react-native-webadded;@radix-ui/react-progressremoved.2.6.0) the epic's PoC findings (Spike: PoC Tamagui as the combined primitives + styling choice for #578/#591 #629, Replace Radix Tooltip — coordinate with the tap/click unification in #568 #583) are based on, rather than drifting to latest (2.7.1) — avoids re-litigating verified findings against an untested version. Latest also requiresTamaguiProvider's newdefaultThemeprop, which2.6.0's types don't — another reason to stay pinned for now.tamagui.config.ts:@tamagui/config's default preset with breakpoints aligned to the app's own SCSS scale (sm/md/mdUp), per Spike: PoC Tamagui as the combined primitives + styling choice for #578/#591 #629's findings.vite.config.ts:@tamagui/vite-plugin's compiler wired in alongside (not replacing) the existing maplibre-gl static-copy workaround.<TamaguiProvider>mounted at the app root (main.tsx) and as a Storybook global decorator, so future Tamagui-based stories don't each need their own wrap.ProgressBar
Swapped
Progress.Rootfor Tamagui'sProgresswithunstyledset, soProgressBar.module.scssstays the sole source of visual truth — the same role Radix's bareProgress.Rootplayed. The fill stays a plain styled<div>, notProgress's ownIndicator, matching the original's design (Radix'sIndicatorwas never used either) and avoidingIndicator's transform-based positioning model, which doesn't match this component's percent-width fill.A real bug found and fixed, not just a test artifact
Map.tsxrenders tooltip content (includingProgressBar, via #673's village-progress tooltip) into a second, independent React root (createRoot(host), for imperative position-tracking) that doesn't inheritmain.tsx's<TamaguiProvider>context — React context follows the component tree, not DOM nesting. Without re-providing it at that second root, tapping a village marker would throw in production, not just in tests. Fixed by wrapping that root's render in its own<TamaguiProvider>.This also means #580's "no in-app consumer" premise is now stale —
Map/MapTooltips.tsxstarted consumingProgressBarvia #673, merged after #580 was written. Worth a follow-up comment on #580/#578 to correct the record.Verification
Map.test.tsx, updated to wrap renders inTamaguiProvider)tsc --noEmitcleannpm run lint: unchanged fromdevelopment's existing 14 pre-existing problems (confirmed by diffing against unmodifieddevelopment, not just eyeballing the count)indexchunk: +431 kB raw / +121 kB gzip (measured directly, both branches built with the same toolchain) — a bit above Spike: PoC Tamagui as the combined primitives + styling choice for #578/#591 #629's PoC estimate (+383/+102), expected since this lands a real component on top of the fixed provider cost, not just the provider itself.Not verified: Storybook's browser-mode a11y suite (
vitest --project storybook) — this sandbox lacks thechrome-headless-shellbinary that provider needs. Confirmed pre-existing by reproducing the identical failure on unmodifieddevelopment, so it isn't a regression from this change, but it means that specific acceptance-criterion item is unverified here rather than passing.Acceptance criteria (from #580)
@radix-ui/react-progressimport remains;role/aria-valuenow/aria-valuemax/aria-labelsemantics preserved (verified by test)offsetWidthmeasurement — no native target exists yet to give it anonLayoutpath)ProgressBar.test.tsxpassesProgressBar.stories.tsx+ Storybook a11y addon — not verified, see aboveProgresssemantics (role/aria-valuenow/aria-valuemax) verified directly against real assertions, not inferred from other components🤖 Generated with Claude Code
Generated by Claude Code