Skip to content

feat(title): add recipe and tokens - #31539

Open
thetaPC wants to merge 27 commits into
FW-6863-testsfrom
FW-6863
Open

thetaPC wants to merge 27 commits into
FW-6863-testsfrom
FW-6863

Conversation

@thetaPC

@thetaPC thetaPC commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Issue number: resolves internal


What is the current behavior?

ion-title does not fragment styles based on themes.

What is the new behavior?

  • Migrates ion-title to Modular Ionic: one token-driven stylesheet, IonTitleRecipe and IonTitleConfig, and per-theme token defaults for ios, md and ionic.
  • Adds a hue prop (bold by default, or subtle). The ionic theme now applies color, matching ios and md. The hue test covers every color in ios, md and ionic, so the separate color test is removed.
  • The ionic title's padding moves from the toolbar into the title's tokens, so an ionic title outside a toolbar now gets the same inline padding as ios and md.
  • size accepts medium, which is the default from the new IonTitle.size config. The header's condense effect also reads that config, so a title made large through it condenses. Size classes are now title-size-small, title-size-medium and title-size-large, and toolbar's matching classes are toolbar-title-size-*.
  • Replaces --color with --ion-title-color, which also reaches the copy of a large title shown during the iOS page transition.
  • Removes runtime theme branching (getIonTheme and the theme virtual prop) and the title-rtl class.
  • box-sizing: border-box and pointer-events: none are set in the stylesheet for every theme instead of through tokens. In md, a tap on the title's padding now reaches the toolbar, as it already did in ios and ionic.
  • The iOS large title's min-width: 100% moves to toolbar.ios.scss, next to the flex-wrap rule it works with.
  • iOS small title inset: the small title's side padding is now --ion-spacing-lg (16px) instead of 9px, matching the navigation bar prompt in Apple's iOS 17 and 18 design kits. Long small titles wrap a little sooner.
  • md title letter spacing: now 0.0075em (0.15px at 20px) instead of 0.0125em, matching Headline 6 in Google's Material 2 design kit. The old value came from a 2019 toolbar update (fix(toolbar): update md toolbar button spacing and segment padding #17537).
  • Removes the iOS toolbar's large title rule and its title-large order value. The rule's selector can't reach the slotted title, so it never applied, and the title already computes order: 0. Rendering doesn't change.
  • Adds a dynamicFontMax token helper, and rounds scaled sizes in dynamicFontMin and dynamicFontMax.
  • Snapshot changes: every md screenshot that shows a title changes on the title row only, because the tighter letter spacing shifts the text slightly. That includes other components' pages, such as the popover header and the page header behind an action sheet. The iOS title-basic screenshots change where the long small title wraps. The hue screenshots now include ios. In header's "root iOS header in an MD app" screenshot, the title follows the page's theme: an ancestor mode attribute now only affects behavior, as it already does for every migrated component.

Does this introduce a breaking change?

  • Yes
  • No

ion-title CSS variables and classes are replaced by token-driven custom properties and prop-named classes. Use the global token for theme-wide styling, or the CSS variable for component-specific overrides.

  1. Color
Old Token (global) CSS variable (component-specific)
--color IonTitle.color --ion-title-color
  1. Size classes
Old New
title-default title-size-medium
title-small title-size-small
title-large title-size-large
toolbar-title-default toolbar-title-size-medium
toolbar-title-small toolbar-title-size-small
toolbar-title-large toolbar-title-size-large
  1. RTL class: title-rtl is removed. Use ion-title:dir(rtl) instead.

  2. Theme classes: remove any instances that target ion-title.md or ion-title.ios.

  3. Taps on the title's padding: in md, a tap on the padding at the start or end of ion-title now reaches the element behind it, usually ion-toolbar. Listen on ion-toolbar if those taps need to count.

Other information

Left for the parents

