authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-08-05 18:03:10+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-05 16:03:10+00:00
logde592a00e89776d2e0614f3be6e666012d90cd51
treedacbe55ace1bf68532b584f843ef736ce3a8ce34
parent2a04db134c2d88f06e5b8d61a8410cb51ea07430
signature Signed by PGP key B5690EEEBB952194

Enrich terminal font previews (#5428)


3 files changed, 84 insertions(+), 18 deletions(-)

apps/mobile/src/features/settings/appearance/components/AppearancePreviews.tsx+47-6
......@@ -1,4 +1,11 @@
1import { Platform, ScrollView, View, useColorScheme } from "react-native";
1import {
2 Platform,
3 ScrollView,
4 type StyleProp,
5 type TextStyle,
6 View,
7 useColorScheme,
8} from "react-native";
29
310import { AppText as Text } from "../../../../components/AppText";
411import {
......@@ -54,14 +61,48 @@ export function TerminalAppearancePreview(props: { readonly fontSize: number })
5461 fontSize: props.fontSize,
5562 lineHeight,
5663 } as const;
64 // AppText stamps the sans font on every node, so nested spans must
65 // re-apply the terminal font instead of relying on inheritance, exactly
66 // like the code preview's tokens below.
67 const span = (color: string, extra?: TextStyle): StyleProp<TextStyle> => [
68 lineStyle,
69 { color, ...extra },
70 ];
5771
5872 return (
5973 <View className="p-4">
60 <Text style={[lineStyle, { color: theme.foreground }]}>$ npm run dev</Text>
61 <Text style={[lineStyle, { color: theme.palette[2] }]}>✓ Ready in 430ms</Text>
62 <Text style={[lineStyle, { color: theme.foreground }]}>
63 Local: http://localhost:3000{" "}
64 <Text style={[lineStyle, { color: theme.cursorForeground }]}>▏</Text>
74 <Text style={span(theme.foreground)}>
75 <Text style={span(theme.palette[2])}>→ </Text>
76 <Text style={span(theme.palette[6])}>t3code </Text>
77 <Text style={span(theme.palette[4])}>git:(</Text>
78 <Text style={span(theme.palette[1])}>main</Text>
79 <Text style={span(theme.palette[4])}>)</Text>
80 <Text style={span(theme.palette[3])}> ✗</Text>
81 <Text style={span(theme.foreground)}> vpr dev</Text>
82 </Text>
83 <Text style={span(theme.foreground)}>
84 <Text style={span(theme.palette[2])}>VITE v7.1.1</Text>
85 <Text style={span(theme.mutedForeground)}> ready in</Text>
86 <Text style={span(theme.foreground)}> 1.24s</Text>
87 </Text>
88 <Text style={span(theme.foreground)}>
89 <Text style={span(theme.palette[2])}>→ </Text>
90 <Text style={span(theme.mutedForeground)}>Local: </Text>
91 <Text style={span(theme.palette[6], { textDecorationLine: "underline" })}>
92 http://127.0.0.1:5173/
93 </Text>
94 </Text>
95 <Text style={span(theme.foreground)}>
96 <Text style={span(theme.palette[2])}>✓ 85 passed</Text>
97 <Text style={span(theme.palette[3])}> △ 2 warnings</Text>
98 <Text style={span(theme.palette[1])}> ✗ 0 failed</Text>
99 </Text>
100 <Text style={span(theme.foreground)}>
101 <Text style={span(theme.background, { backgroundColor: theme.palette[2] })}>
102 {" READY "}
103 </Text>
104 <Text style={span(theme.mutedForeground)}> watching for changes</Text>{" "}
105 <Text style={span(theme.cursorForeground)}>▏</Text>
65106 </Text>
66107 </View>
67108 );
apps/web/src/components/settings/SettingsFontPreviews.tsx+20-5
......@@ -120,11 +120,26 @@ export function CodeFontPreview() {
120120 );
121121}
122122
123const TERMINAL_PROMPT = "\x1b[2m$\x1b[0m ";
123// A zsh-style prompt: green arrow, cyan project, blue/red git segment,
124// yellow dirty marker. It doubles as the echo loop's fresh-line prompt.
125const TERMINAL_PROMPT =
126 "\x1b[1;32m→\x1b[0m \x1b[1;36mt3code\x1b[0m \x1b[1;34mgit:(\x1b[1;31mmain\x1b[1;34m)\x1b[0m \x1b[1;33m✗\x1b[0m ";
127// A dev-server startup: brand line, addresses, a test summary, and a READY
128// badge. Together the lines cover bold, dim, underline, the six accent
129// colors, and a background cell, so a font choice shows every SGR the
130// terminal actually renders.
124131const TERMINAL_PREVIEW_TRANSCRIPT =
125 `${TERMINAL_PROMPT}npm run dev\r\n` +
126 "\x1b[32m✓\x1b[0m Ready in 430ms\r\n" +
127 "\x1b[2mLocal:\x1b[0m \x1b[36mhttp://localhost:3000\x1b[0m\r\n" +
132 `${TERMINAL_PROMPT}vpr dev\r\n` +
133 "\r\n" +
134 " \x1b[1;32mVITE\x1b[0m \x1b[32mv7.1.1\x1b[0m \x1b[2mready in\x1b[0m \x1b[1m1.24s\x1b[0m\r\n" +
135 "\r\n" +
136 " \x1b[32m→\x1b[0m \x1b[2mLocal:\x1b[0m \x1b[4;36mhttp://127.0.0.1:5173/\x1b[0m\r\n" +
137 " \x1b[32m→\x1b[0m \x1b[2mNetwork:\x1b[0m \x1b[4;36mhttp://192.168.1.24:5173/\x1b[0m\r\n" +
138 "\r\n" +
139 " \x1b[32m✓ 85 passed\x1b[0m \x1b[33m△ 2 warnings\x1b[0m \x1b[31m✗ 0 failed\x1b[0m\r\n" +
140 "\r\n" +
141 " \x1b[42;30m READY \x1b[0m \x1b[2mwatching for changes — press\x1b[0m \x1b[1mq\x1b[0m \x1b[2mto quit\x1b[0m\r\n" +
142 "\r\n" +
128143 TERMINAL_PROMPT;
129144
130145/** The surface treats an omitted family or size as "use the built-in default". */
......@@ -225,7 +240,7 @@ export function TerminalFontPreview({ family, size }: { family: string; size: nu
225240 return (
226241 <div
227242 ref={mountRef}
228 className="relative mt-1 mb-2 h-36 overflow-hidden rounded-lg border border-border"
243 className="relative mt-1 mb-2 h-52 overflow-hidden rounded-lg border border-border"
229244 aria-label="Terminal font preview"
230245 />
231246 );
scripts/mobile-showcase-environment.ts+17-7
......@@ -44,17 +44,27 @@ const PROJECT_SCRIPTS = JSON.stringify([
4444 },
4545]);
4646
47const SHOWCASE_TERMINAL_PROMPT =
48 "\u001b[1;32m→\u001b[0m \u001b[1;36mt3code\u001b[0m \u001b[1;34mgit:(\u001b[1;31mfeat/remote-command-center\u001b[1;34m)\u001b[0m \u001b[1;33m✗\u001b[0m ";
49
50// A dev-server startup mirroring the web settings' terminal font preview:
51// zsh-style prompt, brand line, addresses, the thread's 612-test summary,
52// and a READY badge, so the scene exercises bold, dim, underline, the six
53// accent colors, and a background cell.
4754export const SHOWCASE_TERMINAL_BUFFER = [
48 "\u001b[38;5;75m~/Code/t3code\u001b[0m \u001b[38;5;212mfeat/remote-command-center\u001b[0m",
49 "$ vp test run --changed",
55 `${SHOWCASE_TERMINAL_PROMPT}vpr dev`,
56 "",
57 " \u001b[1;32mVITE\u001b[0m \u001b[32mv7.1.1\u001b[0m \u001b[2mready in\u001b[0m \u001b[1m1.24s\u001b[0m",
58 "",
59 " \u001b[32m→\u001b[0m \u001b[2mLocal:\u001b[0m \u001b[4;36mhttp://127.0.0.1:5173/\u001b[0m",
60 " \u001b[32m→\u001b[0m \u001b[2mNetwork:\u001b[0m \u001b[4;36mhttp://192.168.1.24:5173/\u001b[0m",
61 " \u001b[32m→\u001b[0m \u001b[2mProject:\u001b[0m \u001b[1mt3code\u001b[0m \u001b[2m— ~/Code/t3code\u001b[0m",
5062 "",
51 " \u001b[38;5;117mt3code-mobile\u001b[0m 184 passed",
52 " \u001b[38;5;213mclient-runtime\u001b[0m 263 passed",
53 " \u001b[38;5;221mserver\u001b[0m 165 passed",
63 " \u001b[32m✓ 612 passed\u001b[0m \u001b[33m△ 2 warnings\u001b[0m \u001b[31m✗ 0 failed\u001b[0m",
5464 "",
55 "\u001b[32m✨ 612 tests passed\u001b[0m · 3 environments online",
65 " \u001b[42;30m READY \u001b[0m \u001b[2mwatching for changes — press\u001b[0m \u001b[1mq\u001b[0m \u001b[2mto quit\u001b[0m",
5666 "",
57 "\u001b[38;5;75m~/Code/t3code\u001b[0m \u001b[38;5;212mfeat/remote-command-center\u001b[0m $ ",
67 SHOWCASE_TERMINAL_PROMPT,
5868].join("\r\n");
5969
6070const BASE_ENVIRONMENT_PRESENCE = `export function environmentLabel(count: number): string {