Skip to content

Commit e29ad76

Browse files
Unify mobile typography tokens across the app (#3162)
Co-authored-by: codex <codex@users.noreply.github.com>
1 parent cdaba7f commit e29ad76

59 files changed

Lines changed: 415 additions & 289 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/mobile/.swiftlint.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
included:
22
- ios/T3Code
3+
- modules/t3-composer-editor/ios
34
- modules/t3-terminal/ios
45
- modules/t3-review-diff/ios
56

apps/mobile/global.css

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,31 @@
192192
}
193193
}
194194

195-
/* ─── Font family ───────────────────────────────────────────────────── */
195+
/* ─── Typography ────────────────────────────────────────────────────── */
196196
@theme {
197197
--font-sans: "DMSans_400Regular";
198198
--font-medium: "DMSans_500Medium";
199199
--font-bold: "DMSans_700Bold";
200+
201+
/* Keep this scale aligned with src/lib/typography.ts for native style props. */
202+
--text-3xs: 10px;
203+
--text-3xs--line-height: 13px;
204+
--text-2xs: 11px;
205+
--text-2xs--line-height: 15px;
206+
--text-xs: 12px;
207+
--text-xs--line-height: 16px;
208+
--text-sm: 13px;
209+
--text-sm--line-height: 18px;
210+
--text-base: 15px;
211+
--text-base--line-height: 22px;
212+
--text-lg: 17px;
213+
--text-lg--line-height: 22px;
214+
--text-xl: 20px;
215+
--text-xl--line-height: 26px;
216+
--text-2xl: 24px;
217+
--text-2xl--line-height: 30px;
218+
--text-3xl: 28px;
219+
--text-3xl--line-height: 34px;
200220
}
201221

202222
/* ─── Custom utilities ──────────────────────────────────────────────── */

apps/mobile/modules/t3-composer-editor/ios/T3ComposerEditorView.swift

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,8 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate {
275275
fileTint: "#737373"
276276
)
277277
private var fontFamily = "DMSans_400Regular"
278-
private var fontSize: CGFloat = 15
279-
private var lineHeight: CGFloat = 22
278+
private var fontSize: CGFloat = 14
279+
private var lineHeight: CGFloat = 20
280280
private var contentInsetVertical: CGFloat = 0
281281
private var shouldAutoFocus = false
282282
private var didAutoFocus = false
@@ -460,9 +460,19 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate {
460460
guard !isApplyingControlledValue else {
461461
return
462462
}
463+
restoreBaseTypingAttributes()
463464
emitSelection()
464465
}
465466

467+
public func textView(
468+
_ textView: UITextView,
469+
shouldChangeTextIn range: NSRange,
470+
replacementText text: String
471+
) -> Bool {
472+
restoreBaseTypingAttributes()
473+
return true
474+
}
475+
466476
public func textViewDidBeginEditing(_ textView: UITextView) {
467477
onComposerFocus()
468478
}
@@ -484,6 +494,7 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate {
484494
let targetSelection = requestedSelection ?? previousSelection
485495
requestedSelection = nil
486496
textView.selectedRange = displayRange(for: targetSelection)
497+
restoreBaseTypingAttributes()
487498
isApplyingControlledValue = false
488499
updatePlaceholderVisibility()
489500
emitContentSizeIfNeeded()
@@ -556,7 +567,12 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate {
556567
size: image.size,
557568
baselineOffset: baselineOffset
558569
)
559-
return NSAttributedString(attachment: attachment)
570+
let attributedAttachment = NSMutableAttributedString(attachment: attachment)
571+
attributedAttachment.addAttributes(
572+
baseAttributes(),
573+
range: NSRange(location: 0, length: attributedAttachment.length)
574+
)
575+
return attributedAttachment
560576
}
561577

562578
private func renderChip(
@@ -660,11 +676,18 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate {
660676
let font = UIFont(name: fontFamily, size: fontSize)
661677
?? UIFont.systemFont(ofSize: fontSize)
662678
textView.font = font
663-
textView.typingAttributes = baseAttributes()
679+
restoreBaseTypingAttributes()
664680
placeholderLabel.font = font
665681
setNeedsLayout()
666682
}
667683

684+
private func restoreBaseTypingAttributes() {
685+
guard textView.markedTextRange == nil else {
686+
return
687+
}
688+
textView.typingAttributes = baseAttributes()
689+
}
690+
668691
private func applyTheme() {
669692
textView.textColor = UIColor(composerHex: theme.text) ?? .label
670693
placeholderLabel.textColor = UIColor(composerHex: theme.placeholder) ?? .placeholderText

apps/mobile/src/app/+not-found.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export default function NotFoundRoute() {
2121
}}
2222
style={[{ flex: 1 }, screenBgStyle]}
2323
>
24-
<Text className="text-[28px] font-t3-bold text-foreground" selectable>
24+
<Text className="text-3xl font-t3-bold text-foreground" selectable>
2525
Route not found
2626
</Text>
2727
<Link href="/" asChild>
@@ -35,7 +35,7 @@ export default function NotFoundRoute() {
3535
primaryBgStyle,
3636
]}
3737
>
38-
<Text className="text-[16px] font-t3-bold text-primary-foreground">Return home</Text>
38+
<Text className="text-base font-t3-bold text-primary-foreground">Return home</Text>
3939
</Pressable>
4040
</Link>
4141
</ScrollView>