Some ion-title styles still live in, or depend on, its parents. They move with that parent's work, so they aren't part of this PR.

  • Toolbar (FW-6864): the text-align rules in toolbar.ionic.scss, the iOS title's own centering and its 90px side padding in title.scss (marked TODO(FW-6864)), and the iOS large title's full-width row in toolbar.ios.scss. Once the toolbar places the title in every theme, the title's centering and side padding can go.
  • Header scroll effects: the rules in header.common.scss that hide and fade the title as the large title collapses. They depend on the header's scroll state and include its condense motion, so they move in the header migration (FW-6843).

How to test

Open each before and after link side by side.

Check Before After What to look for
Color, ionic theme none, the color page is replaced by the hue page after Each titled color is drawn in that color. Before this PR, the ionic theme drew every title dark gray
Hue, every theme none, new page ios, md and ionic The bold titles use the full color, and the subtle titles a muted one
No theme before after Before, titles use the md styles. After, they render as plain text with no padding, which is how a migrated component looks without a theme
Basic, ios theme before after Looks the same, except the long small title in the blue toolbar, which has more room at its sides and can wrap a word sooner
Basic, md theme before after Looks the same, with titles very slightly tighter from the letter spacing
Basic, ionic theme before after Looks the same on both, including the titles' padding, which now comes from the title instead of the toolbar

@thetaPC
thetaPC added this pull request to stack #31538 October 6, 2026 22:14
@vercel

vercel Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
ionic-framework Ready Ready Preview Oct 22, 2026 5:52pm UTC

Request Review

@github-actions github-actions Bot added package: core @ionic/core package package: angular @ionic/angular package package: vue @ionic/vue package package: react @ionic/react package labels Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The title in this snapshot now follows the page's md theme instead of the header's mode="ios", since migrated components take their look from the theme and mode only affects behavior; the header itself is still visible, which is what the test checks.

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

Looks good! I requested some changes. 🙂

Comment thread core/src/components/title/test/hue/index.html
Comment thread core/src/components/toolbar/toolbar.ionic.scss Outdated
Comment thread core/src/components/title/test/hue/title.e2e.ts Outdated
Comment thread core/src/components/title/title.interface.ts
Comment thread core/src/themes/ios/default.tokens.ts Outdated
Comment thread core/src/components/header/header.utils.ts
Comment thread core/src/components/title/title.interface.ts Outdated
Comment thread BREAKING.md Outdated
Comment thread BREAKING.md Outdated
Comment thread BREAKING.md Outdated

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

Looks good just one optional change in the interface!

Comment thread core/src/components/title/title.interface.ts Outdated
# Conflicts:
#	core/src/components/title/test/color/title.e2e.ts
thetaPC and others added 2 commits October 22, 2026 10:47
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
# Conflicts:
#	core/src/components/title/test/color/title.e2e.ts-snapshots/title-color-ionic-md-ltr-light-Mobile-Chrome-linux.png
#	core/src/components/title/test/color/title.e2e.ts-snapshots/title-color-ionic-md-ltr-light-Mobile-Firefox-linux.png
#	core/src/components/title/test/color/title.e2e.ts-snapshots/title-color-ionic-md-ltr-light-Mobile-Safari-linux.png
#	core/src/components/title/test/color/title.e2e.ts-snapshots/title-color-ios-ltr-Mobile-Chrome-linux.png
#	core/src/components/title/test/color/title.e2e.ts-snapshots/title-color-ios-ltr-Mobile-Firefox-linux.png
#	core/src/components/title/test/color/title.e2e.ts-snapshots/title-color-ios-ltr-Mobile-Safari-linux.png
#	core/src/components/title/test/color/title.e2e.ts-snapshots/title-color-md-ltr-Mobile-Chrome-linux.png
#	core/src/components/title/test/color/title.e2e.ts-snapshots/title-color-md-ltr-Mobile-Firefox-linux.png
#	core/src/components/title/test/color/title.e2e.ts-snapshots/title-color-md-ltr-Mobile-Safari-linux.png

This branch was successfully deployed

1 active deployment
Preview — 9c6738e7 Deployed Oct 22, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: angular @ionic/angular package package: core @ionic/core package package: react @ionic/react package package: vue @ionic/vue package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants