Skip to content

Commit 1b0f4b6

Browse files
amgleitmanAdam Gleitman
andauthored
Use FRNFontMetrics module in Text (#2269)
* Add FRNFontMetrics module * Remove debugging `console.log` statements * Use a hook to access font metrics * Add NativeFontMetrics package * Remove unneeded API * Fix spacing * Change files * Add @types/use-subscription dependency * Update yarn.lock * Add use-subscription as a dependency * Update yarn.lock again * NativeFontMetrics.tsx -> NativeFontMetrics.ts * Make NativeFontMetrics iOS only, part 1 * Stub out NativeFontMetrics for non-iOS platforms * Keep use-subscription version consistent with react-native and react-native-macos * Remove core-android capability * id -> UIFontTextStyle * Delete old changefile * Regenerate lockfiles * Delete duplicate NativeFontMetrics.tsx file * Change files * allScaleFactors -> currentScaleFactors * Use pure events to update font metrics * Update package.nuspec * Use pure JS hook to make V2 Texts rerender * Change files * Update snapshot * Remove unneeded dependency * Move fontMetrics to iOS specific file * Better isolation of iOS-specific code * Add useFontMetrics.ios.ts * Remove useFontMetricsScaleFactors warning on non-iOS platforms * Move fontMetrics accesses outside of continuation, and improve typing * Fix Text rerender shallow equality test * Handle case when NativeFontMetrics isn't defined * IFontMetrics -> FontMetrics * Keep `mergedProps` spreads next to each other Co-authored-by: Adam Gleitman <[email protected]>
1 parent bc62b6f commit 1b0f4b6

19 files changed

+168
-59
lines changed

apps/fluent-tester/ios/Podfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ use_test_app! do |target|
2424
target.app do
2525
platform :ios, '14.0'
2626

27+
# There is a bug where autolinking isn't working, do specify these manually.
28+
pod 'FRNFontMetrics', :path => '../../../packages/experimental/NativeFontMetrics/FRNFontMetrics.podspec'
29+
2730
script_phase name: 'Start Packager',
2831
script: start_packager_script,
2932
execution_position: :before_compile

apps/fluent-tester/ios/Podfile.lock

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ PODS:
1010
- React-jsi (= 0.68.5)
1111
- ReactCommon/turbomodule/core (= 0.68.5)
1212
- fmt (6.2.1)
13-
- FRNAvatar (0.16.20):
13+
- FRNAvatar (0.16.24):
1414
- MicrosoftFluentUI (= 0.8.3)
1515
- React
1616
- FRNDatePicker (0.7.3):
1717
- MicrosoftFluentUI (= 0.8.3)
1818
- React
19+
- FRNFontMetrics (0.2.0):
20+
- React
1921
- glog (0.3.5)
2022
- MicrosoftFluentUI (0.8.3):
2123
- MicrosoftFluentUI/ActivityIndicator_ios (= 0.8.3)
@@ -384,7 +386,7 @@ PODS:
384386
- glog
385387
- react-native-menu (0.1.2):
386388
- React
387-
- react-native-slider (4.3.2):
389+
- react-native-slider (4.3.3):
388390
- React-Core
389391
- React-perflogger (0.68.5)
390392
- React-RCTActionSheet (0.68.5):
@@ -468,6 +470,7 @@ DEPENDENCIES:
468470
- FBReactNativeSpec (from `../../../node_modules/react-native/React/FBReactNativeSpec`)
469471
- FRNAvatar (from `../../../packages/experimental/Avatar`)
470472
- FRNDatePicker (from `../../../packages/experimental/NativeDatePicker`)
473+
- FRNFontMetrics (from `../../../packages/experimental/NativeFontMetrics/FRNFontMetrics.podspec`)
471474
- glog (from `../../../node_modules/react-native/third-party-podspecs/glog.podspec`)
472475
- RCT-Folly (from `../../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
473476
- RCTRequired (from `../../../node_modules/react-native/Libraries/RCTRequired`)
@@ -522,6 +525,8 @@ EXTERNAL SOURCES:
522525
:path: "../../../packages/experimental/Avatar"
523526
FRNDatePicker:
524527
:path: "../../../packages/experimental/NativeDatePicker"
528+
FRNFontMetrics:
529+
:path: "../../../packages/experimental/NativeFontMetrics/FRNFontMetrics.podspec"
525530
glog:
526531
:podspec: "../../../node_modules/react-native/third-party-podspecs/glog.podspec"
527532
RCT-Folly:
@@ -595,8 +600,9 @@ SPEC CHECKSUMS:
595600
FBLazyVector: 2b47ff52037bd9ae07cc9b051c9975797814b736
596601
FBReactNativeSpec: dd89c4a5591e20015aa55c6efbf9c7740a83efbf
597602
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
598-
FRNAvatar: de1aec8a9011ade478f2148677b4f2c076d77110
603+
FRNAvatar: 3911021ed95a08f19e0ee696712aa48b6dff010a
599604
FRNDatePicker: 241cd55b8d2b63d4427d782951f31504f09fbe1a
605+
FRNFontMetrics: 472e7952e454ece364a91babd8bb2a32219676e7
600606
glog: 476ee3e89abb49e07f822b48323c51c57124b572
601607
MicrosoftFluentUI: e30487dd18aba04beeed4caf1ce1988073f8b03a
602608
RCT-Folly: 4d8508a426467c48885f1151029bc15fa5d7b3b8
@@ -613,7 +619,7 @@ SPEC CHECKSUMS:
613619
React-jsinspector: eb202e43b3879aba9a14f3f65788aec85d4e1ea9
614620
React-logger: 98f663b292a60967ebbc6d803ae96c1381183b6d
615621
react-native-menu: 9fe07f72e075b250295eeae25425490cc9608951
616-
react-native-slider: e540525ea731783850802b7af457d8551edb0711
622+
react-native-slider: 7d19220da2f2ae7cbb9aa80127cb73c597fa221f
617623
React-perflogger: 0458a87ea9a7342079e7a31b0d32b3734fb8415f
618624
React-RCTActionSheet: 22538001ea2926dea001111dd2846c13a0730bc9
619625
React-RCTAnimation: 732ce66878d4aa151d56a0d142b1105aa12fd313
@@ -632,6 +638,6 @@ SPEC CHECKSUMS:
632638
RNSVG: 302bfc9905bd8122f08966dc2ce2d07b7b52b9f8
633639
Yoga: c4d61225a466f250c35c1ee78d2d0b3d41fe661c
634640

635-
PODFILE CHECKSUM: eeba196fb25cf059c631787109cecd08a4ac85a6
641+
PODFILE CHECKSUM: 819f14a4e3e6e335a0b1993fe37edad50db02d86
636642

637643
COCOAPODS: 1.11.3
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "minor",
3+
"comment": "Send new font metrics information through a JS event",
4+
"packageName": "@fluentui-react-native/experimental-native-font-metrics",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "minor",
3+
"comment": "Add Dynamic Type support",
4+
"packageName": "@fluentui-react-native/tester",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "minor",
3+
"comment": "Add Dynamic Type support",
4+
"packageName": "@fluentui-react-native/text",
5+
"email": "[email protected]",
6+
"dependentChangeType": "patch"
7+
}

package.nuspec

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
<!-- iOS device ship -->
1313
<file src="DerivedData\Build\Products\Release-iphoneos\FRNAvatar\libFRNAvatar.a" target="Ship-iphoneos"/>
1414
<file src="DerivedData\Build\Products\Release-iphoneos\FRNDatePicker\libFRNDatePicker.a" target="Ship-iphoneos"/>
15+
<file src="DerivedData\Build\Products\Release-iphoneos\FRNFontMetrics\libFRNFontMetrics.a" target="Ship-iphoneos"/>
1516

1617
<!-- iOS simulator ship -->
1718
<file src="DerivedData\Build\Products\Release-iphonesimulator\FRNAvatar\libFRNAvatar.a" target="Ship-iphonesimulator"/>
1819
<file src="DerivedData\Build\Products\Release-iphonesimulator\FRNDatePicker\libFRNDatePicker.a" target="Ship-iphonesimulator"/>
20+
<file src="DerivedData\Build\Products\Release-iphonesimulator\FRNFontMetrics\libFRNFontMetrics.a" target="Ship-iphoneos"/>
1921

2022
<!-- macOS ship -->
2123
<file src="DerivedData\Build\Products\Release\FRNAvatar\libFRNAvatar.a" target="Ship-macosx"/>

packages/components/text/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"dependencies": {
2929
"@uifabricshared/foundation-compose": "^1.12.22",
3030
"@fluentui-react-native/adapters": ">=0.10.0 <1.0.0",
31+
"@fluentui-react-native/experimental-native-font-metrics": "^0.2.0",
3132
"@fluentui-react-native/framework": "0.8.21",
3233
"@fluentui-react-native/interactive-hooks": ">=0.21.2 <1.0.0",
3334
"@fluentui-react-native/theme-tokens": ">=0.21.3 <1.0.0",

packages/components/text/src/Text.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { I18nManager, Platform, Text as RNText } from 'react-native';
1515
import { textName, TextProps, TextTokens } from './Text.types';
1616
import { useTextTokens } from './TextTokens';
1717
import React from 'react';
18+
import { useFontMetricsScaleFactors } from '@fluentui-react-native/experimental-native-font-metrics';
1819

1920
const emptyProps = {};
2021
export const Text = compressible<TextProps, TextTokens>((props: TextProps, useTokens: UseTokens<TextTokens>) => {
@@ -49,6 +50,9 @@ export const Text = compressible<TextProps, TextTokens>((props: TextProps, useTo
4950
// get the tokens from the theme
5051
let [tokens, cache] = useTokens(theme);
5152

53+
// TODO(#2268): Remove once RN Core properly supports Dynamic Type scaling
54+
const fontMetricsScaleFactors = useFontMetricsScaleFactors();
55+
5256
const textAlign = I18nManager.isRTL
5357
? align === 'start'
5458
? 'right'
@@ -79,6 +83,9 @@ export const Text = compressible<TextProps, TextTokens>((props: TextProps, useTo
7983
[onPress, onAccessibilityTap],
8084
);
8185

86+
// TODO(#2268): Remove once RN Core properly supports Dynamic Type scaling
87+
const dynamicTypeVariant = Platform.OS === 'ios' ? tokens.dynamicTypeRamp : undefined;
88+
8289
// override tokens from props
8390
[tokens, cache] = patchTokens(tokens, cache, {
8491
color,
@@ -106,6 +113,19 @@ export const Text = compressible<TextProps, TextTokens>((props: TextProps, useTo
106113
['color', 'fontStyle', 'textAlign', 'textDecorationLine', ...fontStyles.keys],
107114
);
108115

116+
// [TODO(#2268): Remove once RN Core properly supports Dynamic Type scaling
117+
let scaleStyleAdjustments: TextTokens = emptyProps;
118+
// tokenStyle.fontSize and tokenStyle.lineHeight can also be strings (e.g., "14px").
119+
// Therefore, we only support scaling for number-based size values in order to avoid any messy calculations.
120+
if (dynamicTypeVariant !== undefined && typeof tokenStyle.fontSize === 'number' && typeof tokenStyle.lineHeight === 'number') {
121+
const scaleFactor = fontMetricsScaleFactors[dynamicTypeVariant] ?? 1;
122+
scaleStyleAdjustments = {
123+
fontSize: tokenStyle.fontSize * scaleFactor,
124+
lineHeight: tokenStyle.lineHeight * scaleFactor,
125+
};
126+
}
127+
// ]TODO(#2268)
128+
109129
const isWinPlatform = Platform.OS === (('win32' as any) || 'windows');
110130
const filteredProps = {
111131
onKeyUp: isWinPlatform ? onKeyUp : undefined,
@@ -124,9 +144,10 @@ export const Text = compressible<TextProps, TextTokens>((props: TextProps, useTo
124144
...keyProps,
125145
...filteredProps,
126146
...extra,
147+
...(dynamicTypeVariant !== undefined && { allowFontScaling: false }), // TODO(#2268): Remove once RN Core properly supports Dynamic Type scaling
127148
onPress,
128149
numberOfLines: truncate || !wrap ? 1 : 0,
129-
style: mergeStyles(tokenStyle, props.style, extra?.style),
150+
style: mergeStyles(tokenStyle, props.style, extra?.style, scaleStyleAdjustments),
130151
};
131152
return (
132153
<RNText ellipsizeMode={!wrap && !truncate ? 'clip' : 'tail'} {...mergedProps}>

packages/components/text/src/Text.types.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ export const textName = 'Text';
88
* Text tokens, these are the internally configurable values for Text elements. In particular these
99
* drive decisions on how to build the styles
1010
*/
11-
export type TextTokens = Omit<FontTokens, 'fontFamily'> & IForegroundColorTokens & Omit<TextStyle, 'fontSize' | 'fontWeight' | 'color'>;
11+
export type TextTokens = Omit<FontTokens, 'fontFamily'> &
12+
IForegroundColorTokens &
13+
Omit<TextStyle, 'fontSize' | 'fontWeight' | 'color'> & {
14+
dynamicTypeRamp?: string; // TODO(#2268): Remove once RN Core properly supports Dynamic Type scaling
15+
};
1216

1317
export type TextAlign = 'start' | 'center' | 'end' | 'justify';
1418
export type TextFont = 'base' | 'monospace' | 'numeric';
Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,57 @@
11
import { Text } from './Text';
22

3+
// TODO(#2268): Remove "as any" designations once RN Core properly supports Dynamic Type scaling
4+
35
export const Caption1 = Text.customize({
46
variant: 'caption1',
5-
});
7+
dynamicTypeRamp: 'footnote',
8+
} as any);
69
export const Caption1Strong = Text.customize({
710
variant: 'caption1Strong',
8-
});
11+
dynamicTypeRamp: 'footnote',
12+
} as any);
913
export const Caption2 = Text.customize({
1014
variant: 'caption2',
11-
});
15+
dynamicTypeRamp: 'caption1',
16+
} as any);
1217
export const Body1 = Text.customize({
1318
variant: 'body1',
14-
});
19+
dynamicTypeRamp: 'body',
20+
} as any);
1521
export const Body1Strong = Text.customize({
1622
variant: 'body1Strong',
17-
});
23+
dynamicTypeRamp: 'body',
24+
} as any);
1825
export const Body2 = Text.customize({
1926
variant: 'body2',
20-
});
27+
dynamicTypeRamp: 'subheadline',
28+
} as any);
2129
export const Body2Strong = Text.customize({
2230
variant: 'body2Strong',
23-
});
31+
dynamicTypeRamp: 'subheadline',
32+
} as any);
2433
export const Subtitle1 = null; // Not supported on iOS
2534
export const Subtitle1Strong = null; // Not supported on iOS
2635
export const Subtitle2 = null; // Not supported on iOS
2736
export const Subtitle2Strong = null; // Not supported on iOS
2837
export const Title1 = Text.customize({
2938
variant: 'title1',
30-
});
39+
dynamicTypeRamp: 'title1',
40+
} as any);
3141
export const Title1Strong = null; // Not supported on iOS
3242
export const Title2 = Text.customize({
3343
variant: 'title2',
34-
});
44+
dynamicTypeRamp: 'title2',
45+
} as any);
3546
export const Title3 = Text.customize({
3647
variant: 'title3',
37-
});
48+
dynamicTypeRamp: 'title3',
49+
} as any);
3850
export const LargeTitle = Text.customize({
3951
variant: 'largeTitle',
40-
});
52+
dynamicTypeRamp: 'largeTitle',
53+
} as any);
4154
export const Display = Text.customize({
4255
variant: 'display',
43-
});
56+
dynamicTypeRamp: 'largeTitle',
57+
} as any);

0 commit comments

Comments
 (0)