apps/mobile/src/app/connections/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export default function ConnectionsRouteScreen() {
8585
type="monochrome"
8686
/>
8787
</View>
88-
<Text className="text-center text-[14px] leading-[20px] text-foreground-muted">
88+
<Text className="text-center text-sm leading-[20px] text-foreground-muted">
8989
No environments connected yet.{"\n"}Tap{" "}
9090
<Text className="font-t3-bold text-foreground">+</Text> to add one.
9191
</Text>

apps/mobile/src/app/connections/new.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ export default function ConnectionsNewRouteScreen() {
171171
className="items-center gap-3 rounded-[24px] bg-card px-5 py-8"
172172
style={{ borderCurve: "continuous" }}
173173
>
174-
<Text className="text-center text-[14px] leading-[20px] text-foreground-muted">
174+
<Text className="text-center text-sm leading-[20px] text-foreground-muted">
175175
Camera permission is required to scan a QR code.
176176
</Text>
177177
<ConnectionSheetButton
@@ -189,7 +189,7 @@ export default function ConnectionsNewRouteScreen() {
189189
<View collapsable={false} className="gap-4 rounded-[24px] bg-card p-4">
190190
<View collapsable={false} className="gap-1.5">
191191
<Text
192-
className="text-[11px] font-t3-bold uppercase text-foreground-muted"
192+
className="text-2xs font-t3-bold uppercase text-foreground-muted"
193193
style={{ letterSpacing: 0.8 }}
194194
>
195195
Host
@@ -202,13 +202,13 @@ export default function ConnectionsNewRouteScreen() {
202202
placeholderTextColor={placeholderColor}
203203
value={hostInput}
204204
onChangeText={handleHostChange}
205-
className="rounded-[14px] border border-input-border bg-input px-4 py-3.5 text-[15px] text-foreground"
205+
className="rounded-[14px] border border-input-border bg-input px-4 py-3.5 text-base text-foreground"
206206
/>
207207
</View>
208208

209209
<View collapsable={false} className="gap-1.5">
210210
<Text
211-
className="text-[11px] font-t3-bold uppercase text-foreground-muted"
211+
className="text-2xs font-t3-bold uppercase text-foreground-muted"
212212
style={{ letterSpacing: 0.8 }}
213213
>
214214
Pairing code
@@ -220,7 +220,7 @@ export default function ConnectionsNewRouteScreen() {
220220
placeholderTextColor={placeholderColor}
221221
value={codeInput}
222222
onChangeText={handleCodeChange}
223-
className="rounded-[14px] border border-input-border bg-input px-4 py-3.5 text-[15px] text-foreground"
223+
className="rounded-[14px] border border-input-border bg-input px-4 py-3.5 text-base text-foreground"
224224
/>
225225
</View>
226226

apps/mobile/src/app/new/index.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,18 +129,18 @@ export default function NewTaskRoute() {
129129
{items.length === 0 ? (
130130
<View collapsable={false} className="items-center gap-3 rounded-[24px] bg-card px-6 py-8">
131131
{projectEmptyState.loading ? <ActivityIndicator color={accentColor} /> : null}
132-
<Text className="text-center text-[17px] font-t3-bold text-foreground">
132+
<Text className="text-center text-lg font-t3-bold text-foreground">
133133
{projectEmptyState.title}
134134
</Text>
135-
<Text className="text-center text-[14px] leading-[20px] text-foreground-muted">
135+
<Text className="text-center text-sm leading-[20px] text-foreground-muted">
136136
{projectEmptyState.detail}
137137
</Text>
138138
{!catalogState.hasReadyEnvironment ? (
139139
<Pressable
140140
className="mt-1 rounded-full bg-primary px-4 py-2.5 active:opacity-70"
141141
onPress={() => router.push("/connections/new")}
142142
>
143-
<Text className="text-[13px] font-t3-bold text-primary-foreground">
143+
<Text className="text-sm font-t3-bold text-primary-foreground">
144144
Add environment
145145
</Text>
146146
</Pressable>
@@ -149,7 +149,7 @@ export default function NewTaskRoute() {
149149
className="mt-1 rounded-full bg-primary px-4 py-2.5 active:opacity-70"
150150
onPress={() => router.push("/new/add-project")}
151151
>
152-
<Text className="text-[13px] font-t3-bold text-primary-foreground">
152+
<Text className="text-sm font-t3-bold text-primary-foreground">
153153
Add new project
154154
</Text>
155155
</Pressable>
@@ -197,9 +197,7 @@ export default function NewTaskRoute() {
197197
/>
198198
</View>
199199
<View className="flex-1">
200-
<Text className="text-[16px] leading-[21px] font-t3-bold">
201-
{item.title}
202-
</Text>
200+
<Text className="text-base leading-[21px] font-t3-bold">{item.title}</Text>
203201
</View>
204202
<SymbolView
205203
name="chevron.right"

apps/mobile/src/app/settings/environments.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export default function SettingsEnvironmentsRouteScreen() {
111111
type="monochrome"
112112
/>
113113
</View>
114-
<Text className="text-center text-[14px] leading-[20px] text-foreground-muted">
114+
<Text className="text-center text-sm leading-[20px] text-foreground-muted">
115115
No environments connected yet.{"\n"}Tap{" "}
116116
<Text className="font-t3-bold text-foreground">+</Text> to add one.
117117
</Text>
@@ -160,7 +160,7 @@ function ConfiguredCloudEnvironmentRows(props: {
160160
return (
161161
<View collapsable={false} className="mt-5 gap-3">
162162
<View className="flex-row items-center justify-between px-1">
163-
<Text className="text-[13px] font-t3-bold uppercase text-foreground-muted">T3 Cloud</Text>
163+
<Text className="text-sm font-t3-bold uppercase text-foreground-muted">T3 Cloud</Text>
164164
<Pressable
165165
accessibilityRole="button"
166166
disabled={controller.relayDiscovery.isRefreshing}
@@ -204,16 +204,16 @@ function ConfiguredCloudEnvironmentRows(props: {
204204
) : controller.relayDiscovery.isRefreshing ? (
205205
<View collapsable={false} className="items-center gap-3 rounded-[24px] bg-card p-6">
206206
<ActivityIndicator color={iconColor} />
207-
<Text className="text-center text-[14px] leading-[20px] text-foreground-muted">
207+
<Text className="text-center text-sm leading-[20px] text-foreground-muted">
208208
Loading linked cloud environments.
209209
</Text>
210210
</View>
211211
) : controller.relayDiscovery.error ? (
212212
<View collapsable={false} className="gap-3 rounded-[24px] bg-card p-5">
213-
<Text className="text-[15px] font-t3-bold text-foreground">
213+
<Text className="text-base font-t3-bold text-foreground">
214214
Could not load T3 Cloud environments
215215
</Text>
216-
<Text className="text-[13px] leading-[18px] text-foreground-muted">
216+
<Text className="text-sm leading-[18px] text-foreground-muted">
217217
{controller.relayDiscovery.error}
218218
</Text>
219219
{controller.relayDiscovery.errorTraceId ? (
@@ -222,7 +222,7 @@ function ConfiguredCloudEnvironmentRows(props: {
222222
</View>
223223
) : (
224224
<View collapsable={false} className="rounded-[24px] bg-card p-5">
225-
<Text className="text-[14px] leading-[20px] text-foreground-muted">
225+
<Text className="text-sm leading-[20px] text-foreground-muted">
226226
No additional linked cloud environments.
227227
</Text>
228228
</View>
@@ -361,7 +361,7 @@ function CloudEnvironmentRowShell(props: {
361361
<View className="min-w-0 flex-row items-center gap-2">
362362
<ConnectionStatusDot state={props.connectionState} pulse={shouldPulse} size={7} />
363363
<Text
364-
className="min-w-0 flex-shrink text-[16px] font-t3-bold leading-[21px] text-foreground"
364+
className="min-w-0 flex-shrink text-base font-t3-bold leading-[21px] text-foreground"
365365
numberOfLines={1}
366366
>
367367
{props.label}
@@ -370,7 +370,7 @@ function CloudEnvironmentRowShell(props: {
370370
{props.connectionError ? (
371371
<Text
372372
aria-hidden
373-
className={cn("absolute left-0 right-0 text-[12px] leading-[16px]", statusClassName)}
373+
className={cn("absolute left-0 right-0 text-xs leading-[16px]", statusClassName)}
374374
onTextLayout={onMeasuredErrorTextLayout}
375375
style={{ opacity: 0, zIndex: -1 }}
376376
>
@@ -384,7 +384,7 @@ function CloudEnvironmentRowShell(props: {
384384
className="min-w-0 flex-row items-start gap-1"
385385
>
386386
<Text
387-
className={cn("min-w-0 flex-1 text-[12px] leading-[16px]", statusClassName)}
387+
className={cn("min-w-0 flex-1 text-xs leading-[16px]", statusClassName)}
388388
numberOfLines={isErrorExpanded ? undefined : 1}
389389
>
390390
{statusText}
@@ -394,7 +394,7 @@ function CloudEnvironmentRowShell(props: {
394394
<Text
395395
accessibilityHint="Copies the trace ID"
396396
accessibilityRole="button"
397-
className={cn("text-[12px] leading-[16px] underline", statusClassName)}
397+
className={cn("text-xs leading-[16px] underline", statusClassName)}
398398
onLongPress={(event) => {
399399
event.stopPropagation();
400400
copyTextWithHaptic(errorTraceId);
@@ -446,7 +446,7 @@ function CopyTraceIdButton(props: { readonly traceId: string }) {
446446
className="self-start flex-row items-center gap-1.5 rounded-full bg-subtle px-3 py-2 active:opacity-70"
447447
>
448448
<SymbolView name="doc.on.doc" size={12} tintColor={iconColor} type="monochrome" />
449-
<Text className="text-[12px] font-t3-bold text-foreground">Copy trace ID</Text>
449+
<Text className="text-xs font-t3-bold text-foreground">Copy trace ID</Text>
450450
</Pressable>
451451
);
452452
}

apps/mobile/src/app/settings/index.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ function ConfiguredSettingsRouteScreen() {
346346
onPress={openAccount}
347347
/>
348348
</SettingsSection>
349-
<Text className="px-2 text-[13px] leading-[18px] text-foreground-muted">
349+
<Text className="px-2 text-sm leading-[18px] text-foreground-muted">
350350
T3 Code works locally without signing in. Cloud features are optional.
351351
</Text>
352352
</View>
@@ -389,7 +389,7 @@ type SymbolName = ComponentProps<typeof SymbolView>["name"];
389389
function SettingsSection(props: { readonly title: string; readonly children: ReactNode }) {
390390
return (
391391
<View className="gap-2">
392-
<Text className="px-2 text-[13px] font-t3-medium text-foreground-muted">{props.title}</Text>
392+
<Text className="px-2 text-sm font-t3-medium text-foreground-muted">{props.title}</Text>
393393
<View
394394
className="overflow-hidden rounded-[28px] bg-card"
395395
style={{ borderCurve: "continuous" }}
@@ -413,8 +413,8 @@ function AppSettingsSection() {
413413
type="monochrome"
414414
weight="regular"
415415
/>
416-
<Text className="flex-1 text-[17px] text-foreground">Version</Text>
417-
<Text className="text-[17px] text-foreground-muted">Alpha</Text>
416+
<Text className="flex-1 text-lg text-foreground">Version</Text>
417+
<Text className="text-lg text-foreground-muted">Alpha</Text>
418418
</View>
419419
</SettingsSection>
420420
);
@@ -444,13 +444,13 @@ function SettingsRow(props: {
444444
style={{ opacity: props.disabled ? 0.45 : 1 }}
445445
>
446446
<SymbolView name={props.icon} size={22} tintColor={icon} type="monochrome" weight="regular" />
447-
<Text className="shrink-0 text-[17px] text-foreground" numberOfLines={1}>
447+
<Text className="shrink-0 text-lg text-foreground" numberOfLines={1}>
448448
{props.label}
449449
</Text>
450450
<View className="min-w-0 flex-1 items-end">
451451
{props.value ? (
452452
<Text
453-
className="max-w-[180px] text-right text-[16px] text-foreground-muted"
453+
className="max-w-[180px] text-right text-base text-foreground-muted"
454454
ellipsizeMode="middle"
455455
numberOfLines={1}
456456
>
@@ -502,7 +502,7 @@ function SettingsSwitchRow(props: {
502502
style={{ opacity: props.disabled ? 0.45 : 1 }}
503503
>
504504
<SymbolView name={props.icon} size={22} tintColor={icon} type="monochrome" weight="regular" />
505-
<Text className="flex-1 text-[17px] text-foreground">{props.label}</Text>
505+
<Text className="flex-1 text-lg text-foreground">{props.label}</Text>
506506
<Switch
507507
disabled={props.disabled}
508508
ios_backgroundColor={track}

apps/mobile/src/components/AppText.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function AppTextInput({
4040
<RNTextInput
4141
ref={ref}
4242
className={cn(
43-
"min-h-[54px] rounded-2xl border border-input-border bg-input px-3.5 py-3 font-sans text-[15px] text-foreground",
43+
"min-h-[54px] rounded-2xl border border-input-border bg-input px-3.5 py-3 font-sans text-base text-foreground",
4444
className,
4545
)}
4646
placeholderTextColor={placeholderTextColor ?? placeholderColor}

0 commit comments

Comments
 (0)