Skip to content

upgrade to nativewind@4 - #3826

Open
FLGMwt wants to merge 9 commits into
mainfrom
MOB-1148-nativewind4
Open

upgrade to nativewind@4#3826
FLGMwt wants to merge 9 commits into
mainfrom
MOB-1148-nativewind4

Conversation

@FLGMwt

@FLGMwt FLGMwt commented Jul 13, 2026

Copy link
Copy Markdown
Member

Closes MOB-1148

This PR upgrades to Nativewind@4 (note: v3 was canceled, 4 is the next step from 2). Nativewind 4 is a significant rewrite so this necessarily touches quite a few files.

I cherry-picked the first commit from a spike I did on this in May, which includes everything necessary to wire up the project on v4. There were a number of things off in this commit around text, maps, but the core interface are functional.

For fixing the rest, this is my first time using Claude for a "big" problem. I thought it would be well-suited at finding the nooks and crannies of the app to apply systemic / migratory changes. I'm sharing the Claude Plan Document and Claude's summary of changes below:

Plan for fixing some enumerated styling issues

Finish the NativeWind 2 → 4 migration

Context

The spike commit (7a999b474) did the core wiring correctly: babel preset, metro withNativeWind, global.css with @tailwind directives, nativewind/preset in tailwind config, and removal of styled(). I verified empirically (compiled the real CSS through nativewind's cssToReactNativeRuntime, and rendered real Typography components through the repo's actual babel chain in jest) that the font classes themselves compile and apply correctlyfont-Lato-*fontFamily: "Lato-*" end to end, including with the react-compiler plugin active.

Answer to the open question: nothing needs to move from tailwind.config.js to CSS. NativeWind 4 uses Tailwind 3's JS config; global.css stays as just the three @tailwind directives. (Moving theme to CSS is a Tailwind v4 / NativeWind v5 thing.)

The reported symptoms map to four real, verified issues:

Symptom Root cause
Cramped / smaller NativeWind 4 inlines rem at 14px (v2 used 16px) → all rem-based spacing (p-*, m-*, gap-*, h-22, …) shrank 12.5%. Verified: p-4 compiles to 14 instead of 16.
System font shows Third-party components lost styled() and are NOT auto-interop'd in v4 — className on them is silently ignored (BottomSheetTextInput, SafeAreaView, LinearGradient, FasterImageView). Also a pre-existing bug: KebabMenu.tsx:43 sets fontFamily: tailwindFontMedium (the class name "font-Lato-Medium") instead of the font name → kebab menu items always fell back to system font.
Wrong weights v4 resolves conflicting classes by stylesheet order, not className string order. Verified via probe: an element with both font-Lato-Regular and font-Lato-Bold renders Regular regardless of string order (Regular is generated last among the Lato keys). Anywhere that appends a font override onto a base class that already has a font class now picks the wrong one.
Jest suite broken The css-interop babel plugin rewrites React.createElement(...) to a hoisted _ReactNativeCSSInterop.createInteropElement(...) import; jest.mock factories in tests/jest.setup.js:196-208 use React.createElement → babel-plugin-jest-hoist rejects the out-of-scope reference.

Changes

1. Restore 16px rem base — metro.config.js

withNativeWind( configWithRozenite, { input: "./global.css", inlineRem: 16 } )

This alone should fix the app-wide cramped look.

2. Register third-party components — src/components/styledComponents.ts

Core RN components (View, Text, TextInput, Modal, Pressable, ScrollView, Image, ImageBackground, KeyboardAvoidingView…) are auto-registered in v4 — leave those as plain re-exports. PressableWithTracking is fine too (it forwards props to core Pressable from app-compiled code). Register the rest:

import { cssInterop } from "nativewind";

const SafeAreaView = cssInterop( UnstyledSafeAreaView, { className: "style" } );
const LinearGradient = cssInterop( UnstyledLinearGradient, { className: "style" } );
const FasterImageView = cssInterop( UnstyledFasterImageView, { className: "style" } );
const BottomSheetTextInput = cssInterop( StyledBottomSheetTextInput, { className: "style" } );

(Keep the existing SafeAreaView === undefined jest fallback.)

3. Wrong weights — fix real double-font-class sites

Most elements carry only one font class because InatText's {...props} spread replaces the merged className (pre-existing behavior, unchanged by the migration — verified in the probe). So this is an audit, not a rewrite:

  • Grep for places that combine a component/base classes containing one font-Lato-* with a caller-supplied second font-* class via proper classnames() merging (e.g. src/navigation/, CustomTabBar, button/label components — the files matching props.className + classnames).
  • Fix each by removing the redundant base font class or making the override the only font class present.
  • Do NOT reorder fontFamily keys in tailwind.config.js to game the cascade — it can't restore string-order semantics and just moves the problem.

