* Add maximumSize

* Remove extra LimitedDisplay customization

* Change files

* Simplify maximumFontSize math

* grammar

* Add comment about iOS-only FontStyleTokens props

* Add documentation for custom TextTokens

* TODO(#2268) -> GH #2268

* Add MaximumFontSize test element

* Organize imports

* Change files

Co-authored-by: Adam Gleitman <adgleitm@microsoft.com>
This commit is contained in:
Adam Gleitman 2022-12-15 06:22:37 -08:00 коммит произвёл GitHub
Родитель 3500d25b49
Коммит ac1a77d965
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
15 изменённых файлов: 127 добавлений и 19 удалений

Просмотреть файл

@ -10,7 +10,7 @@ PODS:
- React-jsi (= 0.68.5)
- ReactCommon/turbomodule/core (= 0.68.5)
- fmt (6.2.1)
- FRNAvatar (0.16.25):
- FRNAvatar (0.16.26):
- MicrosoftFluentUI (= 0.8.3)
- React
- FRNDatePicker (0.7.3):
@ -453,7 +453,7 @@ PODS:
- React-jsi (= 0.68.5)
- React-logger (= 0.68.5)
- React-perflogger (= 0.68.5)
- ReactTestApp-DevSupport (2.1.0):
- ReactTestApp-DevSupport (2.1.1):
- React-Core
- React-jsi
- ReactTestApp-Resources (1.0.0-dev)
@ -600,7 +600,7 @@ SPEC CHECKSUMS:
FBLazyVector: 2b47ff52037bd9ae07cc9b051c9975797814b736
FBReactNativeSpec: dd89c4a5591e20015aa55c6efbf9c7740a83efbf
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
FRNAvatar: 0c18045ffd13fb317f27c4111c5de6f4ad0ab1a8
FRNAvatar: b34747d6662c3c556970518a0f3d886eca2205b8
FRNDatePicker: 241cd55b8d2b63d4427d782951f31504f09fbe1a
FRNFontMetrics: c756b9bb1627909a7673b68caf7a7b14239c212e
glog: 476ee3e89abb49e07f822b48323c51c57124b572
@ -632,7 +632,7 @@ SPEC CHECKSUMS:
React-RCTVibration: 9819a3bf6230e4b2a99877c21268b0b2416157a1
React-runtimeexecutor: b1f1995089b90696dbc2a7ffe0059a80db5c8eb1
ReactCommon: 149e2c0acab9bac61378da0db5b2880a1b5ff59b
ReactTestApp-DevSupport: bc72bbe8928c428f73e23d740fb13161609d9b9d
ReactTestApp-DevSupport: 7ca8e4d798fce59f47adedd8f05a94d41d312921
ReactTestApp-Resources: ecba662266ac5af3e30e1e3004c0fa8c0298b61a
RNCPicker: 0bf8ef8f7800524f32d2bb2a8bcadd53eda0ecd1
RNSVG: 302bfc9905bd8122f08966dc2ce2d07b7b52b9f8

Просмотреть файл

@ -0,0 +1,29 @@
import * as React from 'react';
import { Text, View } from 'react-native';
import { Stack } from '@fluentui-react-native/stack';
import { stackStyle } from '../Common/styles';
import { Caption1, Title2, Title3 } from '@fluentui-react-native/text';
import { Separator } from '@fluentui/react-native';
const maximumFontSizeStyle = { maximumFontSize: 36 };
const CappedTitle2 = Title2.customize(maximumFontSizeStyle);
const CappedTitle3 = Title3.customize(maximumFontSizeStyle);
export const MaximumFontSizeUsage: React.FunctionComponent = () => {
return (
<View>
<Stack style={stackStyle} gap={5}>
<Caption1>Play with the preferred content size. The marked elements should not grow larger than 36 points.</Caption1>
<Separator />
<Title2>Title2</Title2>
<Title3>Title3</Title3>
<CappedTitle2>Title2 (capped)</CappedTitle2>
<CappedTitle3>Title3 (capped)</CappedTitle3>
<Text allowFontScaling={false} style={{ fontSize: 36, fontWeight: '600' }}>
This is 36 pt
</Text>
</Stack>
</View>
);
};

Просмотреть файл

@ -0,0 +1,6 @@
import * as React from 'react';
import { Text } from 'react-native';
export const MaximumFontSizeUsage: React.FunctionComponent = () => {
return <Text>Only available on iOS.</Text>;
};

Просмотреть файл

@ -1,11 +1,12 @@
import * as React from 'react';
import { StandardUsage } from './StandardUsage';
import { V2Usage } from './V2Usage';
import { MaximumFontSizeUsage } from './MaximumFontSize';
import { CustomizeUsage } from './CustomizeUsage';
import { PressableUsage } from './PressableUsage';
import { Test, TestSection, PlatformStatus } from '../Test';
import { E2EExperimentalTextTest } from './ExperimentalTextE2ETest';
import { EXPERIMENTAL_TEXT_TESTPAGE } from './consts';
import { V2Usage } from './V2Usage';
const textSections: TestSection[] = [
{
@ -17,6 +18,10 @@ const textSections: TestSection[] = [
name: 'V2/V1 Comparison',
component: V2Usage,
},
{
name: 'Maximum Font Size Usage',
component: MaximumFontSizeUsage,
},
{
name: 'Customize Usage',
component: CustomizeUsage,

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Add maximumSize",
"packageName": "@fluentui-react-native/button",
"email": "adgleitm@microsoft.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Add maximumSize",
"packageName": "@fluentui-react-native/tester",
"email": "adgleitm@microsoft.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Add maximumSize",
"packageName": "@fluentui-react-native/text",
"email": "adgleitm@microsoft.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Add MaximumFontSize test element",
"packageName": "@fluentui-react-native/theme-types",
"email": "adgleitm@microsoft.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Add maximumSize",
"packageName": "@fluentui-react-native/tokens",
"email": "adgleitm@microsoft.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -107,6 +107,7 @@ exports[`Button component tests Button composed 1`] = `
"marginEnd": 0,
"marginStart": 0,
"marginTop": 0,
"maximumFontSize": undefined,
}
}
>

Просмотреть файл

@ -50,7 +50,7 @@ export const Text = compressible<TextProps, TextTokens>((props: TextProps, useTo
// get the tokens from the theme
let [tokens, cache] = useTokens(theme);
// TODO(#2268): Remove once RN Core properly supports Dynamic Type scaling
// GH #2268: Remove once RN Core properly supports Dynamic Type scaling
const fontMetricsScaleFactors = useFontMetricsScaleFactors();
const textAlign = I18nManager.isRTL
@ -88,6 +88,7 @@ export const Text = compressible<TextProps, TextTokens>((props: TextProps, useTo
color,
variant,
fontFamily: font == 'base' ? 'primary' : font,
fontMaximumSize: tokens.maximumFontSize,
fontSize: globalTokens.font['size' + size],
fontWeight: globalTokens.font.weight[weight] as FontWeightValue,
// leave it undefined for tokens to be set by user
@ -110,21 +111,24 @@ export const Text = compressible<TextProps, TextTokens>((props: TextProps, useTo
['color', 'fontStyle', 'textAlign', 'textDecorationLine', ...fontStyles.keys],
);
// TODO(#2268): Remove once RN Core properly supports Dynamic Type scaling
// [GH #2268: Remove once RN Core properly supports Dynamic Type scaling
const dynamicTypeVariant = Platform.OS === 'ios' ? tokenStyle.dynamicTypeRamp : undefined;
const maximumFontSize = tokenStyle.maximumFontSize ?? Number.POSITIVE_INFINITY;
// [TODO(#2268): Remove once RN Core properly supports Dynamic Type scaling
let scaleStyleAdjustments: TextTokens = emptyProps;
// tokenStyle.fontSize and tokenStyle.lineHeight can also be strings (e.g., "14px").
// Therefore, we only support scaling for number-based size values in order to avoid any messy calculations.
if (dynamicTypeVariant !== undefined && typeof tokenStyle.fontSize === 'number' && typeof tokenStyle.lineHeight === 'number') {
const scaleFactor = fontMetricsScaleFactors[dynamicTypeVariant] ?? 1;
const requestedScaleFactor = fontMetricsScaleFactors[dynamicTypeVariant] ?? 1;
const maximumScaleFactor = maximumFontSize / tokenStyle.fontSize;
const scaleFactor = Math.min(requestedScaleFactor, maximumScaleFactor);
scaleStyleAdjustments = {
fontSize: tokenStyle.fontSize * scaleFactor,
lineHeight: tokenStyle.lineHeight * scaleFactor,
lineHeight: tokenStyle.lineHeight * scaleFactor, // scale accordingly with fontSize
};
}
// ]TODO(#2268)
// ]GH #2268
const isWinPlatform = Platform.OS === (('win32' as any) || 'windows');
const filteredProps = {
@ -144,12 +148,16 @@ export const Text = compressible<TextProps, TextTokens>((props: TextProps, useTo
...keyProps,
...filteredProps,
...extra,
...(dynamicTypeVariant !== undefined && { allowFontScaling: false }), // TODO(#2268): Remove once RN Core properly supports Dynamic Type scaling
...(dynamicTypeVariant !== undefined && { allowFontScaling: false }), // GH #2268: Remove once RN Core properly supports Dynamic Type scaling
onPress,
numberOfLines: truncate || !wrap ? 1 : 0,
style: mergeStyles(tokenStyle, props.style, extra?.style, scaleStyleAdjustments),
};
delete (mergedProps.style as TextTokens).dynamicTypeRamp; // TODO(#2268): RN Text doesn't recognize dynamicTypeRamp yet, so don't let it leak through or RN will complain about it being an invalid prop
// GH #2268: RN Text doesn't recognize these properties yet, so don't let them leak through or RN will complain about invalid props
delete (mergedProps.style as TextTokens).dynamicTypeRamp;
delete (mergedProps.style as TextTokens).maximumFontSize;
return (
<RNText ellipsizeMode={!wrap && !truncate ? 'clip' : 'tail'} {...mergedProps}>
{children}

Просмотреть файл

@ -11,7 +11,18 @@ export const textName = 'Text';
export type TextTokens = Omit<FontTokens, 'fontFamily'> &
IForegroundColorTokens &
Omit<TextStyle, 'fontSize' | 'fontWeight' | 'color'> & {
dynamicTypeRamp?: string; // TODO(#2268): Remove once RN Core properly supports Dynamic Type scaling
// GH #2268: Remove these once RN Core properly supports Dynamic Type scaling
/**
* (iOS only) The Dynamic Type ramp that a Text element should follow as the user changes their
* preferred content size.
*/
dynamicTypeRamp?: string;
/**
* (iOS only) The maximum font size that a Text element will grow to as the user changes their
* preferred content size.
*/
maximumFontSize?: number;
};
export type TextAlign = 'start' | 'center' | 'end' | 'justify';

Просмотреть файл

@ -1,6 +1,6 @@
import { Text } from './Text';
// TODO(#2268): Remove "as any" designations once RN Core properly supports Dynamic Type scaling
// GH #2268: Remove "as any" designations once RN Core properly supports Dynamic Type scaling
export const Caption1 = Text.customize({
variant: 'caption1',

Просмотреть файл

@ -104,7 +104,7 @@ export type FontLetterSpacing = number;
/**
* On iOS, the Dynamic Type ramp that this variant should conform to.
*/
export type FontDynamicTypeRamp = string; // TODO(#2268): Import type from RN directly
export type FontDynamicTypeRamp = string; // GH #2268: Import type from RN directly
/**
* A font variant value.

Просмотреть файл

@ -14,14 +14,16 @@ export interface FontStyleTokens {
fontWeight?: keyof Typography['weights'] | TextStyle['fontWeight'];
fontLineHeight?: TextStyle['lineHeight'];
fontLetterSpacing?: TextStyle['letterSpacing'];
fontDynamicTypeRamp?: string; // TODO(#2268): Import type from RN directly
// Props below are used on iOS only. GH #2268: Import these from RN directly
fontDynamicTypeRamp?: string;
fontMaximumSize?: number;
}
export type FontTokens = FontStyleTokens & FontVariantTokens;
export const fontStyles: TokenBuilder<FontTokens> = {
from: (
{ fontDynamicTypeRamp, fontFamily, fontLetterSpacing, fontLineHeight, fontSize, fontWeight, variant }: FontTokens,
{ fontDynamicTypeRamp, fontFamily, fontLetterSpacing, fontLineHeight, fontMaximumSize, fontSize, fontWeight, variant }: FontTokens,
{ typography }: Theme,
) => {
const { families, sizes, weights, variants } = typography;
@ -30,6 +32,7 @@ export const fontStyles: TokenBuilder<FontTokens> = {
fontFamily !== undefined ||
fontLetterSpacing !== undefined ||
fontLineHeight !== undefined ||
fontMaximumSize !== undefined ||
fontSize !== undefined ||
fontWeight !== undefined ||
variant !== undefined
@ -41,12 +44,22 @@ export const fontStyles: TokenBuilder<FontTokens> = {
lineHeight: fontLineHeight ?? variants[variant]?.lineHeight,
letterSpacing: fontLetterSpacing ?? variants[variant]?.letterSpacing,
dynamicTypeRamp: fontDynamicTypeRamp ?? variants[variant]?.dynamicTypeRamp,
maximumFontSize: fontMaximumSize,
};
}
return {};
},
keys: ['fontDynamicTypeRamp', 'fontFamily', 'fontLineHeight', 'fontLetterSpacing', 'fontSize', 'fontWeight', 'variant'],
keys: [
'fontDynamicTypeRamp',
'fontFamily',
'fontLineHeight',
'fontLetterSpacing',
'fontMaximumSize',
'fontSize',
'fontWeight',
'variant',
],
};
function _buildTextStyles(tokens: FontTokens, theme: Theme): ITextProps {