You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Due for payment 2026-11-11] [$175] [CFI] Show the full report field name on hover when the name is cut off #105158
On a report, a long report field name gets cut off and you can't read it. Some workspaces use long text as a report field name, such as an authorization statement. You can't see the full name anywhere in the report view.
Solution
When a report field name is cut off, show the full name in a tooltip on hover. This matches how we handle other long labels in the App.
Expected result
Create a workspace report field with a very long name.
Open a report on that workspace.
Hover over the cut-off field name. A tooltip shows the full name.
Notes
Wrapping the name instead of cutting it off is a possible follow-up. For now, we want the hover.
changed the title [-]Report fields - Show the full field name on hover when the name is cut off[/-][+][CFI] Report fields - Show the full field name on hover when the name is cut off[/+]on Oct 27, 2026
Please re-state the problem that we are trying to solve in this issue.
A long report field name is cut off on the report, and you can't see the full name anywhere.
What is the root cause of that problem?
Every report field on the report view renders through ReportFieldInlineInput. It passes the field name as the label of a TextInput (or DatePicker, which wraps TextInput). TextInputLabel forces that label onto one line with a tail ellipsis. It never adds a tooltip, so the clipped text is lost.
The label also has pointerEventsNone, so it can't receive hover events itself. That keeps clicks going to the input, so we shouldn't remove it.
What changes do you think we should make in order to solve the problem?
Add an opt-in "tooltip when the label is cut off" option to the text input. Then turn it on for report fields.
TextInputLabel (web): add an optional callback that reports whether the label is cut off. Measure it in onLayout the same way TextWithTooltip does (scrollWidth > offsetWidth). The native version ignores it, since there is no hover there.
BaseTextInput: add a prop such as shouldShowLabelTooltipWhenTruncated. When it is set, wrap the input container (the element that already receives pointer events) in Tooltip. Pass text={isLabelTruncated ? label : undefined}. Always render the Tooltip and toggle only text. Toggling shouldRender changes the component tree, which would remount the input and drop focus or a draft value.
DatePicker: forward the new prop to its TextInput. It lists its props explicitly, so this won't pass through on its own.
ReportFieldInlineInput: pass the prop on all three branches: date, list, and text/formula/read-only.
Because the label shrinks when the field is focused or filled, re-check truncation when the value or focus changes, not only on first layout.
Code references
Label built from the field name: ReportFieldInlineInput.tsx:99. Passed to DatePicker (L171-189), the list TextInput (L255-276) and the plain TextInput (L285-301).
What alternative solutions did you explore? (Optional)
Tooltip on the label only: this means removing pointerEventsNone. The label is absolutely positioned across the input, so it would then take clicks and text selection meant for the input.
Always show the tooltip: this is simpler, but the issue asks for it only when the name is cut off.
Wrap the name instead of truncating: the issue lists this as a possible follow-up.
Mobile has no hover, so long names will still be cut off there. That matches the scope of this issue.
Next Steps for Contributor+ team: To accept:@MelvinBot implement [this](https://github.com/Expensify/App/issues/105158) to create a draft PR. To refine:@MelvinBot <your feedback> To reject: Explain why you are rejecting Melvin's proposal.
changed the title [-][CFI] Report fields - Show the full field name on hover when the name is cut off[/-][+][$175] [CFI] Report fields - Show the full field name on hover when the name is cut off[/+]on Oct 27, 2026
Please re-state the problem that we are trying to solve in this issue.
When a workspace report field has a long name, its label in the report view (ReportFieldInlineInput — text, date, and list fields) is truncated with an ellipsis (...), and hovering over the field does not show a tooltip with the full field name.
TextInputLabel renders <Text numberOfLines={!isMultiline || shouldLabelStayOnSingleLine ? 1 : undefined}> inside an <Animated.View style={[styles.textInputLabelContainer, animatedStyle, styles.pointerEventsNone]}>, which truncates long single-line labels with text-overflow: ellipsis, but neither TextInputLabel nor BaseTextInput detects truncation or renders a <Tooltip>.
Important animation subtlety with TextInputLabel: In src/styles/index.ts, getTextInputLabelTransformation animates fontSize via a Reanimated worklet between 15px (INACTIVE_LABEL_SCALE = 1 when empty/unfocused) and 11px (ACTIVE_LABEL_SCALE = 0.7333 when focused or filled) over CONST.ANIMATED_TRANSITION (300ms).
On Web (react-native-web), a truncated <Text numberOfLines={1}> already occupies 100% of its container width (offsetWidth === clientWidth). When fontSize animates between 15px and 11px, scrollWidth changes while offsetWidth stays fixed, so onLayout (ResizeObserver) does not re-fire.
A label that truncates at 15px (empty/unfocused) may fit completely at 11px (filled/focused), so relying solely on onLayout leaves isLabelTruncated stale after focus/blur/value transitions.
What changes do you think we should make in order to solve the problem?
src/components/TextInput/TextInputLabel/types.ts:
Add an optional callback prop onLabelTruncatedChange?: (isTruncated: boolean) => void; to TextInputLabelProps.
Attach a ref (labelRef) to the <Text> element and a helper checkTruncation that checks el.scrollWidth > el.clientWidth on web (onLabelTruncatedChange?.(el.scrollWidth > el.clientWidth)).
Call checkTruncation inside <Text onLayout={checkTruncation}> (which handles initial mount and container width/window resize changes) and when label changes.
Use useAnimatedReaction on labelScale so that whenever labelScale settles at ACTIVE_LABEL_SCALE or INACTIVE_LABEL_SCALE after the font-size interpolation finishes, runOnJS(checkTruncation)() re-evaluates whether the label is truncated at its current font size:
Keep styles.pointerEventsNone on TextInputLabel's <Animated.View> so click-to-focus on TextInput, DatePicker, and FilterPopupButton continues to pass pointer events through to the underlying input/pressable without regression.
Pass onLabelTruncatedChange={setIsLabelTruncated} to <TextInputLabel />.
Wrap the input's <PressableWithoutFeedback> (lines 380–617) in <Tooltip text={isLabelTruncated ? label : ''}>. Because BaseTooltip gates rendering on hasValidText (!StringUtils.isEmptyString(text)), the tooltip is completely inert whenever the label is not truncated, and automatically works across all report field types (Text, Formula, Date, List, and read-only/disabled fields).
What alternative solutions did you explore? (Optional)
Removing styles.pointerEventsNone from TextInputLabel and wrapping <Text> inside TextInputLabel with TextWithTooltip: rejected because TextInputLabel is absolutely positioned (zIndex: 1, width: '100%') over the input box; enabling pointer events on it intercepts clicks/taps meant for focusing BaseTextInput or opening DatePicker / FilterPopupButton.
Checking scrollWidth > offsetWidth only inside onLayout: rejected because ResizeObserver does not fire when fontSize interpolates between INACTIVE_LABEL_SCALE (15px) and ACTIVE_LABEL_SCALE (11px) inside a fixed-width container.
Activity
[-]Report fields - Show the full field name on hover when the name is cut off[/-][+][CFI] Report fields - Show the full field name on hover when the name is cut off[/+]trjExpensify commentedon Oct 27, 2026
@MelvinBot proposal a solution for this.
MelvinBot commentedon Oct 27, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
A long report field name is cut off on the report, and you can't see the full name anywhere.
What is the root cause of that problem?
Every report field on the report view renders through
ReportFieldInlineInput. It passes the field name as thelabelof aTextInput(orDatePicker, which wrapsTextInput).TextInputLabelforces that label onto one line with a tail ellipsis. It never adds a tooltip, so the clipped text is lost.The label also has
pointerEventsNone, so it can't receive hover events itself. That keeps clicks going to the input, so we shouldn't remove it.What changes do you think we should make in order to solve the problem?
Add an opt-in "tooltip when the label is cut off" option to the text input. Then turn it on for report fields.
TextInputLabel(web): add an optional callback that reports whether the label is cut off. Measure it inonLayoutthe same wayTextWithTooltipdoes (scrollWidth > offsetWidth). The native version ignores it, since there is no hover there.BaseTextInput: add a prop such asshouldShowLabelTooltipWhenTruncated. When it is set, wrap the input container (the element that already receives pointer events) inTooltip. Passtext={isLabelTruncated ? label : undefined}. Always render theTooltipand toggle onlytext. TogglingshouldRenderchanges the component tree, which would remount the input and drop focus or a draft value.DatePicker: forward the new prop to itsTextInput. It lists its props explicitly, so this won't pass through on its own.ReportFieldInlineInput: pass the prop on all three branches: date, list, and text/formula/read-only.Because the label shrinks when the field is focused or filled, re-check truncation when the value or focus changes, not only on first layout.
Code references
ReportFieldInlineInput.tsx:99. Passed toDatePicker(L171-189), the listTextInput(L255-276) and the plainTextInput(L285-301).MoneyRequestViewReportFields.tsx:94pointerEventsNone:TextInputLabel/index.tsx:32-40BaseTextInput/implementation/index.tsx:380-430TextWithTooltip/index.tsx:27-37shouldRender={false}returns bare children, which changes the tree:Tooltip/index.tsx:7-12DatePickerbuilds itsTextInputprops explicitly:DatePicker/index.tsx:234-260What alternative solutions did you explore? (Optional)
pointerEventsNone. The label is absolutely positioned across the input, so it would then take clicks and text selection meant for the input.Mobile has no hover, so long names will still be cut off there. That matches the scope of this issue.
Next Steps for Contributor+ team:
To accept:
@MelvinBot implement [this](https://github.com/Expensify/App/issues/105158)to create a draft PR.To refine:
@MelvinBot <your feedback>To reject: Explain why you are rejecting Melvin's proposal.
melvin-bot commentedon Oct 27, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @huult (
External)[-][CFI] Report fields - Show the full field name on hover when the name is cut off[/-][+][$175] [CFI] Report fields - Show the full field name on hover when the name is cut off[/+]melvin-bot commentedon Oct 27, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022115168392823246429
trjExpensify commentedon Oct 27, 2026
@huult can you review Melvin's proposal and progress it if it's good please? Thanks!
Enes2553 commentedon Oct 27, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When a workspace report field has a long name, its label in the report view (
ReportFieldInlineInput— text, date, and list fields) is truncated with an ellipsis (...), and hovering over the field does not show a tooltip with the full field name.What is the root cause of that problem?
src/components/MoneyRequestReportView/ReportFieldInlineInput.tsx, all report field variants (DatePicker,FilterPopupButton'sTextInput, and the defaultTextInput) passlabel={label}down toBaseTextInput, which rendersTextInputLabel.TextInputLabelrenders<Text numberOfLines={!isMultiline || shouldLabelStayOnSingleLine ? 1 : undefined}>inside an<Animated.View style={[styles.textInputLabelContainer, animatedStyle, styles.pointerEventsNone]}>, which truncates long single-line labels withtext-overflow: ellipsis, but neitherTextInputLabelnorBaseTextInputdetects truncation or renders a<Tooltip>.TextInputLabel: Insrc/styles/index.ts,getTextInputLabelTransformationanimatesfontSizevia a Reanimated worklet between15px(INACTIVE_LABEL_SCALE = 1when empty/unfocused) and11px(ACTIVE_LABEL_SCALE = 0.7333when focused or filled) overCONST.ANIMATED_TRANSITION(300ms).react-native-web), a truncated<Text numberOfLines={1}>already occupies100%of its container width (offsetWidth === clientWidth). WhenfontSizeanimates between15pxand11px,scrollWidthchanges whileoffsetWidthstays fixed, soonLayout(ResizeObserver) does not re-fire.15px(empty/unfocused) may fit completely at11px(filled/focused), so relying solely ononLayoutleavesisLabelTruncatedstale after focus/blur/value transitions.What changes do you think we should make in order to solve the problem?
src/components/TextInput/TextInputLabel/types.ts:onLabelTruncatedChange?: (isTruncated: boolean) => void;toTextInputLabelProps.src/components/TextInput/TextInputLabel/index.tsx(and.native.tsxno-op compatibility):labelRef) to the<Text>element and a helpercheckTruncationthat checksel.scrollWidth > el.clientWidthon web (onLabelTruncatedChange?.(el.scrollWidth > el.clientWidth)).checkTruncationinside<Text onLayout={checkTruncation}>(which handles initial mount and container width/window resize changes) and whenlabelchanges.useAnimatedReactiononlabelScaleso that wheneverlabelScalesettles atACTIVE_LABEL_SCALEorINACTIVE_LABEL_SCALEafter the font-size interpolation finishes,runOnJS(checkTruncation)()re-evaluates whether the label is truncated at its current font size:styles.pointerEventsNoneonTextInputLabel's<Animated.View>so click-to-focus onTextInput,DatePicker, andFilterPopupButtoncontinues to pass pointer events through to the underlying input/pressable without regression.src/components/TextInput/BaseTextInput/implementation/index.tsx:const [isLabelTruncated, setIsLabelTruncated] = useState(false);.onLabelTruncatedChange={setIsLabelTruncated}to<TextInputLabel />.<PressableWithoutFeedback>(lines 380–617) in<Tooltip text={isLabelTruncated ? label : ''}>. BecauseBaseTooltipgates rendering onhasValidText(!StringUtils.isEmptyString(text)), the tooltip is completely inert whenever the label is not truncated, and automatically works across all report field types (Text, Formula, Date, List, and read-only/disabled fields).What alternative solutions did you explore? (Optional)
styles.pointerEventsNonefromTextInputLabeland wrapping<Text>insideTextInputLabelwithTextWithTooltip: rejected becauseTextInputLabelis absolutely positioned (zIndex: 1,width: '100%') over the input box; enabling pointer events on it intercepts clicks/taps meant for focusingBaseTextInputor openingDatePicker/FilterPopupButton.scrollWidth > offsetWidthonly insideonLayout: rejected becauseResizeObserverdoes not fire whenfontSizeinterpolates betweenINACTIVE_LABEL_SCALE(15px) andACTIVE_LABEL_SCALE(11px) inside a fixed-width container.apoorv-xs commentedon Oct 28, 2026
melvin-bot commentedon Oct 28, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
huult commentedon Oct 28, 2026
Screen.Recording.2026-10-28.at.10.31.39.mov
We can proceed with @MelvinBot’s proposal.
🎀 👀 🎀 c+ reviewed.
20 remaining items
jeffrey-graham commentedon Nov 7, 2026
melvin-bot commentedon Nov 7, 2026
melvin-bot commentedon Nov 10, 2026
Triggered auto assignment to @mallenexpensify (
Awaiting Payment)melvin-bot commentedon Nov 10, 2026
Payment Summary
Resolving PRs:
Show the full report field name in a tooltip when it is cut off #105279
Reviewer: @huult owed $175 via NewDot
BugZero Checklist (@mallenexpensify)
mallenexpensify commentedon Nov 13, 2026
Claude posting on behalf of Matt:
Ready. Job price: $175 (standard, no Help Wanted, assigned 2026-10-27).
No deploy blockers or regressions on the issue or the PR.
Next: press Caps+Y, then pay.
Evidence
PAYPREP v1