4. Pre-existing font bug (drive-by) — src/components/SharedComponents/KebabMenu.tsx:43

fontFamily: tailwindFontMediumfontFamily: fontMedium (import from appConstants/fontFamilies).

5. Fix jest

  • tests/jest.setup.js:196-208: rewrite the two jest.mock factories to avoid the createElement rewrite — e.g. jest.fn( ( { children } ) => children ?? null ), or jest.requireActual( "react" ).createElement if a host element is required (the plugin only rewrites bindings imported via require("react")/import).
  • Add a CSS module mapping so App.js's import "../../global.css" doesn't break tests: moduleNameMapper: { "\\.css$": "<rootDir>/tests/mocks/cssMock.js" } (new empty-object mock file).
  • Run both suites (npm run test:unit, integration). Expect some churn: className styles do NOT resolve to style objects in jest anymore (metro injects the compiled CSS; jest has no CSS registered), so snapshots/assertions that relied on tailwind-derived styles may need updating. tests/unit/components/SharedComponents/DisplayTaxon.test.js asserts opacity: 0.5 via toHaveStyle — check whether that comes from an inline style (fine) or a class (needs adjustment).
  • Contingency if many tests depend on resolved tailwind styles: register compiled CSS in a setupFilesAfterEnv using nativewind/test helpers (requires adding @tailwindcss/container-queries as a devDependency — I already confirmed the helper needs it).

6. Housekeeping

  • Bump tailwindcss ^3.3.2^3.4.17 (nativewind 4's recommended line; peer range allows it).
  • Delete the probe file I created: tests/unit/nativewind4-font-probe.test.tsx.
  • node_modules has an unsaved @tailwindcss/container-queries install (--no-save) — either add it as devDependency (contingency above) or npm install to restore.

Verification

  1. npm run ios (or android) and check against main side by side:
    • Developer > UI Library > Typography screen (src/components/Developer/UiLibrary/Typography.js) — every Heading/Body variant shows correct Lato weight/size.
    • Spacing/padding on the observations list and detail screens no longer cramped (rem fix).
    • BottomSheetTextInput-based inputs and SearchBar show Lato, gradients/safe-area layouts styled again.
    • Kebab menu items show Lato-Medium.
  2. Optionally call verifyInstallation() from nativewind once in dev to confirm the runtime sees the compiled CSS, then remove.
  3. npm run test:unit and npm run test:integration pass.
Summary of changes

NativeWind 2 → 4 migration summary

Your spike wiring (babel preset, metro withNativeWind, preset in tailwind config, styled() removal) was correct. The problems were all runtime behavior changes between v2 and v4:

The core mental-model shift (explains almost every symptom): NativeWind 2's babel plugin resolved className on every capitalized component into styles at the call site, cascading through wrapper layers as style arrays where later-in-array won. NativeWind 4 only styles components explicitly registered with the interop, className rides along as a plain prop, conflicting classes resolve by stylesheet order instead of string order, and inline styles beat classes.

What was fixed:

  1. rem base 16→14 shrank all spacing 12.5% → inlineRem: 16 in metro config ("cramped" look)
  2. Third-party components lost styling → cssInterop() registrations for SafeAreaView, LinearGradient, FasterImageView, BottomSheetTextInput, and MapView (the broken maps — flex-1 was dead so the map had no size)
  3. Typography defaults dropped when callers passed className → all 15 Typography components + ScreenShell + Button now merge with tailwind-merge so later classes win per property, restoring v2 semantics (fixed wrong weights, system fonts, black-instead-of-darkGray, and the "overexposed" modals where bg-white was beating bg-black)
  4. Inline textAlign: "left" in InatText beat text-center classes → default skipped when an alignment class is present (Licenses link, button labels, modal text)
  5. space-x/y-* polyfills removed in v4 → converted all 34 usages to gap-* (login pill spacing, DQA screens, sheets)
  6. className dead on SVG components → arrow on Me tab wrapped in a positioned View
  7. Function styles dropped by the interop → INatIconButton uses active:opacity-95/opacity-50 classes; also now forwards className
  8. Animated.View + className unreliable → 6 call sites converted to inline styles
  9. Metro crashed on tailwind hot updates → bumped to nativewind 4.2.6 / css-interop 0.2.6 (upstream fix); tailwindcss bumped to 3.4.x

Jest: CSS is compiled once in globalSetup and injected per worker (tests/nativewind.setup.js), so classNames resolve to real styles in tests like they did in v2; two jest.mock factories needed jest.requireActual("react") to dodge the interop's createElement rewrite; snapshots re-blessed after verifying diffs were value-identical.

Drive-by fix: KebabMenu was passing the class name "font-Lato-Medium" as a fontFamily value (kebab menus have been system-font for a while).

Context for twMerge / classnames

why use twmerge in some cases like @src/components/SharedComponents/ViewWrapper.tsx and classnames() in some places like @src/components/SharedComponents/Typography/Body1.tsx ?

Short answer: twMerge is doing conflict resolution, classnames is just string concatenation — and on this NativeWind 4 branch that difference actually matters.

twMerge = conflict resolution. In NativeWind 4, when one element has two conflicting classes (bg-white bg-black), the winner is decided by stylesheet order, not the order in the className string — so plain concatenation no longer lets a caller's class beat a component's default. twMerge fixes that by actually parsing the Tailwind classes and dropping the earlier one of each conflicting pair, so "later in the string wins" behavior is restored deterministically. That's why it's used in the components that own overridable defaults and render the actual native element: ViewWrapper's ScreenShell (bg-white must lose to a caller's bg-black), InatText, Button.

