Skip to content

Commit d39fa1f

Browse files
authored
fix(slot-text): clip glyphs instead of ellipsizing during width anima… (#459)
1 parent 6d0d9e1 commit d39fa1f

4 files changed

Lines changed: 18 additions & 1 deletion

File tree

src/components/SlotText/SlotText.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export function SlotText({
4949
colorFadeDurationMs,
5050
containerStyle,
5151
durationMs,
52+
ellipsizeMode,
5253
exitOffsetMs,
5354
maxFontSizeMultiplier,
5455
maxGraphemes,
@@ -59,6 +60,7 @@ export function SlotText({
5960
textClassName,
6061
textStyle,
6162
}: SlotTextProps) {
63+
const resolvedEllipsizeMode = ellipsizeMode ?? 'clip';
6264
const reducedMotion = useReducedMotion();
6365
const resolved = resolveSlotTextOptions({
6466
bounce,
@@ -174,6 +176,7 @@ export function SlotText({
174176
accessible={false}
175177
allowFontScaling={allowFontScaling}
176178
className={textClassName}
179+
ellipsizeMode={resolvedEllipsizeMode}
177180
maxFontSizeMultiplier={maxFontSizeMultiplier}
178181
numberOfLines={1}
179182
style={textStyle}
@@ -230,6 +233,7 @@ export function SlotText({
230233
allowFontScaling={allowFontScaling}
231234
currentSegment={currentSegment}
232235
currentWidth={currentMetrics?.width ?? 0}
236+
ellipsizeMode={resolvedEllipsizeMode}
233237
entryPhaseStartMs={transitionPhaseTiming.entryPhaseStartMs}
234238
exitPhaseDurationMs={transitionPhaseTiming.exitPhaseDurationMs}
235239
height={height}
@@ -252,6 +256,7 @@ export function SlotText({
252256
accessible={false}
253257
allowFontScaling={allowFontScaling}
254258
className={textClassName}
259+
ellipsizeMode={resolvedEllipsizeMode}
255260
maxFontSizeMultiplier={maxFontSizeMultiplier}
256261
numberOfLines={1}
257262
style={textStyle}
@@ -272,6 +277,7 @@ export function SlotText({
272277
accessible={false}
273278
allowFontScaling={allowFontScaling}
274279
className={textClassName}
280+
ellipsizeMode={resolvedEllipsizeMode}
275281
key={segment}
276282
maxFontSizeMultiplier={maxFontSizeMultiplier}
277283
numberOfLines={1}

src/components/SlotText/SlotText.types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ export type SlotTextProps = {
1515
/** Keep a grapheme static only when it is unchanged and its slot offset will not move. */
1616
skipUnchanged?: boolean;
1717
staggerMs?: number;
18+
/** How a grapheme is truncated when its slot is narrower than the glyph. Defaults to 'clip'. */
19+
ellipsizeMode?: 'head' | 'middle' | 'tail' | 'clip';
1820
testID?: string;
1921
text: string;
2022
textClassName?: string;

src/components/SlotText/components/SlotGlyph.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type SlotGlyphProps = {
3535
allowFontScaling?: boolean;
3636
currentSegment: string;
3737
currentWidth: number;
38+
ellipsizeMode?: 'head' | 'middle' | 'tail' | 'clip';
3839
entryPhaseStartMs: number;
3940
exitPhaseDurationMs: number;
4041
height: number;
@@ -53,7 +54,7 @@ type SlotGlyphProps = {
5354

5455
type GlyphTextProps = Pick<
5556
SlotGlyphProps,
56-
'allowFontScaling' | 'maxFontSizeMultiplier' | 'textClassName' | 'textStyle'
57+
'allowFontScaling' | 'ellipsizeMode' | 'maxFontSizeMultiplier' | 'textClassName' | 'textStyle'
5758
> & {
5859
color?: string;
5960
segment: string;
@@ -63,6 +64,7 @@ export function SlotGlyph({
6364
allowFontScaling,
6465
currentSegment,
6566
currentWidth,
67+
ellipsizeMode,
6668
entryPhaseStartMs,
6769
exitPhaseDurationMs,
6870
height,
@@ -222,6 +224,7 @@ export function SlotGlyph({
222224
<Animated.View style={[faceStyle, outgoingStyle]}>
223225
<GlyphText
224226
allowFontScaling={allowFontScaling}
227+
ellipsizeMode={ellipsizeMode}
225228
maxFontSizeMultiplier={maxFontSizeMultiplier}
226229
segment={currentSegment}
227230
textClassName={textClassName}
@@ -234,6 +237,7 @@ export function SlotGlyph({
234237
<Animated.View style={[faceStyle, incomingStyle]}>
235238
<GlyphText
236239
allowFontScaling={allowFontScaling}
240+
ellipsizeMode={ellipsizeMode}
237241
maxFontSizeMultiplier={maxFontSizeMultiplier}
238242
segment={targetSegment}
239243
textClassName={textClassName}
@@ -247,6 +251,7 @@ export function SlotGlyph({
247251
<GlyphText
248252
allowFontScaling={allowFontScaling}
249253
color={highlightColor}
254+
ellipsizeMode={ellipsizeMode}
250255
maxFontSizeMultiplier={maxFontSizeMultiplier}
251256
segment={targetSegment}
252257
textClassName={textClassName}
@@ -261,6 +266,7 @@ export function SlotGlyph({
261266
<View style={faceStyle}>
262267
<GlyphText
263268
allowFontScaling={allowFontScaling}
269+
ellipsizeMode={ellipsizeMode}
264270
maxFontSizeMultiplier={maxFontSizeMultiplier}
265271
segment={targetSegment}
266272
textClassName={textClassName}
@@ -308,6 +314,7 @@ function createFaceAnimationStyle(
308314
function GlyphText({
309315
allowFontScaling,
310316
color,
317+
ellipsizeMode,
311318
maxFontSizeMultiplier,
312319
segment,
313320
textClassName,
@@ -318,6 +325,7 @@ function GlyphText({
318325
accessible={false}
319326
allowFontScaling={allowFontScaling}
320327
className={textClassName}
328+
ellipsizeMode={ellipsizeMode}
321329
maxFontSizeMultiplier={maxFontSizeMultiplier}
322330
numberOfLines={1}
323331
style={[textStyle, color ? { color } : undefined]}

src/screens/ChatScreen/input/components/ChatInputReasoningSection.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export function ChatInputReasoningSection({
7070
<View className="flex-row items-center gap-1.5">
7171
<Text className="font-medium text-base text-foreground">{t('chat.reasoning.title')}</Text>
7272
<SlotText
73+
ellipsizeMode="clip"
7374
text={currentOption ? t(currentOption.labelKey) : ''}
7475
textClassName="font-semibold text-base text-foreground"
7576
textStyle={

0 commit comments

Comments
 (0)