Skip to content

fix(text): inherit parent styles in nested Text - #5040

Merged
Doberjohn merged 14 commits into
mainfrom
@Doberjohn/nested-text-inheritance
Nov 4, 2026
Merged

Doberjohn merged 14 commits into
mainfrom
@Doberjohn/nested-text-inheritance

Conversation

@Doberjohn

@Doberjohn Doberjohn commented Aug 7, 2026 •

Copy link
Copy Markdown
Collaborator

Motivation

A nested Text reset the font and color it should inherit: a Text with a variant in a contained Button rendered in onSurface, barely visible in dark theme, and a Chip around a plain Text lost its font.

Now a nested Text or AnimatedText sets only its style and variant font and inherits the rest. With its own theme it renders like a top-level one.

Related issue

Fixes #4351.

Screenshots / Videos

Before

Before

After

After

Test plan

iOS, Android and web, light and dark: nest Text with and without a variant or theme, and a Text with a variant in a Chip and a contained Button. Children keep the parent color unless they have a theme. Known limit (#5162): a Text in a View in a Text gets the native default color.

A nested Text or AnimatedText without a variant applied its fallback font unconditionally, overriding the font, weight, letter spacing and color it should have inherited from the enclosing text. React Native inherits these, so a nested one now declares only its own style. The shared context lives in its own module to keep the Text and AnimatedText imports one-directional. Fixes #4351.
@Doberjohn Doberjohn self-assigned this Aug 7, 2026
@Doberjohn Doberjohn changed the title @doberjohn/nested text inheritance Fix nested Text style inheritance Aug 7, 2026
@Doberjohn Doberjohn changed the title Fix nested Text style inheritance fix(text): inherit parent styles in nested Text Aug 7, 2026
@Doberjohn
Doberjohn requested a review from satya164 August 7, 2026 10:40
@Doberjohn
Doberjohn marked this pull request as ready for review August 7, 2026 10:40
@Doberjohn
Doberjohn requested a review from artus9033 August 7, 2026 10:44
@Doberjohn

Copy link
Copy Markdown
Collaborator Author

A quick note on the Typography work: because a nested Text without a variant no longer applies fonts.default at all, this fix is immune to Body variants switching typeface. Before it, that switch would have caused a visible sans-serif inside sans-serif-medium mismatch on Android. A nested Text that declares its own variant still applies it, which is unchanged here.

@MikitasK MikitasK left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

overall, these changes looks good to me 👌 the approach looks solid & aligns with RN's text inheritance behavior 👍
just a few point to address before merge:

Comment thread src/components/Typography/Text.tsx Resolved
Doberjohn and others added 2 commits August 13, 2026 17:04
Co-authored-by: Mikita Kliushun <nikita.kliushun@gmail.com>
Co-authored-by: Mikita Kliushun <nikita.kliushun@gmail.com>
@Doberjohn

Copy link
Copy Markdown
Collaborator Author

@MikitasK thanks for the review, your proposed changes sounded good!

@MikitasK MikitasK left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM ✅

@JKobrynski JKobrynski left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, good job!

@JKobrynski

Copy link
Copy Markdown
Collaborator

@satya164 @artus9033 all yours

@satya164 satya164 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.

please remove all LLM generated comments, they are either unnecessary or could be replaced with 1-2 lines describing the purpose.

only add comments where you think it's needed for understanding something and write it by hand.

for tests: add tests where

  • Text isn't a direct child and can be nested inside another component that's used inside Text
  • child text also sets its variant and theme

this implementation also isn't accurate to what react native does. a View nested inside Text will reset the inheritance, though it might be a reasonable limitation.

@satya164
satya164 requested a balanced review from Copilot September 15, 2026 20:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@satya164

Copy link
Copy Markdown
Member

Review by Claude

Screenshots of this code added to the Typography screen, dark theme:

<Text variant="headlineSmall" style={{ color: 'tomato' }}>
  A tomato <Text>plain child</Text>
</Text>
<Text variant="headlineSmall" style={{ color: 'tomato' }}>
  B tomato <Text variant="bodyLarge">variant child</Text>
</Text>
<Text style={{ color: 'tomato', fontWeight: 'bold' }}>
  C tomato bold <Text variant="titleLarge">variant child</Text>
</Text>
<Text variant="headlineSmall">
  D parent <Text theme={{ colors: { onSurface: 'green' } }}>green theme child</Text>
</Text>
<Chip selected onPress={() => {}}><Text variant="labelLarge">Var</Text></Chip>
<Button mode="contained"><Text variant="labelLarge">Var</Text></Button>

iOS

iOS, dark theme: nested Text with a variant or a theme

  • Nested Text with a variant drops the parent color. Steps: render B, C and the "Var" button above. What happens: the children render in onSurface, and the "Var" button label is almost invisible on the primary container. Expected: B and C stay tomato, and the button label keeps the button label color. (via Claude, verify if it makes sense)
  • Nested Text without a variant ignores its theme prop. Steps: render D above. What happens: the child renders in the parent color. Expected: the child renders green, as it does on main. (via Claude, verify if it makes sense)

Android

Android, dark theme: nested Text with a variant or a theme

  • Nested Text with a variant drops the parent color. Same steps and result as on iOS. (via Claude, verify if it makes sense)
  • Nested Text without a variant ignores its theme prop. Same steps and result as on iOS. (via Claude, verify if it makes sense)

Web

Web, dark theme: nested Text with a variant or a theme

  • Nested Text with a variant drops the parent color. Same steps and result as on iOS. (via Claude, verify if it makes sense)
  • Nested Text without a variant ignores its theme prop. Same steps and result as on iOS. (via Claude, verify if it makes sense)

@satya164 satya164 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.

Review by Claude

See the inline comments. (via Claude, verify if it makes sense)

Comment thread src/components/Typography/Text.tsx Resolved
Comment thread src/components/Typography/Text.tsx Resolved
Keep a comment only where it helps, in one line, and drop the context
sentence that the nested font change made wrong.

Check every child for an element instead of copying React Native's
three-child cutoff. The provider is still skipped when the children
are only strings or numbers.
Assert that a nested Text sets no color of its own and inherits the
parent's, and cover a Text nested through another component. Fold the
test that did not check what its title said into the one above it,
drop the duplicate of the default font test, and replace the three
AnimatedText tests with one.
A nested Text or AnimatedText with its own theme renders like a
top-level one again, with the theme's color, as it does on main.
A nested Text or AnimatedText with a variant now applies only the
variant font, so it no longer resets the color to onSurface. A Text
with a variant inside a contained Button keeps the button's label
color.
The nested section was inserted above the Custom Variant sample, which
made that sample read as one of the nested cases.
@Doberjohn

Copy link
Copy Markdown
Collaborator Author

Comments are trimmed to one line where they help (890995c). New tests cover a Text nested through another component, and a child with its own variant, its own theme, or both (eebf4c7, 34bca85, 0ad63eb). On View: Paper's context doesn't reset there, so on iOS and Android a Paper Text inside a View inside a Text gets React Native's default color and font, while web inherits fine; passing theme or a color works around it. Tracked in #5162, with a fix that uses React Native's own text ancestor context on native.

@Doberjohn
Doberjohn dismissed satya164’s stale review November 3, 2026 21:01

Review points addressed in 890995c to 0ad63eb; replies are in each thread.

@Doberjohn
Doberjohn requested review from JKobrynski and MikitasK and removed request for MikitasK and artus9033 November 3, 2026 21:03
Comment thread src/components/Typography/Text.tsx Resolved

@MikitasK MikitasK left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM ✅

@Doberjohn
Doberjohn merged commit 12054e3 into main Nov 4, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nested Text components do not inherit style

5 participants