| author | |
| committer | |
| log | e29ad7604b1597e3a741868c85ffd76bca84fa7f |
| tree | 197f7e2849ae141cce69265514e9312a589a1fa9 |
| parent | cdaba7fa8b9c94dba783b7161e265a6db03b3d93 |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: codex <codex@users.noreply.github.com>59 files changed, 415 insertions(+), 289 deletions(-)
apps/mobile/.swiftlint.yml+1| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | included: | 1 | included: |
| 2 | - ios/T3Code | 2 | - ios/T3Code |
| 3 | - modules/t3-composer-editor/ios | ||
| 3 | - modules/t3-terminal/ios | 4 | - modules/t3-terminal/ios |
| 4 | - modules/t3-review-diff/ios | 5 | - modules/t3-review-diff/ios |
| 5 | 6 |
apps/mobile/global.css+21-1| ... | @@ -192,11 +192,31 @@ | ... | @@ -192,11 +192,31 @@ |
| 192 | } | 192 | } |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | /* ─── Font family ───────────────────────────────────────────────────── */ | 195 | /* ─── Typography ────────────────────────────────────────────────────── */ |
| 196 | @theme { | 196 | @theme { |
| 197 | --font-sans: "DMSans_400Regular"; | 197 | --font-sans: "DMSans_400Regular"; |
| 198 | --font-medium: "DMSans_500Medium"; | 198 | --font-medium: "DMSans_500Medium"; |
| 199 | --font-bold: "DMSans_700Bold"; | 199 | --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; | ||
| 200 | } | 220 | } |
| 201 | 221 | ||
| 202 | /* ─── Custom utilities ──────────────────────────────────────────────── */ | 222 | /* ─── Custom utilities ──────────────────────────────────────────────── */ |
apps/mobile/modules/t3-composer-editor/ios/T3ComposerEditorView.swift+27-4| ... | @@ -275,8 +275,8 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate { | ... | @@ -275,8 +275,8 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate { |
| 275 | fileTint: "#737373" | 275 | fileTint: "#737373" |
| 276 | ) | 276 | ) |
| 277 | private var fontFamily = "DMSans_400Regular" | 277 | private var fontFamily = "DMSans_400Regular" |
| 278 | private var fontSize: CGFloat = 15 | 278 | private var fontSize: CGFloat = 14 |
| 279 | private var lineHeight: CGFloat = 22 | 279 | private var lineHeight: CGFloat = 20 |
| 280 | private var contentInsetVertical: CGFloat = 0 | 280 | private var contentInsetVertical: CGFloat = 0 |
| 281 | private var shouldAutoFocus = false | 281 | private var shouldAutoFocus = false |
| 282 | private var didAutoFocus = false | 282 | private var didAutoFocus = false |
| ... | @@ -460,9 +460,19 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate { | ... | @@ -460,9 +460,19 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate { |
| 460 | guard !isApplyingControlledValue else { | 460 | guard !isApplyingControlledValue else { |
| 461 | return | 461 | return |
| 462 | } | 462 | } |
| 463 | restoreBaseTypingAttributes() | ||
| 463 | emitSelection() | 464 | emitSelection() |
| 464 | } | 465 | } |
| 465 | 466 | ||
| 467 | public func textView( | ||
| 468 | _ textView: UITextView, | ||
| 469 | shouldChangeTextIn range: NSRange, | ||
| 470 | replacementText text: String | ||
| 471 | ) -> Bool { | ||
| 472 | restoreBaseTypingAttributes() | ||
| 473 | return true | ||
| 474 | } | ||
| 475 | |||
| 466 | public func textViewDidBeginEditing(_ textView: UITextView) { | 476 | public func textViewDidBeginEditing(_ textView: UITextView) { |
| 467 | onComposerFocus() | 477 | onComposerFocus() |
| 468 | } | 478 | } |
| ... | @@ -484,6 +494,7 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate { | ... | @@ -484,6 +494,7 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate { |
| 484 | let targetSelection = requestedSelection ?? previousSelection | 494 | let targetSelection = requestedSelection ?? previousSelection |
| 485 | requestedSelection = nil | 495 | requestedSelection = nil |
| 486 | textView.selectedRange = displayRange(for: targetSelection) | 496 | textView.selectedRange = displayRange(for: targetSelection) |
| 497 | restoreBaseTypingAttributes() | ||
| 487 | isApplyingControlledValue = false | 498 | isApplyingControlledValue = false |
| 488 | updatePlaceholderVisibility() | 499 | updatePlaceholderVisibility() |
| 489 | emitContentSizeIfNeeded() | 500 | emitContentSizeIfNeeded() |
| ... | @@ -556,7 +567,12 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate { | ... | @@ -556,7 +567,12 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate { |
| 556 | size: image.size, | 567 | size: image.size, |
| 557 | baselineOffset: baselineOffset | 568 | baselineOffset: baselineOffset |
| 558 | ) | 569 | ) |
| 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 | ||
| 560 | } | 576 | } |
| 561 | 577 | ||
| 562 | private func renderChip( | 578 | private func renderChip( |
| ... | @@ -660,11 +676,18 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate { | ... | @@ -660,11 +676,18 @@ public final class T3ComposerEditorView: ExpoView, UITextViewDelegate { |
| 660 | let font = UIFont(name: fontFamily, size: fontSize) | 676 | let font = UIFont(name: fontFamily, size: fontSize) |
| 661 | ?? UIFont.systemFont(ofSize: fontSize) | 677 | ?? UIFont.systemFont(ofSize: fontSize) |
| 662 | textView.font = font | 678 | textView.font = font |
| 663 | textView.typingAttributes = baseAttributes() | 679 | restoreBaseTypingAttributes() |
| 664 | placeholderLabel.font = font | 680 | placeholderLabel.font = font |
| 665 | setNeedsLayout() | 681 | setNeedsLayout() |
| 666 | } | 682 | } |
| 667 | 683 | ||
| 684 | private func restoreBaseTypingAttributes() { | ||
| 685 | guard textView.markedTextRange == nil else { | ||
| 686 | return | ||
| 687 | } | ||
| 688 | textView.typingAttributes = baseAttributes() | ||
| 689 | } | ||
| 690 | |||
| 668 | private func applyTheme() { | 691 | private func applyTheme() { |
| 669 | textView.textColor = UIColor(composerHex: theme.text) ?? .label | 692 | textView.textColor = UIColor(composerHex: theme.text) ?? .label |
| 670 | placeholderLabel.textColor = UIColor(composerHex: theme.placeholder) ?? .placeholderText | 693 | placeholderLabel.textColor = UIColor(composerHex: theme.placeholder) ?? .placeholderText |
apps/mobile/src/app/+not-found.tsx+2-2| ... | @@ -21,7 +21,7 @@ export default function NotFoundRoute() { | ... | @@ -21,7 +21,7 @@ export default function NotFoundRoute() { |
| 21 | }} | 21 | }} |
| 22 | style={[{ flex: 1 }, screenBgStyle]} | 22 | style={[{ flex: 1 }, screenBgStyle]} |
| 23 | > | 23 | > |
| 24 | <Text className="text-[28px] font-t3-bold text-foreground" selectable> | 24 | <Text className="text-3xl font-t3-bold text-foreground" selectable> |
| 25 | Route not found | 25 | Route not found |
| 26 | </Text> | 26 | </Text> |
| 27 | <Link href="/" asChild> | 27 | <Link href="/" asChild> |
| ... | @@ -35,7 +35,7 @@ export default function NotFoundRoute() { | ... | @@ -35,7 +35,7 @@ export default function NotFoundRoute() { |
| 35 | primaryBgStyle, | 35 | primaryBgStyle, |
| 36 | ]} | 36 | ]} |
| 37 | > | 37 | > |
| 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> |
| 39 | </Pressable> | 39 | </Pressable> |
| 40 | </Link> | 40 | </Link> |
| 41 | </ScrollView> | 41 | </ScrollView> |
apps/mobile/src/app/connections/index.tsx+1-1| ... | @@ -85,7 +85,7 @@ export default function ConnectionsRouteScreen() { | ... | @@ -85,7 +85,7 @@ export default function ConnectionsRouteScreen() { |
| 85 | type="monochrome" | 85 | type="monochrome" |
| 86 | /> | 86 | /> |
| 87 | </View> | 87 | </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"> |
| 89 | No environments connected yet.{"\n"}Tap{" "} | 89 | No environments connected yet.{"\n"}Tap{" "} |
| 90 | <Text className="font-t3-bold text-foreground">+</Text> to add one. | 90 | <Text className="font-t3-bold text-foreground">+</Text> to add one. |
| 91 | </Text> | 91 | </Text> |
apps/mobile/src/app/connections/new.tsx+5-5| ... | @@ -171,7 +171,7 @@ export default function ConnectionsNewRouteScreen() { | ... | @@ -171,7 +171,7 @@ export default function ConnectionsNewRouteScreen() { |
| 171 | className="items-center gap-3 rounded-[24px] bg-card px-5 py-8" | 171 | className="items-center gap-3 rounded-[24px] bg-card px-5 py-8" |
| 172 | style={{ borderCurve: "continuous" }} | 172 | style={{ borderCurve: "continuous" }} |
| 173 | > | 173 | > |
| 174 | <Text className="text-center text-[14px] leading-[20px] text-foreground-muted"> | 174 | <Text className="text-center text-sm leading-[20px] text-foreground-muted"> |
| 175 | Camera permission is required to scan a QR code. | 175 | Camera permission is required to scan a QR code. |
| 176 | </Text> | 176 | </Text> |
| 177 | <ConnectionSheetButton | 177 | <ConnectionSheetButton |
| ... | @@ -189,7 +189,7 @@ export default function ConnectionsNewRouteScreen() { | ... | @@ -189,7 +189,7 @@ export default function ConnectionsNewRouteScreen() { |
| 189 | <View collapsable={false} className="gap-4 rounded-[24px] bg-card p-4"> | 189 | <View collapsable={false} className="gap-4 rounded-[24px] bg-card p-4"> |
| 190 | <View collapsable={false} className="gap-1.5"> | 190 | <View collapsable={false} className="gap-1.5"> |
| 191 | <Text | 191 | <Text |
| 192 | className="text-[11px] font-t3-bold uppercase text-foreground-muted" | 192 | className="text-2xs font-t3-bold uppercase text-foreground-muted" |
| 193 | style={{ letterSpacing: 0.8 }} | 193 | style={{ letterSpacing: 0.8 }} |
| 194 | > | 194 | > |
| 195 | Host | 195 | Host |
| ... | @@ -202,13 +202,13 @@ export default function ConnectionsNewRouteScreen() { | ... | @@ -202,13 +202,13 @@ export default function ConnectionsNewRouteScreen() { |
| 202 | placeholderTextColor={placeholderColor} | 202 | placeholderTextColor={placeholderColor} |
| 203 | value={hostInput} | 203 | value={hostInput} |
| 204 | onChangeText={handleHostChange} | 204 | 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" |
| 206 | /> | 206 | /> |
| 207 | </View> | 207 | </View> |
| 208 | 208 | ||
| 209 | <View collapsable={false} className="gap-1.5"> | 209 | <View collapsable={false} className="gap-1.5"> |
| 210 | <Text | 210 | <Text |
| 211 | className="text-[11px] font-t3-bold uppercase text-foreground-muted" | 211 | className="text-2xs font-t3-bold uppercase text-foreground-muted" |
| 212 | style={{ letterSpacing: 0.8 }} | 212 | style={{ letterSpacing: 0.8 }} |
| 213 | > | 213 | > |
| 214 | Pairing code | 214 | Pairing code |
| ... | @@ -220,7 +220,7 @@ export default function ConnectionsNewRouteScreen() { | ... | @@ -220,7 +220,7 @@ export default function ConnectionsNewRouteScreen() { |
| 220 | placeholderTextColor={placeholderColor} | 220 | placeholderTextColor={placeholderColor} |
| 221 | value={codeInput} | 221 | value={codeInput} |
| 222 | onChangeText={handleCodeChange} | 222 | 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" |
| 224 | /> | 224 | /> |
| 225 | </View> | 225 | </View> |
| 226 | 226 |
apps/mobile/src/app/new/index.tsx+5-7| ... | @@ -129,10 +129,10 @@ export default function NewTaskRoute() { | ... | @@ -129,10 +129,10 @@ export default function NewTaskRoute() { |
| 129 | {items.length === 0 ? ( | 129 | {items.length === 0 ? ( |
| 130 | <View collapsable={false} className="items-center gap-3 rounded-[24px] bg-card px-6 py-8"> | 130 | <View collapsable={false} className="items-center gap-3 rounded-[24px] bg-card px-6 py-8"> |
| 131 | {projectEmptyState.loading ? <ActivityIndicator color={accentColor} /> : null} | 131 | {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"> |
| 133 | {projectEmptyState.title} | 133 | {projectEmptyState.title} |
| 134 | </Text> | 134 | </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"> |
| 136 | {projectEmptyState.detail} | 136 | {projectEmptyState.detail} |
| 137 | </Text> | 137 | </Text> |
| 138 | {!catalogState.hasReadyEnvironment ? ( | 138 | {!catalogState.hasReadyEnvironment ? ( |
| ... | @@ -140,7 +140,7 @@ export default function NewTaskRoute() { | ... | @@ -140,7 +140,7 @@ export default function NewTaskRoute() { |
| 140 | className="mt-1 rounded-full bg-primary px-4 py-2.5 active:opacity-70" | 140 | className="mt-1 rounded-full bg-primary px-4 py-2.5 active:opacity-70" |
| 141 | onPress={() => router.push("/connections/new")} | 141 | onPress={() => router.push("/connections/new")} |
| 142 | > | 142 | > |
| 143 | <Text className="text-[13px] font-t3-bold text-primary-foreground"> | 143 | <Text className="text-sm font-t3-bold text-primary-foreground"> |
| 144 | Add environment | 144 | Add environment |
| 145 | </Text> | 145 | </Text> |
| 146 | </Pressable> | 146 | </Pressable> |
| ... | @@ -149,7 +149,7 @@ export default function NewTaskRoute() { | ... | @@ -149,7 +149,7 @@ export default function NewTaskRoute() { |
| 149 | className="mt-1 rounded-full bg-primary px-4 py-2.5 active:opacity-70" | 149 | className="mt-1 rounded-full bg-primary px-4 py-2.5 active:opacity-70" |
| 150 | onPress={() => router.push("/new/add-project")} | 150 | onPress={() => router.push("/new/add-project")} |
| 151 | > | 151 | > |
| 152 | <Text className="text-[13px] font-t3-bold text-primary-foreground"> | 152 | <Text className="text-sm font-t3-bold text-primary-foreground"> |
| 153 | Add new project | 153 | Add new project |
| 154 | </Text> | 154 | </Text> |
| 155 | </Pressable> | 155 | </Pressable> |
| ... | @@ -197,9 +197,7 @@ export default function NewTaskRoute() { | ... | @@ -197,9 +197,7 @@ export default function NewTaskRoute() { |
| 197 | /> | 197 | /> |
| 198 | </View> | 198 | </View> |
| 199 | <View className="flex-1"> | 199 | <View className="flex-1"> |
| 200 | <Text className="text-[16px] leading-[21px] font-t3-bold"> | 200 | <Text className="text-base leading-[21px] font-t3-bold">{item.title}</Text> |
| 201 | {item.title} | ||
| 202 | </Text> | ||
| 203 | </View> | 201 | </View> |
| 204 | <SymbolView | 202 | <SymbolView |
| 205 | name="chevron.right" | 203 | name="chevron.right" |
apps/mobile/src/app/settings/environments.tsx+11-11| ... | @@ -111,7 +111,7 @@ export default function SettingsEnvironmentsRouteScreen() { | ... | @@ -111,7 +111,7 @@ export default function SettingsEnvironmentsRouteScreen() { |
| 111 | type="monochrome" | 111 | type="monochrome" |
| 112 | /> | 112 | /> |
| 113 | </View> | 113 | </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"> |
| 115 | No environments connected yet.{"\n"}Tap{" "} | 115 | No environments connected yet.{"\n"}Tap{" "} |
| 116 | <Text className="font-t3-bold text-foreground">+</Text> to add one. | 116 | <Text className="font-t3-bold text-foreground">+</Text> to add one. |
| 117 | </Text> | 117 | </Text> |
| ... | @@ -160,7 +160,7 @@ function ConfiguredCloudEnvironmentRows(props: { | ... | @@ -160,7 +160,7 @@ function ConfiguredCloudEnvironmentRows(props: { |
| 160 | return ( | 160 | return ( |
| 161 | <View collapsable={false} className="mt-5 gap-3"> | 161 | <View collapsable={false} className="mt-5 gap-3"> |
| 162 | <View className="flex-row items-center justify-between px-1"> | 162 | <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> |
| 164 | <Pressable | 164 | <Pressable |
| 165 | accessibilityRole="button" | 165 | accessibilityRole="button" |
| 166 | disabled={controller.relayDiscovery.isRefreshing} | 166 | disabled={controller.relayDiscovery.isRefreshing} |
| ... | @@ -204,16 +204,16 @@ function ConfiguredCloudEnvironmentRows(props: { | ... | @@ -204,16 +204,16 @@ function ConfiguredCloudEnvironmentRows(props: { |
| 204 | ) : controller.relayDiscovery.isRefreshing ? ( | 204 | ) : controller.relayDiscovery.isRefreshing ? ( |
| 205 | <View collapsable={false} className="items-center gap-3 rounded-[24px] bg-card p-6"> | 205 | <View collapsable={false} className="items-center gap-3 rounded-[24px] bg-card p-6"> |
| 206 | <ActivityIndicator color={iconColor} /> | 206 | <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"> |
| 208 | Loading linked cloud environments. | 208 | Loading linked cloud environments. |
| 209 | </Text> | 209 | </Text> |
| 210 | </View> | 210 | </View> |
| 211 | ) : controller.relayDiscovery.error ? ( | 211 | ) : controller.relayDiscovery.error ? ( |
| 212 | <View collapsable={false} className="gap-3 rounded-[24px] bg-card p-5"> | 212 | <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"> |
| 214 | Could not load T3 Cloud environments | 214 | Could not load T3 Cloud environments |
| 215 | </Text> | 215 | </Text> |
| 216 | <Text className="text-[13px] leading-[18px] text-foreground-muted"> | 216 | <Text className="text-sm leading-[18px] text-foreground-muted"> |
| 217 | {controller.relayDiscovery.error} | 217 | {controller.relayDiscovery.error} |
| 218 | </Text> | 218 | </Text> |
| 219 | {controller.relayDiscovery.errorTraceId ? ( | 219 | {controller.relayDiscovery.errorTraceId ? ( |
| ... | @@ -222,7 +222,7 @@ function ConfiguredCloudEnvironmentRows(props: { | ... | @@ -222,7 +222,7 @@ function ConfiguredCloudEnvironmentRows(props: { |
| 222 | </View> | 222 | </View> |
| 223 | ) : ( | 223 | ) : ( |
| 224 | <View collapsable={false} className="rounded-[24px] bg-card p-5"> | 224 | <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"> |
| 226 | No additional linked cloud environments. | 226 | No additional linked cloud environments. |
| 227 | </Text> | 227 | </Text> |
| 228 | </View> | 228 | </View> |
| ... | @@ -361,7 +361,7 @@ function CloudEnvironmentRowShell(props: { | ... | @@ -361,7 +361,7 @@ function CloudEnvironmentRowShell(props: { |
| 361 | <View className="min-w-0 flex-row items-center gap-2"> | 361 | <View className="min-w-0 flex-row items-center gap-2"> |
| 362 | <ConnectionStatusDot state={props.connectionState} pulse={shouldPulse} size={7} /> | 362 | <ConnectionStatusDot state={props.connectionState} pulse={shouldPulse} size={7} /> |
| 363 | <Text | 363 | <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" |
| 365 | numberOfLines={1} | 365 | numberOfLines={1} |
| 366 | > | 366 | > |
| 367 | {props.label} | 367 | {props.label} |
| ... | @@ -370,7 +370,7 @@ function CloudEnvironmentRowShell(props: { | ... | @@ -370,7 +370,7 @@ function CloudEnvironmentRowShell(props: { |
| 370 | {props.connectionError ? ( | 370 | {props.connectionError ? ( |
| 371 | <Text | 371 | <Text |
| 372 | aria-hidden | 372 | 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)} |
| 374 | onTextLayout={onMeasuredErrorTextLayout} | 374 | onTextLayout={onMeasuredErrorTextLayout} |
| 375 | style={{ opacity: 0, zIndex: -1 }} | 375 | style={{ opacity: 0, zIndex: -1 }} |
| 376 | > | 376 | > |
| ... | @@ -384,7 +384,7 @@ function CloudEnvironmentRowShell(props: { | ... | @@ -384,7 +384,7 @@ function CloudEnvironmentRowShell(props: { |
| 384 | className="min-w-0 flex-row items-start gap-1" | 384 | className="min-w-0 flex-row items-start gap-1" |
| 385 | > | 385 | > |
| 386 | <Text | 386 | <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)} |
| 388 | numberOfLines={isErrorExpanded ? undefined : 1} | 388 | numberOfLines={isErrorExpanded ? undefined : 1} |
| 389 | > | 389 | > |
| 390 | {statusText} | 390 | {statusText} |
| ... | @@ -394,7 +394,7 @@ function CloudEnvironmentRowShell(props: { | ... | @@ -394,7 +394,7 @@ function CloudEnvironmentRowShell(props: { |
| 394 | <Text | 394 | <Text |
| 395 | accessibilityHint="Copies the trace ID" | 395 | accessibilityHint="Copies the trace ID" |
| 396 | accessibilityRole="button" | 396 | accessibilityRole="button" |
| 397 | className={cn("text-[12px] leading-[16px] underline", statusClassName)} | 397 | className={cn("text-xs leading-[16px] underline", statusClassName)} |
| 398 | onLongPress={(event) => { | 398 | onLongPress={(event) => { |
| 399 | event.stopPropagation(); | 399 | event.stopPropagation(); |
| 400 | copyTextWithHaptic(errorTraceId); | 400 | copyTextWithHaptic(errorTraceId); |
| ... | @@ -446,7 +446,7 @@ function CopyTraceIdButton(props: { readonly traceId: string }) { | ... | @@ -446,7 +446,7 @@ function CopyTraceIdButton(props: { readonly traceId: string }) { |
| 446 | className="self-start flex-row items-center gap-1.5 rounded-full bg-subtle px-3 py-2 active:opacity-70" | 446 | className="self-start flex-row items-center gap-1.5 rounded-full bg-subtle px-3 py-2 active:opacity-70" |
| 447 | > | 447 | > |
| 448 | <SymbolView name="doc.on.doc" size={12} tintColor={iconColor} type="monochrome" /> | 448 | <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> |
| 450 | </Pressable> | 450 | </Pressable> |
| 451 | ); | 451 | ); |
| 452 | } | 452 | } |
apps/mobile/src/app/settings/index.tsx+7-7| ... | @@ -346,7 +346,7 @@ function ConfiguredSettingsRouteScreen() { | ... | @@ -346,7 +346,7 @@ function ConfiguredSettingsRouteScreen() { |
| 346 | onPress={openAccount} | 346 | onPress={openAccount} |
| 347 | /> | 347 | /> |
| 348 | </SettingsSection> | 348 | </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"> |
| 350 | T3 Code works locally without signing in. Cloud features are optional. | 350 | T3 Code works locally without signing in. Cloud features are optional. |
| 351 | </Text> | 351 | </Text> |
| 352 | </View> | 352 | </View> |
| ... | @@ -389,7 +389,7 @@ type SymbolName = ComponentProps<typeof SymbolView>["name"]; | ... | @@ -389,7 +389,7 @@ type SymbolName = ComponentProps<typeof SymbolView>["name"]; |
| 389 | function SettingsSection(props: { readonly title: string; readonly children: ReactNode }) { | 389 | function SettingsSection(props: { readonly title: string; readonly children: ReactNode }) { |
| 390 | return ( | 390 | return ( |
| 391 | <View className="gap-2"> | 391 | <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> |
| 393 | <View | 393 | <View |
| 394 | className="overflow-hidden rounded-[28px] bg-card" | 394 | className="overflow-hidden rounded-[28px] bg-card" |
| 395 | style={{ borderCurve: "continuous" }} | 395 | style={{ borderCurve: "continuous" }} |
| ... | @@ -413,8 +413,8 @@ function AppSettingsSection() { | ... | @@ -413,8 +413,8 @@ function AppSettingsSection() { |
| 413 | type="monochrome" | 413 | type="monochrome" |
| 414 | weight="regular" | 414 | weight="regular" |
| 415 | /> | 415 | /> |
| 416 | <Text className="flex-1 text-[17px] text-foreground">Version</Text> | 416 | <Text className="flex-1 text-lg text-foreground">Version</Text> |
| 417 | <Text className="text-[17px] text-foreground-muted">Alpha</Text> | 417 | <Text className="text-lg text-foreground-muted">Alpha</Text> |
| 418 | </View> | 418 | </View> |
| 419 | </SettingsSection> | 419 | </SettingsSection> |
| 420 | ); | 420 | ); |
| ... | @@ -444,13 +444,13 @@ function SettingsRow(props: { | ... | @@ -444,13 +444,13 @@ function SettingsRow(props: { |
| 444 | style={{ opacity: props.disabled ? 0.45 : 1 }} | 444 | style={{ opacity: props.disabled ? 0.45 : 1 }} |
| 445 | > | 445 | > |
| 446 | <SymbolView name={props.icon} size={22} tintColor={icon} type="monochrome" weight="regular" /> | 446 | <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}> |
| 448 | {props.label} | 448 | {props.label} |
| 449 | </Text> | 449 | </Text> |
| 450 | <View className="min-w-0 flex-1 items-end"> | 450 | <View className="min-w-0 flex-1 items-end"> |
| 451 | {props.value ? ( | 451 | {props.value ? ( |
| 452 | <Text | 452 | <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" |
| 454 | ellipsizeMode="middle" | 454 | ellipsizeMode="middle" |
| 455 | numberOfLines={1} | 455 | numberOfLines={1} |
| 456 | > | 456 | > |
| ... | @@ -502,7 +502,7 @@ function SettingsSwitchRow(props: { | ... | @@ -502,7 +502,7 @@ function SettingsSwitchRow(props: { |
| 502 | style={{ opacity: props.disabled ? 0.45 : 1 }} | 502 | style={{ opacity: props.disabled ? 0.45 : 1 }} |
| 503 | > | 503 | > |
| 504 | <SymbolView name={props.icon} size={22} tintColor={icon} type="monochrome" weight="regular" /> | 504 | <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> |
| 506 | <Switch | 506 | <Switch |
| 507 | disabled={props.disabled} | 507 | disabled={props.disabled} |
| 508 | ios_backgroundColor={track} | 508 | ios_backgroundColor={track} |
apps/mobile/src/components/AppText.tsx+1-1| ... | @@ -40,7 +40,7 @@ export function AppTextInput({ | ... | @@ -40,7 +40,7 @@ export function AppTextInput({ |
| 40 | <RNTextInput | 40 | <RNTextInput |
| 41 | ref={ref} | 41 | ref={ref} |
| 42 | className={cn( | 42 | 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", |
| 44 | className, | 44 | className, |
| 45 | )} | 45 | )} |
| 46 | placeholderTextColor={placeholderTextColor ?? placeholderColor} | 46 | placeholderTextColor={placeholderTextColor ?? placeholderColor} |
apps/mobile/src/components/BrandMark.tsx+3-6| ... | @@ -22,15 +22,12 @@ export function BrandMark(props: { readonly compact?: boolean; readonly stageLab | ... | @@ -22,15 +22,12 @@ export function BrandMark(props: { readonly compact?: boolean; readonly stageLab |
| 22 | /> | 22 | /> |
| 23 | <View className="gap-1"> | 23 | <View className="gap-1"> |
| 24 | <View className="flex-row items-center gap-2"> | 24 | <View className="flex-row items-center gap-2"> |
| 25 | <Text | 25 | <Text className="text-lg font-t3-bold text-foreground" style={{ letterSpacing: -0.4 }}> |
| 26 | className="text-[17px] font-t3-bold text-foreground" | ||
| 27 | style={{ letterSpacing: -0.4 }} | ||
| 28 | > | ||
| 29 | T3 Code | 26 | T3 Code |
| 30 | </Text> | 27 | </Text> |
| 31 | <View className="rounded-full bg-subtle px-2 py-1"> | 28 | <View className="rounded-full bg-subtle px-2 py-1"> |
| 32 | <Text | 29 | <Text |
| 33 | className="text-[10px] font-t3-bold uppercase text-foreground-muted" | 30 | className="text-3xs font-t3-bold uppercase text-foreground-muted" |
| 34 | style={{ letterSpacing: 1.1 }} | 31 | style={{ letterSpacing: 1.1 }} |
| 35 | > | 32 | > |
| 36 | {stageLabel} | 33 | {stageLabel} |
| ... | @@ -38,7 +35,7 @@ export function BrandMark(props: { readonly compact?: boolean; readonly stageLab | ... | @@ -38,7 +35,7 @@ export function BrandMark(props: { readonly compact?: boolean; readonly stageLab |
| 38 | </View> | 35 | </View> |
| 39 | </View> | 36 | </View> |
| 40 | {!compact ? ( | 37 | {!compact ? ( |
| 41 | <Text className="text-[12px] font-medium text-foreground-muted"> | 38 | <Text className="text-xs font-medium text-foreground-muted"> |
| 42 | Mobile control surface for your live coding environments | 39 | Mobile control surface for your live coding environments |
| 43 | </Text> | 40 | </Text> |
| 44 | ) : null} | 41 | ) : null} |
apps/mobile/src/components/ComposerToolbarTrigger.tsx+1-1| ... | @@ -223,7 +223,7 @@ export function ComposerToolbarButton(props: { | ... | @@ -223,7 +223,7 @@ export function ComposerToolbarButton(props: { |
| 223 | {props.label ? ( | 223 | {props.label ? ( |
| 224 | <Text | 224 | <Text |
| 225 | className={cn( | 225 | className={cn( |
| 226 | "shrink text-center text-[13px] font-t3-bold", | 226 | "shrink text-center text-sm font-t3-bold", |
| 227 | variant === "primary" | 227 | variant === "primary" |
| 228 | ? props.disabled | 228 | ? props.disabled |
| 229 | ? "text-foreground-muted" | 229 | ? "text-foreground-muted" |
apps/mobile/src/components/ControlPill.tsx+1-1| ... | @@ -48,7 +48,7 @@ export function ControlPill(props: { | ... | @@ -48,7 +48,7 @@ export function ControlPill(props: { |
| 48 | : "bg-subtle", | 48 | : "bg-subtle", |
| 49 | ); | 49 | ); |
| 50 | const labelClassName = cn( | 50 | const labelClassName = cn( |
| 51 | "text-center text-[12px] font-t3-bold", | 51 | "text-center text-xs font-t3-bold", |
| 52 | variant === "primary" | 52 | variant === "primary" |
| 53 | ? props.disabled | 53 | ? props.disabled |
| 54 | ? "text-foreground-muted" | 54 | ? "text-foreground-muted" |
apps/mobile/src/components/EmptyState.tsx+1-3| ... | @@ -19,9 +19,7 @@ export function EmptyState(props: { | ... | @@ -19,9 +19,7 @@ export function EmptyState(props: { |
| 19 | className="mt-4 self-start rounded-full bg-primary px-4 py-2.5 active:opacity-70" | 19 | className="mt-4 self-start rounded-full bg-primary px-4 py-2.5 active:opacity-70" |
| 20 | onPress={props.onAction} | 20 | onPress={props.onAction} |
| 21 | > | 21 | > |
| 22 | <Text className="text-[13px] font-t3-bold text-primary-foreground"> | 22 | <Text className="text-sm font-t3-bold text-primary-foreground">{props.actionLabel}</Text> |
| 23 | {props.actionLabel} | ||
| 24 | </Text> | ||
| 25 | </Pressable> | 23 | </Pressable> |
| 26 | ) : null} | 24 | ) : null} |
| 27 | </View> | 25 | </View> |
apps/mobile/src/components/ErrorBanner.tsx+1-1| ... | @@ -4,7 +4,7 @@ import { AppText as Text } from "./AppText"; | ... | @@ -4,7 +4,7 @@ import { AppText as Text } from "./AppText"; |
| 4 | export function ErrorBanner(props: { readonly message: string }) { | 4 | export function ErrorBanner(props: { readonly message: string }) { |
| 5 | return ( | 5 | return ( |
| 6 | <View className="rounded-2xl border border-rose-300/70 bg-rose-100/80 px-3.5 py-3 dark:border-rose-400/28 dark:bg-rose-500/12"> | 6 | <View className="rounded-2xl border border-rose-300/70 bg-rose-100/80 px-3.5 py-3 dark:border-rose-400/28 dark:bg-rose-500/12"> |
| 7 | <Text className="font-t3-medium text-[13px] leading-[18px] text-rose-700 dark:text-rose-300"> | 7 | <Text className="font-t3-medium text-sm leading-[18px] text-rose-700 dark:text-rose-300"> |
| 8 | {props.message} | 8 | {props.message} |
| 9 | </Text> | 9 | </Text> |
| 10 | </View> | 10 | </View> |
apps/mobile/src/components/StatusPill.tsx+1-1| ... | @@ -26,7 +26,7 @@ export function StatusPill( | ... | @@ -26,7 +26,7 @@ export function StatusPill( |
| 26 | <Text | 26 | <Text |
| 27 | className={cn( | 27 | className={cn( |
| 28 | "font-t3-bold", | 28 | "font-t3-bold", |
| 29 | size === "compact" ? "text-[11px]" : "text-xs", | 29 | size === "compact" ? "text-2xs" : "text-xs", |
| 30 | props.textClassName, | 30 | props.textClassName, |
| 31 | )} | 31 | )} |
| 32 | > | 32 | > |
apps/mobile/src/features/archive/ArchivedThreadsScreen.tsx+11-9| ... | @@ -147,14 +147,14 @@ function ProjectGroupLabel(props: { | ... | @@ -147,14 +147,14 @@ function ProjectGroupLabel(props: { |
| 147 | workspaceRoot={props.project.workspaceRoot} | 147 | workspaceRoot={props.project.workspaceRoot} |
| 148 | /> | 148 | /> |
| 149 | <Text | 149 | <Text |
| 150 | className="flex-1 text-[12px] font-t3-medium uppercase text-foreground-muted" | 150 | className="flex-1 text-xs font-t3-medium uppercase text-foreground-muted" |
| 151 | numberOfLines={1} | 151 | numberOfLines={1} |
| 152 | style={{ letterSpacing: 0.5 }} | 152 | style={{ letterSpacing: 0.5 }} |
| 153 | > | 153 | > |
| 154 | {props.project.title} | 154 | {props.project.title} |
| 155 | </Text> | 155 | </Text> |
| 156 | {props.environmentLabel ? ( | 156 | {props.environmentLabel ? ( |
| 157 | <Text className="max-w-[42%] text-[11px] text-foreground-tertiary" numberOfLines={1}> | 157 | <Text className="max-w-[42%] text-2xs text-foreground-tertiary" numberOfLines={1}> |
| 158 | {props.environmentLabel} | 158 | {props.environmentLabel} |
| 159 | </Text> | 159 | </Text> |
| 160 | ) : null} | 160 | ) : null} |
| ... | @@ -265,13 +265,13 @@ function ArchivedThreadRow(props: { | ... | @@ -265,13 +265,13 @@ function ArchivedThreadRow(props: { |
| 265 | <View className="min-w-0 flex-1 gap-1"> | 265 | <View className="min-w-0 flex-1 gap-1"> |
| 266 | <View className="flex-row items-center gap-2"> | 266 | <View className="flex-row items-center gap-2"> |
| 267 | <Text | 267 | <Text |
| 268 | className="min-w-0 flex-1 text-[15px] font-t3-bold leading-[20px] text-foreground" | 268 | className="min-w-0 flex-1 text-base font-t3-bold leading-[20px] text-foreground" |
| 269 | numberOfLines={1} | 269 | numberOfLines={1} |
| 270 | > | 270 | > |
| 271 | {props.thread.title} | 271 | {props.thread.title} |
| 272 | </Text> | 272 | </Text> |
| 273 | <Text | 273 | <Text |
| 274 | className="text-[12px] text-foreground-tertiary" | 274 | className="text-xs text-foreground-tertiary" |
| 275 | style={{ fontVariant: ["tabular-nums"] }} | 275 | style={{ fontVariant: ["tabular-nums"] }} |
| 276 | > | 276 | > |
| 277 | {timestamp} | 277 | {timestamp} |
| ... | @@ -286,7 +286,7 @@ function ArchivedThreadRow(props: { | ... | @@ -286,7 +286,7 @@ function ArchivedThreadRow(props: { |
| 286 | type="monochrome" | 286 | type="monochrome" |
| 287 | /> | 287 | /> |
| 288 | <Text | 288 | <Text |
| 289 | className="min-w-0 flex-1 text-[11px] text-foreground-tertiary" | 289 | className="min-w-0 flex-1 text-2xs text-foreground-tertiary" |
| 290 | numberOfLines={1} | 290 | numberOfLines={1} |
| 291 | style={{ fontFamily: "monospace" }} | 291 | style={{ fontFamily: "monospace" }} |
| 292 | > | 292 | > |
| ... | @@ -314,10 +314,12 @@ function ArchivedThreadRow(props: { | ... | @@ -314,10 +314,12 @@ function ArchivedThreadRow(props: { |
| 314 | function ArchiveError(props: { readonly message: string; readonly onRetry: () => void }) { | 314 | function ArchiveError(props: { readonly message: string; readonly onRetry: () => void }) { |
| 315 | return ( | 315 | return ( |
| 316 | <View className="rounded-[20px] border border-danger-border bg-danger p-4"> | 316 | <View className="rounded-[20px] border border-danger-border bg-danger p-4"> |
| 317 | <Text className="font-t3-bold text-danger-foreground">Could not load every archive</Text> | 317 | <Text className="text-base font-t3-bold text-danger-foreground"> |
| 318 | <Text className="mt-1 text-[13px] leading-[18px] text-foreground-muted">{props.message}</Text> | 318 | Could not load every archive |
| 319 | </Text> | ||
| 320 | <Text className="mt-1 text-sm leading-[18px] text-foreground-muted">{props.message}</Text> | ||
| 319 | <Pressable className="mt-3 self-start active:opacity-60" onPress={props.onRetry}> | 321 | <Pressable className="mt-3 self-start active:opacity-60" onPress={props.onRetry}> |
| 320 | <Text className="text-[13px] font-t3-bold text-danger-foreground">Try again</Text> | 322 | <Text className="text-sm font-t3-bold text-danger-foreground">Try again</Text> |
| 321 | </Pressable> | 323 | </Pressable> |
| 322 | </View> | 324 | </View> |
| 323 | ); | 325 | ); |
| ... | @@ -386,7 +388,7 @@ export function ArchivedThreadsScreen(props: { | ... | @@ -386,7 +388,7 @@ export function ArchivedThreadsScreen(props: { |
| 386 | {isInitialLoad ? ( | 388 | {isInitialLoad ? ( |
| 387 | <View className="items-center py-16"> | 389 | <View className="items-center py-16"> |
| 388 | <ActivityIndicator color={refreshTint} /> | 390 | <ActivityIndicator color={refreshTint} /> |
| 389 | <Text className="mt-3 text-[13px] text-foreground-muted">Loading archive…</Text> | 391 | <Text className="mt-3 text-sm text-foreground-muted">Loading archive…</Text> |
| 390 | </View> | 392 | </View> |
| 391 | ) : props.groups.length === 0 ? ( | 393 | ) : props.groups.length === 0 ? ( |
| 392 | <EmptyState | 394 | <EmptyState |
apps/mobile/src/features/cloud/CloudWaitlistEnrollment.tsx+8-12| ... | @@ -2,6 +2,7 @@ import { useWaitlist } from "@clerk/expo"; | ... | @@ -2,6 +2,7 @@ import { useWaitlist } from "@clerk/expo"; |
| 2 | import { ActivityIndicator, Pressable, StyleSheet, Text, TextInput, View } from "react-native"; | 2 | import { ActivityIndicator, Pressable, StyleSheet, Text, TextInput, View } from "react-native"; |
| 3 | import { useState } from "react"; | 3 | import { useState } from "react"; |
| 4 | 4 | ||
| 5 | import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 5 | import { useThemeColor } from "../../lib/useThemeColor"; | 6 | import { useThemeColor } from "../../lib/useThemeColor"; |
| 6 | 7 | ||
| 7 | export function CloudWaitlistEnrollment(props: { readonly onSignIn: () => void }) { | 8 | export function CloudWaitlistEnrollment(props: { readonly onSignIn: () => void }) { |
| ... | @@ -141,12 +142,11 @@ function useCloudWaitlistColors() { | ... | @@ -141,12 +142,11 @@ function useCloudWaitlistColors() { |
| 141 | const styles = StyleSheet.create({ | 142 | const styles = StyleSheet.create({ |
| 142 | body: { | 143 | body: { |
| 143 | fontFamily: "DMSans_400Regular", | 144 | fontFamily: "DMSans_400Regular", |
| 144 | fontSize: 15, | 145 | ...MOBILE_TYPOGRAPHY.body, |
| 145 | lineHeight: 21, | ||
| 146 | }, | 146 | }, |
| 147 | buttonText: { | 147 | buttonText: { |
| 148 | fontFamily: "DMSans_700Bold", | 148 | fontFamily: "DMSans_700Bold", |
| 149 | fontSize: 16, | 149 | fontSize: MOBILE_TYPOGRAPHY.body.fontSize, |
| 150 | }, | 150 | }, |
| 151 | content: { | 151 | content: { |
| 152 | gap: 18, | 152 | gap: 18, |
| ... | @@ -156,8 +156,7 @@ const styles = StyleSheet.create({ | ... | @@ -156,8 +156,7 @@ const styles = StyleSheet.create({ |
| 156 | }, | 156 | }, |
| 157 | error: { | 157 | error: { |
| 158 | fontFamily: "DMSans_400Regular", | 158 | fontFamily: "DMSans_400Regular", |
| 159 | fontSize: 13, | 159 | ...MOBILE_TYPOGRAPHY.footnote, |
| 160 | lineHeight: 18, | ||
| 161 | }, | 160 | }, |
| 162 | field: { | 161 | field: { |
| 163 | gap: 8, | 162 | gap: 8, |
| ... | @@ -167,15 +166,14 @@ const styles = StyleSheet.create({ | ... | @@ -167,15 +166,14 @@ const styles = StyleSheet.create({ |
| 167 | borderRadius: 16, | 166 | borderRadius: 16, |
| 168 | borderWidth: 1, | 167 | borderWidth: 1, |
| 169 | fontFamily: "DMSans_400Regular", | 168 | fontFamily: "DMSans_400Regular", |
| 170 | fontSize: 17, | 169 | fontSize: MOBILE_TYPOGRAPHY.headline.fontSize, |
| 171 | minHeight: 54, | 170 | minHeight: 54, |
| 172 | paddingHorizontal: 16, | 171 | paddingHorizontal: 16, |
| 173 | paddingVertical: 14, | 172 | paddingVertical: 14, |
| 174 | }, | 173 | }, |
| 175 | label: { | 174 | label: { |
| 176 | fontFamily: "DMSans_700Bold", | 175 | fontFamily: "DMSans_700Bold", |
| 177 | fontSize: 13, | 176 | ...MOBILE_TYPOGRAPHY.footnote, |
| 178 | lineHeight: 18, | ||
| 179 | }, | 177 | }, |
| 180 | primaryButton: { | 178 | primaryButton: { |
| 181 | alignItems: "center", | 179 | alignItems: "center", |
| ... | @@ -196,13 +194,11 @@ const styles = StyleSheet.create({ | ... | @@ -196,13 +194,11 @@ const styles = StyleSheet.create({ |
| 196 | }, | 194 | }, |
| 197 | signInText: { | 195 | signInText: { |
| 198 | fontFamily: "DMSans_700Bold", | 196 | fontFamily: "DMSans_700Bold", |
| 199 | fontSize: 15, | 197 | ...MOBILE_TYPOGRAPHY.body, |
| 200 | lineHeight: 21, | ||
| 201 | }, | 198 | }, |
| 202 | title: { | 199 | title: { |
| 203 | fontFamily: "DMSans_700Bold", | 200 | fontFamily: "DMSans_700Bold", |
| 204 | fontSize: 20, | 201 | ...MOBILE_TYPOGRAPHY.title, |
| 205 | lineHeight: 26, | ||
| 206 | textAlign: "center", | 202 | textAlign: "center", |
| 207 | }, | 203 | }, |
| 208 | }); | 204 | }); |
apps/mobile/src/features/connection/ConnectionEnvironmentRow.tsx+9-12| ... | @@ -76,19 +76,16 @@ export function ConnectionEnvironmentRow(props: { | ... | @@ -76,19 +76,16 @@ export function ConnectionEnvironmentRow(props: { |
| 76 | /> | 76 | /> |
| 77 | 77 | ||
| 78 | <View className="flex-1 gap-0.5"> | 78 | <View className="flex-1 gap-0.5"> |
| 79 | <Text | 79 | <Text className="text-base font-t3-bold leading-[21px] text-foreground" numberOfLines={1}> |
| 80 | className="text-[16px] font-t3-bold leading-[21px] text-foreground" | ||
| 81 | numberOfLines={1} | ||
| 82 | > | ||
| 83 | {props.environment.environmentLabel} | 80 | {props.environment.environmentLabel} |
| 84 | </Text> | 81 | </Text> |
| 85 | <Text className="text-[12px] leading-[16px] text-foreground-muted" numberOfLines={1}> | 82 | <Text className="text-xs leading-[16px] text-foreground-muted" numberOfLines={1}> |
| 86 | {props.environment.displayUrl} | 83 | {props.environment.displayUrl} |
| 87 | </Text> | 84 | </Text> |
| 88 | {statusLabel ? ( | 85 | {statusLabel ? ( |
| 89 | <Text | 86 | <Text |
| 90 | className={cn( | 87 | className={cn( |
| 91 | "text-[12px] leading-[16px]", | 88 | "text-xs leading-[16px]", |
| 92 | hasConnectionFailure ? "text-rose-500 dark:text-rose-400" : "text-foreground-muted", | 89 | hasConnectionFailure ? "text-rose-500 dark:text-rose-400" : "text-foreground-muted", |
| 93 | )} | 90 | )} |
| 94 | numberOfLines={props.expanded ? undefined : 1} | 91 | numberOfLines={props.expanded ? undefined : 1} |
| ... | @@ -137,14 +134,14 @@ export function ConnectionEnvironmentRow(props: { | ... | @@ -137,14 +134,14 @@ export function ConnectionEnvironmentRow(props: { |
| 137 | className="gap-3 px-4 pb-4" | 134 | className="gap-3 px-4 pb-4" |
| 138 | > | 135 | > |
| 139 | {props.environment.isRelayManaged ? ( | 136 | {props.environment.isRelayManaged ? ( |
| 140 | <Text className="text-[13px] leading-[18px] text-foreground-muted"> | 137 | <Text className="text-sm leading-[18px] text-foreground-muted"> |
| 141 | Managed by T3 Cloud. Tunnel details update automatically. | 138 | Managed by T3 Cloud. Tunnel details update automatically. |
| 142 | </Text> | 139 | </Text> |
| 143 | ) : ( | 140 | ) : ( |
| 144 | <> | 141 | <> |
| 145 | <View className="gap-1.5"> | 142 | <View className="gap-1.5"> |
| 146 | <Text | 143 | <Text |
| 147 | className="text-[11px] font-t3-bold uppercase text-foreground-muted" | 144 | className="text-2xs font-t3-bold uppercase text-foreground-muted" |
| 148 | style={{ letterSpacing: 0.8 }} | 145 | style={{ letterSpacing: 0.8 }} |
| 149 | > | 146 | > |
| 150 | Label | 147 | Label |
| ... | @@ -156,13 +153,13 @@ export function ConnectionEnvironmentRow(props: { | ... | @@ -156,13 +153,13 @@ export function ConnectionEnvironmentRow(props: { |
| 156 | placeholderTextColor={placeholderColor} | 153 | placeholderTextColor={placeholderColor} |
| 157 | value={label} | 154 | value={label} |
| 158 | onChangeText={setLabel} | 155 | onChangeText={setLabel} |
| 159 | className="rounded-[14px] border border-input-border bg-input px-4 py-3 text-[15px] text-foreground" | 156 | className="rounded-[14px] border border-input-border bg-input px-4 py-3 text-base text-foreground" |
| 160 | /> | 157 | /> |
| 161 | </View> | 158 | </View> |
| 162 | 159 | ||
| 163 | <View className="gap-1.5"> | 160 | <View className="gap-1.5"> |
| 164 | <Text | 161 | <Text |
| 165 | className="text-[11px] font-t3-bold uppercase text-foreground-muted" | 162 | className="text-2xs font-t3-bold uppercase text-foreground-muted" |
| 166 | style={{ letterSpacing: 0.8 }} | 163 | style={{ letterSpacing: 0.8 }} |
| 167 | > | 164 | > |
| 168 | URL | 165 | URL |
| ... | @@ -175,7 +172,7 @@ export function ConnectionEnvironmentRow(props: { | ... | @@ -175,7 +172,7 @@ export function ConnectionEnvironmentRow(props: { |
| 175 | placeholderTextColor={placeholderColor} | 172 | placeholderTextColor={placeholderColor} |
| 176 | value={url} | 173 | value={url} |
| 177 | onChangeText={setUrl} | 174 | onChangeText={setUrl} |
| 178 | className="rounded-[14px] border border-input-border bg-input px-4 py-3 text-[15px] text-foreground" | 175 | className="rounded-[14px] border border-input-border bg-input px-4 py-3 text-base text-foreground" |
| 179 | /> | 176 | /> |
| 180 | </View> | 177 | </View> |
| 181 | </> | 178 | </> |
| ... | @@ -189,7 +186,7 @@ export function ConnectionEnvironmentRow(props: { | ... | @@ -189,7 +186,7 @@ export function ConnectionEnvironmentRow(props: { |
| 189 | > | 186 | > |
| 190 | <SymbolView name="checkmark" size={13} tintColor={primaryFg} type="monochrome" /> | 187 | <SymbolView name="checkmark" size={13} tintColor={primaryFg} type="monochrome" /> |
| 191 | <Text | 188 | <Text |
| 192 | className="text-[12px] font-t3-bold uppercase text-primary-foreground" | 189 | className="text-xs font-t3-bold uppercase text-primary-foreground" |
| 193 | style={{ letterSpacing: 0.8 }} | 190 | style={{ letterSpacing: 0.8 }} |
| 194 | > | 191 | > |
| 195 | Save | 192 | Save |
apps/mobile/src/features/connection/ConnectionSheetButton.tsx+1-1| ... | @@ -104,7 +104,7 @@ export function ConnectionSheetButton(props: { | ... | @@ -104,7 +104,7 @@ export function ConnectionSheetButton(props: { |
| 104 | type="monochrome" | 104 | type="monochrome" |
| 105 | /> | 105 | /> |
| 106 | <Text | 106 | <Text |
| 107 | className="text-[12px] font-t3-bold uppercase" | 107 | className="text-xs font-t3-bold uppercase" |
| 108 | style={{ color: colors.textColor, letterSpacing: 0.8 }} | 108 | style={{ color: colors.textColor, letterSpacing: 0.8 }} |
| 109 | > | 109 | > |
| 110 | {props.label} | 110 | {props.label} |
apps/mobile/src/features/connection/EnvironmentConnectionNotice.tsx+3-3| ... | @@ -73,10 +73,10 @@ export function EnvironmentConnectionNotice(props: { | ... | @@ -73,10 +73,10 @@ export function EnvironmentConnectionNotice(props: { |
| 73 | /> | 73 | /> |
| 74 | )} | 74 | )} |
| 75 | 75 | ||
| 76 | <Text className="text-center text-[17px] font-t3-bold leading-[22px] text-foreground"> | 76 | <Text className="text-center text-lg font-t3-bold leading-[22px] text-foreground"> |
| 77 | {noticeTitle(props.connection.phase, props.environmentLabel)} | 77 | {noticeTitle(props.connection.phase, props.environmentLabel)} |
| 78 | </Text> | 78 | </Text> |
| 79 | <Text className="text-center text-[14px] leading-[20px] text-foreground-muted"> | 79 | <Text className="text-center text-sm leading-[20px] text-foreground-muted"> |
| 80 | {noticeDetail(props.connection.phase, props.resourceName, props.connection.error)} | 80 | {noticeDetail(props.connection.phase, props.resourceName, props.connection.error)} |
| 81 | {props.connection.traceId ? ( | 81 | {props.connection.traceId ? ( |
| 82 | <> | 82 | <> |
| ... | @@ -99,7 +99,7 @@ export function EnvironmentConnectionNotice(props: { | ... | @@ -99,7 +99,7 @@ export function EnvironmentConnectionNotice(props: { |
| 99 | className="mt-1 rounded-full bg-subtle px-4 py-2.5 active:opacity-70" | 99 | className="mt-1 rounded-full bg-subtle px-4 py-2.5 active:opacity-70" |
| 100 | onPress={props.onRetry} | 100 | onPress={props.onRetry} |
| 101 | > | 101 | > |
| 102 | <Text className="text-[13px] font-t3-bold text-foreground">Retry now</Text> | 102 | <Text className="text-sm font-t3-bold text-foreground">Retry now</Text> |
| 103 | </Pressable> | 103 | </Pressable> |
| 104 | ) : null} | 104 | ) : null} |
| 105 | </View> | 105 | </View> |
apps/mobile/src/features/files/FileMarkdownPreview.tsx+3-4| ... | @@ -7,6 +7,7 @@ import { | ... | @@ -7,6 +7,7 @@ import { |
| 7 | } from "react-native-nitro-markdown"; | 7 | } from "react-native-nitro-markdown"; |
| 8 | import { Linking, ScrollView, Text as NativeText, View } from "react-native"; | 8 | import { Linking, ScrollView, Text as NativeText, View } from "react-native"; |
| 9 | 9 | ||
| 10 | import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 10 | import { useThemeColor } from "../../lib/useThemeColor"; | 11 | import { useThemeColor } from "../../lib/useThemeColor"; |
| 11 | import { | 12 | import { |
| 12 | hasNativeSelectableMarkdownText, | 13 | hasNativeSelectableMarkdownText, |
| ... | @@ -72,8 +73,7 @@ function useMarkdownPreviewStyles(): MarkdownPreviewStyles { | ... | @@ -72,8 +73,7 @@ function useMarkdownPreviewStyles(): MarkdownPreviewStyles { |
| 72 | text: { | 73 | text: { |
| 73 | color: body, | 74 | color: body, |
| 74 | fontFamily: "DMSans_400Regular", | 75 | fontFamily: "DMSans_400Regular", |
| 75 | fontSize: 15, | 76 | ...MOBILE_TYPOGRAPHY.body, |
| 76 | lineHeight: 22, | ||
| 77 | }, | 77 | }, |
| 78 | heading: { | 78 | heading: { |
| 79 | color: strong, | 79 | color: strong, |
| ... | @@ -123,8 +123,7 @@ function useMarkdownPreviewStyles(): MarkdownPreviewStyles { | ... | @@ -123,8 +123,7 @@ function useMarkdownPreviewStyles(): MarkdownPreviewStyles { |
| 123 | skillTextColor: codeText, | 123 | skillTextColor: codeText, |
| 124 | quoteMarkerColor: blockquoteBorder, | 124 | quoteMarkerColor: blockquoteBorder, |
| 125 | dividerColor: horizontalRule, | 125 | dividerColor: horizontalRule, |
| 126 | fontSize: 15, | 126 | ...MOBILE_TYPOGRAPHY.body, |
| 127 | lineHeight: 22, | ||
| 128 | fontFamily: "DMSans_400Regular", | 127 | fontFamily: "DMSans_400Regular", |
| 129 | headingFontFamily: "DMSans_700Bold", | 128 | headingFontFamily: "DMSans_700Bold", |
| 130 | boldFontFamily: "DMSans_700Bold", | 129 | boldFontFamily: "DMSans_700Bold", |
apps/mobile/src/features/files/FileTreeBrowser.tsx+6-8| ... | @@ -64,7 +64,7 @@ const FileTreeRow = memo(function FileTreeRow(props: { | ... | @@ -64,7 +64,7 @@ const FileTreeRow = memo(function FileTreeRow(props: { |
| 64 | <PierreEntryIcon path={node.path} kind={node.kind} size={17} /> | 64 | <PierreEntryIcon path={node.path} kind={node.kind} size={17} /> |
| 65 | <Text | 65 | <Text |
| 66 | className={cn( | 66 | className={cn( |
| 67 | "min-w-0 flex-1 text-[14px] leading-[19px]", | 67 | "min-w-0 flex-1 text-sm leading-[19px]", |
| 68 | selected ? "font-t3-bold text-foreground" : "font-t3-medium text-foreground-secondary", | 68 | selected ? "font-t3-bold text-foreground" : "font-t3-medium text-foreground-secondary", |
| 69 | )} | 69 | )} |
| 70 | numberOfLines={1} | 70 | numberOfLines={1} |
| ... | @@ -72,7 +72,7 @@ const FileTreeRow = memo(function FileTreeRow(props: { | ... | @@ -72,7 +72,7 @@ const FileTreeRow = memo(function FileTreeRow(props: { |
| 72 | {node.name} | 72 | {node.name} |
| 73 | </Text> | 73 | </Text> |
| 74 | {node.kind === "directory" ? ( | 74 | {node.kind === "directory" ? ( |
| 75 | <Text className="text-[11px] font-t3-medium text-foreground-tertiary"> | 75 | <Text className="text-2xs font-t3-medium text-foreground-tertiary"> |
| 76 | {node.children.length} | 76 | {node.children.length} |
| 77 | </Text> | 77 | </Text> |
| 78 | ) : null} | 78 | ) : null} |
| ... | @@ -142,10 +142,8 @@ export function FileTreeBrowser(props: { | ... | @@ -142,10 +142,8 @@ export function FileTreeBrowser(props: { |
| 142 | <View className="flex-1 bg-sheet"> | 142 | <View className="flex-1 bg-sheet"> |
| 143 | {props.error && props.entries.length === 0 ? ( | 143 | {props.error && props.entries.length === 0 ? ( |
| 144 | <View className="px-4 py-5"> | 144 | <View className="px-4 py-5"> |
| 145 | <Text className="text-[13px] font-t3-bold text-foreground">Files unavailable</Text> | 145 | <Text className="text-sm font-t3-bold text-foreground">Files unavailable</Text> |
| 146 | <Text className="mt-1 text-[12px] leading-[18px] text-foreground-muted"> | 146 | <Text className="mt-1 text-xs leading-[18px] text-foreground-muted">{props.error}</Text> |
| 147 | {props.error} | ||
| 148 | </Text> | ||
| 149 | </View> | 147 | </View> |
| 150 | ) : ( | 148 | ) : ( |
| 151 | <FlatList | 149 | <FlatList |
| ... | @@ -174,8 +172,8 @@ export function FileTreeBrowser(props: { | ... | @@ -174,8 +172,8 @@ export function FileTreeBrowser(props: { |
| 174 | <ActivityIndicator size="small" /> | 172 | <ActivityIndicator size="small" /> |
| 175 | ) : ( | 173 | ) : ( |
| 176 | <> | 174 | <> |
| 177 | <Text className="text-[13px] font-t3-bold text-foreground">No files found</Text> | 175 | <Text className="text-sm font-t3-bold text-foreground">No files found</Text> |
| 178 | <Text className="mt-1 text-[12px] leading-[18px] text-foreground-muted"> | 176 | <Text className="mt-1 text-xs leading-[18px] text-foreground-muted"> |
| 179 | {props.searchQuery.trim().length > 0 | 177 | {props.searchQuery.trim().length > 0 |
| 180 | ? "Try a different search." | 178 | ? "Try a different search." |
| 181 | : "The workspace file index is empty."} | 179 | : "The workspace file index is empty."} |
apps/mobile/src/features/files/SourceFileSurface.tsx+15-9| ... | @@ -18,6 +18,7 @@ import { | ... | @@ -18,6 +18,7 @@ import { |
| 18 | } from "../review/reviewDiffRendering"; | 18 | } from "../review/reviewDiffRendering"; |
| 19 | import type { ReviewHighlightedToken } from "../review/shikiReviewHighlighter"; | 19 | import type { ReviewHighlightedToken } from "../review/shikiReviewHighlighter"; |
| 20 | import { cn } from "../../lib/cn"; | 20 | import { cn } from "../../lib/cn"; |
| 21 | import { MOBILE_CODE_SURFACE } from "../../lib/typography"; | ||
| 21 | import { | 22 | import { |
| 22 | buildNativeSourceRows, | 23 | buildNativeSourceRows, |
| 23 | buildNativeSourceTokens, | 24 | buildNativeSourceTokens, |
| ... | @@ -28,8 +29,8 @@ import { | ... | @@ -28,8 +29,8 @@ import { |
| 28 | } from "./nativeSourceFileAdapter"; | 29 | } from "./nativeSourceFileAdapter"; |
| 29 | import { sourceHighlightAtom } from "./sourceHighlightingState"; | 30 | import { sourceHighlightAtom } from "./sourceHighlightingState"; |
| 30 | 31 | ||
| 31 | const SOURCE_LINE_HEIGHT = 24; | 32 | const SOURCE_LINE_HEIGHT = MOBILE_CODE_SURFACE.rowHeight; |
| 32 | const SOURCE_LINE_NUMBER_WIDTH = 58; | 33 | const SOURCE_LINE_NUMBER_WIDTH = MOBILE_CODE_SURFACE.gutterWidth; |
| 33 | const NATIVE_SOURCE_STYLE_JSON = JSON.stringify(NATIVE_SOURCE_STYLE); | 34 | const NATIVE_SOURCE_STYLE_JSON = JSON.stringify(NATIVE_SOURCE_STYLE); |
| 34 | 35 | ||
| 35 | interface SourceFileSurfaceProps { | 36 | interface SourceFileSurfaceProps { |
| ... | @@ -56,10 +57,12 @@ const HighlightedSourceLine = memo(function HighlightedSourceLine(props: { | ... | @@ -56,10 +57,12 @@ const HighlightedSourceLine = memo(function HighlightedSourceLine(props: { |
| 56 | style={{ minHeight: SOURCE_LINE_HEIGHT }} | 57 | style={{ minHeight: SOURCE_LINE_HEIGHT }} |
| 57 | > | 58 | > |
| 58 | <NativeText | 59 | <NativeText |
| 59 | className="select-none pr-3 text-right text-[11px] leading-[24px] text-foreground-tertiary" | 60 | className="select-none pr-3 text-right text-foreground-tertiary" |
| 60 | style={{ | 61 | style={{ |
| 61 | width: SOURCE_LINE_NUMBER_WIDTH, | 62 | width: SOURCE_LINE_NUMBER_WIDTH, |
| 62 | fontFamily: REVIEW_MONO_FONT_FAMILY, | 63 | fontFamily: REVIEW_MONO_FONT_FAMILY, |
| 64 | fontSize: MOBILE_CODE_SURFACE.lineNumberFontSize, | ||
| 65 | lineHeight: MOBILE_CODE_SURFACE.rowHeight, | ||
| 63 | }} | 66 | }} |
| 64 | > | 67 | > |
| 65 | {props.index + 1} | 68 | {props.index + 1} |
| ... | @@ -67,8 +70,13 @@ const HighlightedSourceLine = memo(function HighlightedSourceLine(props: { | ... | @@ -67,8 +70,13 @@ const HighlightedSourceLine = memo(function HighlightedSourceLine(props: { |
| 67 | <NativeText | 70 | <NativeText |
| 68 | selectable | 71 | selectable |
| 69 | numberOfLines={1} | 72 | numberOfLines={1} |
| 70 | className="text-[13px] font-medium leading-[24px] text-foreground" | 73 | className="font-normal text-foreground" |
| 71 | style={{ fontFamily: REVIEW_MONO_FONT_FAMILY, minWidth: 320 }} | 74 | style={{ |
| 75 | fontFamily: REVIEW_MONO_FONT_FAMILY, | ||
| 76 | fontSize: MOBILE_CODE_SURFACE.fontSize, | ||
| 77 | lineHeight: MOBILE_CODE_SURFACE.rowHeight, | ||
| 78 | minWidth: 320, | ||
| 79 | }} | ||
| 72 | > | 80 | > |
| 73 | {props.tokens && props.tokens.length > 0 | 81 | {props.tokens && props.tokens.length > 0 |
| 74 | ? (() => { | 82 | ? (() => { |
| ... | @@ -80,7 +88,7 @@ const HighlightedSourceLine = memo(function HighlightedSourceLine(props: { | ... | @@ -80,7 +88,7 @@ const HighlightedSourceLine = memo(function HighlightedSourceLine(props: { |
| 80 | const fontWeight = | 88 | const fontWeight = |
| 81 | token.fontStyle !== null && (token.fontStyle & 2) === 2 | 89 | token.fontStyle !== null && (token.fontStyle & 2) === 2 |
| 82 | ? ("700" as const) | 90 | ? ("700" as const) |
| 83 | : ("500" as const); | 91 | : ("400" as const); |
| 84 | const fontStyle = | 92 | const fontStyle = |
| 85 | token.fontStyle !== null && (token.fontStyle & 1) === 1 | 93 | token.fontStyle !== null && (token.fontStyle & 1) === 1 |
| 86 | ? ("italic" as const) | 94 | ? ("italic" as const) |
| ... | @@ -142,9 +150,7 @@ function SourceHighlightStatusView(props: { readonly status: SourceHighlightStat | ... | @@ -142,9 +150,7 @@ function SourceHighlightStatusView(props: { readonly status: SourceHighlightStat |
| 142 | if (props.status === "error") { | 150 | if (props.status === "error") { |
| 143 | return ( | 151 | return ( |
| 144 | <View className="border-b border-border bg-card px-4 py-2"> | 152 | <View className="border-b border-border bg-card px-4 py-2"> |
| 145 | <Text className="text-[11px] font-t3-medium uppercase text-foreground-muted"> | 153 | <Text className="text-2xs font-t3-medium uppercase text-foreground-muted">Plain text</Text> |
| 146 | Plain text | ||
| 147 | </Text> | ||
| 148 | </View> | 154 | </View> |
| 149 | ); | 155 | ); |
| 150 | } | 156 | } |
apps/mobile/src/features/files/ThreadFilesRouteScreen.tsx+8-7| ... | @@ -24,6 +24,7 @@ import { EmptyState } from "../../components/EmptyState"; | ... | @@ -24,6 +24,7 @@ import { EmptyState } from "../../components/EmptyState"; |
| 24 | import { LoadingScreen } from "../../components/LoadingScreen"; | 24 | import { LoadingScreen } from "../../components/LoadingScreen"; |
| 25 | import { cn } from "../../lib/cn"; | 25 | import { cn } from "../../lib/cn"; |
| 26 | import { buildThreadFilesNavigation } from "../../lib/routes"; | 26 | import { buildThreadFilesNavigation } from "../../lib/routes"; |
| 27 | import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 27 | import { useThemeColor } from "../../lib/useThemeColor"; | 28 | import { useThemeColor } from "../../lib/useThemeColor"; |
| 28 | import { useThreadSelection } from "../../state/use-thread-selection"; | 29 | import { useThreadSelection } from "../../state/use-thread-selection"; |
| 29 | import { useSelectedThreadWorktree } from "../../state/use-selected-thread-worktree"; | 30 | import { useSelectedThreadWorktree } from "../../state/use-selected-thread-worktree"; |
| ... | @@ -100,7 +101,7 @@ function ModeButton(props: { | ... | @@ -100,7 +101,7 @@ function ModeButton(props: { |
| 100 | <SymbolView name={props.icon} size={13} tintColor={iconColor} type="monochrome" /> | 101 | <SymbolView name={props.icon} size={13} tintColor={iconColor} type="monochrome" /> |
| 101 | <Text | 102 | <Text |
| 102 | className={cn( | 103 | className={cn( |
| 103 | "text-[12px] font-t3-bold", | 104 | "text-xs font-t3-bold", |
| 104 | props.active ? "text-primary-foreground" : "text-foreground-muted", | 105 | props.active ? "text-primary-foreground" : "text-foreground-muted", |
| 105 | )} | 106 | )} |
| 106 | > | 107 | > |
| ... | @@ -187,7 +188,7 @@ function FileBreadcrumbs(props: { readonly projectName: string; readonly relativ | ... | @@ -187,7 +188,7 @@ function FileBreadcrumbs(props: { readonly projectName: string; readonly relativ |
| 187 | ) : null} | 188 | ) : null} |
| 188 | <Text | 189 | <Text |
| 189 | className={cn( | 190 | className={cn( |
| 190 | "max-w-[180px] px-1 text-[12px]", | 191 | "max-w-[180px] px-1 text-xs", |
| 191 | crumb.kind === "file" | 192 | crumb.kind === "file" |
| 192 | ? "font-t3-bold text-foreground" | 193 | ? "font-t3-bold text-foreground" |
| 193 | : "font-t3-medium text-foreground-muted", | 194 | : "font-t3-medium text-foreground-muted", |
| ... | @@ -308,7 +309,7 @@ function FileContent(props: { | ... | @@ -308,7 +309,7 @@ function FileContent(props: { |
| 308 | return ( | 309 | return ( |
| 309 | <View className="flex-1 items-center justify-center gap-3 bg-card px-6"> | 310 | <View className="flex-1 items-center justify-center gap-3 bg-card px-6"> |
| 310 | <ActivityIndicator /> | 311 | <ActivityIndicator /> |
| 311 | <Text className="text-center text-[13px] text-foreground-muted">Loading file...</Text> | 312 | <Text className="text-center text-sm text-foreground-muted">Loading file...</Text> |
| 312 | </View> | 313 | </View> |
| 313 | ); | 314 | ); |
| 314 | } | 315 | } |
| ... | @@ -317,10 +318,10 @@ function FileContent(props: { | ... | @@ -317,10 +318,10 @@ function FileContent(props: { |
| 317 | <View className="flex-1 bg-card"> | 318 | <View className="flex-1 bg-card"> |
| 318 | {props.truncated ? ( | 319 | {props.truncated ? ( |
| 319 | <View className="border-b border-amber-200 bg-amber-50 px-4 py-2 dark:border-amber-900/60 dark:bg-amber-950/40"> | 320 | <View className="border-b border-amber-200 bg-amber-50 px-4 py-2 dark:border-amber-900/60 dark:bg-amber-950/40"> |
| 320 | <Text className="text-[11px] font-t3-bold uppercase text-amber-700 dark:text-amber-300"> | 321 | <Text className="text-2xs font-t3-bold uppercase text-amber-700 dark:text-amber-300"> |
| 321 | Partial file | 322 | Partial file |
| 322 | </Text> | 323 | </Text> |
| 323 | <Text className="text-[12px] leading-[17px] text-amber-800 dark:text-amber-200"> | 324 | <Text className="text-xs leading-[17px] text-amber-800 dark:text-amber-200"> |
| 324 | Preview limited to the first 1 MB of a truncated file. | 325 | Preview limited to the first 1 MB of a truncated file. |
| 325 | </Text> | 326 | </Text> |
| 326 | </View> | 327 | </View> |
| ... | @@ -389,7 +390,7 @@ function FilesHeaderTitle(props: { readonly projectName: string }) { | ... | @@ -389,7 +390,7 @@ function FilesHeaderTitle(props: { readonly projectName: string }) { |
| 389 | style={{ | 390 | style={{ |
| 390 | color: foregroundColor, | 391 | color: foregroundColor, |
| 391 | fontFamily: "DMSans_700Bold", | 392 | fontFamily: "DMSans_700Bold", |
| 392 | fontSize: 18, | 393 | fontSize: MOBILE_TYPOGRAPHY.headline.fontSize, |
| 393 | fontWeight: "900", | 394 | fontWeight: "900", |
| 394 | letterSpacing: -0.4, | 395 | letterSpacing: -0.4, |
| 395 | }} | 396 | }} |
| ... | @@ -401,7 +402,7 @@ function FilesHeaderTitle(props: { readonly projectName: string }) { | ... | @@ -401,7 +402,7 @@ function FilesHeaderTitle(props: { readonly projectName: string }) { |
| 401 | style={{ | 402 | style={{ |
| 402 | color: secondaryForegroundColor, | 403 | color: secondaryForegroundColor, |
| 403 | fontFamily: "DMSans_500Medium", | 404 | fontFamily: "DMSans_500Medium", |
| 404 | fontSize: 12, | 405 | fontSize: MOBILE_TYPOGRAPHY.label.fontSize, |
| 405 | fontWeight: "500", | 406 | fontWeight: "500", |
| 406 | letterSpacing: 0.2, | 407 | letterSpacing: 0.2, |
| 407 | }} | 408 | }} |
apps/mobile/src/features/files/WorkspaceFileImagePreview.tsx+2-2| ... | @@ -81,7 +81,7 @@ function CachedWorkspaceFileImagePreview(props: { | ... | @@ -81,7 +81,7 @@ function CachedWorkspaceFileImagePreview(props: { |
| 81 | return ( | 81 | return ( |
| 82 | <View className="flex-1 items-center justify-center gap-3 bg-card px-6"> | 82 | <View className="flex-1 items-center justify-center gap-3 bg-card px-6"> |
| 83 | <ActivityIndicator /> | 83 | <ActivityIndicator /> |
| 84 | <Text className="text-center text-[13px] text-foreground-muted">Loading image...</Text> | 84 | <Text className="text-center text-sm text-foreground-muted">Loading image...</Text> |
| 85 | </View> | 85 | </View> |
| 86 | ); | 86 | ); |
| 87 | } | 87 | } |
| ... | @@ -102,7 +102,7 @@ export function WorkspaceFileImagePreview(props: { | ... | @@ -102,7 +102,7 @@ export function WorkspaceFileImagePreview(props: { |
| 102 | return ( | 102 | return ( |
| 103 | <View className="flex-1 items-center justify-center gap-3 bg-card px-6"> | 103 | <View className="flex-1 items-center justify-center gap-3 bg-card px-6"> |
| 104 | <ActivityIndicator /> | 104 | <ActivityIndicator /> |
| 105 | <Text className="text-center text-[13px] text-foreground-muted"> | 105 | <Text className="text-center text-sm text-foreground-muted"> |
| 106 | Preparing image preview... | 106 | Preparing image preview... |
| 107 | </Text> | 107 | </Text> |
| 108 | </View> | 108 | </View> |
apps/mobile/src/features/files/WorkspaceFileWebPreview.tsx+3-5| ... | @@ -13,7 +13,7 @@ export function WorkspaceFileWebPreview(props: { readonly uri: string | null }) | ... | @@ -13,7 +13,7 @@ export function WorkspaceFileWebPreview(props: { readonly uri: string | null }) |
| 13 | return ( | 13 | return ( |
| 14 | <View className="flex-1 items-center justify-center gap-3 bg-card px-6"> | 14 | <View className="flex-1 items-center justify-center gap-3 bg-card px-6"> |
| 15 | <ActivityIndicator /> | 15 | <ActivityIndicator /> |
| 16 | <Text className="text-center text-[13px] text-foreground-muted">Preparing preview...</Text> | 16 | <Text className="text-center text-sm text-foreground-muted">Preparing preview...</Text> |
| 17 | </View> | 17 | </View> |
| 18 | ); | 18 | ); |
| 19 | } | 19 | } |
| ... | @@ -23,10 +23,8 @@ export function WorkspaceFileWebPreview(props: { readonly uri: string | null }) | ... | @@ -23,10 +23,8 @@ export function WorkspaceFileWebPreview(props: { readonly uri: string | null }) |
| 23 | {loadProgress > 0 && loadProgress < 1 ? <LoadingStrip progress={loadProgress} /> : null} | 23 | {loadProgress > 0 && loadProgress < 1 ? <LoadingStrip progress={loadProgress} /> : null} |
| 24 | {loadError ? ( | 24 | {loadError ? ( |
| 25 | <View className="border-b border-border bg-card px-4 py-2"> | 25 | <View className="border-b border-border bg-card px-4 py-2"> |
| 26 | <Text className="text-[12px] font-t3-bold text-foreground">Preview failed</Text> | 26 | <Text className="text-xs font-t3-bold text-foreground">Preview failed</Text> |
| 27 | <Text className="mt-0.5 text-[12px] leading-[17px] text-foreground-muted"> | 27 | <Text className="mt-0.5 text-xs leading-[17px] text-foreground-muted">{loadError}</Text> |
| 28 | {loadError} | ||
| 29 | </Text> | ||
| 30 | </View> | 28 | </View> |
| 31 | ) : null} | 29 | ) : null} |
| 32 | <WebView | 30 | <WebView |
apps/mobile/src/features/files/nativeSourceFileAdapter.test.ts+20| ... | @@ -3,10 +3,30 @@ import { describe, expect, it } from "vite-plus/test"; | ... | @@ -3,10 +3,30 @@ import { describe, expect, it } from "vite-plus/test"; |
| 3 | import { | 3 | import { |
| 4 | buildNativeSourceRows, | 4 | buildNativeSourceRows, |
| 5 | buildNativeSourceTokens, | 5 | buildNativeSourceTokens, |
| 6 | NATIVE_SOURCE_ROW_HEIGHT, | ||
| 7 | NATIVE_SOURCE_STYLE, | ||
| 6 | nativeSourceRowId, | 8 | nativeSourceRowId, |
| 7 | } from "./nativeSourceFileAdapter"; | 9 | } from "./nativeSourceFileAdapter"; |
| 10 | import { | ||
| 11 | NATIVE_REVIEW_DIFF_ROW_HEIGHT, | ||
| 12 | NATIVE_REVIEW_DIFF_STYLE, | ||
| 13 | } from "../review/nativeReviewDiffAdapter"; | ||
| 8 | 14 | ||
| 9 | describe("nativeSourceFileAdapter", () => { | 15 | describe("nativeSourceFileAdapter", () => { |
| 16 | it("uses the same compact code typography as the diff viewer", () => { | ||
| 17 | expect(NATIVE_SOURCE_ROW_HEIGHT).toBe(NATIVE_REVIEW_DIFF_ROW_HEIGHT); | ||
| 18 | expect(NATIVE_SOURCE_STYLE).toMatchObject({ | ||
| 19 | rowHeight: NATIVE_REVIEW_DIFF_STYLE.rowHeight, | ||
| 20 | gutterWidth: NATIVE_REVIEW_DIFF_STYLE.gutterWidth, | ||
| 21 | codePadding: NATIVE_REVIEW_DIFF_STYLE.codePadding, | ||
| 22 | textVerticalInset: NATIVE_REVIEW_DIFF_STYLE.textVerticalInset, | ||
| 23 | codeFontSize: NATIVE_REVIEW_DIFF_STYLE.codeFontSize, | ||
| 24 | codeFontWeight: NATIVE_REVIEW_DIFF_STYLE.codeFontWeight, | ||
| 25 | lineNumberFontSize: NATIVE_REVIEW_DIFF_STYLE.lineNumberFontSize, | ||
| 26 | lineNumberFontWeight: NATIVE_REVIEW_DIFF_STYLE.lineNumberFontWeight, | ||
| 27 | }); | ||
| 28 | }); | ||
| 29 | |||
| 10 | it("maps plain source lines onto context rows with stable line numbers", () => { | 30 | it("maps plain source lines onto context rows with stable line numbers", () => { |
| 11 | expect(buildNativeSourceRows(["const value = 1;", "\treturn value;"])).toEqual([ | 31 | expect(buildNativeSourceRows(["const value = 1;", "\treturn value;"])).toEqual([ |
| 12 | { | 32 | { |
apps/mobile/src/features/files/nativeSourceFileAdapter.ts+10-8| ... | @@ -3,22 +3,24 @@ import type { | ... | @@ -3,22 +3,24 @@ import type { |
| 3 | NativeReviewDiffStyle, | 3 | NativeReviewDiffStyle, |
| 4 | NativeReviewDiffToken, | 4 | NativeReviewDiffToken, |
| 5 | } from "../diffs/nativeReviewDiffSurface"; | 5 | } from "../diffs/nativeReviewDiffSurface"; |
| 6 | import { MOBILE_CODE_SURFACE, MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 6 | import type { SourceHighlightTokens } from "./sourceHighlightingState"; | 7 | import type { SourceHighlightTokens } from "./sourceHighlightingState"; |
| 7 | 8 | ||
| 8 | export const NATIVE_SOURCE_ROW_HEIGHT = 24; | 9 | export const NATIVE_SOURCE_ROW_HEIGHT = MOBILE_CODE_SURFACE.rowHeight; |
| 9 | export const NATIVE_SOURCE_CONTENT_WIDTH = 32_000; | 10 | export const NATIVE_SOURCE_CONTENT_WIDTH = 32_000; |
| 10 | 11 | ||
| 11 | export const NATIVE_SOURCE_STYLE: NativeReviewDiffStyle = { | 12 | export const NATIVE_SOURCE_STYLE: NativeReviewDiffStyle = { |
| 12 | rowHeight: NATIVE_SOURCE_ROW_HEIGHT, | 13 | rowHeight: NATIVE_SOURCE_ROW_HEIGHT, |
| 13 | contentWidth: NATIVE_SOURCE_CONTENT_WIDTH, | 14 | contentWidth: NATIVE_SOURCE_CONTENT_WIDTH, |
| 14 | changeBarWidth: 0, | 15 | changeBarWidth: 0, |
| 15 | gutterWidth: 58, | 16 | gutterWidth: MOBILE_CODE_SURFACE.gutterWidth, |
| 16 | codePadding: 8, | 17 | codePadding: MOBILE_CODE_SURFACE.codePadding, |
| 17 | codeFontSize: 13, | 18 | textVerticalInset: MOBILE_CODE_SURFACE.textVerticalInset, |
| 18 | codeFontWeight: "medium", | 19 | codeFontSize: MOBILE_CODE_SURFACE.fontSize, |
| 19 | lineNumberFontSize: 11, | 20 | codeFontWeight: "regular", |
| 20 | lineNumberFontWeight: "medium", | 21 | lineNumberFontSize: MOBILE_CODE_SURFACE.lineNumberFontSize, |
| 21 | emptyStateFontSize: 12, | 22 | lineNumberFontWeight: "regular", |
| 23 | emptyStateFontSize: MOBILE_TYPOGRAPHY.label.fontSize, | ||
| 22 | emptyStateFontWeight: "medium", | 24 | emptyStateFontWeight: "medium", |
| 23 | }; | 25 | }; |
| 24 | 26 |
apps/mobile/src/features/home/HomeHeader.tsx+3-2| ... | @@ -12,6 +12,7 @@ import { Stack } from "expo-router"; | ... | @@ -12,6 +12,7 @@ import { Stack } from "expo-router"; |
| 12 | import { Text as RNText, View } from "react-native"; | 12 | import { Text as RNText, View } from "react-native"; |
| 13 | 13 | ||
| 14 | import { useThemeColor } from "../../lib/useThemeColor"; | 14 | import { useThemeColor } from "../../lib/useThemeColor"; |
| 15 | import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 15 | import type { HomeProjectSortOrder } from "./homeThreadList"; | 16 | import type { HomeProjectSortOrder } from "./homeThreadList"; |
| 16 | 17 | ||
| 17 | export interface HomeHeaderEnvironment { | 18 | export interface HomeHeaderEnvironment { |
| ... | @@ -118,7 +119,7 @@ export function HomeHeader(props: { | ... | @@ -118,7 +119,7 @@ export function HomeHeader(props: { |
| 118 | <RNText | 119 | <RNText |
| 119 | style={{ | 120 | style={{ |
| 120 | fontFamily: "DMSans_700Bold", | 121 | fontFamily: "DMSans_700Bold", |
| 121 | fontSize: 17, | 122 | fontSize: MOBILE_TYPOGRAPHY.headline.fontSize, |
| 122 | color: iconColor, | 123 | color: iconColor, |
| 123 | letterSpacing: -0.4, | 124 | letterSpacing: -0.4, |
| 124 | }} | 125 | }} |
| ... | @@ -136,7 +137,7 @@ export function HomeHeader(props: { | ... | @@ -136,7 +137,7 @@ export function HomeHeader(props: { |
| 136 | <RNText | 137 | <RNText |
| 137 | style={{ | 138 | style={{ |
| 138 | fontFamily: "DMSans_700Bold", | 139 | fontFamily: "DMSans_700Bold", |
| 139 | fontSize: 10, | 140 | fontSize: MOBILE_TYPOGRAPHY.micro.fontSize, |
| 140 | color: mutedColor, | 141 | color: mutedColor, |
| 141 | letterSpacing: 1.1, | 142 | letterSpacing: 1.1, |
| 142 | textTransform: "uppercase", | 143 | textTransform: "uppercase", |
apps/mobile/src/features/home/HomeScreen.tsx+7-7| ... | @@ -186,7 +186,7 @@ function ProjectGroupLabel(props: { | ... | @@ -186,7 +186,7 @@ function ProjectGroupLabel(props: { |
| 186 | workspaceRoot={props.project.workspaceRoot} | 186 | workspaceRoot={props.project.workspaceRoot} |
| 187 | /> | 187 | /> |
| 188 | <Text | 188 | <Text |
| 189 | className="flex-1 text-[12px] font-t3-medium uppercase text-foreground-muted" | 189 | className="flex-1 text-xs font-t3-medium uppercase text-foreground-muted" |
| 190 | style={{ letterSpacing: 0.5 }} | 190 | style={{ letterSpacing: 0.5 }} |
| 191 | numberOfLines={1} | 191 | numberOfLines={1} |
| 192 | > | 192 | > |
| ... | @@ -196,7 +196,7 @@ function ProjectGroupLabel(props: { | ... | @@ -196,7 +196,7 @@ function ProjectGroupLabel(props: { |
| 196 | {hiddenCount > 0 ? ( | 196 | {hiddenCount > 0 ? ( |
| 197 | <Pressable onPress={props.onToggleExpand} hitSlop={8}> | 197 | <Pressable onPress={props.onToggleExpand} hitSlop={8}> |
| 198 | <Text | 198 | <Text |
| 199 | className="text-[12px] font-t3-medium text-foreground-muted" | 199 | className="text-xs font-t3-medium text-foreground-muted" |
| 200 | style={{ letterSpacing: 0.4 }} | 200 | style={{ letterSpacing: 0.4 }} |
| 201 | > | 201 | > |
| 202 | {props.isExpanded ? "Show less" : `${hiddenCount} more`} | 202 | {props.isExpanded ? "Show less" : `${hiddenCount} more`} |
| ... | @@ -335,7 +335,7 @@ function ThreadRow(props: { | ... | @@ -335,7 +335,7 @@ function ThreadRow(props: { |
| 335 | <View style={{ flex: 1, gap: 3 }}> | 335 | <View style={{ flex: 1, gap: 3 }}> |
| 336 | <View className="flex-row items-center justify-between gap-2"> | 336 | <View className="flex-row items-center justify-between gap-2"> |
| 337 | <Text | 337 | <Text |
| 338 | className="flex-1 text-[15px] font-t3-bold leading-[20px] text-foreground" | 338 | className="flex-1 text-base font-t3-bold leading-[20px] text-foreground" |
| 339 | numberOfLines={1} | 339 | numberOfLines={1} |
| 340 | > | 340 | > |
| 341 | {props.thread.title} | 341 | {props.thread.title} |
| ... | @@ -345,12 +345,12 @@ function ThreadRow(props: { | ... | @@ -345,12 +345,12 @@ function ThreadRow(props: { |
| 345 | className={tone.pillClassName} | 345 | className={tone.pillClassName} |
| 346 | style={{ borderRadius: 99, paddingHorizontal: 6, paddingVertical: 2 }} | 346 | style={{ borderRadius: 99, paddingHorizontal: 6, paddingVertical: 2 }} |
| 347 | > | 347 | > |
| 348 | <Text className={`text-[10px] font-t3-bold ${tone.textClassName}`}> | 348 | <Text className={`text-3xs font-t3-bold ${tone.textClassName}`}> |
| 349 | {tone.label} | 349 | {tone.label} |
| 350 | </Text> | 350 | </Text> |
| 351 | </View> | 351 | </View> |
| 352 | <Text | 352 | <Text |
| 353 | className="text-[12px] text-foreground-tertiary" | 353 | className="text-xs text-foreground-tertiary" |
| 354 | style={{ fontVariant: ["tabular-nums"] }} | 354 | style={{ fontVariant: ["tabular-nums"] }} |
| 355 | > | 355 | > |
| 356 | {timestamp} | 356 | {timestamp} |
| ... | @@ -367,7 +367,7 @@ function ThreadRow(props: { | ... | @@ -367,7 +367,7 @@ function ThreadRow(props: { |
| 367 | type="monochrome" | 367 | type="monochrome" |
| 368 | /> | 368 | /> |
| 369 | <Text | 369 | <Text |
| 370 | className="text-[11px] text-foreground-tertiary" | 370 | className="text-2xs text-foreground-tertiary" |
| 371 | numberOfLines={1} | 371 | numberOfLines={1} |
| 372 | style={{ fontFamily: "monospace" }} | 372 | style={{ fontFamily: "monospace" }} |
| 373 | > | 373 | > |
| ... | @@ -429,7 +429,7 @@ function StaleCatalogStatusPill(props: { | ... | @@ -429,7 +429,7 @@ function StaleCatalogStatusPill(props: { |
| 429 | weight="semibold" | 429 | weight="semibold" |
| 430 | /> | 430 | /> |
| 431 | )} | 431 | )} |
| 432 | <Text className="max-w-[260px] text-[13px] font-t3-bold text-foreground" numberOfLines={1}> | 432 | <Text className="max-w-[260px] text-sm font-t3-bold text-foreground" numberOfLines={1}> |
| 433 | {label} | 433 | {label} |
| 434 | </Text> | 434 | </Text> |
| 435 | </Pressable> | 435 | </Pressable> |
apps/mobile/src/features/home/thread-swipe-actions.tsx+1-1| ... | @@ -167,7 +167,7 @@ function SwipeActionButton(props: { | ... | @@ -167,7 +167,7 @@ function SwipeActionButton(props: { |
| 167 | </Animated.View> | 167 | </Animated.View> |
| 168 | </View> | 168 | </View> |
| 169 | <Animated.View style={[{ paddingTop: 2 }, labelStyle]}> | 169 | <Animated.View style={[{ paddingTop: 2 }, labelStyle]}> |
| 170 | <Text className="text-[10px] font-t3-medium text-foreground-muted">{props.label}</Text> | 170 | <Text className="text-3xs font-t3-medium text-foreground-muted">{props.label}</Text> |
| 171 | </Animated.View> | 171 | </Animated.View> |
| 172 | </Pressable> | 172 | </Pressable> |
| 173 | </Animated.View> | 173 | </Animated.View> |
apps/mobile/src/features/projects/AddProjectScreen.tsx+11-11| ... | @@ -100,7 +100,7 @@ function sourceFromParam(value: string | string[] | undefined): AddProjectRemote | ... | @@ -100,7 +100,7 @@ function sourceFromParam(value: string | string[] | undefined): AddProjectRemote |
| 100 | function SectionTitle(props: { readonly children: string }) { | 100 | function SectionTitle(props: { readonly children: string }) { |
| 101 | return ( | 101 | return ( |
| 102 | <Text | 102 | <Text |
| 103 | className="px-1 text-[11px] font-t3-bold uppercase text-foreground-muted" | 103 | className="px-1 text-2xs font-t3-bold uppercase text-foreground-muted" |
| 104 | style={{ letterSpacing: 0.7 }} | 104 | style={{ letterSpacing: 0.7 }} |
| 105 | > | 105 | > |
| 106 | {props.children} | 106 | {props.children} |
| ... | @@ -168,9 +168,9 @@ function ListRow(props: { | ... | @@ -168,9 +168,9 @@ function ListRow(props: { |
| 168 | {props.icon} | 168 | {props.icon} |
| 169 | </View> | 169 | </View> |
| 170 | <View className="flex-1 gap-0.5"> | 170 | <View className="flex-1 gap-0.5"> |
| 171 | <Text className="text-[16px] leading-[21px] font-t3-bold">{props.title}</Text> | 171 | <Text className="text-base leading-[21px] font-t3-bold">{props.title}</Text> |
| 172 | {props.subtitle ? ( | 172 | {props.subtitle ? ( |
| 173 | <Text className="text-[13px] leading-[17px] text-foreground-muted" numberOfLines={2}> | 173 | <Text className="text-sm leading-[17px] text-foreground-muted" numberOfLines={2}> |
| 174 | {props.subtitle} | 174 | {props.subtitle} |
| 175 | </Text> | 175 | </Text> |
| 176 | ) : null} | 176 | ) : null} |
| ... | @@ -202,7 +202,7 @@ function PrimaryActionButton(props: { | ... | @@ -202,7 +202,7 @@ function PrimaryActionButton(props: { |
| 202 | {props.loading ? ( | 202 | {props.loading ? ( |
| 203 | <ActivityIndicator color={String(primaryForeground)} /> | 203 | <ActivityIndicator color={String(primaryForeground)} /> |
| 204 | ) : ( | 204 | ) : ( |
| 205 | <Text className="text-[14px] font-t3-bold text-primary-foreground">{props.label}</Text> | 205 | <Text className="text-base font-t3-bold text-primary-foreground">{props.label}</Text> |
| 206 | )} | 206 | )} |
| 207 | </Pressable> | 207 | </Pressable> |
| 208 | ); | 208 | ); |
| ... | @@ -215,7 +215,7 @@ function ProjectPathInput(props: { | ... | @@ -215,7 +215,7 @@ function ProjectPathInput(props: { |
| 215 | }) { | 215 | }) { |
| 216 | return ( | 216 | return ( |
| 217 | <TextInput | 217 | <TextInput |
| 218 | className="h-12 min-h-12 rounded-[24px] px-4 py-0 text-[15px] leading-[20px]" | 218 | className="h-12 min-h-12 rounded-[24px] px-4 py-0 text-base leading-[20px]" |
| 219 | value={props.value} | 219 | value={props.value} |
| 220 | onChangeText={props.onChangeText} | 220 | onChangeText={props.onChangeText} |
| 221 | autoCapitalize="none" | 221 | autoCapitalize="none" |
| ... | @@ -273,15 +273,15 @@ function EmptyEnvironmentState() { | ... | @@ -273,15 +273,15 @@ function EmptyEnvironmentState() { |
| 273 | 273 | ||
| 274 | return ( | 274 | return ( |
| 275 | <View className="items-center gap-3 rounded-2xl bg-card px-5 py-8"> | 275 | <View className="items-center gap-3 rounded-2xl bg-card px-5 py-8"> |
| 276 | <Text className="text-center text-[17px] font-t3-bold">No environments connected</Text> | 276 | <Text className="text-center text-lg font-t3-bold">No environments connected</Text> |
| 277 | <Text className="text-center text-[14px] leading-[20px] text-foreground-muted"> | 277 | <Text className="text-center text-sm leading-[20px] text-foreground-muted"> |
| 278 | Add an environment before adding a project. | 278 | Add an environment before adding a project. |
| 279 | </Text> | 279 | </Text> |
| 280 | <Pressable | 280 | <Pressable |
| 281 | onPress={() => router.replace("/connections/new")} | 281 | onPress={() => router.replace("/connections/new")} |
| 282 | className="mt-1 rounded-full bg-primary px-4 py-2.5 active:opacity-70" | 282 | className="mt-1 rounded-full bg-primary px-4 py-2.5 active:opacity-70" |
| 283 | > | 283 | > |
| 284 | <Text className="text-[13px] font-t3-bold text-primary-foreground">Add environment</Text> | 284 | <Text className="text-sm font-t3-bold text-primary-foreground">Add environment</Text> |
| 285 | </Pressable> | 285 | </Pressable> |
| 286 | </View> | 286 | </View> |
| 287 | ); | 287 | ); |
| ... | @@ -565,7 +565,7 @@ export function AddProjectRepositoryScreen() { | ... | @@ -565,7 +565,7 @@ export function AddProjectRepositoryScreen() { |
| 565 | <AddProjectShell> | 565 | <AddProjectShell> |
| 566 | {error ? <ErrorBanner message={error} /> : null} | 566 | {error ? <ErrorBanner message={error} /> : null} |
| 567 | <TextInput | 567 | <TextInput |
| 568 | className="h-12 min-h-12 rounded-[24px] px-4 py-0 text-[15px] leading-[20px]" | 568 | className="h-12 min-h-12 rounded-[24px] px-4 py-0 text-base leading-[20px]" |
| 569 | value={repositoryInput} | 569 | value={repositoryInput} |
| 570 | onChangeText={setRepositoryInput} | 570 | onChangeText={setRepositoryInput} |
| 571 | autoCapitalize="none" | 571 | autoCapitalize="none" |
| ... | @@ -806,8 +806,8 @@ export function AddProjectDestinationScreen() { | ... | @@ -806,8 +806,8 @@ export function AddProjectDestinationScreen() { |
| 806 | {error ? <ErrorBanner message={error} /> : null} | 806 | {error ? <ErrorBanner message={error} /> : null} |
| 807 | {repositoryTitle ? ( | 807 | {repositoryTitle ? ( |
| 808 | <View className="rounded-[24px] bg-card px-4 py-3"> | 808 | <View className="rounded-[24px] bg-card px-4 py-3"> |
| 809 | <Text className="text-[14px] font-t3-bold">{repositoryTitle}</Text> | 809 | <Text className="text-base font-t3-bold">{repositoryTitle}</Text> |
| 810 | <Text className="mt-0.5 text-[12px] text-foreground-muted" numberOfLines={2}> | 810 | <Text className="mt-0.5 text-xs text-foreground-muted" numberOfLines={2}> |
| 811 | {remoteUrl} | 811 | {remoteUrl} |
| 812 | </Text> | 812 | </Text> |
| 813 | </View> | 813 | </View> |
apps/mobile/src/features/review/ReviewCommentComposerSheet.tsx+8-8| ... | @@ -159,26 +159,26 @@ export function ReviewCommentComposerSheet() { | ... | @@ -159,26 +159,26 @@ export function ReviewCommentComposerSheet() { |
| 159 | <SymbolView name="xmark" size={18} tintColor={iconTint} type="monochrome" /> | 159 | <SymbolView name="xmark" size={18} tintColor={iconTint} type="monochrome" /> |
| 160 | </Pressable> | 160 | </Pressable> |
| 161 | 161 | ||
| 162 | <Text className="text-[18px] font-t3-bold text-foreground">Add Comment</Text> | 162 | <Text className="text-lg font-t3-bold text-foreground">Add Comment</Text> |
| 163 | 163 | ||
| 164 | <View className="h-12 w-12" /> | 164 | <View className="h-12 w-12" /> |
| 165 | </View> | 165 | </View> |
| 166 | 166 | ||
| 167 | {!target ? ( | 167 | {!target ? ( |
| 168 | <View className="rounded-[22px] border border-border bg-card px-4 py-5"> | 168 | <View className="rounded-[22px] border border-border bg-card px-4 py-5"> |
| 169 | <Text className="text-[15px] font-t3-bold text-foreground">No selection</Text> | 169 | <Text className="text-base font-t3-bold text-foreground">No selection</Text> |
| 170 | <Text className="mt-1 text-[13px] leading-[19px] text-foreground-muted"> | 170 | <Text className="mt-1 text-sm leading-[19px] text-foreground-muted"> |
| 171 | Select a diff line or range first. | 171 | Select a diff line or range first. |
| 172 | </Text> | 172 | </Text> |
| 173 | </View> | 173 | </View> |
| 174 | ) : ( | 174 | ) : ( |
| 175 | <View className="min-h-0 flex-1 gap-4"> | 175 | <View className="min-h-0 flex-1 gap-4"> |
| 176 | <View className="gap-1 px-1"> | 176 | <View className="gap-1 px-1"> |
| 177 | <Text className="text-[11px] font-t3-bold uppercase text-foreground-muted"> | 177 | <Text className="text-2xs font-t3-bold uppercase text-foreground-muted"> |
| 178 | {selectionLabel} | 178 | {selectionLabel} |
| 179 | </Text> | 179 | </Text> |
| 180 | <Text | 180 | <Text |
| 181 | className="font-mono text-[12px] leading-[17px] text-foreground-muted" | 181 | className="font-mono text-xs leading-[17px] text-foreground-muted" |
| 182 | ellipsizeMode="middle" | 182 | ellipsizeMode="middle" |
| 183 | numberOfLines={2} | 183 | numberOfLines={2} |
| 184 | > | 184 | > |
| ... | @@ -215,7 +215,7 @@ export function ReviewCommentComposerSheet() { | ... | @@ -215,7 +215,7 @@ export function ReviewCommentComposerSheet() { |
| 215 | > | 215 | > |
| 216 | <ReviewChangeBar change={line.change} /> | 216 | <ReviewChangeBar change={line.change} /> |
| 217 | <Text | 217 | <Text |
| 218 | className="w-9 py-1 pr-1 text-right text-[11px] font-t3-medium text-foreground-muted" | 218 | className="w-9 py-1 pr-1 text-right text-2xs font-t3-medium text-foreground-muted" |
| 219 | style={{ fontFamily: REVIEW_MONO_FONT_FAMILY }} | 219 | style={{ fontFamily: REVIEW_MONO_FONT_FAMILY }} |
| 220 | > | 220 | > |
| 221 | {lineNumber ?? ""} | 221 | {lineNumber ?? ""} |
| ... | @@ -236,7 +236,7 @@ export function ReviewCommentComposerSheet() { | ... | @@ -236,7 +236,7 @@ export function ReviewCommentComposerSheet() { |
| 236 | </View> | 236 | </View> |
| 237 | 237 | ||
| 238 | <View className="min-h-0 flex-1 gap-2"> | 238 | <View className="min-h-0 flex-1 gap-2"> |
| 239 | <Text className="text-[13px] font-t3-bold text-foreground">Comment</Text> | 239 | <Text className="text-sm font-t3-bold text-foreground">Comment</Text> |
| 240 | <View className="min-h-[132px] flex-1 overflow-hidden rounded-[20px] border border-border bg-card"> | 240 | <View className="min-h-[132px] flex-1 overflow-hidden rounded-[20px] border border-border bg-card"> |
| 241 | <View className="min-h-0 flex-1 px-4 pt-3.5"> | 241 | <View className="min-h-0 flex-1 px-4 pt-3.5"> |
| 242 | <TextInputWrapper onPaste={handleNativePaste} style={{ flex: 1, minHeight: 0 }}> | 242 | <TextInputWrapper onPaste={handleNativePaste} style={{ flex: 1, minHeight: 0 }}> |
| ... | @@ -248,7 +248,7 @@ export function ReviewCommentComposerSheet() { | ... | @@ -248,7 +248,7 @@ export function ReviewCommentComposerSheet() { |
| 248 | textAlignVertical="top" | 248 | textAlignVertical="top" |
| 249 | value={commentText} | 249 | value={commentText} |
| 250 | onChangeText={setCommentText} | 250 | onChangeText={setCommentText} |
| 251 | className="h-full flex-1 border-0 bg-transparent px-0 py-0 font-sans text-[15px]" | 251 | className="h-full flex-1 border-0 bg-transparent px-0 py-0 font-sans text-base" |
| 252 | style={{ flex: 1, minHeight: 0 }} | 252 | style={{ flex: 1, minHeight: 0 }} |
| 253 | /> | 253 | /> |
| 254 | </TextInputWrapper> | 254 | </TextInputWrapper> |
apps/mobile/src/features/review/ReviewSheet.tsx+19-18| ... | @@ -20,6 +20,7 @@ import { environmentCatalog } from "../../connection/catalog"; | ... | @@ -20,6 +20,7 @@ import { environmentCatalog } from "../../connection/catalog"; |
| 20 | import { useEnvironmentPresentation } from "../../state/presentation"; | 20 | import { useEnvironmentPresentation } from "../../state/presentation"; |
| 21 | import { useAtomCommand } from "../../state/use-atom-command"; | 21 | import { useAtomCommand } from "../../state/use-atom-command"; |
| 22 | import { useThemeColor } from "../../lib/useThemeColor"; | 22 | import { useThemeColor } from "../../lib/useThemeColor"; |
| 23 | import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 23 | import { useThreadDraftForThread } from "../../state/use-thread-composer-state"; | 24 | import { useThreadDraftForThread } from "../../state/use-thread-composer-state"; |
| 24 | import { EnvironmentConnectionNotice } from "../connection/EnvironmentConnectionNotice"; | 25 | import { EnvironmentConnectionNotice } from "../connection/EnvironmentConnectionNotice"; |
| 25 | import { useReviewCacheForThread } from "./reviewState"; | 26 | import { useReviewCacheForThread } from "./reviewState"; |
| ... | @@ -41,10 +42,10 @@ const REVIEW_HEADER_SPACING = 0; | ... | @@ -41,10 +42,10 @@ const REVIEW_HEADER_SPACING = 0; |
| 41 | const ReviewNotice = memo(function ReviewNotice(props: { readonly notice: string }) { | 42 | const ReviewNotice = memo(function ReviewNotice(props: { readonly notice: string }) { |
| 42 | return ( | 43 | return ( |
| 43 | <View className="border-b border-amber-200 bg-amber-50 px-4 py-3 dark:border-amber-900/60 dark:bg-amber-950/40"> | 44 | <View className="border-b border-amber-200 bg-amber-50 px-4 py-3 dark:border-amber-900/60 dark:bg-amber-950/40"> |
| 44 | <Text className="text-[12px] font-t3-bold uppercase text-amber-700 dark:text-amber-300"> | 45 | <Text className="text-xs font-t3-bold uppercase text-amber-700 dark:text-amber-300"> |
| 45 | Partial diff | 46 | Partial diff |
| 46 | </Text> | 47 | </Text> |
| 47 | <Text className="text-[12px] leading-[18px] text-amber-800 dark:text-amber-200"> | 48 | <Text className="text-xs leading-[18px] text-amber-800 dark:text-amber-200"> |
| 48 | {props.notice} | 49 | {props.notice} |
| 49 | </Text> | 50 | </Text> |
| 50 | </View> | 51 | </View> |
| ... | @@ -69,7 +70,7 @@ function ReviewSelectionActionBar(props: { | ... | @@ -69,7 +70,7 @@ function ReviewSelectionActionBar(props: { |
| 69 | tintColor="#ffffff" | 70 | tintColor="#ffffff" |
| 70 | type="monochrome" | 71 | type="monochrome" |
| 71 | /> | 72 | /> |
| 72 | <Text className="text-[15px] font-t3-bold text-white">{props.title}</Text> | 73 | <Text className="text-base font-t3-bold text-white">{props.title}</Text> |
| 73 | </> | 74 | </> |
| 74 | ); | 75 | ); |
| 75 | 76 | ||
| ... | @@ -218,8 +219,8 @@ export function ReviewSheet() { | ... | @@ -218,8 +219,8 @@ export function ReviewSheet() { |
| 218 | if (error) { | 219 | if (error) { |
| 219 | children.push( | 220 | children.push( |
| 220 | <View key="review-error" className="border-b border-border bg-card px-4 py-3"> | 221 | <View key="review-error" className="border-b border-border bg-card px-4 py-3"> |
| 221 | <Text className="text-[13px] font-t3-bold text-foreground">Review unavailable</Text> | 222 | <Text className="text-sm font-t3-bold text-foreground">Review unavailable</Text> |
| 222 | <Text className="text-[12px] leading-[18px] text-foreground-muted">{error}</Text> | 223 | <Text className="text-xs leading-[18px] text-foreground-muted">{error}</Text> |
| 223 | </View>, | 224 | </View>, |
| 224 | ); | 225 | ); |
| 225 | } | 226 | } |
| ... | @@ -251,7 +252,7 @@ export function ReviewSheet() { | ... | @@ -251,7 +252,7 @@ export function ReviewSheet() { |
| 251 | numberOfLines={1} | 252 | numberOfLines={1} |
| 252 | style={{ | 253 | style={{ |
| 253 | fontFamily: "DMSans_700Bold", | 254 | fontFamily: "DMSans_700Bold", |
| 254 | fontSize: 18, | 255 | fontSize: MOBILE_TYPOGRAPHY.headline.fontSize, |
| 255 | fontWeight: "900", | 256 | fontWeight: "900", |
| 256 | color: headerForeground, | 257 | color: headerForeground, |
| 257 | letterSpacing: -0.4, | 258 | letterSpacing: -0.4, |
| ... | @@ -273,7 +274,7 @@ export function ReviewSheet() { | ... | @@ -273,7 +274,7 @@ export function ReviewSheet() { |
| 273 | <NativeText | 274 | <NativeText |
| 274 | style={{ | 275 | style={{ |
| 275 | fontFamily: "DMSans_700Bold", | 276 | fontFamily: "DMSans_700Bold", |
| 276 | fontSize: 12, | 277 | fontSize: MOBILE_TYPOGRAPHY.label.fontSize, |
| 277 | fontWeight: "700", | 278 | fontWeight: "700", |
| 278 | color: "#16a34a", | 279 | color: "#16a34a", |
| 279 | }} | 280 | }} |
| ... | @@ -283,7 +284,7 @@ export function ReviewSheet() { | ... | @@ -283,7 +284,7 @@ export function ReviewSheet() { |
| 283 | <NativeText | 284 | <NativeText |
| 284 | style={{ | 285 | style={{ |
| 285 | fontFamily: "DMSans_700Bold", | 286 | fontFamily: "DMSans_700Bold", |
| 286 | fontSize: 12, | 287 | fontSize: MOBILE_TYPOGRAPHY.label.fontSize, |
| 287 | fontWeight: "700", | 288 | fontWeight: "700", |
| 288 | color: "#e11d48", | 289 | color: "#e11d48", |
| 289 | }} | 290 | }} |
| ... | @@ -294,7 +295,7 @@ export function ReviewSheet() { | ... | @@ -294,7 +295,7 @@ export function ReviewSheet() { |
| 294 | <NativeText | 295 | <NativeText |
| 295 | style={{ | 296 | style={{ |
| 296 | fontFamily: "DMSans_700Bold", | 297 | fontFamily: "DMSans_700Bold", |
| 297 | fontSize: 12, | 298 | fontSize: MOBILE_TYPOGRAPHY.label.fontSize, |
| 298 | fontWeight: "700", | 299 | fontWeight: "700", |
| 299 | color: "#b45309", | 300 | color: "#b45309", |
| 300 | }} | 301 | }} |
| ... | @@ -309,7 +310,7 @@ export function ReviewSheet() { | ... | @@ -309,7 +310,7 @@ export function ReviewSheet() { |
| 309 | numberOfLines={1} | 310 | numberOfLines={1} |
| 310 | style={{ | 311 | style={{ |
| 311 | fontFamily: "DMSans_700Bold", | 312 | fontFamily: "DMSans_700Bold", |
| 312 | fontSize: 12, | 313 | fontSize: MOBILE_TYPOGRAPHY.label.fontSize, |
| 313 | fontWeight: "700", | 314 | fontWeight: "700", |
| 314 | color: headerMuted, | 315 | color: headerMuted, |
| 315 | }} | 316 | }} |
| ... | @@ -320,7 +321,7 @@ export function ReviewSheet() { | ... | @@ -320,7 +321,7 @@ export function ReviewSheet() { |
| 320 | <NativeText | 321 | <NativeText |
| 321 | style={{ | 322 | style={{ |
| 322 | fontFamily: "DMSans_700Bold", | 323 | fontFamily: "DMSans_700Bold", |
| 323 | fontSize: 12, | 324 | fontSize: MOBILE_TYPOGRAPHY.label.fontSize, |
| 324 | fontWeight: "700", | 325 | fontWeight: "700", |
| 325 | color: "#b45309", | 326 | color: "#b45309", |
| 326 | }} | 327 | }} |
| ... | @@ -430,30 +431,30 @@ export function ReviewSheet() { | ... | @@ -430,30 +431,30 @@ export function ReviewSheet() { |
| 430 | {listHeader} | 431 | {listHeader} |
| 431 | {!selectedSection ? ( | 432 | {!selectedSection ? ( |
| 432 | <View className="border-b border-border bg-card px-4 py-5"> | 433 | <View className="border-b border-border bg-card px-4 py-5"> |
| 433 | <Text className="text-[14px] font-t3-bold text-foreground">No review diffs</Text> | 434 | <Text className="text-sm font-t3-bold text-foreground">No review diffs</Text> |
| 434 | <Text className="text-[12px] leading-[18px] text-foreground-muted"> | 435 | <Text className="text-xs leading-[18px] text-foreground-muted"> |
| 435 | This thread has no ready turn diffs and the worktree diff is empty. | 436 | This thread has no ready turn diffs and the worktree diff is empty. |
| 436 | </Text> | 437 | </Text> |
| 437 | </View> | 438 | </View> |
| 438 | ) : selectedSection.isLoading && selectedSection.diff === null ? ( | 439 | ) : selectedSection.isLoading && selectedSection.diff === null ? ( |
| 439 | <View className="items-center gap-3 border-b border-border bg-card px-4 py-6"> | 440 | <View className="items-center gap-3 border-b border-border bg-card px-4 py-6"> |
| 440 | <ActivityIndicator size="small" /> | 441 | <ActivityIndicator size="small" /> |
| 441 | <Text className="text-[12px] text-foreground-muted">Loading diff…</Text> | 442 | <Text className="text-xs text-foreground-muted">Loading diff…</Text> |
| 442 | </View> | 443 | </View> |
| 443 | ) : parsedDiff.kind === "empty" ? ( | 444 | ) : parsedDiff.kind === "empty" ? ( |
| 444 | <View className="border-b border-border bg-card px-4 py-5"> | 445 | <View className="border-b border-border bg-card px-4 py-5"> |
| 445 | <Text className="text-[14px] font-t3-bold text-foreground">No changes</Text> | 446 | <Text className="text-sm font-t3-bold text-foreground">No changes</Text> |
| 446 | <Text className="text-[12px] leading-[18px] text-foreground-muted"> | 447 | <Text className="text-xs leading-[18px] text-foreground-muted"> |
| 447 | {selectedSection.subtitle ?? "This diff is empty."} | 448 | {selectedSection.subtitle ?? "This diff is empty."} |
| 448 | </Text> | 449 | </Text> |
| 449 | </View> | 450 | </View> |
| 450 | ) : parsedDiff.kind === "raw" ? ( | 451 | ) : parsedDiff.kind === "raw" ? ( |
| 451 | <View className="gap-3 border-b border-border bg-card px-4 py-4"> | 452 | <View className="gap-3 border-b border-border bg-card px-4 py-4"> |
| 452 | <Text className="text-[12px] leading-[18px] text-foreground-muted"> | 453 | <Text className="text-xs leading-[18px] text-foreground-muted"> |
| 453 | {parsedDiff.reason} | 454 | {parsedDiff.reason} |
| 454 | </Text> | 455 | </Text> |
| 455 | <ScrollView horizontal showsHorizontalScrollIndicator={false} bounces={false}> | 456 | <ScrollView horizontal showsHorizontalScrollIndicator={false} bounces={false}> |
| 456 | <Text selectable className="font-mono text-[12px] leading-[19px] text-foreground"> | 457 | <Text selectable className="font-mono text-xs leading-[19px] text-foreground"> |
| 457 | {parsedDiff.text} | 458 | {parsedDiff.text} |
| 458 | </Text> | 459 | </Text> |
| 459 | </ScrollView> | 460 | </ScrollView> |
apps/mobile/src/features/review/nativeReviewDiffAdapter.ts+7-6| ... | @@ -5,6 +5,7 @@ import type { | ... | @@ -5,6 +5,7 @@ import type { |
| 5 | } from "../diffs/nativeReviewDiffTypes"; | 5 | } from "../diffs/nativeReviewDiffTypes"; |
| 6 | import * as Arr from "effect/Array"; | 6 | import * as Arr from "effect/Array"; |
| 7 | import { pipe } from "effect/Function"; | 7 | import { pipe } from "effect/Function"; |
| 8 | import { MOBILE_CODE_SURFACE } from "../../lib/typography"; | ||
| 8 | import { getPierreTerminalTheme, type TerminalAppearanceScheme } from "../terminal/terminalTheme"; | 9 | import { getPierreTerminalTheme, type TerminalAppearanceScheme } from "../terminal/terminalTheme"; |
| 9 | import { computeWordAltDiffRanges } from "./reviewWordDiffs"; | 10 | import { computeWordAltDiffRanges } from "./reviewWordDiffs"; |
| 10 | import { | 11 | import { |
| ... | @@ -18,16 +19,16 @@ import type { ReviewInlineComment } from "./reviewCommentSelection"; | ... | @@ -18,16 +19,16 @@ import type { ReviewInlineComment } from "./reviewCommentSelection"; |
| 18 | const NATIVE_REVIEW_MAX_WORD_DIFF_RANGE_COUNT = 4; | 19 | const NATIVE_REVIEW_MAX_WORD_DIFF_RANGE_COUNT = 4; |
| 19 | const NATIVE_REVIEW_MAX_WORD_DIFF_COVERAGE = 0.45; | 20 | const NATIVE_REVIEW_MAX_WORD_DIFF_COVERAGE = 0.45; |
| 20 | 21 | ||
| 21 | export const NATIVE_REVIEW_DIFF_ROW_HEIGHT = 20; | 22 | export const NATIVE_REVIEW_DIFF_ROW_HEIGHT = MOBILE_CODE_SURFACE.rowHeight; |
| 22 | export const NATIVE_REVIEW_DIFF_CONTENT_WIDTH = 2_800; | 23 | export const NATIVE_REVIEW_DIFF_CONTENT_WIDTH = 2_800; |
| 23 | 24 | ||
| 24 | export const NATIVE_REVIEW_DIFF_STYLE = { | 25 | export const NATIVE_REVIEW_DIFF_STYLE = { |
| 25 | rowHeight: NATIVE_REVIEW_DIFF_ROW_HEIGHT, | 26 | rowHeight: NATIVE_REVIEW_DIFF_ROW_HEIGHT, |
| 26 | contentWidth: NATIVE_REVIEW_DIFF_CONTENT_WIDTH, | 27 | contentWidth: NATIVE_REVIEW_DIFF_CONTENT_WIDTH, |
| 27 | changeBarWidth: 4, | 28 | changeBarWidth: 4, |
| 28 | gutterWidth: 46, | 29 | gutterWidth: MOBILE_CODE_SURFACE.gutterWidth, |
| 29 | codePadding: 7, | 30 | codePadding: MOBILE_CODE_SURFACE.codePadding, |
| 30 | textVerticalInset: 2, | 31 | textVerticalInset: MOBILE_CODE_SURFACE.textVerticalInset, |
| 31 | fileHeaderHeight: 56, | 32 | fileHeaderHeight: 56, |
| 32 | fileHeaderHorizontalMargin: 8, | 33 | fileHeaderHorizontalMargin: 8, |
| 33 | fileHeaderVerticalMargin: 6, | 34 | fileHeaderVerticalMargin: 6, |
| ... | @@ -36,9 +37,9 @@ export const NATIVE_REVIEW_DIFF_STYLE = { | ... | @@ -36,9 +37,9 @@ export const NATIVE_REVIEW_DIFF_STYLE = { |
| 36 | fileHeaderPathRightPadding: 118, | 37 | fileHeaderPathRightPadding: 118, |
| 37 | fileHeaderCountColumnWidth: 38, | 38 | fileHeaderCountColumnWidth: 38, |
| 38 | fileHeaderCountGap: 5, | 39 | fileHeaderCountGap: 5, |
| 39 | codeFontSize: 11, | 40 | codeFontSize: MOBILE_CODE_SURFACE.fontSize, |
| 40 | codeFontWeight: "regular", | 41 | codeFontWeight: "regular", |
| 41 | lineNumberFontSize: 10, | 42 | lineNumberFontSize: MOBILE_CODE_SURFACE.lineNumberFontSize, |
| 42 | lineNumberFontWeight: "regular", | 43 | lineNumberFontWeight: "regular", |
| 43 | hunkFontSize: 11, | 44 | hunkFontSize: 11, |
| 44 | hunkFontWeight: "medium", | 45 | hunkFontWeight: "medium", |
apps/mobile/src/features/review/reviewDiffRendering.tsx+14-5| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | import { Platform, Text as NativeText, View } from "react-native"; | 1 | import { Platform, Text as NativeText, View } from "react-native"; |
| 2 | 2 | ||
| 3 | import { cn } from "../../lib/cn"; | 3 | import { cn } from "../../lib/cn"; |
| 4 | import { MOBILE_CODE_SURFACE } from "../../lib/typography"; | ||
| 4 | 5 | ||
| 5 | import type { ReviewRenderableLineRow } from "./reviewModel"; | 6 | import type { ReviewRenderableLineRow } from "./reviewModel"; |
| 6 | import type { ReviewHighlightedToken } from "./shikiReviewHighlighter"; | 7 | import type { ReviewHighlightedToken } from "./shikiReviewHighlighter"; |
| ... | @@ -11,7 +12,7 @@ export const REVIEW_MONO_FONT_FAMILY = Platform.select({ | ... | @@ -11,7 +12,7 @@ export const REVIEW_MONO_FONT_FAMILY = Platform.select({ |
| 11 | default: "monospace", | 12 | default: "monospace", |
| 12 | }); | 13 | }); |
| 13 | 14 | ||
| 14 | export const REVIEW_DIFF_LINE_HEIGHT = 26; | 15 | export const REVIEW_DIFF_LINE_HEIGHT = MOBILE_CODE_SURFACE.rowHeight; |
| 15 | const REVIEW_DELETE_STRIPE_COUNT = REVIEW_DIFF_LINE_HEIGHT / 2; | 16 | const REVIEW_DELETE_STRIPE_COUNT = REVIEW_DIFF_LINE_HEIGHT / 2; |
| 16 | 17 | ||
| 17 | export function renderVisibleWhitespace(value: string): string { | 18 | export function renderVisibleWhitespace(value: string): string { |
| ... | @@ -71,8 +72,12 @@ export function DiffTokenText(props: { | ... | @@ -71,8 +72,12 @@ export function DiffTokenText(props: { |
| 71 | <NativeText | 72 | <NativeText |
| 72 | numberOfLines={1} | 73 | numberOfLines={1} |
| 73 | selectable | 74 | selectable |
| 74 | className={cn("text-[13px] leading-[17px] font-medium text-foreground", props.className)} | 75 | className={cn("font-normal text-foreground", props.className)} |
| 75 | style={{ fontFamily: REVIEW_MONO_FONT_FAMILY }} | 76 | style={{ |
| 77 | fontFamily: REVIEW_MONO_FONT_FAMILY, | ||
| 78 | fontSize: MOBILE_CODE_SURFACE.fontSize, | ||
| 79 | lineHeight: MOBILE_CODE_SURFACE.rowHeight, | ||
| 80 | }} | ||
| 76 | > | 81 | > |
| 77 | {renderVisibleWhitespace(props.fallback || " ")} | 82 | {renderVisibleWhitespace(props.fallback || " ")} |
| 78 | </NativeText> | 83 | </NativeText> |
| ... | @@ -83,8 +88,12 @@ export function DiffTokenText(props: { | ... | @@ -83,8 +88,12 @@ export function DiffTokenText(props: { |
| 83 | <NativeText | 88 | <NativeText |
| 84 | numberOfLines={1} | 89 | numberOfLines={1} |
| 85 | selectable | 90 | selectable |
| 86 | className={cn("text-[13px] leading-[17px] font-medium text-foreground", props.className)} | 91 | className={cn("font-normal text-foreground", props.className)} |
| 87 | style={{ fontFamily: REVIEW_MONO_FONT_FAMILY }} | 92 | style={{ |
| 93 | fontFamily: REVIEW_MONO_FONT_FAMILY, | ||
| 94 | fontSize: MOBILE_CODE_SURFACE.fontSize, | ||
| 95 | lineHeight: MOBILE_CODE_SURFACE.rowHeight, | ||
| 96 | }} | ||
| 88 | > | 97 | > |
| 89 | {(() => { | 98 | {(() => { |
| 90 | let offset = 0; | 99 | let offset = 0; |
apps/mobile/src/features/terminal/NativeTerminalSurface.tsx+6-5| ... | @@ -11,6 +11,7 @@ import { | ... | @@ -11,6 +11,7 @@ import { |
| 11 | } from "react-native"; | 11 | } from "react-native"; |
| 12 | 12 | ||
| 13 | import { AppText as Text } from "../../components/AppText"; | 13 | import { AppText as Text } from "../../components/AppText"; |
| 14 | import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 14 | import { resolveNativeTerminalSurfaceView } from "./nativeTerminalModule"; | 15 | import { resolveNativeTerminalSurfaceView } from "./nativeTerminalModule"; |
| 15 | import { | 16 | import { |
| 16 | buildGhosttyThemeConfig, | 17 | buildGhosttyThemeConfig, |
| ... | @@ -53,7 +54,7 @@ function estimateGridSize(input: { | ... | @@ -53,7 +54,7 @@ function estimateGridSize(input: { |
| 53 | } | 54 | } |
| 54 | 55 | ||
| 55 | const FallbackTerminalSurface = memo(function FallbackTerminalSurface(props: TerminalSurfaceProps) { | 56 | const FallbackTerminalSurface = memo(function FallbackTerminalSurface(props: TerminalSurfaceProps) { |
| 56 | const fontSize = props.fontSize ?? 12; | 57 | const fontSize = props.fontSize ?? MOBILE_TYPOGRAPHY.label.fontSize; |
| 57 | const inputRef = useRef<TextInput>(null); | 58 | const inputRef = useRef<TextInput>(null); |
| 58 | const appearanceScheme = useColorScheme() === "light" ? "light" : "dark"; | 59 | const appearanceScheme = useColorScheme() === "light" ? "light" : "dark"; |
| 59 | const theme = props.theme ?? getPierreTerminalTheme(appearanceScheme); | 60 | const theme = props.theme ?? getPierreTerminalTheme(appearanceScheme); |
| ... | @@ -93,7 +94,7 @@ const FallbackTerminalSurface = memo(function FallbackTerminalSurface(props: Ter | ... | @@ -93,7 +94,7 @@ const FallbackTerminalSurface = memo(function FallbackTerminalSurface(props: Ter |
| 93 | <Text | 94 | <Text |
| 94 | style={{ | 95 | style={{ |
| 95 | color: theme.mutedForeground, | 96 | color: theme.mutedForeground, |
| 96 | fontSize: 11, | 97 | fontSize: MOBILE_TYPOGRAPHY.caption.fontSize, |
| 97 | paddingBottom: 8, | 98 | paddingBottom: 8, |
| 98 | }} | 99 | }} |
| 99 | > | 100 | > |
| ... | @@ -140,7 +141,7 @@ const FallbackTerminalSurface = memo(function FallbackTerminalSurface(props: Ter | ... | @@ -140,7 +141,7 @@ const FallbackTerminalSurface = memo(function FallbackTerminalSurface(props: Ter |
| 140 | color: theme.foreground, | 141 | color: theme.foreground, |
| 141 | flex: 1, | 142 | flex: 1, |
| 142 | fontFamily: "Menlo", | 143 | fontFamily: "Menlo", |
| 143 | fontSize: 13, | 144 | fontSize: MOBILE_TYPOGRAPHY.footnote.fontSize, |
| 144 | padding: 0, | 145 | padding: 0, |
| 145 | }} | 146 | }} |
| 146 | onSubmitEditing={(event) => { | 147 | onSubmitEditing={(event) => { |
| ... | @@ -165,7 +166,7 @@ const FallbackTerminalSurface = memo(function FallbackTerminalSurface(props: Ter | ... | @@ -165,7 +166,7 @@ const FallbackTerminalSurface = memo(function FallbackTerminalSurface(props: Ter |
| 165 | style={{ | 166 | style={{ |
| 166 | color: theme.foreground, | 167 | color: theme.foreground, |
| 167 | fontFamily: "DMSans_700Bold", | 168 | fontFamily: "DMSans_700Bold", |
| 168 | fontSize: 11, | 169 | fontSize: MOBILE_TYPOGRAPHY.caption.fontSize, |
| 169 | }} | 170 | }} |
| 170 | > | 171 | > |
| 171 | Ctrl-C | 172 | Ctrl-C |
| ... | @@ -177,7 +178,7 @@ const FallbackTerminalSurface = memo(function FallbackTerminalSurface(props: Ter | ... | @@ -177,7 +178,7 @@ const FallbackTerminalSurface = memo(function FallbackTerminalSurface(props: Ter |
| 177 | }); | 178 | }); |
| 178 | 179 | ||
| 179 | export const TerminalSurface = memo(function TerminalSurface(props: TerminalSurfaceProps) { | 180 | export const TerminalSurface = memo(function TerminalSurface(props: TerminalSurfaceProps) { |
| 180 | const fontSize = props.fontSize ?? 12; | 181 | const fontSize = props.fontSize ?? MOBILE_TYPOGRAPHY.label.fontSize; |
| 181 | const keyboardInputRef = useRef<TextInput>(null); | 182 | const keyboardInputRef = useRef<TextInput>(null); |
| 182 | const appearanceScheme = useColorScheme() === "light" ? "light" : "dark"; | 183 | const appearanceScheme = useColorScheme() === "light" ? "light" : "dark"; |
| 183 | const theme = props.theme ?? getPierreTerminalTheme(appearanceScheme); | 184 | const theme = props.theme ?? getPierreTerminalTheme(appearanceScheme); |
apps/mobile/src/features/terminal/ThreadTerminalPanel.tsx+3-3| ... | @@ -127,16 +127,16 @@ export const ThreadTerminalPanel = memo(function ThreadTerminalPanel( | ... | @@ -127,16 +127,16 @@ export const ThreadTerminalPanel = memo(function ThreadTerminalPanel( |
| 127 | <View className="absolute inset-x-3 bottom-28 top-28 overflow-hidden rounded-[8px] border border-white/10 bg-neutral-950 shadow-2xl"> | 127 | <View className="absolute inset-x-3 bottom-28 top-28 overflow-hidden rounded-[8px] border border-white/10 bg-neutral-950 shadow-2xl"> |
| 128 | <View className="flex-row items-center justify-between border-b border-white/10 px-3 py-2"> | 128 | <View className="flex-row items-center justify-between border-b border-white/10 px-3 py-2"> |
| 129 | <View className="min-w-0 flex-1"> | 129 | <View className="min-w-0 flex-1"> |
| 130 | <Text className="font-t3-bold text-[13px] text-neutral-100" numberOfLines={1}> | 130 | <Text className="font-t3-bold text-sm text-neutral-100" numberOfLines={1}> |
| 131 | Terminal | 131 | Terminal |
| 132 | </Text> | 132 | </Text> |
| 133 | <Text className="text-[11px] text-neutral-500" numberOfLines={1}> | 133 | <Text className="text-2xs text-neutral-500" numberOfLines={1}> |
| 134 | {nativeTerminalAvailable ? "Native Ghostty surface" : "Text fallback active"} | 134 | {nativeTerminalAvailable ? "Native Ghostty surface" : "Text fallback active"} |
| 135 | </Text> | 135 | </Text> |
| 136 | </View> | 136 | </View> |
| 137 | <View className="flex-row items-center gap-2"> | 137 | <View className="flex-row items-center gap-2"> |
| 138 | {terminal.error ? ( | 138 | {terminal.error ? ( |
| 139 | <Text className="max-w-44 text-right text-[11px] text-red-300" numberOfLines={1}> | 139 | <Text className="max-w-44 text-right text-2xs text-red-300" numberOfLines={1}> |
| 140 | {terminal.error} | 140 | {terminal.error} |
| 141 | </Text> | 141 | </Text> |
| 142 | ) : null} | 142 | ) : null} |
apps/mobile/src/features/terminal/ThreadTerminalRouteScreen.tsx+3-2| ... | @@ -25,6 +25,7 @@ import { terminalEnvironment } from "../../state/terminal"; | ... | @@ -25,6 +25,7 @@ import { terminalEnvironment } from "../../state/terminal"; |
| 25 | import { useAtomCommand } from "../../state/use-atom-command"; | 25 | import { useAtomCommand } from "../../state/use-atom-command"; |
| 26 | import { useWorkspaceState } from "../../state/workspace"; | 26 | import { useWorkspaceState } from "../../state/workspace"; |
| 27 | import { buildThreadTerminalNavigation } from "../../lib/routes"; | 27 | import { buildThreadTerminalNavigation } from "../../lib/routes"; |
| 28 | import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 28 | import { | 29 | import { |
| 29 | useAttachedTerminalSession, | 30 | useAttachedTerminalSession, |
| 30 | useKnownTerminalSessions, | 31 | useKnownTerminalSessions, |
| ... | @@ -920,7 +921,7 @@ export function ThreadTerminalRouteScreen() { | ... | @@ -920,7 +921,7 @@ export function ThreadTerminalRouteScreen() { |
| 920 | style={{ | 921 | style={{ |
| 921 | color: terminalTheme.foreground, | 922 | color: terminalTheme.foreground, |
| 922 | fontFamily: "DMSans_700Bold", | 923 | fontFamily: "DMSans_700Bold", |
| 923 | fontSize: 13, | 924 | fontSize: MOBILE_TYPOGRAPHY.footnote.fontSize, |
| 924 | lineHeight: 16, | 925 | lineHeight: 16, |
| 925 | }} | 926 | }} |
| 926 | > | 927 | > |
| ... | @@ -932,7 +933,7 @@ export function ThreadTerminalRouteScreen() { | ... | @@ -932,7 +933,7 @@ export function ThreadTerminalRouteScreen() { |
| 932 | style={{ | 933 | style={{ |
| 933 | color: terminalTheme.mutedForeground, | 934 | color: terminalTheme.mutedForeground, |
| 934 | fontFamily: "Menlo", | 935 | fontFamily: "Menlo", |
| 935 | fontSize: 11, | 936 | fontSize: MOBILE_TYPOGRAPHY.caption.fontSize, |
| 936 | lineHeight: 14, | 937 | lineHeight: 14, |
| 937 | }} | 938 | }} |
| 938 | > | 939 | > |
apps/mobile/src/features/threads/ComposerCommandPopover.tsx+13-4| ... | @@ -7,6 +7,7 @@ import { Pressable, ScrollView, useColorScheme, View, type ViewStyle } from "rea | ... | @@ -7,6 +7,7 @@ import { Pressable, ScrollView, useColorScheme, View, type ViewStyle } from "rea |
| 7 | 7 | ||
| 8 | import { AppText as Text } from "../../components/AppText"; | 8 | import { AppText as Text } from "../../components/AppText"; |
| 9 | import { PierreEntryIcon } from "../../components/PierreEntryIcon"; | 9 | import { PierreEntryIcon } from "../../components/PierreEntryIcon"; |
| 10 | import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 10 | 11 | ||
| 11 | export type ComposerCommandItem = | 12 | export type ComposerCommandItem = |
| 12 | | { | 13 | | { |
| ... | @@ -156,14 +157,22 @@ const CommandRow = memo(function CommandRow(props: { | ... | @@ -156,14 +157,22 @@ const CommandRow = memo(function CommandRow(props: { |
| 156 | <SymbolView name={iconName} size={14} tintColor={iconColor} type="monochrome" /> | 157 | <SymbolView name={iconName} size={14} tintColor={iconColor} type="monochrome" /> |
| 157 | ) : null} | 158 | ) : null} |
| 158 | <Text | 159 | <Text |
| 159 | className="text-[14px] font-t3-medium text-foreground" | 160 | className="text-base font-t3-medium text-foreground" |
| 160 | numberOfLines={1} | 161 | numberOfLines={1} |
| 161 | style={{ flexShrink: 0 }} | 162 | style={{ flexShrink: 0 }} |
| 162 | > | 163 | > |
| 163 | {props.item.label} | 164 | {props.item.label} |
| 164 | </Text> | 165 | </Text> |
| 165 | {props.item.description ? ( | 166 | {props.item.description ? ( |
| 166 | <Text numberOfLines={1} style={{ flex: 1, minWidth: 0, fontSize: 12, color: "#a1a1aa" }}> | 167 | <Text |
| 168 | numberOfLines={1} | ||
| 169 | style={{ | ||
| 170 | flex: 1, | ||
| 171 | minWidth: 0, | ||
| 172 | fontSize: MOBILE_TYPOGRAPHY.label.fontSize, | ||
| 173 | color: "#a1a1aa", | ||
| 174 | }} | ||
| 175 | > | ||
| 167 | {props.item.description} | 176 | {props.item.description} |
| 168 | </Text> | 177 | </Text> |
| 169 | ) : null} | 178 | ) : null} |
| ... | @@ -182,7 +191,7 @@ export const ComposerCommandPopover = memo(function ComposerCommandPopover( | ... | @@ -182,7 +191,7 @@ export const ComposerCommandPopover = memo(function ComposerCommandPopover( |
| 182 | {label ? ( | 191 | {label ? ( |
| 183 | <View style={{ paddingHorizontal: 14, paddingTop: 10, paddingBottom: 4 }}> | 192 | <View style={{ paddingHorizontal: 14, paddingTop: 10, paddingBottom: 4 }}> |
| 184 | <Text | 193 | <Text |
| 185 | className="text-[10px] font-t3-bold text-foreground-muted" | 194 | className="text-3xs font-t3-bold text-foreground-muted" |
| 186 | style={{ letterSpacing: 0.8, textTransform: "uppercase" }} | 195 | style={{ letterSpacing: 0.8, textTransform: "uppercase" }} |
| 187 | > | 196 | > |
| 188 | {label} | 197 | {label} |
| ... | @@ -206,7 +215,7 @@ export const ComposerCommandPopover = memo(function ComposerCommandPopover( | ... | @@ -206,7 +215,7 @@ export const ComposerCommandPopover = memo(function ComposerCommandPopover( |
| 206 | </ScrollView> | 215 | </ScrollView> |
| 207 | ) : ( | 216 | ) : ( |
| 208 | <View style={{ paddingHorizontal: 14, paddingVertical: 10 }}> | 217 | <View style={{ paddingHorizontal: 14, paddingVertical: 10 }}> |
| 209 | <Text className="text-[12px] text-foreground-tertiary"> | 218 | <Text className="text-xs text-foreground-tertiary"> |
| 210 | {emptyText(props.triggerKind, props.isLoading)} | 219 | {emptyText(props.triggerKind, props.isLoading)} |
| 211 | </Text> | 220 | </Text> |
| 212 | </View> | 221 | </View> |
apps/mobile/src/features/threads/GitActionProgressOverlay.tsx+2-2| ... | @@ -73,12 +73,12 @@ function OverlayContent(props: { readonly progress: GitActionProgress }) { | ... | @@ -73,12 +73,12 @@ function OverlayContent(props: { readonly progress: GitActionProgress }) { |
| 73 | 73 | ||
| 74 | <View className="flex-1 gap-0.5"> | 74 | <View className="flex-1 gap-0.5"> |
| 75 | {progress.label ? ( | 75 | {progress.label ? ( |
| 76 | <Text className="text-[13px] font-t3-bold text-foreground" numberOfLines={1}> | 76 | <Text className="text-sm font-t3-bold text-foreground" numberOfLines={1}> |
| 77 | {progress.label} | 77 | {progress.label} |
| 78 | </Text> | 78 | </Text> |
| 79 | ) : null} | 79 | ) : null} |
| 80 | {progress.description ? ( | 80 | {progress.description ? ( |
| 81 | <Text className="text-[11px] text-foreground-muted" numberOfLines={1}> | 81 | <Text className="text-2xs text-foreground-muted" numberOfLines={1}> |
| 82 | {progress.description} | 82 | {progress.description} |
| 83 | </Text> | 83 | </Text> |
| 84 | ) : null} | 84 | ) : null} |
apps/mobile/src/features/threads/NewTaskDraftScreen.tsx+2-1| ... | @@ -30,6 +30,7 @@ import { | ... | @@ -30,6 +30,7 @@ import { |
| 30 | resolveProviderOptionDescriptors, | 30 | resolveProviderOptionDescriptors, |
| 31 | } from "../../lib/providerOptions"; | 31 | } from "../../lib/providerOptions"; |
| 32 | import { buildThreadRoutePath } from "../../lib/routes"; | 32 | import { buildThreadRoutePath } from "../../lib/routes"; |
| 33 | import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 33 | import { useProjects } from "../../state/entities"; | 34 | import { useProjects } from "../../state/entities"; |
| 34 | import { branchBadgeLabel, useNewTaskFlow } from "./new-task-flow-provider"; | 35 | import { branchBadgeLabel, useNewTaskFlow } from "./new-task-flow-provider"; |
| 35 | import { useCreateProjectThread } from "./use-project-actions"; | 36 | import { useCreateProjectThread } from "./use-project-actions"; |
| ... | @@ -430,7 +431,7 @@ export function NewTaskDraftScreen(props: { | ... | @@ -430,7 +431,7 @@ export function NewTaskDraftScreen(props: { |
| 430 | onPasteImages={(uris) => void handleNativePasteImages(uris)} | 431 | onPasteImages={(uris) => void handleNativePasteImages(uris)} |
| 431 | placeholder={`Describe a coding task in ${selectedProject.title}`} | 432 | placeholder={`Describe a coding task in ${selectedProject.title}`} |
| 432 | style={{ flex: 1, minHeight: 0 }} | 433 | style={{ flex: 1, minHeight: 0 }} |
| 433 | textStyle={{ fontSize: 18, lineHeight: 28 }} | 434 | textStyle={MOBILE_TYPOGRAPHY.composer} |
| 434 | /> | 435 | /> |
| 435 | </View> | 436 | </View> |
| 436 | 437 |
apps/mobile/src/features/threads/PendingApprovalCard.tsx+1-1| ... | @@ -16,7 +16,7 @@ export interface PendingApprovalCardProps { | ... | @@ -16,7 +16,7 @@ export interface PendingApprovalCardProps { |
| 16 | export function PendingApprovalCard(props: PendingApprovalCardProps) { | 16 | export function PendingApprovalCard(props: PendingApprovalCardProps) { |
| 17 | return ( | 17 | return ( |
| 18 | <View className="gap-2.5 rounded-[20px] border border-neutral-200 bg-neutral-100/80 p-4 dark:border-white/6 dark:bg-neutral-900/80"> | 18 | <View className="gap-2.5 rounded-[20px] border border-neutral-200 bg-neutral-100/80 p-4 dark:border-white/6 dark:bg-neutral-900/80"> |
| 19 | <Text className="font-t3-bold text-[11px] uppercase tracking-[1.1px] text-sky-700 dark:text-sky-300"> | 19 | <Text className="font-t3-bold text-2xs uppercase tracking-[1.1px] text-sky-700 dark:text-sky-300"> |
| 20 | Approval needed | 20 | Approval needed |
| 21 | </Text> | 21 | </Text> |
| 22 | <Text className="font-t3-bold text-lg text-neutral-950 dark:text-neutral-50"> | 22 | <Text className="font-t3-bold text-lg text-neutral-950 dark:text-neutral-50"> |
apps/mobile/src/features/threads/PendingUserInputCard.tsx+4-4| ... | @@ -26,7 +26,7 @@ export interface PendingUserInputCardProps { | ... | @@ -26,7 +26,7 @@ export interface PendingUserInputCardProps { |
| 26 | export function PendingUserInputCard(props: PendingUserInputCardProps) { | 26 | export function PendingUserInputCard(props: PendingUserInputCardProps) { |
| 27 | return ( | 27 | return ( |
| 28 | <View className="gap-2.5 rounded-[20px] border border-neutral-200 bg-neutral-100/80 p-4 dark:border-white/6 dark:bg-neutral-900/80"> | 28 | <View className="gap-2.5 rounded-[20px] border border-neutral-200 bg-neutral-100/80 p-4 dark:border-white/6 dark:bg-neutral-900/80"> |
| 29 | <Text className="font-t3-bold text-[11px] uppercase tracking-[1.1px] text-sky-700 dark:text-sky-300"> | 29 | <Text className="font-t3-bold text-2xs uppercase tracking-[1.1px] text-sky-700 dark:text-sky-300"> |
| 30 | User input needed | 30 | User input needed |
| 31 | </Text> | 31 | </Text> |
| 32 | <Text className="font-t3-bold text-lg text-neutral-950 dark:text-neutral-50"> | 32 | <Text className="font-t3-bold text-lg text-neutral-950 dark:text-neutral-50"> |
| ... | @@ -39,7 +39,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) { | ... | @@ -39,7 +39,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) { |
| 39 | <Text className="font-t3-bold text-xs uppercase tracking-[1px] text-neutral-500 dark:text-neutral-500"> | 39 | <Text className="font-t3-bold text-xs uppercase tracking-[1px] text-neutral-500 dark:text-neutral-500"> |
| 40 | {question.header} | 40 | {question.header} |
| 41 | </Text> | 41 | </Text> |
| 42 | <Text className="font-sans text-[15px] leading-[21px] text-neutral-950 dark:text-neutral-50"> | 42 | <Text className="font-sans text-base leading-[21px] text-neutral-950 dark:text-neutral-50"> |
| 43 | {question.question} | 43 | {question.question} |
| 44 | </Text> | 44 | </Text> |
| 45 | <View className="flex-row flex-wrap gap-2.5"> | 45 | <View className="flex-row flex-wrap gap-2.5"> |
| ... | @@ -65,7 +65,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) { | ... | @@ -65,7 +65,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) { |
| 65 | > | 65 | > |
| 66 | <Text | 66 | <Text |
| 67 | className={cn( | 67 | className={cn( |
| 68 | "font-t3-bold text-[13px]", | 68 | "font-t3-bold text-sm", |
| 69 | selected | 69 | selected |
| 70 | ? "text-sky-700 dark:text-sky-300" | 70 | ? "text-sky-700 dark:text-sky-300" |
| 71 | : "text-neutral-600 dark:text-neutral-300", | 71 | : "text-neutral-600 dark:text-neutral-300", |
| ... | @@ -83,7 +83,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) { | ... | @@ -83,7 +83,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) { |
| 83 | props.onChangeCustomAnswer(props.pendingUserInput.requestId, question.id, value) | 83 | props.onChangeCustomAnswer(props.pendingUserInput.requestId, question.id, value) |
| 84 | } | 84 | } |
| 85 | placeholder="Or type a custom answer" | 85 | placeholder="Or type a custom answer" |
| 86 | className="min-h-[54px] rounded-2xl border border-neutral-200 bg-white px-3.5 py-3 font-sans text-[15px] text-neutral-950 dark:border-white/8 dark:bg-neutral-950/70 dark:text-neutral-50" | 86 | className="min-h-[54px] rounded-2xl border border-neutral-200 bg-white px-3.5 py-3 font-sans text-base text-neutral-950 dark:border-white/8 dark:bg-neutral-950/70 dark:text-neutral-50" |
| 87 | /> | 87 | /> |
| 88 | </View> | 88 | </View> |
| 89 | ); | 89 | ); |
apps/mobile/src/features/threads/ThreadComposer.tsx+5-6| ... | @@ -43,6 +43,7 @@ import { ControlPill, ControlPillMenu } from "../../components/ControlPill"; | ... | @@ -43,6 +43,7 @@ import { ControlPill, ControlPillMenu } from "../../components/ControlPill"; |
| 43 | import { ProviderIcon } from "../../components/ProviderIcon"; | 43 | import { ProviderIcon } from "../../components/ProviderIcon"; |
| 44 | import type { DraftComposerImageAttachment } from "../../lib/composerImages"; | 44 | import type { DraftComposerImageAttachment } from "../../lib/composerImages"; |
| 45 | import { buildModelOptions, groupByProvider } from "../../lib/modelOptions"; | 45 | import { buildModelOptions, groupByProvider } from "../../lib/modelOptions"; |
| 46 | import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 46 | import type { RemoteClientConnectionState } from "../../lib/connection"; | 47 | import type { RemoteClientConnectionState } from "../../lib/connection"; |
| 47 | import { | 48 | import { |
| 48 | insertRankedSearchResult, | 49 | insertRankedSearchResult, |
| ... | @@ -189,7 +190,7 @@ const ComposerConnectionStatusPill = memo(function ComposerConnectionStatusPill( | ... | @@ -189,7 +190,7 @@ const ComposerConnectionStatusPill = memo(function ComposerConnectionStatusPill( |
| 189 | <View className="h-2 w-2 rounded-full bg-red-500" /> | 190 | <View className="h-2 w-2 rounded-full bg-red-500" /> |
| 190 | )} | 191 | )} |
| 191 | <Text | 192 | <Text |
| 192 | className="max-w-[260px] text-[13px] font-t3-bold leading-[17px] text-foreground" | 193 | className="max-w-[260px] text-sm font-t3-bold leading-[17px] text-foreground" |
| 193 | numberOfLines={1} | 194 | numberOfLines={1} |
| 194 | > | 195 | > |
| 195 | {props.status.label} | 196 | {props.status.label} |
| ... | @@ -717,8 +718,7 @@ export const ThreadComposer = memo(function ThreadComposer(props: ThreadComposer | ... | @@ -717,8 +718,7 @@ export const ThreadComposer = memo(function ThreadComposer(props: ThreadComposer |
| 717 | } | 718 | } |
| 718 | } | 719 | } |
| 719 | textStyle={{ | 720 | textStyle={{ |
| 720 | fontSize: 15, | 721 | ...MOBILE_TYPOGRAPHY.composer, |
| 721 | lineHeight: isExpanded ? 22 : 20, | ||
| 722 | color: foregroundColor, | 722 | color: foregroundColor, |
| 723 | fontFamily: "DMSans_400Regular", | 723 | fontFamily: "DMSans_400Regular", |
| 724 | }} | 724 | }} |
| ... | @@ -751,7 +751,7 @@ export const ThreadComposer = memo(function ThreadComposer(props: ThreadComposer | ... | @@ -751,7 +751,7 @@ export const ThreadComposer = memo(function ThreadComposer(props: ThreadComposer |
| 751 | justifyContent: "center", | 751 | justifyContent: "center", |
| 752 | }} | 752 | }} |
| 753 | > | 753 | > |
| 754 | <Text className="text-foreground-muted text-[11px] font-t3-bold"> | 754 | <Text className="text-foreground-muted text-2xs font-t3-bold"> |
| 755 | +{props.draftAttachments.length - 3} | 755 | +{props.draftAttachments.length - 3} |
| 756 | </Text> | 756 | </Text> |
| 757 | </View> | 757 | </View> |
| ... | @@ -831,8 +831,7 @@ export const ThreadComposer = memo(function ThreadComposer(props: ThreadComposer | ... | @@ -831,8 +831,7 @@ export const ThreadComposer = memo(function ThreadComposer(props: ThreadComposer |
| 831 | <Text | 831 | <Text |
| 832 | className="text-foreground-muted" | 832 | className="text-foreground-muted" |
| 833 | style={{ | 833 | style={{ |
| 834 | fontSize: 12, | 834 | ...MOBILE_TYPOGRAPHY.label, |
| 835 | lineHeight: 18, | ||
| 836 | paddingTop: 8, | 835 | paddingTop: 8, |
| 837 | }} | 836 | }} |
| 838 | > | 837 | > |
apps/mobile/src/features/threads/ThreadFeed.tsx+12-14| ... | @@ -56,6 +56,7 @@ import { buildReviewParsedDiff } from "../review/reviewModel"; | ... | @@ -56,6 +56,7 @@ import { buildReviewParsedDiff } from "../review/reviewModel"; |
| 56 | import { cn } from "../../lib/cn"; | 56 | import { cn } from "../../lib/cn"; |
| 57 | import type { LayoutVariant } from "../../lib/layout"; | 57 | import type { LayoutVariant } from "../../lib/layout"; |
| 58 | import { buildThreadFilesNavigation } from "../../lib/routes"; | 58 | import { buildThreadFilesNavigation } from "../../lib/routes"; |
| 59 | import { MOBILE_CODE_SURFACE, MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 59 | import { markdownFileIconSource } from "@t3tools/mobile-markdown-text/file-icons"; | 60 | import { markdownFileIconSource } from "@t3tools/mobile-markdown-text/file-icons"; |
| 60 | import { resolveMarkdownLinkPresentation } from "@t3tools/mobile-markdown-text/links"; | 61 | import { resolveMarkdownLinkPresentation } from "@t3tools/mobile-markdown-text/links"; |
| 61 | import { | 62 | import { |
| ... | @@ -444,8 +445,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe | ... | @@ -444,8 +445,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe |
| 444 | marginRight: 5, | 445 | marginRight: 5, |
| 445 | color: inlineTextColor, | 446 | color: inlineTextColor, |
| 446 | fontFamily: "DMSans_400Regular", | 447 | fontFamily: "DMSans_400Regular", |
| 447 | fontSize: 15, | 448 | ...MOBILE_TYPOGRAPHY.body, |
| 448 | lineHeight: 22, | ||
| 449 | textAlign: ordered ? "right" : "center", | 449 | textAlign: ordered ? "right" : "center", |
| 450 | }} | 450 | }} |
| 451 | > | 451 | > |
| ... | @@ -466,7 +466,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe | ... | @@ -466,7 +466,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe |
| 466 | style={{ | 466 | style={{ |
| 467 | color: inlineCodeTextColor, | 467 | color: inlineCodeTextColor, |
| 468 | fontFamily: "ui-monospace", | 468 | fontFamily: "ui-monospace", |
| 469 | fontSize: 12, | 469 | fontSize: MOBILE_TYPOGRAPHY.label.fontSize, |
| 470 | lineHeight: 22, | 470 | lineHeight: 22, |
| 471 | }} | 471 | }} |
| 472 | > | 472 | > |
| ... | @@ -503,7 +503,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe | ... | @@ -503,7 +503,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe |
| 503 | style={{ | 503 | style={{ |
| 504 | color: markdownBodyColor, | 504 | color: markdownBodyColor, |
| 505 | fontFamily: "ui-monospace", | 505 | fontFamily: "ui-monospace", |
| 506 | fontSize: 12, | 506 | fontSize: MOBILE_TYPOGRAPHY.label.fontSize, |
| 507 | opacity: 0.7, | 507 | opacity: 0.7, |
| 508 | textTransform: "uppercase", | 508 | textTransform: "uppercase", |
| 509 | }} | 509 | }} |
| ... | @@ -523,7 +523,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe | ... | @@ -523,7 +523,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe |
| 523 | style={{ | 523 | style={{ |
| 524 | color: blockTextColor, | 524 | color: blockTextColor, |
| 525 | fontFamily: "ui-monospace", | 525 | fontFamily: "ui-monospace", |
| 526 | fontSize: 12, | 526 | fontSize: MOBILE_TYPOGRAPHY.label.fontSize, |
| 527 | lineHeight: 18, | 527 | lineHeight: 18, |
| 528 | }} | 528 | }} |
| 529 | > | 529 | > |
| ... | @@ -603,8 +603,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe | ... | @@ -603,8 +603,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe |
| 603 | skillTextColor: "#f0abfc", | 603 | skillTextColor: "#f0abfc", |
| 604 | quoteMarkerColor: markdownUserBodyColor, | 604 | quoteMarkerColor: markdownUserBodyColor, |
| 605 | dividerColor: markdownUserBodyColor, | 605 | dividerColor: markdownUserBodyColor, |
| 606 | fontSize: 15, | 606 | ...MOBILE_TYPOGRAPHY.body, |
| 607 | lineHeight: 22, | ||
| 608 | fontFamily: "DMSans_400Regular", | 607 | fontFamily: "DMSans_400Regular", |
| 609 | headingFontFamily: "DMSans_700Bold", | 608 | headingFontFamily: "DMSans_700Bold", |
| 610 | boldFontFamily: "DMSans_700Bold", | 609 | boldFontFamily: "DMSans_700Bold", |
| ... | @@ -633,8 +632,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe | ... | @@ -633,8 +632,7 @@ function useMarkdownStyles(onLinkPress: (href: string) => void): MarkdownStyleSe |
| 633 | skillTextColor: inlineSkillForeground, | 632 | skillTextColor: inlineSkillForeground, |
| 634 | quoteMarkerColor: markdownBlockquoteBorder, | 633 | quoteMarkerColor: markdownBlockquoteBorder, |
| 635 | dividerColor: markdownHrColor, | 634 | dividerColor: markdownHrColor, |
| 636 | fontSize: 15, | 635 | ...MOBILE_TYPOGRAPHY.body, |
| 637 | lineHeight: 22, | ||
| 638 | fontFamily: "DMSans_400Regular", | 636 | fontFamily: "DMSans_400Regular", |
| 639 | headingFontFamily: "DMSans_700Bold", | 637 | headingFontFamily: "DMSans_700Bold", |
| 640 | boldFontFamily: "DMSans_700Bold", | 638 | boldFontFamily: "DMSans_700Bold", |
| ... | @@ -821,7 +819,7 @@ function renderFeedEntry( | ... | @@ -821,7 +819,7 @@ function renderFeedEntry( |
| 821 | className="max-w-[85%] gap-2 rounded-[22px] rounded-br-[6px] px-3.5 py-2.5 opacity-60" | 819 | className="max-w-[85%] gap-2 rounded-[22px] rounded-br-[6px] px-3.5 py-2.5 opacity-60" |
| 822 | style={{ backgroundColor: userBubbleColor }} | 820 | style={{ backgroundColor: userBubbleColor }} |
| 823 | > | 821 | > |
| 824 | <Text className="font-sans text-[15px] leading-[22px] text-white"> | 822 | <Text className="font-sans text-base leading-[22px] text-white"> |
| 825 | {entry.queuedMessage.text} | 823 | {entry.queuedMessage.text} |
| 826 | </Text> | 824 | </Text> |
| 827 | {entry.queuedMessage.attachments.length > 0 ? ( | 825 | {entry.queuedMessage.attachments.length > 0 ? ( |
| ... | @@ -995,7 +993,7 @@ const ReviewCommentCard = memo(function ReviewCommentCard(props: { | ... | @@ -995,7 +993,7 @@ const ReviewCommentCard = memo(function ReviewCommentCard(props: { |
| 995 | </View> | 993 | </View> |
| 996 | <View className="min-w-0 flex-1"> | 994 | <View className="min-w-0 flex-1"> |
| 997 | <Text | 995 | <Text |
| 998 | className="font-mono text-[12px] leading-[16px]" | 996 | className="font-mono text-xs leading-[16px]" |
| 999 | numberOfLines={1} | 997 | numberOfLines={1} |
| 1000 | style={{ color: props.colors.text }} | 998 | style={{ color: props.colors.text }} |
| 1001 | > | 999 | > |
| ... | @@ -1040,8 +1038,8 @@ const ReviewCommentCard = memo(function ReviewCommentCard(props: { | ... | @@ -1040,8 +1038,8 @@ const ReviewCommentCard = memo(function ReviewCommentCard(props: { |
| 1040 | style={{ | 1038 | style={{ |
| 1041 | color: props.colors.text, | 1039 | color: props.colors.text, |
| 1042 | fontFamily: "ui-monospace", | 1040 | fontFamily: "ui-monospace", |
| 1043 | fontSize: 12, | 1041 | fontSize: MOBILE_CODE_SURFACE.fontSize, |
| 1044 | lineHeight: 18, | 1042 | lineHeight: MOBILE_CODE_SURFACE.rowHeight, |
| 1045 | }} | 1043 | }} |
| 1046 | > | 1044 | > |
| 1047 | {props.comment.diff.trim()} | 1045 | {props.comment.diff.trim()} |
| ... | @@ -1052,7 +1050,7 @@ const ReviewCommentCard = memo(function ReviewCommentCard(props: { | ... | @@ -1052,7 +1050,7 @@ const ReviewCommentCard = memo(function ReviewCommentCard(props: { |
| 1052 | <View className="border-t px-3 py-3" style={{ borderColor: props.colors.border }}> | 1050 | <View className="border-t px-3 py-3" style={{ borderColor: props.colors.border }}> |
| 1053 | <Text | 1051 | <Text |
| 1054 | selectable | 1052 | selectable |
| 1055 | className="text-[15px] leading-[21px]" | 1053 | className="text-base leading-[21px]" |
| 1056 | style={{ color: props.colors.text }} | 1054 | style={{ color: props.colors.text }} |
| 1057 | > | 1055 | > |
| 1058 | {props.comment.text} | 1056 | {props.comment.text} |
apps/mobile/src/features/threads/ThreadNavigationDrawer.tsx+5-7| ... | @@ -152,7 +152,7 @@ export function ThreadNavigationDrawer(props: { | ... | @@ -152,7 +152,7 @@ export function ThreadNavigationDrawer(props: { |
| 152 | ]} | 152 | ]} |
| 153 | > | 153 | > |
| 154 | <View className="flex-row items-center justify-between px-4 pb-5"> | 154 | <View className="flex-row items-center justify-between px-4 pb-5"> |
| 155 | <Text className="text-[26px] font-t3-bold">Threads</Text> | 155 | <Text className="text-2xl font-t3-bold">Threads</Text> |
| 156 | <Pressable | 156 | <Pressable |
| 157 | onPress={() => { | 157 | onPress={() => { |
| 158 | props.onClose(); | 158 | props.onClose(); |
| ... | @@ -224,7 +224,7 @@ function ThreadNavigationDrawerContent(props: { | ... | @@ -224,7 +224,7 @@ function ThreadNavigationDrawerContent(props: { |
| 224 | {groupedThreads.map((group) => ( | 224 | {groupedThreads.map((group) => ( |
| 225 | <View key={group.key} className="gap-3"> | 225 | <View key={group.key} className="gap-3"> |
| 226 | <Text | 226 | <Text |
| 227 | className="px-1 text-[15px] font-t3-bold text-foreground-muted" | 227 | className="px-1 text-base font-t3-bold text-foreground-muted" |
| 228 | style={{ letterSpacing: -0.2 }} | 228 | style={{ letterSpacing: -0.2 }} |
| 229 | > | 229 | > |
| 230 | {group.title} | 230 | {group.title} |
| ... | @@ -233,9 +233,7 @@ function ThreadNavigationDrawerContent(props: { | ... | @@ -233,9 +233,7 @@ function ThreadNavigationDrawerContent(props: { |
| 233 | <View className="overflow-hidden rounded-[22px] bg-card"> | 233 | <View className="overflow-hidden rounded-[22px] bg-card"> |
| 234 | {group.threads.length === 0 ? ( | 234 | {group.threads.length === 0 ? ( |
| 235 | <View className="px-4 py-4"> | 235 | <View className="px-4 py-4"> |
| 236 | <Text className="text-[14px] font-medium text-foreground-tertiary"> | 236 | <Text className="text-sm font-medium text-foreground-tertiary">No threads yet</Text> |
| 237 | No threads yet | ||
| 238 | </Text> | ||
| 239 | </View> | 237 | </View> |
| 240 | ) : ( | 238 | ) : ( |
| 241 | group.threads.map((thread, index) => { | 239 | group.threads.map((thread, index) => { |
| ... | @@ -260,11 +258,11 @@ function ThreadNavigationDrawerContent(props: { | ... | @@ -260,11 +258,11 @@ function ThreadNavigationDrawerContent(props: { |
| 260 | > | 258 | > |
| 261 | <View className="flex-row items-start justify-between gap-3"> | 259 | <View className="flex-row items-start justify-between gap-3"> |
| 262 | <View className="flex-1 gap-1"> | 260 | <View className="flex-1 gap-1"> |
| 263 | <Text className="text-[16px] font-t3-bold" numberOfLines={1}> | 261 | <Text className="text-base font-t3-bold" numberOfLines={1}> |
| 264 | {thread.title} | 262 | {thread.title} |
| 265 | </Text> | 263 | </Text> |
| 266 | <Text | 264 | <Text |
| 267 | className="text-[13px] font-medium text-foreground-muted" | 265 | className="text-sm font-medium text-foreground-muted" |
| 268 | numberOfLines={1} | 266 | numberOfLines={1} |
| 269 | > | 267 | > |
| 270 | {relativeTime(thread.updatedAt ?? thread.createdAt)} | 268 | {relativeTime(thread.updatedAt ?? thread.createdAt)} |
apps/mobile/src/features/threads/ThreadRouteScreen.tsx+3-2| ... | @@ -20,6 +20,7 @@ import { EmptyState } from "../../components/EmptyState"; | ... | @@ -20,6 +20,7 @@ import { EmptyState } from "../../components/EmptyState"; |
| 20 | import { LoadingScreen } from "../../components/LoadingScreen"; | 20 | import { LoadingScreen } from "../../components/LoadingScreen"; |
| 21 | import { buildThreadRoutePath, buildThreadTerminalNavigation } from "../../lib/routes"; | 21 | import { buildThreadRoutePath, buildThreadTerminalNavigation } from "../../lib/routes"; |
| 22 | import { scopedThreadKey } from "../../lib/scopedEntities"; | 22 | import { scopedThreadKey } from "../../lib/scopedEntities"; |
| 23 | import { MOBILE_TYPOGRAPHY } from "../../lib/typography"; | ||
| 23 | import { connectionTone } from "../connection/connectionTone"; | 24 | import { connectionTone } from "../connection/connectionTone"; |
| 24 | 25 | ||
| 25 | import { | 26 | import { |
| ... | @@ -390,7 +391,7 @@ export function ThreadRouteScreen() { | ... | @@ -390,7 +391,7 @@ export function ThreadRouteScreen() { |
| 390 | numberOfLines={1} | 391 | numberOfLines={1} |
| 391 | style={{ | 392 | style={{ |
| 392 | fontFamily: "DMSans_700Bold", | 393 | fontFamily: "DMSans_700Bold", |
| 393 | fontSize: 18, | 394 | fontSize: MOBILE_TYPOGRAPHY.headline.fontSize, |
| 394 | fontWeight: "900", | 395 | fontWeight: "900", |
| 395 | color: foregroundColor, | 396 | color: foregroundColor, |
| 396 | letterSpacing: -0.4, | 397 | letterSpacing: -0.4, |
| ... | @@ -402,7 +403,7 @@ export function ThreadRouteScreen() { | ... | @@ -402,7 +403,7 @@ export function ThreadRouteScreen() { |
| 402 | numberOfLines={1} | 403 | numberOfLines={1} |
| 403 | style={{ | 404 | style={{ |
| 404 | fontFamily: "DMSans_700Bold", | 405 | fontFamily: "DMSans_700Bold", |
| 405 | fontSize: 12, | 406 | fontSize: MOBILE_TYPOGRAPHY.label.fontSize, |
| 406 | fontWeight: "700", | 407 | fontWeight: "700", |
| 407 | color: secondaryFg, | 408 | color: secondaryFg, |
| 408 | letterSpacing: 0.3, | 409 | letterSpacing: 0.3, |
apps/mobile/src/features/threads/git/GitBranchesSheet.tsx+10-12| ... | @@ -69,7 +69,7 @@ export function GitBranchesSheet() { | ... | @@ -69,7 +69,7 @@ export function GitBranchesSheet() { |
| 69 | > | 69 | > |
| 70 | <View className="gap-2 rounded-[18px] border border-border bg-card px-4 py-4"> | 70 | <View className="gap-2 rounded-[18px] border border-border bg-card px-4 py-4"> |
| 71 | <Text | 71 | <Text |
| 72 | className="text-foreground-secondary text-[11px] font-t3-bold uppercase" | 72 | className="text-foreground-secondary text-2xs font-t3-bold uppercase" |
| 73 | style={{ letterSpacing: 1 }} | 73 | style={{ letterSpacing: 1 }} |
| 74 | > | 74 | > |
| 75 | New branch | 75 | New branch |
| ... | @@ -78,7 +78,7 @@ export function GitBranchesSheet() { | ... | @@ -78,7 +78,7 @@ export function GitBranchesSheet() { |
| 78 | value={newBranchName} | 78 | value={newBranchName} |
| 79 | onChangeText={setNewBranchName} | 79 | onChangeText={setNewBranchName} |
| 80 | placeholder="feature/mobile-polish" | 80 | placeholder="feature/mobile-polish" |
| 81 | className="rounded-[18px] px-3.5 py-3 font-sans text-[15px]" | 81 | className="rounded-[18px] px-3.5 py-3 font-sans text-base" |
| 82 | style={{ | 82 | style={{ |
| 83 | borderWidth: 1, | 83 | borderWidth: 1, |
| 84 | borderColor: inputBorderColor, | 84 | borderColor: inputBorderColor, |
| ... | @@ -104,7 +104,7 @@ export function GitBranchesSheet() { | ... | @@ -104,7 +104,7 @@ export function GitBranchesSheet() { |
| 104 | 104 | ||
| 105 | <View className="gap-2 rounded-[18px] border border-border bg-card px-4 py-4"> | 105 | <View className="gap-2 rounded-[18px] border border-border bg-card px-4 py-4"> |
| 106 | <Text | 106 | <Text |
| 107 | className="text-foreground-secondary text-[11px] font-t3-bold uppercase" | 107 | className="text-foreground-secondary text-2xs font-t3-bold uppercase" |
| 108 | style={{ letterSpacing: 1 }} | 108 | style={{ letterSpacing: 1 }} |
| 109 | > | 109 | > |
| 110 | New worktree | 110 | New worktree |
| ... | @@ -113,7 +113,7 @@ export function GitBranchesSheet() { | ... | @@ -113,7 +113,7 @@ export function GitBranchesSheet() { |
| 113 | value={worktreeBaseBranch} | 113 | value={worktreeBaseBranch} |
| 114 | onChangeText={setWorktreeBaseBranch} | 114 | onChangeText={setWorktreeBaseBranch} |
| 115 | placeholder="main" | 115 | placeholder="main" |
| 116 | className="rounded-[18px] px-3.5 py-3 font-sans text-[15px]" | 116 | className="rounded-[18px] px-3.5 py-3 font-sans text-base" |
| 117 | style={{ | 117 | style={{ |
| 118 | borderWidth: 1, | 118 | borderWidth: 1, |
| 119 | borderColor: inputBorderColor, | 119 | borderColor: inputBorderColor, |
| ... | @@ -125,7 +125,7 @@ export function GitBranchesSheet() { | ... | @@ -125,7 +125,7 @@ export function GitBranchesSheet() { |
| 125 | value={worktreeBranchName} | 125 | value={worktreeBranchName} |
| 126 | onChangeText={setWorktreeBranchName} | 126 | onChangeText={setWorktreeBranchName} |
| 127 | placeholder="feature/mobile-thread" | 127 | placeholder="feature/mobile-thread" |
| 128 | className="rounded-[18px] px-3.5 py-3 font-sans text-[15px]" | 128 | className="rounded-[18px] px-3.5 py-3 font-sans text-base" |
| 129 | style={{ | 129 | style={{ |
| 130 | borderWidth: 1, | 130 | borderWidth: 1, |
| 131 | borderColor: inputBorderColor, | 131 | borderColor: inputBorderColor, |
| ... | @@ -154,18 +154,16 @@ export function GitBranchesSheet() { | ... | @@ -154,18 +154,16 @@ export function GitBranchesSheet() { |
| 154 | 154 | ||
| 155 | <View className="gap-2"> | 155 | <View className="gap-2"> |
| 156 | <Text | 156 | <Text |
| 157 | className="text-foreground-secondary text-[11px] font-t3-bold uppercase" | 157 | className="text-foreground-secondary text-2xs font-t3-bold uppercase" |
| 158 | style={{ letterSpacing: 1 }} | 158 | style={{ letterSpacing: 1 }} |
| 159 | > | 159 | > |
| 160 | Existing branches | 160 | Existing branches |
| 161 | </Text> | 161 | </Text> |
| 162 | {branchesLoading ? ( | 162 | {branchesLoading ? ( |
| 163 | <Text className="text-foreground-secondary text-[13px] font-medium"> | 163 | <Text className="text-foreground-secondary text-sm font-medium">Loading branches...</Text> |
| 164 | Loading branches... | ||
| 165 | </Text> | ||
| 166 | ) : null} | 164 | ) : null} |
| 167 | {!branchesLoading && availableBranches.length === 0 ? ( | 165 | {!branchesLoading && availableBranches.length === 0 ? ( |
| 168 | <Text className="text-foreground-secondary text-[13px] font-medium"> | 166 | <Text className="text-foreground-secondary text-sm font-medium"> |
| 169 | No local branches found. | 167 | No local branches found. |
| 170 | </Text> | 168 | </Text> |
| 171 | ) : null} | 169 | ) : null} |
| ... | @@ -195,8 +193,8 @@ export function GitBranchesSheet() { | ... | @@ -195,8 +193,8 @@ export function GitBranchesSheet() { |
| 195 | }} | 193 | }} |
| 196 | > | 194 | > |
| 197 | <View className="absolute inset-0 rounded-[18px] bg-card" /> | 195 | <View className="absolute inset-0 rounded-[18px] bg-card" /> |
| 198 | <Text className="text-foreground text-[15px] font-t3-bold">{branch.name}</Text> | 196 | <Text className="text-foreground text-base font-t3-bold">{branch.name}</Text> |
| 199 | <Text className="text-foreground-secondary text-[12px] font-medium">{subtitle}</Text> | 197 | <Text className="text-foreground-secondary text-xs font-medium">{subtitle}</Text> |
| 200 | </Pressable> | 198 | </Pressable> |
| 201 | ); | 199 | ); |
| 202 | })} | 200 | })} |
apps/mobile/src/features/threads/git/GitCommitSheet.tsx+18-18| ... | @@ -79,14 +79,14 @@ export function GitCommitSheet() { | ... | @@ -79,14 +79,14 @@ export function GitCommitSheet() { |
| 79 | > | 79 | > |
| 80 | <View className="gap-3 rounded-[22px] border border-border bg-card px-4 py-4"> | 80 | <View className="gap-3 rounded-[22px] border border-border bg-card px-4 py-4"> |
| 81 | <View className="flex-row items-center justify-between gap-3"> | 81 | <View className="flex-row items-center justify-between gap-3"> |
| 82 | <Text className="text-foreground-muted text-[13px] font-medium">Branch</Text> | 82 | <Text className="text-foreground-muted text-sm font-medium">Branch</Text> |
| 83 | <Text className="text-foreground text-[15px] font-t3-bold"> | 83 | <Text className="text-foreground text-base font-t3-bold"> |
| 84 | {gitStatus.data?.refName ?? "(detached HEAD)"} | 84 | {gitStatus.data?.refName ?? "(detached HEAD)"} |
| 85 | </Text> | 85 | </Text> |
| 86 | </View> | 86 | </View> |
| 87 | {isDefaultRef ? ( | 87 | {isDefaultRef ? ( |
| 88 | <Text | 88 | <Text |
| 89 | className="text-[12px] leading-[18px]" | 89 | className="text-xs leading-[18px]" |
| 90 | style={{ color: isDarkMode ? "#fbbf24" : "#b45309" }} | 90 | style={{ color: isDarkMode ? "#fbbf24" : "#b45309" }} |
| 91 | > | 91 | > |
| 92 | Warning: this is the default branch. | 92 | Warning: this is the default branch. |
| ... | @@ -97,8 +97,8 @@ export function GitCommitSheet() { | ... | @@ -97,8 +97,8 @@ export function GitCommitSheet() { |
| 97 | <View className="gap-3 rounded-[22px] border border-border bg-card px-4 py-4"> | 97 | <View className="gap-3 rounded-[22px] border border-border bg-card px-4 py-4"> |
| 98 | <View className="flex-row items-center justify-between gap-3"> | 98 | <View className="flex-row items-center justify-between gap-3"> |
| 99 | <View className="gap-1"> | 99 | <View className="gap-1"> |
| 100 | <Text className="text-foreground text-[16px] font-t3-bold">Files</Text> | 100 | <Text className="text-foreground text-base font-t3-bold">Files</Text> |
| 101 | <Text className="text-foreground-muted text-[12px] leading-[18px]"> | 101 | <Text className="text-foreground-muted text-xs leading-[18px]"> |
| 102 | {selectedFiles.length} selected · +{selectedInsertions} / -{selectedDeletions} | 102 | {selectedFiles.length} selected · +{selectedInsertions} / -{selectedDeletions} |
| 103 | </Text> | 103 | </Text> |
| 104 | </View> | 104 | </View> |
| ... | @@ -108,14 +108,14 @@ export function GitCommitSheet() { | ... | @@ -108,14 +108,14 @@ export function GitCommitSheet() { |
| 108 | className="bg-subtle rounded-full px-3 py-2" | 108 | className="bg-subtle rounded-full px-3 py-2" |
| 109 | onPress={() => setExcludedFiles(new Set())} | 109 | onPress={() => setExcludedFiles(new Set())} |
| 110 | > | 110 | > |
| 111 | <Text className="text-foreground text-[11px] font-t3-bold uppercase">Reset</Text> | 111 | <Text className="text-foreground text-2xs font-t3-bold uppercase">Reset</Text> |
| 112 | </Pressable> | 112 | </Pressable> |
| 113 | ) : null} | 113 | ) : null} |
| 114 | <Pressable | 114 | <Pressable |
| 115 | className="bg-subtle rounded-full px-3 py-2" | 115 | className="bg-subtle rounded-full px-3 py-2" |
| 116 | onPress={() => setIsEditingFiles((current) => !current)} | 116 | onPress={() => setIsEditingFiles((current) => !current)} |
| 117 | > | 117 | > |
| 118 | <Text className="text-foreground text-[11px] font-t3-bold uppercase"> | 118 | <Text className="text-foreground text-2xs font-t3-bold uppercase"> |
| 119 | {isEditingFiles ? "Done" : "Edit"} | 119 | {isEditingFiles ? "Done" : "Edit"} |
| 120 | </Text> | 120 | </Text> |
| 121 | </Pressable> | 121 | </Pressable> |
| ... | @@ -123,26 +123,26 @@ export function GitCommitSheet() { | ... | @@ -123,26 +123,26 @@ export function GitCommitSheet() { |
| 123 | </View> | 123 | </View> |
| 124 | 124 | ||
| 125 | {allFiles.length === 0 ? ( | 125 | {allFiles.length === 0 ? ( |
| 126 | <Text className="text-foreground-secondary text-[13px] leading-[19px]"> | 126 | <Text className="text-foreground-secondary text-sm leading-[19px]"> |
| 127 | No changed files are available to commit. | 127 | No changed files are available to commit. |
| 128 | </Text> | 128 | </Text> |
| 129 | ) : !isEditingFiles ? ( | 129 | ) : !isEditingFiles ? ( |
| 130 | <View className="gap-2"> | 130 | <View className="gap-2"> |
| 131 | {selectedFilePreview.map((file) => ( | 131 | {selectedFilePreview.map((file) => ( |
| 132 | <View key={file.path} className="flex-row items-center justify-between gap-3"> | 132 | <View key={file.path} className="flex-row items-center justify-between gap-3"> |
| 133 | <Text className="text-foreground flex-1 text-[13px] font-medium" numberOfLines={1}> | 133 | <Text className="text-foreground flex-1 text-sm font-medium" numberOfLines={1}> |
| 134 | {file.path} | 134 | {file.path} |
| 135 | </Text> | 135 | </Text> |
| 136 | <Text className="text-[12px] font-t3-bold" style={{ color: "#10b981" }}> | 136 | <Text className="text-xs font-t3-bold" style={{ color: "#10b981" }}> |
| 137 | +{file.insertions} | 137 | +{file.insertions} |
| 138 | </Text> | 138 | </Text> |
| 139 | <Text className="text-[12px] font-t3-bold" style={{ color: "#f43f5e" }}> | 139 | <Text className="text-xs font-t3-bold" style={{ color: "#f43f5e" }}> |
| 140 | -{file.deletions} | 140 | -{file.deletions} |
| 141 | </Text> | 141 | </Text> |
| 142 | </View> | 142 | </View> |
| 143 | ))} | 143 | ))} |
| 144 | {selectedFiles.length > selectedFilePreview.length ? ( | 144 | {selectedFiles.length > selectedFilePreview.length ? ( |
| 145 | <Text className="text-foreground-muted text-[12px] leading-[17px]"> | 145 | <Text className="text-foreground-muted text-xs leading-[17px]"> |
| 146 | +{selectedFiles.length - selectedFilePreview.length} more files | 146 | +{selectedFiles.length - selectedFilePreview.length} more files |
| 147 | </Text> | 147 | </Text> |
| 148 | ) : null} | 148 | ) : null} |
| ... | @@ -177,21 +177,21 @@ export function GitCommitSheet() { | ... | @@ -177,21 +177,21 @@ export function GitCommitSheet() { |
| 177 | <View className="flex-1 gap-1"> | 177 | <View className="flex-1 gap-1"> |
| 178 | <Text | 178 | <Text |
| 179 | selectable | 179 | selectable |
| 180 | className={`text-[13px] font-t3-bold ${included ? "text-foreground" : "text-foreground-muted"}`} | 180 | className={`text-sm font-t3-bold ${included ? "text-foreground" : "text-foreground-muted"}`} |
| 181 | > | 181 | > |
| 182 | {file.path} | 182 | {file.path} |
| 183 | </Text> | 183 | </Text> |
| 184 | {!included ? ( | 184 | {!included ? ( |
| 185 | <Text className="text-foreground-muted text-[11px] leading-[16px]"> | 185 | <Text className="text-foreground-muted text-2xs leading-[16px]"> |
| 186 | Excluded from this commit | 186 | Excluded from this commit |
| 187 | </Text> | 187 | </Text> |
| 188 | ) : null} | 188 | ) : null} |
| 189 | </View> | 189 | </View> |
| 190 | <View className="items-end gap-1"> | 190 | <View className="items-end gap-1"> |
| 191 | <Text className="text-[12px] font-t3-bold" style={{ color: "#10b981" }}> | 191 | <Text className="text-xs font-t3-bold" style={{ color: "#10b981" }}> |
| 192 | +{file.insertions} | 192 | +{file.insertions} |
| 193 | </Text> | 193 | </Text> |
| 194 | <Text className="text-[12px] font-t3-bold" style={{ color: "#f43f5e" }}> | 194 | <Text className="text-xs font-t3-bold" style={{ color: "#f43f5e" }}> |
| 195 | -{file.deletions} | 195 | -{file.deletions} |
| 196 | </Text> | 196 | </Text> |
| 197 | </View> | 197 | </View> |
| ... | @@ -204,14 +204,14 @@ export function GitCommitSheet() { | ... | @@ -204,14 +204,14 @@ export function GitCommitSheet() { |
| 204 | </View> | 204 | </View> |
| 205 | 205 | ||
| 206 | <View className="gap-2"> | 206 | <View className="gap-2"> |
| 207 | <Text className="text-foreground text-[13px] font-t3-bold">Commit message</Text> | 207 | <Text className="text-foreground text-sm font-t3-bold">Commit message</Text> |
| 208 | <TextInput | 208 | <TextInput |
| 209 | multiline | 209 | multiline |
| 210 | value={dialogCommitMessage} | 210 | value={dialogCommitMessage} |
| 211 | onChangeText={setDialogCommitMessage} | 211 | onChangeText={setDialogCommitMessage} |
| 212 | placeholder="Leave empty to auto-generate" | 212 | placeholder="Leave empty to auto-generate" |
| 213 | textAlignVertical="top" | 213 | textAlignVertical="top" |
| 214 | className="min-h-[128px] rounded-[20px] px-4 py-3.5 font-sans text-[15px]" | 214 | className="min-h-[128px] rounded-[20px] px-4 py-3.5 font-sans text-base" |
| 215 | style={{ | 215 | style={{ |
| 216 | minHeight: 128, | 216 | minHeight: 128, |
| 217 | borderWidth: 1, | 217 | borderWidth: 1, |
apps/mobile/src/features/threads/git/GitConfirmSheet.tsx+3-3| ... | @@ -90,15 +90,15 @@ export function GitConfirmSheet() { | ... | @@ -90,15 +90,15 @@ export function GitConfirmSheet() { |
| 90 | 90 | ||
| 91 | <View className="items-center gap-1 px-5 pb-3 pt-4"> | 91 | <View className="items-center gap-1 px-5 pb-3 pt-4"> |
| 92 | <Text | 92 | <Text |
| 93 | className="text-[12px] font-t3-bold uppercase text-foreground-muted" | 93 | className="text-xs font-t3-bold uppercase text-foreground-muted" |
| 94 | style={{ letterSpacing: 1 }} | 94 | style={{ letterSpacing: 1 }} |
| 95 | > | 95 | > |
| 96 | Confirm | 96 | Confirm |
| 97 | </Text> | 97 | </Text> |
| 98 | <Text className="text-center text-[28px] font-t3-bold"> | 98 | <Text className="text-center text-3xl font-t3-bold"> |
| 99 | {copy?.title ?? "Run action on default branch?"} | 99 | {copy?.title ?? "Run action on default branch?"} |
| 100 | </Text> | 100 | </Text> |
| 101 | <Text className="text-center text-foreground-secondary text-[13px] font-medium leading-[19px]"> | 101 | <Text className="text-center text-foreground-secondary text-sm font-medium leading-[19px]"> |
| 102 | {copy?.description ?? "Choose how to continue."} | 102 | {copy?.description ?? "Choose how to continue."} |
| 103 | </Text> | 103 | </Text> |
| 104 | </View> | 104 | </View> |
apps/mobile/src/features/threads/git/GitOverviewSheet.tsx+3-3| ... | @@ -175,13 +175,13 @@ export function GitOverviewSheet() { | ... | @@ -175,13 +175,13 @@ export function GitOverviewSheet() { |
| 175 | /> | 175 | /> |
| 176 | </Pressable> | 176 | </Pressable> |
| 177 | <Text | 177 | <Text |
| 178 | className="text-[12px] font-t3-bold uppercase text-foreground-muted" | 178 | className="text-xs font-t3-bold uppercase text-foreground-muted" |
| 179 | style={{ letterSpacing: 1 }} | 179 | style={{ letterSpacing: 1 }} |
| 180 | > | 180 | > |
| 181 | Branch | 181 | Branch |
| 182 | </Text> | 182 | </Text> |
| 183 | <Text className="text-[28px] font-t3-bold">{currentBranchLabel}</Text> | 183 | <Text className="text-3xl font-t3-bold">{currentBranchLabel}</Text> |
| 184 | <Text className="text-foreground-secondary text-[13px] font-medium leading-[19px]"> | 184 | <Text className="text-foreground-secondary text-sm font-medium leading-[19px]"> |
| 185 | {statusSummary(gitStatus.data)} | 185 | {statusSummary(gitStatus.data)} |
| 186 | </Text> | 186 | </Text> |
| 187 | </View> | 187 | </View> |
apps/mobile/src/features/threads/git/gitSheetComponents.tsx+5-5| ... | @@ -56,7 +56,7 @@ export function SheetActionButton(props: { | ... | @@ -56,7 +56,7 @@ export function SheetActionButton(props: { |
| 56 | > | 56 | > |
| 57 | <SymbolView name={props.icon} size={16} tintColor={colors.textColor} type="monochrome" /> | 57 | <SymbolView name={props.icon} size={16} tintColor={colors.textColor} type="monochrome" /> |
| 58 | <Text | 58 | <Text |
| 59 | className="text-[12px] font-t3-bold uppercase" | 59 | className="text-xs font-t3-bold uppercase" |
| 60 | style={{ color: colors.textColor, letterSpacing: 0.9 }} | 60 | style={{ color: colors.textColor, letterSpacing: 0.9 }} |
| 61 | > | 61 | > |
| 62 | {props.label} | 62 | {props.label} |
| ... | @@ -69,12 +69,12 @@ export function MetaCard(props: { readonly label: string; readonly value: string | ... | @@ -69,12 +69,12 @@ export function MetaCard(props: { readonly label: string; readonly value: string |
| 69 | return ( | 69 | return ( |
| 70 | <View className="rounded-[18px] border border-border bg-card px-4 py-3"> | 70 | <View className="rounded-[18px] border border-border bg-card px-4 py-3"> |
| 71 | <Text | 71 | <Text |
| 72 | className="text-foreground-muted text-[11px] font-t3-bold uppercase" | 72 | className="text-foreground-muted text-2xs font-t3-bold uppercase" |
| 73 | style={{ letterSpacing: 0.9 }} | 73 | style={{ letterSpacing: 0.9 }} |
| 74 | > | 74 | > |
| 75 | {props.label} | 75 | {props.label} |
| 76 | </Text> | 76 | </Text> |
| 77 | <Text selectable className="text-foreground text-[13px] font-medium" numberOfLines={1}> | 77 | <Text selectable className="text-foreground text-sm font-medium" numberOfLines={1}> |
| 78 | {props.value} | 78 | {props.value} |
| 79 | </Text> | 79 | </Text> |
| 80 | </View> | 80 | </View> |
| ... | @@ -102,9 +102,9 @@ export function SheetListRow(props: { | ... | @@ -102,9 +102,9 @@ export function SheetListRow(props: { |
| 102 | <SymbolView name={props.icon} size={16} tintColor={iconColor} type="monochrome" /> | 102 | <SymbolView name={props.icon} size={16} tintColor={iconColor} type="monochrome" /> |
| 103 | </View> | 103 | </View> |
| 104 | <View className="flex-1 gap-0.5"> | 104 | <View className="flex-1 gap-0.5"> |
| 105 | <Text className="text-foreground text-[16px] font-t3-bold">{props.title}</Text> | 105 | <Text className="text-foreground text-base font-t3-bold">{props.title}</Text> |
| 106 | {props.subtitle ? ( | 106 | {props.subtitle ? ( |
| 107 | <Text className="text-foreground-muted text-[12px] leading-[17px]">{props.subtitle}</Text> | 107 | <Text className="text-foreground-muted text-xs leading-[17px]">{props.subtitle}</Text> |
| 108 | ) : null} | 108 | ) : null} |
| 109 | </View> | 109 | </View> |
| 110 | <SymbolView name="chevron.right" size={13} tintColor={iconSubtleColor} type="monochrome" /> | 110 | <SymbolView name="chevron.right" size={13} tintColor={iconSubtleColor} type="monochrome" /> |
apps/mobile/src/features/threads/thread-work-log.tsx+3-3| ... | @@ -98,7 +98,7 @@ export function ThreadWorkLog(props: { | ... | @@ -98,7 +98,7 @@ export function ThreadWorkLog(props: { |
| 98 | return ( | 98 | return ( |
| 99 | <View className="-mx-1 mb-3 px-1 py-0.5"> | 99 | <View className="-mx-1 mb-3 px-1 py-0.5"> |
| 100 | {!onlyToolRows ? ( | 100 | {!onlyToolRows ? ( |
| 101 | <Text className="px-0.5 pb-0.5 font-t3-medium text-[11px] text-foreground-muted opacity-60"> | 101 | <Text className="px-0.5 pb-0.5 font-t3-medium text-2xs text-foreground-muted opacity-60"> |
| 102 | work log | 102 | work log |
| 103 | </Text> | 103 | </Text> |
| 104 | ) : null} | 104 | ) : null} |
| ... | @@ -164,7 +164,7 @@ export function ThreadWorkLog(props: { | ... | @@ -164,7 +164,7 @@ export function ThreadWorkLog(props: { |
| 164 | 164 | ||
| 165 | <View className="shrink-0 flex-row items-center gap-px"> | 165 | <View className="shrink-0 flex-row items-center gap-px"> |
| 166 | {props.copiedRowId === row.id ? ( | 166 | {props.copiedRowId === row.id ? ( |
| 167 | <Text className="pr-1 font-t3-medium text-[10px] text-emerald-600 dark:text-emerald-400"> | 167 | <Text className="pr-1 font-t3-medium text-3xs text-emerald-600 dark:text-emerald-400"> |
| 168 | Copied | 168 | Copied |
| 169 | </Text> | 169 | </Text> |
| 170 | ) : null} | 170 | ) : null} |
| ... | @@ -209,7 +209,7 @@ export function ThreadWorkLog(props: { | ... | @@ -209,7 +209,7 @@ export function ThreadWorkLog(props: { |
| 209 | > | 209 | > |
| 210 | <Text | 210 | <Text |
| 211 | selectable | 211 | selectable |
| 212 | className="text-[11px] leading-[17px] text-foreground-muted" | 212 | className="text-2xs leading-[17px] text-foreground-muted" |
| 213 | style={{ fontFamily: "ui-monospace" }} | 213 | style={{ fontFamily: "ui-monospace" }} |
| 214 | > | 214 | > |
| 215 | {row.fullDetail} | 215 | {row.fullDetail} |
apps/mobile/src/lib/typography.test.ts created+23| ... | @@ -0,0 +1,23 @@ | ||
| 1 | import { describe, expect, it } from "vite-plus/test"; | ||
| 2 | |||
| 3 | import { MOBILE_CODE_SURFACE, MOBILE_TYPOGRAPHY } from "./typography"; | ||
| 4 | |||
| 5 | describe("mobile typography", () => { | ||
| 6 | it("uses the intentional compact mobile font scale", () => { | ||
| 7 | expect(Object.values(MOBILE_TYPOGRAPHY).map(({ fontSize }) => fontSize)).toEqual([ | ||
| 8 | 10, 11, 12, 13, 14, 15, 17, 20, 24, 28, | ||
| 9 | ]); | ||
| 10 | }); | ||
| 11 | |||
| 12 | it("uses a compact shared style for editable composer text", () => { | ||
| 13 | expect(MOBILE_TYPOGRAPHY.composer).toEqual({ fontSize: 14, lineHeight: 20 }); | ||
| 14 | }); | ||
| 15 | |||
| 16 | it("uses caption-sized code with a compact readable row height", () => { | ||
| 17 | expect(MOBILE_CODE_SURFACE).toMatchObject({ | ||
| 18 | fontSize: MOBILE_TYPOGRAPHY.caption.fontSize, | ||
| 19 | lineNumberFontSize: MOBILE_TYPOGRAPHY.micro.fontSize, | ||
| 20 | rowHeight: 20, | ||
| 21 | }); | ||
| 22 | }); | ||
| 23 | }); | ||
apps/mobile/src/lib/typography.ts created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | export const MOBILE_TYPOGRAPHY = { | ||
| 2 | micro: { fontSize: 10, lineHeight: 13 }, | ||
| 3 | caption: { fontSize: 11, lineHeight: 15 }, | ||
| 4 | label: { fontSize: 12, lineHeight: 16 }, | ||
| 5 | footnote: { fontSize: 13, lineHeight: 18 }, | ||
| 6 | composer: { fontSize: 14, lineHeight: 20 }, | ||
| 7 | body: { fontSize: 15, lineHeight: 22 }, | ||
| 8 | headline: { fontSize: 17, lineHeight: 22 }, | ||
| 9 | title: { fontSize: 20, lineHeight: 26 }, | ||
| 10 | largeTitle: { fontSize: 24, lineHeight: 30 }, | ||
| 11 | display: { fontSize: 28, lineHeight: 34 }, | ||
| 12 | } as const; | ||
| 13 | |||
| 14 | /** Shared geometry for dense, horizontally scrolling code surfaces. */ | ||
| 15 | export const MOBILE_CODE_SURFACE = { | ||
| 16 | rowHeight: 20, | ||
| 17 | gutterWidth: 46, | ||
| 18 | codePadding: 7, | ||
| 19 | textVerticalInset: 2, | ||
| 20 | fontSize: MOBILE_TYPOGRAPHY.caption.fontSize, | ||
| 21 | lineNumberFontSize: MOBILE_TYPOGRAPHY.micro.fontSize, | ||
| 22 | } as const; | ||
apps/mobile/src/native/T3ComposerEditor.ios.tsx+9-2| ... | @@ -6,6 +6,7 @@ import { Image, StyleSheet } from "react-native"; | ... | @@ -6,6 +6,7 @@ import { Image, StyleSheet } from "react-native"; |
| 6 | 6 | ||
| 7 | import { markdownFileIconSource } from "@t3tools/mobile-markdown-text/file-icons"; | 7 | import { markdownFileIconSource } from "@t3tools/mobile-markdown-text/file-icons"; |
| 8 | import { resolveMarkdownFileIcon } from "@t3tools/mobile-markdown-text/links"; | 8 | import { resolveMarkdownFileIcon } from "@t3tools/mobile-markdown-text/links"; |
| 9 | import { MOBILE_TYPOGRAPHY } from "../lib/typography"; | ||
| 9 | import { useThemeColor } from "../lib/useThemeColor"; | 10 | import { useThemeColor } from "../lib/useThemeColor"; |
| 10 | import type { ComposerEditorProps, ComposerEditorSelection } from "./T3ComposerEditor.types"; | 11 | import type { ComposerEditorProps, ComposerEditorSelection } from "./T3ComposerEditor.types"; |
| 11 | 12 | ||
| ... | @@ -150,9 +151,15 @@ export function ComposerEditor({ | ... | @@ -150,9 +151,15 @@ export function ComposerEditor({ |
| 150 | ? resolvedTextStyle.fontFamily | 151 | ? resolvedTextStyle.fontFamily |
| 151 | : "DMSans_400Regular" | 152 | : "DMSans_400Regular" |
| 152 | } | 153 | } |
| 153 | fontSize={typeof resolvedTextStyle.fontSize === "number" ? resolvedTextStyle.fontSize : 15} | 154 | fontSize={ |
| 155 | typeof resolvedTextStyle.fontSize === "number" | ||
| 156 | ? resolvedTextStyle.fontSize | ||
| 157 | : MOBILE_TYPOGRAPHY.composer.fontSize | ||
| 158 | } | ||
| 154 | lineHeight={ | 159 | lineHeight={ |
| 155 | typeof resolvedTextStyle.lineHeight === "number" ? resolvedTextStyle.lineHeight : 22 | 160 | typeof resolvedTextStyle.lineHeight === "number" |
| 161 | ? resolvedTextStyle.lineHeight | ||
| 162 | : MOBILE_TYPOGRAPHY.composer.lineHeight | ||
| 156 | } | 163 | } |
| 157 | contentInsetVertical={contentInsetVertical} | 164 | contentInsetVertical={contentInsetVertical} |
| 158 | editable={props.editable ?? true} | 165 | editable={props.editable ?? true} |
apps/mobile/src/native/T3ComposerEditor.tsx+2-2| ... | @@ -2,6 +2,7 @@ import { TextInputWrapper } from "expo-paste-input"; | ... | @@ -2,6 +2,7 @@ import { TextInputWrapper } from "expo-paste-input"; |
| 2 | import { useImperativeHandle, useRef } from "react"; | 2 | import { useImperativeHandle, useRef } from "react"; |
| 3 | import { TextInput, type TextInput as RNTextInput } from "react-native"; | 3 | import { TextInput, type TextInput as RNTextInput } from "react-native"; |
| 4 | 4 | ||
| 5 | import { MOBILE_TYPOGRAPHY } from "../lib/typography"; | ||
| 5 | import { useThemeColor } from "../lib/useThemeColor"; | 6 | import { useThemeColor } from "../lib/useThemeColor"; |
| 6 | import { useNativePaste } from "../lib/useNativePaste"; | 7 | import { useNativePaste } from "../lib/useNativePaste"; |
| 7 | import type { ComposerEditorProps } from "./T3ComposerEditor.types"; | 8 | import type { ComposerEditorProps } from "./T3ComposerEditor.types"; |
| ... | @@ -47,8 +48,7 @@ export function ComposerEditor({ | ... | @@ -47,8 +48,7 @@ export function ComposerEditor({ |
| 47 | minHeight: 0, | 48 | minHeight: 0, |
| 48 | color: foregroundColor, | 49 | color: foregroundColor, |
| 49 | fontFamily: "DMSans_400Regular", | 50 | fontFamily: "DMSans_400Regular", |
| 50 | fontSize: 15, | 51 | ...MOBILE_TYPOGRAPHY.composer, |
| 51 | lineHeight: 22, | ||
| 52 | paddingVertical: contentInsetVertical, | 52 | paddingVertical: contentInsetVertical, |
| 53 | }, | 53 | }, |
| 54 | textStyle, | 54 | textStyle, |