classnames = cheap concatenation (and conditionals). Body1 doesn't render a Text itself — it just prepends text-base + the font class and hands the combined string to InatText. InatText then runs the entire final string through twMerge before it hits the real . So the conflict resolution still happens exactly once, at the leaf; the intermediate layer only needs to join strings in the right order (caller last). Running twMerge at every layer would be redundant work. classnames also supports the { "some-class": condition } object syntax that ~99 files in the app rely on, which twMerge doesn't do.

Rule of thumb the branch follows: twMerge at the point where a className finally lands on a native element and defaults must be overridable; classnames everywhere upstream of that. The comments in InatText.tsx:24-26 and ViewWrapper.tsx:28-30 document the why.

One thing to keep an eye on: this only stays safe as long as every classnames-composed string eventually flows through a twMerge-ing leaf like InatText. A wrapper that concatenates defaults and passes straight to a raw styled View/Text would silently lose caller overrides — a merge conflict of the kind git can't help you with.

@semanticdiff-com

semanticdiff-com Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review changes with  SemanticDiff

Changed Files
File Status
  tsconfig.json  99% smaller
  src/components/Camera/RotatableIconWrapper.tsx  62% smaller
  src/components/SharedComponents/Typography/List2.tsx  48% smaller
  src/components/SharedComponents/Typography/InatText.tsx  46% smaller
  src/components/SharedComponents/Typography/Heading1.tsx  43% smaller
  src/components/SharedComponents/Typography/Heading4.tsx  43% smaller
  src/components/SharedComponents/Typography/Heading5.tsx  43% smaller
  src/components/SharedComponents/Typography/Heading6.tsx  43% smaller
  src/components/SharedComponents/Typography/UnderlinedLink.tsx  43% smaller
  tests/jest.setup.js  37% smaller
  tests/helpers/mockMortalForIntegration.js  29% smaller
  src/components/SharedComponents/MediaNavButtons.tsx  28% smaller
  src/components/SharedComponents/Buttons/Button.tsx  27% smaller
  src/navigation/FadeInView.tsx  27% smaller
  src/components/SharedComponents/Sheets/BottomSheet.tsx  23% smaller
  src/components/SharedComponents/Typography/Heading3.tsx  22% smaller
  src/components/SharedComponents/Typography/Subheading2.tsx  22% smaller
  src/components/SharedComponents/Typography/Heading2.tsx  22% smaller
  src/components/SharedComponents/Typography/Body3.tsx  22% smaller
  src/components/SharedComponents/Typography/Body2.tsx  22% smaller
  src/components/SharedComponents/Typography/Subheading1.tsx  22% smaller
  src/components/SharedComponents/Typography/Body1.tsx  21% smaller
  src/components/SharedComponents/Typography/Body4.tsx  21% smaller
  src/components/styledComponents.ts  21% smaller
  src/components/SharedComponents/ViewWrapper.tsx  19% smaller
  src/components/Onboarding/OnboardingCarousel.js  19% smaller
  src/components/SharedComponents/Buttons/INatIconButton.tsx  17% smaller
  src/components/SharedComponents/Typography/P.tsx  15% smaller
  src/components/Camera/FadeInOutView.tsx  13% smaller
  src/components/Camera/FocusSquare.tsx  12% smaller
  src/components/Camera/TabletButtons.tsx  11% smaller
  package.json  9% smaller
  src/components/LoginSignUp/LoginSignUpInputField.tsx  1% smaller
  .gitignore Unsupported file format
  AGENTS.md Unsupported file format
  agent-docs/conventions/nativewind-v4.md Unsupported file format
  babel.config.js  0% smaller
  global.css  0% smaller
  jest.config.ts  0% smaller
  metro.config.js  0% smaller
  package-lock.json Unsupported file format
  src/components/AddObsBottomSheet/AddObsBottomSheet.tsx  0% smaller
  src/components/App.js Unsupported file format
  src/components/FullPageWebView/FullPageWebView.tsx  0% smaller
  src/components/Match/PhotosSection.tsx  0% smaller
  src/components/MyObservations/LoginBanner.tsx  0% smaller
  src/components/MyObservations/MyObservationsEmptySimple.js Unsupported file format
  src/components/MyObservations/Search/SearchedTaxonBanner.tsx  0% smaller
  src/components/Notifications/ObsNotification.tsx  0% smaller
  src/components/ObsDetails/DQAContainer.js Unsupported file format
  src/components/ObsDetails/DataQualityAssessment.tsx  0% smaller
  src/components/ObsDetails/DetailsTab/DQAVoteButtons.js Unsupported file format
  src/components/ObsDetails/DetailsTab/DetailsTab.js Unsupported file format
  src/components/ObsDetails/DetailsTab/LocationSection.tsx  0% smaller
  src/components/ObsDetails/Sheets/AgreeWithIDSheet.js Unsupported file format
  src/components/ObsDetails/Sheets/WithdrawIDSheet.js Unsupported file format
  src/components/ObsDetailsSharedComponents/ActivityTab/ActivityHeader.js Unsupported file format
  src/components/ObsDetailsSharedComponents/Sheets/AgreeWithIDSheet.js Unsupported file format
  src/components/ObsDetailsSharedComponents/Sheets/SuggestIDSheet.tsx  0% smaller
  src/components/ObsEdit/EvidenceList.js Unsupported file format
  src/components/SharedComponents/ActivityIndicator.tsx  0% smaller
  src/components/SharedComponents/KebabMenu.tsx  0% smaller
  src/components/SharedComponents/Map/Map.tsx  0% smaller
  src/components/SharedComponents/ObsDetails/ContentWithIcon.tsx  0% smaller
  src/components/SharedComponents/ObservationLocation.tsx  0% smaller
  src/components/SharedComponents/Sheets/TextInputSheet.js Unsupported file format
  src/components/SharedComponents/TaxonSearch.tsx  0% smaller
  tailwind.config.js  0% smaller
  tests/jest.globalSetup.js  0% smaller
  tests/mocks/cssMock.js  0% smaller
  tests/nativewind.setup.js  0% smaller
  tests/unit/components/AddObsBottomSheet/__snapshots__/AddObsButton.test.js.snap Unsupported file format
  tests/unit/components/BottomTabNavigator/__snapshots__/CustomTabBar.test.js.snap Unsupported file format
  tests/unit/components/Camera/__snapshots__/PhotoCarousel.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/ActivityCount/__snapshots__/ActivityCount.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/ActivityCount/__snapshots__/CommentsCount.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/ActivityCount/__snapshots__/IdentificationsCount.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Buttons/__snapshots__/Button.dark.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Buttons/__snapshots__/Button.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Buttons/__snapshots__/ContainedSquareButton.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Buttons/__snapshots__/INatIconButton.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Divider/__snapshots__/Divider.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/InlineUser/__snapshots__/InlineUser.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/ObservationsFlashList/__snapshots__/ObsGridItem.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/PhotoCount/__snapshots__/PhotoCount.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Tabs/__snapshots__/Tabs.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/Body1.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/Body2.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/Body3.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/Body4.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/Heading1.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/Heading2.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/Heading3.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/Heading4.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/Heading5.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/List2.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/Subheading1.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/Typography/__snapshots__/Subheading2.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/UploadStatus/__snapshots__/UploadStatus.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/__snapshots__/TaxonResult.test.js.snap Unsupported file format
  tests/unit/components/SharedComponents/__snapshots__/UserIcon.test.js.snap Unsupported file format
  tests/unit/components/UserText/UserText.test.js  0% smaller


