From 1803de03a4cb2cb0b757f960a57b475bf9bda55b Mon Sep 17 00:00:00 2001 From: DS Boyce <260543580+ds-boyce@users.noreply.github.com> Date: Mon, 20 Jul 2026 09:29:58 -0700 Subject: [PATCH] Lighten blue (link) text for dim and dark themes (#11164) --- oxlint-suppressions.json | 8 ------ package.json | 2 +- pnpm-lock.yaml | 10 +++---- src/components/Composer/index.tsx | 2 +- src/components/FeedInterstitials.tsx | 4 +-- src/components/Link.tsx | 10 +++---- src/components/Post/ShowMoreTextButton.tsx | 12 ++++----- src/components/Post/Translated/index.tsx | 8 +++--- src/components/moderation/ContentHider.tsx | 27 +++++++------------ src/components/moderation/ScreenHider.tsx | 16 +++++------ .../Settings/components/SettingsList.tsx | 2 +- .../com/composer/text-input/TextInput.tsx | 13 ++++----- src/view/com/posts/ViewFullThread.tsx | 3 ++- 13 files changed, 49 insertions(+), 68 deletions(-) diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json index bf1ed59cf4..f533d7cb0d 100644 --- a/oxlint-suppressions.json +++ b/oxlint-suppressions.json @@ -1617,14 +1617,6 @@ "count": 1 } }, - "src/view/com/composer/text-input/TextInput.tsx": { - "typescript/no-floating-promises": { - "count": 1 - }, - "typescript/no-misused-promises": { - "count": 1 - } - }, "src/view/com/composer/text-input/TextInput.web.tsx": { "typescript/no-misused-promises": { "count": 1 diff --git a/package.json b/package.json index 18ed060987..39804cb8e1 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "@atproto/syntax": "0.7.2", "@bitdrift/react-native": "^0.6.8", "@braintree/sanitize-url": "^6.0.2", - "@bsky.app/alf": "^0.1.14", + "@bsky.app/alf": "^0.1.15", "@bsky.app/expo-dynamic-app-icon": "^1.8.5", "@bsky.app/expo-guess-language": "^0.2.8", "@bsky.app/expo-image-crop-tool": "^0.5.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 687c378a94..b0fb87565e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -257,8 +257,8 @@ importers: specifier: ^6.0.2 version: 6.0.4 '@bsky.app/alf': - specifier: ^0.1.14 - version: 0.1.14(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) + specifier: ^0.1.15 + version: 0.1.15(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) '@bsky.app/expo-dynamic-app-icon': specifier: ^1.8.5 version: 1.8.5(expo@54.0.34(@babel/core@7.29.0)(react-native-webview@13.15.0(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0) @@ -1606,8 +1606,8 @@ packages: '@braintree/sanitize-url@6.0.4': resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==} - '@bsky.app/alf@0.1.14': - resolution: {integrity: sha512-c/KK6avyjEnYzhXDsN0rQaTFSbi8BPg4sJCW8aUk8AtKsO34GTaY6FU1adQ2i8xVfe5UIRu9FJjnBoGpuXj21A==} + '@bsky.app/alf@0.1.15': + resolution: {integrity: sha512-e6blt+oZ2klv+Cp7u11FeZckoILdXOtUZ11ATERgjZgb4zX3y7rt4e2fI03JkJO31wTvXHG8A1LnM96Az+ndJg==} peerDependencies: react: '*' react-native: '*' @@ -10072,7 +10072,7 @@ snapshots: '@braintree/sanitize-url@6.0.4': {} - '@bsky.app/alf@0.1.14(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)': + '@bsky.app/alf@0.1.15(react-native@0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0))(react@19.1.0)': dependencies: react: 19.1.0 react-native: 0.81.5(patch_hash=2656ac6deb71b92a4df4af4593d13ace6a5740936432e5e7e8ef32bc3cd05194)(@babel/core@7.29.0)(@types/react@19.1.17)(react@19.1.0) diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index d93c7bb91a..f4a0302ff7 100644 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -286,7 +286,7 @@ export function Composer({ ref={IS_WEB ? sift.refs.setAnchor : undefined} style={ node.type === 'facet' && { - color: t.palette.primary_500, + color: t.atoms.text_link.color, } }> {node.raw} diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx index 02dee2fd6e..7f8820f36f 100644 --- a/src/components/FeedInterstitials.tsx +++ b/src/components/FeedInterstitials.tsx @@ -481,11 +481,11 @@ export function ProfileGrid({ See more diff --git a/src/components/Link.tsx b/src/components/Link.tsx index 0818b2a26f..6d60edb615 100644 --- a/src/components/Link.tsx +++ b/src/components/Link.tsx @@ -415,7 +415,7 @@ function LinkPeek({ // dialog can show. useInAppBrowser: useInAppBrowserPref === true, browserToolbarColor: t.atoms.bg.backgroundColor, - browserControlsColor: t.palette.primary_500, + browserControlsColor: t.atoms.text_link.color, }} borderRadius={borderRadius} // Fires only when not morphing natively (in-app browser off/unset). @@ -487,14 +487,14 @@ export function InlineLinkText({ accessibilityLabel={label} {...rest} style={[ - {color: t.palette.primary_500}, + t.atoms.text_link, interacted && !disableUnderline && { ...web({ outline: 0, textDecorationLine: 'underline', textDecorationColor: - flattenedStyle.color ?? t.palette.primary_500, + flattenedStyle.color ?? t.atoms.text_link.color, }), }, flattenedStyle, @@ -591,14 +591,14 @@ export function SimpleInlineLinkText({ accessibilityLabel={label} {...rest} style={[ - {color: t.palette.primary_500}, + t.atoms.text_link, interacted && !disableUnderline && { ...web({ outline: 0, textDecorationLine: 'underline', textDecorationColor: - flattenedStyle.color ?? t.palette.primary_500, + flattenedStyle.color ?? t.atoms.text_link.color, }), }, flattenedStyle, diff --git a/src/components/Post/ShowMoreTextButton.tsx b/src/components/Post/ShowMoreTextButton.tsx index 1e4e13cd5d..7765fbdd07 100644 --- a/src/components/Post/ShowMoreTextButton.tsx +++ b/src/components/Post/ShowMoreTextButton.tsx @@ -1,8 +1,6 @@ import {useCallback, useMemo} from 'react' import {LayoutAnimation, type TextStyle} from 'react-native' -import {msg} from '@lingui/core/macro' -import {useLingui} from '@lingui/react' -import {Trans} from '@lingui/react/macro' +import {Trans, useLingui} from '@lingui/react/macro' import {HITSLOP_10} from '#/lib/constants' import {atoms as a, flatten, type TextStyleProp, useTheme} from '#/alf' @@ -14,7 +12,7 @@ export function ShowMoreTextButton({ style, }: TextStyleProp & {onPress: () => void}) { const t = useTheme() - const {_} = useLingui() + const {t: l} = useLingui() const onPress = useCallback(() => { LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut) @@ -30,7 +28,7 @@ export function ShowMoreTextButton({ return ( diff --git a/src/components/Post/Translated/index.tsx b/src/components/Post/Translated/index.tsx index 9aff552bbf..94e0ea697a 100644 --- a/src/components/Post/Translated/index.tsx +++ b/src/components/Post/Translated/index.tsx @@ -150,10 +150,10 @@ function TranslationLink({ label={l`Translate`} hoverStyle={[ native({opacity: 0.5}), - web([a.underline, {textDecorationColor: t.palette.primary_500}]), + web([a.underline, {textDecorationColor: t.atoms.text_link.color}]), ]} hitSlop={HITSLOP_30}> - + Translate @@ -229,7 +229,7 @@ function TranslationError({ label={l`Try Google Translate`} hoverStyle={[ native({opacity: 0.5}), - web([a.underline, {textDecorationColor: t.palette.primary_500}]), + web([a.underline, {textDecorationColor: t.atoms.text_link.color}]), ]} hitSlop={HITSLOP_30}> Try Google Translate diff --git a/src/components/moderation/ContentHider.tsx b/src/components/moderation/ContentHider.tsx index b603c738d4..cfdc6c7e12 100644 --- a/src/components/moderation/ContentHider.tsx +++ b/src/components/moderation/ContentHider.tsx @@ -6,9 +6,7 @@ import { type ViewStyle, } from 'react-native' import {type ModerationUI} from '@atproto/api' -import {msg} from '@lingui/core/macro' -import {useLingui} from '@lingui/react' -import {Trans} from '@lingui/react/macro' +import {Trans, useLingui} from '@lingui/react/macro' import { ADULT_CONTENT_LABELS, @@ -78,7 +76,7 @@ function ContentHiderActive({ children?: React.ReactNode }) { const t = useTheme() - const {_} = useLingui() + const {t: l} = useLingui() const {gtMobile} = useBreakpoints() const [override, setOverride] = useState(false) const control = useModerationDetailsDialogControl() @@ -97,7 +95,7 @@ function ContentHiderActive({ (blur.type === 'label' && blur.source.type !== 'user') ) { if (desc.isSubjectAccount) { - return _(msg`${desc.name} (Account)`) + return l`${desc.name} (Account)` } else { return desc.name } @@ -128,7 +126,7 @@ function ContentHiderActive({ const def = cause.labelDef || getDefinition(labelDefs, cause.label) if (def.identifier === 'porn' || def.identifier === 'sexual') { - return _(msg`Adult Content`) + return l`Adult Content` } return getLabelStrings(i18n.locale, globalLabelStrings, def).name }) @@ -138,7 +136,7 @@ function ContentHiderActive({ } return [...new Set(selfBlurNames)].join(', ') }, [ - _, + l, modui.blurs, blur, desc.name, @@ -151,7 +149,6 @@ function ContentHiderActive({ return ( - - {desc.source && blur.type === 'label' && !override && ( )} - {override && {children}} ) diff --git a/src/components/moderation/ScreenHider.tsx b/src/components/moderation/ScreenHider.tsx index cb3d522274..3c0d4584b8 100644 --- a/src/components/moderation/ScreenHider.tsx +++ b/src/components/moderation/ScreenHider.tsx @@ -6,9 +6,7 @@ import { type ViewStyle, } from 'react-native' import {type ModerationUI} from '@atproto/api' -import {msg} from '@lingui/core/macro' -import {useLingui} from '@lingui/react' -import {Trans} from '@lingui/react/macro' +import {Trans, useLingui} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' @@ -38,7 +36,7 @@ export function ScreenHider({ containerStyle?: StyleProp }>) { const t = useTheme() - const {_} = useLingui() + const {t: l} = useLingui() const [override, setOverride] = useState(false) const navigation = useNavigation() const {isMobile} = useWebMediaQueries() @@ -131,15 +129,13 @@ export function ScreenHider({ control.open() }} accessibilityRole="button" - accessibilityLabel={_(msg`Learn more about this warning`)} + accessibilityLabel={l`Learn more about this warning`} accessibilityHint=""> { if (navigation.canGoBack()) { navigation.goBack() @@ -176,7 +172,7 @@ export function ScreenHider({ color="secondary" size="large" style={[a.rounded_full]} - label={_(msg`Show anyway`)} + label={l`Show anyway`} onPress={() => setOverride(v => !v)}> Show anyway diff --git a/src/screens/Settings/components/SettingsList.tsx b/src/screens/Settings/components/SettingsList.tsx index b23eab85f4..268e49339f 100644 --- a/src/screens/Settings/components/SettingsList.tsx +++ b/src/screens/Settings/components/SettingsList.tsx @@ -311,7 +311,7 @@ export function BadgeButton({ a.text_md, a.font_normal, a.text_right, - {color: pressed ? t.palette.contrast_300 : t.palette.primary_500}, + {color: pressed ? t.palette.contrast_300 : t.atoms.text_link.color}, ]}> {label} diff --git a/src/view/com/composer/text-input/TextInput.tsx b/src/view/com/composer/text-input/TextInput.tsx index 313f0becbf..d40e06a215 100644 --- a/src/view/com/composer/text-input/TextInput.tsx +++ b/src/view/com/composer/text-input/TextInput.tsx @@ -6,10 +6,9 @@ import { useState, } from 'react' import { - type NativeSyntheticEvent, Text as RNText, TextInput as RNTextInput, - type TextInputSelectionChangeEventData, + type TextInputSelectionChangeEvent, View, } from 'react-native' import {type PasteEventPayload, TextInputWrapper} from 'expo-paste-input' @@ -141,7 +140,7 @@ export function TextInput({ ) const onSelectionChange = useCallback( - (evt: NativeSyntheticEvent) => { + (evt: TextInputSelectionChangeEvent) => { // NOTE we track the input selection using a ref to avoid excessive renders -prf textInputSelection.current = evt.nativeEvent.selection }, @@ -150,7 +149,7 @@ export function TextInput({ const onSelectAutocompleteItem = useCallback( (item: string) => { - onChangeText( + void onChangeText( insertMentionAt( richtext.text, textInputSelection.current?.start || 0, @@ -201,7 +200,9 @@ export function TextInput({ style={[ inputTextStyle, { - color: segment.facet ? t.palette.primary_500 : t.atoms.text.color, + color: segment.facet + ? t.atoms.text_link.color + : t.atoms.text.color, marginTop: -1, }, ]}> @@ -217,7 +218,7 @@ export function TextInput({ void onChangeText(newText)} onSelectionChange={onSelectionChange} placeholder={placeholder} placeholderTextColor={t.atoms.text_contrast_low.color} diff --git a/src/view/com/posts/ViewFullThread.tsx b/src/view/com/posts/ViewFullThread.tsx index 2a0eb5135f..f346a34396 100644 --- a/src/view/com/posts/ViewFullThread.tsx +++ b/src/view/com/posts/ViewFullThread.tsx @@ -58,7 +58,8 @@ export function ViewFullThread({uri}: {uri: string}) { {/* HACKFIX: Trans isn't working after SDK 53 upgrade -sfn */} {l`View full thread`}