1import { NATIVE_WORKSPACE_COLUMNS_SUPPORTED } from "../native/NativeWorkspaceColumns";
2import Constants from "expo-constants";
3import type { NativeStackNavigationOptions } from "@react-navigation/native-stack";
4import { Platform, View } from "react-native";
5
6import { AppText as Text } from "./AppText";
7import { KnifeMark } from "./KnifeMark";
8import { IPAD_HOME_TITLE_OFFSET } from "../lib/layoutMetrics";
9import { resolveMobileStageLabel } from "../lib/mobileBranding";
10import { useAndroidControlSizing } from "./useAndroidControlSizing";
11
12/**
13 * Horizontal correction applied to content rendered in the brand title slot,
14 * shared with the connection-status swap so both align identically.
15 */
16export function brandTitleOffset(): number {
17 if (Platform.OS !== "ios") return 0;
18 return Platform.isPad && !NATIVE_WORKSPACE_COLUMNS_SUPPORTED ? IPAD_HOME_TITLE_OFFSET : 0;
19}
20
21/**
22 * Compact brand lockup sized for native navigation bars.
23 */
24export function CompactBrandTitle(
25 props: {
26 readonly allowFontScaling?: boolean;
27 readonly accessibilityLabel?: string;
28 } = {},
29) {
30 const stageLabel = resolveMobileStageLabel(Constants.expoConfig?.extra?.appVariant);
31 const titleOffset = brandTitleOffset();
32 const { scale } = useAndroidControlSizing();
33
34 return (
35 <View
36 aria-level={1}
37 accessibilityLabel={props.accessibilityLabel ?? "The Knife, Threads"}
38 accessible
39 role="heading"
40 className="flex-row items-center gap-1.5"
41 style={[{ marginLeft: titleOffset }, Platform.OS === "android" && { gap: 5.25 * scale }]}
42 >
43 <KnifeMark height={Math.round(26 * scale)} />
44 <Text
45 allowFontScaling={props.allowFontScaling}
46 className="font-t3-medium text-foreground-muted"
47 style={{ fontSize: 21 * scale, letterSpacing: -0.5 * scale }}
48 >
49 The Knife
50 </Text>
51 <View
52 className="rounded-full bg-subtle px-1.5 py-0.5"
53 style={
54 Platform.OS === "android"
55 ? { paddingHorizontal: 5.25 * scale, paddingVertical: 1.75 * scale }
56 : undefined
57 }
58 >
59 <Text
60 allowFontScaling={props.allowFontScaling}
61 className="font-t3-bold text-foreground-muted uppercase"
62 style={{ fontSize: 9 * scale, letterSpacing: 0.9 * scale }}
63 >
64 {stageLabel}
65 </Text>
66 </View>
67 </View>
68 );
69}
70
71export function renderCompactBrandTitle() {
72 return <CompactBrandTitle allowFontScaling={Platform.OS === "ios"} />;
73}
74
75export function getCompactBrandHeaderOptions(
76 fallbackTitleStyle?: NativeStackNavigationOptions["headerTitleStyle"],
77): NativeStackNavigationOptions {
78 return {
79 headerTitle: renderCompactBrandTitle,
80 headerTitleStyle: fallbackTitleStyle,
81 title: "Threads",
82 unstable_headerLeftItems: undefined,
83 };
84}