const GREEN_CIRCLE_CLASS = "bg-inatGreen rounded-full h-[36px] w-[36px] mb-2";
const ROW_CLASS = "flex-row justify-center space-x-4 w-full flex-1";
const ROW_CLASS = "flex-row justify-center gap-x-4 w-full flex-1";

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space-x/y-* polyfills removed in v4 → converted all 34 usages to gap


// className support: third-party components need explicit registration with
// nativewind 4 for className to have any effect
cssInterop( MapView, { className: "style" } );

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Third-party components lost styling → cssInterop() registrations for SafeAreaView, LinearGradient, FasterImageView, BottomSheetTextInput, and MapView

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add it to StyledComponent, seems to me the only cssInterop call outside of the pattern.

const Body3 = ( props: TextProps ) => (
// eslint-disable-next-line react/jsx-props-no-spreading
<InatText className={`text-xs ${tailwindFontMedium}`} {...props} />
<InatText {...props} className={classnames( "text-xs", tailwindFontMedium, props.className )} />

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See Context for twMerge / classnames in PR description for further explanation

Comment thread src/components/App.js
@@ -1,5 +1,7 @@
// @flow

import "../../global.css";

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +22 to +24
// Core react-native components are registered with nativewind automatically;
// third-party components need explicit cssInterop registration for className
// to have any effect

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI on styled vs cssInterop

@FLGMwt
FLGMwt marked this pull request as ready for review July 15, 2026 18:16
@jtklein
jtklein self-requested a review July 16, 2026 11:11

@jtklein jtklein left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update related code changes and migrations seem all fine to me. But I do see quite a few regressions in the UI, so I'll post before and after screenshots in Slack for things to fix.

Comment thread tests/nativewind.setup.js
@@ -0,0 +1,28 @@
// Makes className resolve to styles in jest the way it does in the app.

@jtklein jtklein Jul 16, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not so happy about this file and the other jest setups. This seems like a lot of extra setup required just so that we can work with this one package. I couldn't find any reference to jest in the nativewind docs. So, I am wondering how we get to this file content?
Makes me a bit nervous to not find official guidelines on how to setup nativewind with jest.

@FLGMwt FLGMwt Aug 11, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay in getting back to this.

The change is necessary because the package fundamentally changed how it works.

Before: the babel transform wrapped the classname'd components with nativewind wrappers that did tailwind => js styles interpolation within the implementation of the wrapper component
Now: it does more of a tailwind => css => rn-css-interop which is now baked into metro. Since jest doesn't use metro, this nativewind setup recreates that relationship. I couldn't get this to work with the exported nativewind/test helpers because they don't use react-testing-library's render. So I deferred to Claude on this what reverse-engineered the same approach from the internals. I included some of the rationale of this in the new agent doc. Let me know if you think more of this belongs in the file itself.

I agree it's not ideal but I think it's fair that we sometimes have extra setup for key packages (such as Realm).


// className support: third-party components need explicit registration with
// nativewind 4 for className to have any effect
cssInterop( MapView, { className: "style" } );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add it to StyledComponent, seems to me the only cssInterop call outside of the pattern.

@jtklein jtklein left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still seeing wrong styles in the buttons inStandardCamera and SoundRecorder:

Image Image Image

@FLGMwt

FLGMwt commented Aug 11, 2026

Copy link
Copy Markdown
Member Author

@jtklein latest commit addresses the "pill" button issues in media.

On testing, the ? issue is present in TestFlight already so I don't think this PR affects that. I'll test in prod soon.

Screenshot 2026-08-11 at 10 52 56 AM

@jtklein

jtklein commented Aug 11, 2026

Copy link
Copy Markdown
Member

@jtklein latest commit addresses the "pill" button issues in media.

On testing, the ? issue is present in TestFlight already so I don't think this PR affects that. I'll test in prod soon.

I don't see an issue with the ?

@FLGMwt

FLGMwt commented Aug 11, 2026

Copy link
Copy Markdown
Member Author

@jtklein latest commit addresses the "pill" button issues in media.
On testing, the ? issue is present in TestFlight already so I don't think this PR affects that. I'll test in prod soon.

I don't see an issue with the ?

Oh, I saw the ? in the context of the other UI issues that looked wonky and confused myself. I do not see an issue with ? in comparison with designs / TestFlight / Prod.

@jtklein

jtklein commented Aug 13, 2026

Copy link
Copy Markdown
Member

@jtklein latest commit addresses the "pill" button issues in media.

On testing, the ? issue is present in TestFlight already so I don't think this PR affects that. I'll test in prod soon.

Screenshot

Screenshot looking good. Do you want me to test again?

@jtklein jtklein left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't tested the last screenshot again, but did not find anything else in the prior testing round, so if that is fixed I'd say it's good to go, and we fix anything else forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants