refactor(web): migrate refresh Text to Opal Text
Description
This is the last of four cleanup PRs on top of #16234, which is merged (stack: #16240 icons, #16241 raw elements, #16242 refresh components, #16243 Text). It migrates the deprecated refresh Text (@/refresh-components/texts/Text, a boolean-flag API) to Text from @opal/components (font and color enum props).
Before and after
| Before | After | |
|---|---|---|
Files that import refresh Text | 130 | 31 |
Files fully on Opal Text | 0 | 99 |
opal/no-replaced-refresh-import warnings in the repo (all modules) | 155 | 41 |
The work is in four commits. Parts 1 to 3 each cover about a third of the files. Part 4 covers 8 files that the previous PR (Card/Truncated) also changed, migrated on top of that PR's version to avoid merge conflicts. All four commits use the same mapping.
Mapping
Refresh Text | Opal Text |
|---|---|
Font flags (headingH1, mainUiBody, secondaryMono, figureSmallValue, ... 19 in all) | The kebab-case enum ("heading-h1", "main-ui-body", "secondary-mono", "figure-small-value", ...) |
| No font flag | font="main-ui-body", always written out |
Color flags text01..text05, textLight03/05, textDark03/05 | "text-0X", "text-light-0X", "text-dark-0X" |
| No color flag | color="text-05", always written out. The refresh default is text-05, but the Opal default is text-04, so leaving it out would change the color |
| Several flags on one site | The first match in the refresh precedence wins (fonts in declaration order; colors text01 to text05, then light, then dark) |
inverted + text0X / inverted alone | "text-inverted-0X" / "text-inverted-05". Light and dark colors ignore inverted, as before |
Conditional flags (figureSmallLabel={x}, text02={d} text04={!d}) | Ternaries on font and color |
nowrap / whitespace-nowrap | wordWrap="whitespace-nowrap" |
wrap-break-word | wordWrap="wrap-break-word" |
as | Kept |
line-clamp-N, truncate | maxLines={N}, maxLines={1} |
text-center / text-start / text-end on a p | textPosition |
text-action-selection-05 class | color="action-selection-05" |
text-action-danger-05, text-status-error-05 classes | color="status-error-05" (the same red in light and dark) |
Layout classes (margin, padding, width, max-width, select-none, flex centering) | Moved without change to a wrapper <div>, because Opal Text strips className |
font-medium with main-ui-body; text-sm with main-ui-body; m-0! on a p outside prose | Dropped. Each one sets the value the preset or preflight already sets |
Children: Opal Text takes string, RichStr or rich nodes.
- JSX children and
t.rich(...)output are wrapped inrichNodes(...)from@opal/utils. - Numbers become
String(n). - Mixed text and expressions become one template string, for example
`!register ${registrationKey ?? ""}`. - Values that can be null get
?? ""or?? undefined, so they still render as nothing.
In files that still have kept sites, the refresh import is named RefreshText and the Opal import is Text.
Visual differences reviewers should check
- 2px horizontal padding. Opal
Textalways addspx-[2px], so every migrated site gains 2px each side. This is most visible on the inline value spans insidet.richsentences on the billing pages. InSourceTagDetailsCard, the built-in 2px replaces the oldpx-0.5. - Wrapper
divs. Where layout classes moved to a wrapper, the DOM has one more element. It looks the same in the flex contexts I saw. On the CSV footer, the wrapper is block-level where the old span was inline. spantop. Four sites changed so that alignment or truncation still works: theSearchCardblurb, theSourceTagDetailsCardtitle and theSharedAppInputBarplaceholder. Each parent is adiv.LineItem.tsxJSDoc example now uses the Opal syntax.
Kept on purpose (31 files still import refresh Text)
Each kept site needs an Opal Text capability that does not exist yet:
Missing in Opal Text | Where |
|---|---|
className overrides against prose margins (my-0!, my-1!, leading-normal) in markdown renderers, or {...props} pass-through | AppPopup, MemoizedTextComponents, sharedMarkdownComponents, NRFChrome, theme Preview (3 sites) |
whitespace-normal / whitespace-pre-line / whitespace-pre-wrap | QueryHistoryTable (2), PlansView, ExpandableTextDisplay (3), theme Preview |
italic, uppercase tracking-wider, tracking-[0.3em], leading-relaxed, leading-4 | MessageTextRenderer, nrf SettingsPanel (2), document-processing (3), refresh Divider |
A font family or font size set through style | craft IntroContent, BuildWelcome, UserAvatar, CustomAgentAvatar |
Colors that change with group-hover, or color classes computed at runtime | refresh Divider, SourceTag (4), refresh SelectButton, craft BigButton |
inline-block align-middle, or line-clamp-1 that lets a flex item shrink without nowrap | HumanMessage, ExpandableContentWrapper, craft SideBar |
Colors with no Opal token (text-error, text-action-text-danger-05, raw red and green with dark:) | InlineFileManagement (5), OpenAPIAuthenticationModal (2), FederatedConnectorForm |
A font with no Opal preset (text-xs at weight 500, custom font-mono sizes) | ConnectorMultiSelect, OpenAPIAuthenticationModal |
Billing CSS classes (billing-error-text, billing-option-title, billing-option-badge), and text-end on an inline span | BillingDetailsView, CheckoutView, PlansView |
Its own API is the refresh TextProps | refresh Truncated, general-layouts |
The migrate-on-edit hook from #16234 will flag these files whenever an agent edits them. Most of them need an Opal Text addition first, such as whiteSpace and italic props, a tracking option and inline mode.
How Has This Been Tested?
- Full lint (
oxlint) at the top of the stack: 0 errors. 41opal(no-replaced-refresh-import)warnings are left (31 forText, in the kept files listed above). bun run types:checkat the top of the stack: "No type errors. Type coverage: 99.04% (273295 of 275932 identifiers) across 1352 files". Coverage is the same as onmain.- pre-commit (oxfmt, oxlint, typescript-check) passed on each commit.
- Mapping consistency: the agents that did parts 1 to 4 compared their mappings and agreed on the same table, including the explicit
color="text-05"default and theRefreshTextname.
Additional Options
- [Optional] Please cherry-pick this PR to the latest release version.
Summary by CodeRabbit
- Style
- Updated typography across billing, administration, onboarding, search, chat, and other areas of the app for a consistent appearance.
- Preserved existing text and interactions while improving the rendering of translated content, including emphasized text and links.
- Bug Fixes
- Improved handling of missing timestamps and counts to avoid displaying invalid values.