mirror of
https://github.com/stablyai/orca.git
synced 2026-10-07 08:02:21 +00:00
fix(mobile): label the reasoning toggle and give it a full touch target
The toggle now tells a screen reader what it is, "Reasoning: Thought for 3s", as desktop's prefix does, and reaches a 44 pt target. The shared English copy stays private to the module that formats it.
This commit is contained in:
@@ -307,6 +307,9 @@ describe('MobileNativeChatMessage', () => {
|
||||
const tree = render(reasoning())
|
||||
expect(textIn(tree.root)).toContain('Thought for 3s')
|
||||
expect(toggleOf(tree).props.accessibilityState).toEqual({ expanded: false })
|
||||
// Said with what it is, as desktop's screen-reader prefix does, on a 32 + 2 × 6 pt target.
|
||||
expect(toggleOf(tree).props.accessibilityLabel).toBe('Reasoning: Thought for 3s')
|
||||
expect(toggleOf(tree).props.hitSlop).toBe(6)
|
||||
expect(markdownIn(tree)).toHaveLength(0)
|
||||
})
|
||||
|
||||
@@ -328,9 +331,10 @@ describe('MobileNativeChatMessage', () => {
|
||||
|
||||
it('says only what the host saw', () => {
|
||||
expect(textIn(render(reasoning({ state: 'running' })).root)).toContain('Thought')
|
||||
expect(
|
||||
textIn(render(reasoning({ state: undefined, completedAt: undefined })).root)
|
||||
).toContain('Reasoning')
|
||||
const unknown = render(reasoning({ state: undefined, completedAt: undefined }))
|
||||
expect(textIn(unknown.root)).toContain('Reasoning')
|
||||
// No "Reasoning: Reasoning".
|
||||
expect(toggleOf(unknown).props.accessibilityLabel).toBe('Reasoning')
|
||||
expect(textIn(render(reasoning({ completedAt: 1_300 })).root)).toContain('Thought for 1s')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -24,6 +24,8 @@ export function MobileNativeChatReasoningRow({
|
||||
onOpenFile?: (relativePath: string) => void
|
||||
}): React.JSX.Element {
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
const headline = nativeChatReasoningHeadlineText(nativeChatReasoningHeadline(message))
|
||||
const label = nativeChatReasoningHeadlineText({ kind: 'reasoning' })
|
||||
return (
|
||||
<View>
|
||||
<Pressable
|
||||
@@ -32,9 +34,11 @@ export function MobileNativeChatReasoningRow({
|
||||
hitSlop={6}
|
||||
accessibilityRole="button"
|
||||
accessibilityState={{ expanded }}
|
||||
// Desktop's screen-reader prefix: the headline alone does not say what was thought.
|
||||
accessibilityLabel={headline === label ? label : `${label}: ${headline}`}
|
||||
>
|
||||
<Text style={styles.reasoningHeadline} numberOfLines={1}>
|
||||
{nativeChatReasoningHeadlineText(nativeChatReasoningHeadline(message))}
|
||||
{headline}
|
||||
</Text>
|
||||
<View style={expanded ? styles.reasoningCaretOpen : undefined}>
|
||||
<ChevronRight size={14} color={colors.textMuted} strokeWidth={2} />
|
||||
|
||||
@@ -36,7 +36,8 @@ export const styles = StyleSheet.create({
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: spacing.xs,
|
||||
paddingVertical: 3
|
||||
// With the toggle's 6 pt hitSlop above and below, a 44 pt touch target.
|
||||
minHeight: 32
|
||||
},
|
||||
reasoningPressed: {
|
||||
opacity: 0.6
|
||||
|
||||
@@ -44,7 +44,7 @@ export function nativeChatReasoningHeadline(
|
||||
}
|
||||
|
||||
/** English copy for clients without a translation catalog; desktop translates the same three. */
|
||||
export const NATIVE_CHAT_REASONING_COPY = {
|
||||
const NATIVE_CHAT_REASONING_COPY = {
|
||||
reasoning: 'Reasoning',
|
||||
thought: 'Thought',
|
||||
thoughtFor: (duration: string) => `Thought for ${duration}`
|
||||
|
||||
Reference in New Issue
Block a user