Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
28099bb
Add typography token layer and alias text styles to it
grgia Jul 23, 2026
ae34e65
Add Text variant prop and deprecate raw fontSize prop
grgia Jul 23, 2026
cfa5bb1
Add no-raw-typography lint rule with seatbelt baseline
grgia Jul 23, 2026
b8ff6e7
Rename text variants to match the Figma Product type scale
grgia Jul 23, 2026
9bbefa5
Migrate QRShare to Text variants as the example call-site
grgia Jul 23, 2026
b6fa548
Align headline, label, and micro strong values with the Figma library
grgia Jul 24, 2026
6db2269
Merge remote-tracking branch 'origin/main' into georgia-font-lib
grgia Jul 24, 2026
3f17671
Merge remote-tracking branch 'origin/main' into georgia-font-lib
grgia Jul 28, 2026
2c9c878
Rename hero to introHeadline and align line height with Figma
grgia Jul 28, 2026
1ac4e0c
Remove unused fontSizeHeroXL and fontSizeSignInHeroSmall
grgia Jul 28, 2026
50b8207
Delete unused Breadcrumbs component and its styles
grgia Jul 28, 2026
543eb6d
Merge remote-tracking branch 'origin/main' into georgia-font-lib
grgia Aug 10, 2026
04da195
Migrate loading and magic-link screen headings to H1
grgia Aug 11, 2026
ef521fc
Add the remaining Figma Product text styles as variants
grgia Aug 11, 2026
e7cdf9f
Merge remote-tracking branch 'origin/main' into georgia-font-lib
grgia Aug 11, 2026
5b4fdc6
Use the finePrintStrong variant for extra-small button text
grgia Aug 11, 2026
41fb8bb
Restore the large balance line height and clean up comment style
grgia Aug 12, 2026
c1ed760
Assert the text variants match the Figma Product type scale
grgia Aug 12, 2026
ae61851
Fix lint errors in the type scale test
grgia Aug 12, 2026
a98e180
Merge remote-tracking branch 'origin/main' into georgia-font-lib
grgia Aug 12, 2026
44cae82
Merge remote-tracking branch 'origin/main' into georgia-font-lib
grgia Aug 14, 2026
4474d96
Seatbelt raw fontSize added on main in DistanceSymbol styles
grgia Aug 14, 2026
6140382
Merge remote-tracking branch 'origin/main' into georgia-font-lib
grgia Aug 17, 2026
c0e60b2
Unwrap TS assertions before checking for raw typography literals
grgia Aug 17, 2026
bf8e619
Credit index.ts spreads after all style definitions are registered an…
grgia Aug 17, 2026
bc07863
Merge remote-tracking branch 'origin/main' into georgia-font-lib
grgia Aug 18, 2026
8c538fc
Treat unary plus literals as raw typography values
grgia Aug 18, 2026
566d0d8
Drop stale seatbelt entries picked up from an older main
grgia Aug 18, 2026
af1b538
Size suggestion menu emojis like inline emojis and labels like body text
grgia Aug 20, 2026
90889e8
Merge remote-tracking branch 'origin/main' into georgia-font-lib
grgia Aug 20, 2026
c226807
Use microStrong for the participants text style added on main
grgia Aug 20, 2026
61dbba6
Use lineHeightNormal in the report group header and drop settled seat…
grgia Aug 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions config/eslint/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ const config = defineConfig([
'rulesdir/require-a11y-disable-justification': 'error',
'rulesdir/no-direct-pre-insert-fullscreen-under-rhp': 'error',
'rulesdir/no-useOnyx-dependencies-arg': 'error',
'rulesdir/no-raw-typography': 'error',
'rulesdir/prefer-narrow-hook-dependencies': [
'error',
{
Expand Down Expand Up @@ -655,6 +656,14 @@ const config = defineConfig([
rules: {'report-name-utils/no-function-call-in-get-report-name': 'error'},
},

// The typography token files are where raw font sizes and line heights are defined.
{
files: ['src/styles/typography.ts', 'src/styles/variables.ts'],
rules: {
'rulesdir/no-raw-typography': 'off',
},
},

// Restrict `computeReportName` imports everywhere except the one file that
// legitimately consumes it. This block overrides the main `no-restricted-imports`
// for ts/tsx files, so we re-apply the main `restrictedImportPaths`/`restrictedImportPatterns`
Expand Down
21 changes: 21 additions & 0 deletions config/eslint/eslint.seatbelt.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
"../../src/components/CategoryPicker/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/Charts/BarChart/BarChartContent.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/Charts/hooks/useChartLabelFormats.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/Charts/hooks/useChartLabelMeasurements.ts" "rulesdir/no-raw-typography" 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are all changes in this file necessary? We should not add more eslint disablings.

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.

Each new row is an existing violation of the two checks this PR introduces: raw fontSize/lineHeight values, and the now-deprecated fontSize prop on Text. Listing them at today's counts lets both checks ship as errors without migrating all ~60 call sites in this PR. They get removed as files migrate to the tokens.

"../../src/components/Charts/utils/chartFontAssets.native.ts" "@typescript-eslint/no-unsafe-type-assertion" 13
"../../src/components/Charts/utils/chartFontAssets.ts" "@typescript-eslint/no-unsafe-type-assertion" 13
"../../src/components/Charts/utils/chartFontsCache.ts" "@typescript-eslint/no-unsafe-type-assertion" 2
Expand Down Expand Up @@ -194,6 +195,7 @@
"../../src/components/HTMLEngineProvider/HTMLRenderers/AccountManagerLinkRenderer.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/HTMLEngineProvider/HTMLRenderers/ConciergeLinkRenderer.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/HTMLEngineProvider/HTMLRenderers/EditedRenderer.tsx" "@typescript-eslint/no-deprecated/fontSize" 3
"../../src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2
"../../src/components/HTMLEngineProvider/HTMLRenderers/MentionHereRenderer.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
Expand All @@ -203,6 +205,7 @@
"../../src/components/HTMLEngineProvider/HTMLRenderers/TransactionHistoryLinkRenderer.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/components/VictoryChartPie.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/parsers/victorySeriesParser.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/getSkiaLineMetrics.ts" "rulesdir/no-raw-typography" 1
"../../src/components/HTMLEngineProvider/index.tsx" "no-restricted-syntax" 1
"../../src/components/HeaderWithBackButton/index.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2
"../../src/components/Hoverable/ActiveHoverable.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
Expand Down Expand Up @@ -274,6 +277,7 @@
"../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx" "react-hooks/refs" 3
"../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx" "react-hooks/set-state-in-effect" 3
"../../src/components/MoneyRequestReportView/MoneyRequestReportGroupHeader.tsx" "rulesdir/no-raw-typography" 1
"../../src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2
"../../src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx" "no-restricted-imports" 1
"../../src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2
Expand Down Expand Up @@ -347,13 +351,16 @@
"../../src/components/ReportActionItem/MoneyRequestView.tsx" "@typescript-eslint/no-deprecated/deprecatedGetReportName" 2
"../../src/components/ReportActionItem/TaskPreview.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/ReportActionItem/TaskView.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx" "@typescript-eslint/no-deprecated/fontSize" 3
"../../src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx" "no-restricted-imports" 1
"../../src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx" "rulesdir/no-raw-typography" 1
"../../src/components/ReportActionItem/TripRoomPreview.tsx" "no-restricted-imports" 1
"../../src/components/ReportActionItem/receiptHoverUtils/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 2
"../../src/components/ReportWelcomeText.tsx" "@typescript-eslint/no-deprecated/deprecatedGetReportName" 1
"../../src/components/RoomHeaderAvatars.tsx" "no-restricted-syntax" 2
"../../src/components/Rule/RuleBooleanBase.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/Rule/TextBase.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2
"../../src/components/SAMLLoadingIndicator.tsx" "@typescript-eslint/no-deprecated/fontSize" 1
"../../src/components/ScreenShareRequestModal.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1
"../../src/components/ScreenWrapper/ScreenWrapperContainer.tsx" "react-hooks/refs" 2
"../../src/components/Search/FilterComponents/AdvancedFilters/AmountFilterContent.tsx" "no-restricted-imports" 1
Expand Down Expand Up @@ -434,6 +441,7 @@
"../../src/components/SelectionList/BaseSelectionList.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/SelectionList/ListItem/BaseListItem.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/SelectionList/ListItem/SpendRuleListItem.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/SelectionList/ListItem/SplitListItem.tsx" "@typescript-eslint/no-deprecated/fontSize" 1
"../../src/components/SelectionList/ListItem/SplitListItem.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2
"../../src/components/SelectionList/SelectionListWithSections/BaseSelectionListWithSections.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/SelectionList/components/Footer.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
Expand Down Expand Up @@ -482,6 +490,7 @@
"../../src/components/TaxPicker.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/TestCrash/index.native.tsx" "no-restricted-imports" 1
"../../src/components/TestDrive/TestDriveBanner.tsx" "no-restricted-imports" 1
"../../src/components/Text.tsx" "@typescript-eslint/no-deprecated/fontSize" 1
"../../src/components/TextInput/BaseTextInput/implementation/index.native.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/TextInput/BaseTextInput/implementation/index.native.tsx" "react-hooks/refs" 2
"../../src/components/TextInput/BaseTextInput/implementation/index.native.tsx" "react-hooks/static-components" 1
Expand Down Expand Up @@ -516,6 +525,7 @@
"../../src/components/TransactionItemRow/EditableCell/usePopoverEditState.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/UpdateAppModal.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1
"../../src/components/UploadFile.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/components/UserInitialsAvatar.tsx" "@typescript-eslint/no-deprecated/fontSize" 1
"../../src/components/ValidateCodeActionModal/ValidateCodeForm/BaseValidateCodeForm.tsx" "no-restricted-imports" 1
"../../src/components/VideoPlayer/BaseVideoPlayer.tsx" "@typescript-eslint/no-unsafe-type-assertion" 7
"../../src/components/VideoPlayer/BaseVideoPlayer.tsx" "no-restricted-syntax" 1
Expand Down Expand Up @@ -574,6 +584,7 @@
"../../src/hooks/useLazyAsset.ts" "@typescript-eslint/no-unsafe-type-assertion" 3
"../../src/hooks/useLazyAsset.ts" "react-hooks/set-state-in-effect" 1
"../../src/hooks/useListKeyboardNav.ts" "@typescript-eslint/no-unsafe-type-assertion" 2
"../../src/hooks/useMarkdownStyle.ts" "rulesdir/no-raw-typography" 2
"../../src/hooks/useNativeCamera.ts" "react-hooks/refs" 1
"../../src/hooks/useNewTransactions.ts" "react-hooks/refs" 2
"../../src/hooks/useOnyx.ts" "@typescript-eslint/no-unsafe-type-assertion" 10
Expand Down Expand Up @@ -1086,6 +1097,7 @@
"../../src/pages/MissingPersonalDetails/subPages/Address.tsx" "@typescript-eslint/no-unsafe-type-assertion" 5
"../../src/pages/MissingPersonalDetails/subPages/Address.tsx" "react-hooks/refs" 4
"../../src/pages/MissingPersonalDetails/subPages/PIN.tsx" "no-restricted-imports" 1
"../../src/pages/MultifactorAuthentication/AuthorizeTransactionPage/AuthorizeCardTransactionPreview.tsx" "@typescript-eslint/no-deprecated/fontSize" 2
"../../src/pages/MultifactorAuthentication/AuthorizeTransactionPage/AuthorizeTransactionActions.tsx" "no-restricted-imports" 1
"../../src/pages/MultifactorAuthentication/PromptPage.tsx" "no-restricted-imports" 1
"../../src/pages/MultifactorAuthentication/RevokePage.tsx" "@typescript-eslint/no-deprecated/ConfirmModal" 1
Expand Down Expand Up @@ -1181,11 +1193,13 @@
"../../src/pages/ShareCodePage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2
"../../src/pages/TeachersUnite/ImTeacherUpdateEmailPage.tsx" "no-restricted-imports" 1
"../../src/pages/TeachersUnite/SaveTheWorldPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/pages/TransactionDuplicate/Confirmation.tsx" "@typescript-eslint/no-deprecated/fontSize" 1
"../../src/pages/TransactionDuplicate/Confirmation.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/pages/TransactionDuplicate/Confirmation.tsx" "no-restricted-imports" 2
"../../src/pages/TransactionDuplicate/Confirmation.tsx" "react-hooks/refs" 12
"../../src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2
"../../src/pages/TransactionDuplicate/Review.tsx" "no-restricted-imports" 1
"../../src/pages/TransactionDuplicate/ReviewFields.tsx" "@typescript-eslint/no-deprecated/fontSize" 1
"../../src/pages/TransactionMerge/ConfirmationPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/pages/TransactionMerge/ConfirmationPage.tsx" "no-restricted-imports" 1
"../../src/pages/TransactionMerge/DetailsReviewPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
Expand Down Expand Up @@ -1246,6 +1260,7 @@
"../../src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx" "react-hooks/refs" 30
"../../src/pages/inbox/report/EnableNotificationsBanner.tsx" "no-restricted-imports" 1
"../../src/pages/inbox/report/FloatingMessageCounter.tsx" "no-restricted-imports" 1
"../../src/pages/inbox/report/LinkPreviewer.tsx" "@typescript-eslint/no-deprecated/fontSize" 3
"../../src/pages/inbox/report/ListBoundaryLoader.tsx" "react-hooks/set-state-in-effect" 1
"../../src/pages/inbox/report/ReactionList/HeaderReactionList.tsx" "no-restricted-syntax" 1
"../../src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
Expand All @@ -1265,6 +1280,7 @@
"../../src/pages/inbox/report/ReportActionItemMessageEdit.tsx" "react-hooks/preserve-manual-memoization" 1
"../../src/pages/inbox/report/ReportActionItemMessageEdit.tsx" "react-hooks/refs" 5
"../../src/pages/inbox/report/ReportActionItemMessageEdit.tsx" "react-hooks/set-state-in-effect" 1
"../../src/pages/inbox/report/SearchActionHeader.tsx" "@typescript-eslint/no-deprecated/fontSize" 1
"../../src/pages/inbox/report/ShowPreviousMessagesButton.tsx" "no-restricted-imports" 1
"../../src/pages/inbox/report/TripSummary.tsx" "rulesdir/no-default-id-values" 1
"../../src/pages/inbox/report/WhisperBanner.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
Expand All @@ -1274,6 +1290,7 @@
"../../src/pages/inbox/report/actionContents/MemberChangeContent.tsx" "@typescript-eslint/no-deprecated/deprecatedGetReportName" 1
"../../src/pages/inbox/report/actionContents/ReimbursementDeQueuedContent.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/pages/inbox/report/actionContents/ReimbursementQueuedContent.tsx" "no-restricted-imports" 1
"../../src/pages/inbox/report/comment/TextCommentFragment.tsx" "@typescript-eslint/no-deprecated/fontSize" 1
"../../src/pages/inbox/report/shouldUseEmojiPickerSelection/index.web.ts" "no-restricted-syntax" 1
"../../src/pages/inbox/report/useDebouncedSaveDraft.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/pages/inbox/report/withReportAndPrivateNotesOrNotFound.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
Expand Down Expand Up @@ -1567,6 +1584,7 @@
"../../src/pages/workspace/accounting/xero/advanced/DynamicXeroAccountingMethodPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/pages/workspace/accounting/xero/export/DynamicXeroPurchaseBillDateSelectPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/pages/workspace/accounting/xero/export/DynamicXeroPurchaseBillStatusSelectorPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx" "@typescript-eslint/no-deprecated/fontSize" 1
"../../src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx" "no-restricted-syntax" 2
"../../src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx" "rulesdir/no-default-id-values" 1
"../../src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx" "no-restricted-imports" 1
Expand Down Expand Up @@ -1674,12 +1692,14 @@
"../../src/stories/SelectionListWithSections.stories.tsx" "no-restricted-imports" 1
"../../src/stories/TextInput.stories.tsx" "react-hooks/set-state-in-effect" 1
"../../src/styles/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/styles/index.ts" "rulesdir/no-raw-typography" 28
"../../src/styles/theme/utils.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/styles/utils/FontUtils/fontFamily/multiFontFamily/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 2
"../../src/styles/utils/autoCompleteSuggestion/index.web.ts" "no-restricted-syntax" 1
"../../src/styles/utils/cursor/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 13
"../../src/styles/utils/generators/TooltipStyleUtils/isOverlappingAtTop/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/styles/utils/index.ts" "@typescript-eslint/no-unsafe-type-assertion" 2
"../../src/styles/utils/index.ts" "rulesdir/no-raw-typography" 4
"../../src/types/form/SpendRuleForm.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../src/types/onyx/Account.ts" "no-restricted-syntax" 1
"../../src/types/onyx/AccountData.ts" "no-restricted-syntax" 1
Expand Down Expand Up @@ -2080,6 +2100,7 @@
"../../tests/unit/cleanupAndNavigateAfterExpenseCreateTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 9
"../../tests/unit/components/Charts/VictoryTheme.test.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../tests/unit/components/Charts/useChartLabelLayout.test.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../tests/unit/components/HTMLEngineProvider/VictoryChartAttributesParsers.test.ts" "rulesdir/no-raw-typography" 1
"../../tests/unit/components/HTMLEngineProvider/VictoryChartParsers.test.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../tests/unit/components/Image/getImageSource.test.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
"../../tests/unit/components/MoneyRequestConfirmationList/selectorsTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 1
Expand Down
84 changes: 84 additions & 0 deletions eslint-plugin-local-rules/no-raw-typography.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const name = 'no-raw-typography';

const meta = {
type: 'problem',
docs: {
description: 'Disallow raw numeric fontSize/lineHeight values. Type must come from the typography scale so it cannot drift from the design system.',
recommended: 'error',
},
schema: [],
messages: {
rawTypography: 'Raw `{{property}}: {{value}}` is not allowed. Use a `<Text variant="...">` or a token from src/styles/typography.ts (https://github.com/Expensify/App/issues/37503).',
},
};

const BANNED_PROPERTIES = new Set(['fontSize', 'lineHeight']);

/**
* @param {import('estree').Node} key
* @returns {string | undefined}
*/
function getPropertyName(key) {
if (key.type === 'Identifier') {
return key.name;
}
if (key.type === 'Literal' && typeof key.value === 'string') {
return key.value;
}
return undefined;
}

/**
* @param {import('estree').Node} node
* @returns {boolean}
*/
function isNumericLiteral(node) {
if (node.type === 'Literal' && typeof node.value === 'number') {
return true;
}
return node.type === 'UnaryExpression' && node.operator === '-' && isNumericLiteral(node.argument);
Comment thread
grgia marked this conversation as resolved.
Outdated
Comment thread
grgia marked this conversation as resolved.
Outdated
}

/**
* Flags object properties (`{fontSize: 17}`) and JSX attributes (`<Text fontSize={17}>`) that set
* `fontSize`/`lineHeight` to a numeric literal. References to tokens or computed values are allowed.
*
* @param {import('eslint').Rule.RuleContext} context
* @returns {import('eslint').Rule.RuleListener}
*/
function create(context) {
function report(valueNode, propertyName) {
context.report({
node: valueNode,
messageId: 'rawTypography',
data: {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3 Badge Check direct typography assignments

When a style is built or mutated with an assignment such as style.fontSize = 17 or style.lineHeight = 20, the parser emits an AssignmentExpression, so neither listener runs and the new lint gate accepts the raw typography value. This is valid for a TextStyle in both TypeScript and JavaScript; add handling for statically named member assignments and cover both properties in the rule tests.

Useful? React with 👍 / 👎.

property: propertyName,
value: context.sourceCode.getText(valueNode),
},
});
}

return {
Property(node) {
if (node.computed) {
return;
}
const propertyName = getPropertyName(node.key);
if (propertyName === undefined || !BANNED_PROPERTIES.has(propertyName) || !isNumericLiteral(node.value)) {
return;
}
report(node.value, propertyName);
},
JSXAttribute(node) {
if (node.name.type !== 'JSXIdentifier' || !BANNED_PROPERTIES.has(node.name.name)) {
return;
}
if (node.value?.type !== 'JSXExpressionContainer' || !isNumericLiteral(node.value.expression)) {
return;
}
report(node.value.expression, node.name.name);
},
};
}

export {name, meta, create};
5 changes: 2 additions & 3 deletions src/components/QRShare/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ function QRShare({

{!!title && (
<Text
family="EXP_NEW_KANSAS_MEDIUM"
fontSize={variables.fontSizeXLarge}
variant="h1"
numberOfLines={2}
style={styles.qrShareTitle}
>
Expand All @@ -107,7 +106,7 @@ function QRShare({

{!!subtitle && (
<Text
fontSize={variables.fontSizeLabel}
variant="label"
Comment on lines 108 to +109

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.

Example

numberOfLines={2}
style={[styles.mt1, styles.textAlignCenter]}
color={theme.textSupporting}
Expand Down
Loading
Loading