Make jump-to-latest the same chevron, pointing down

It was a labelled button beside a tool group that collapses with a
drawn chevron -- two controls doing the same kind of thing in two
visual languages. Now one `Chevron` composable serves both directions,
parameterised rather than copied, since a pair that differs by a minus
sign drifts and the drift is a bug in exactly one direction.

The comment it replaces argued against an arrow here, on the grounds
that the list is laid out upside down. That reasoning was about the
code: nobody reading the screen knows the list is reversed, and on
screen the newest message is at the bottom, which is where this goes.

It draws no text, so the name lives in its content description -- the
whole of what a screen reader has, and the answer to "what was that
arrow for" later.

Verified on the emulator: scrolled up, the chevron appears bottom
centre matching the group's; tapped, it returns to the newest message
and takes itself away.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Opus 5 committed 2026-08-29 13:46:13 -04:00
1 parent 011ed0d0e1
commit 73923dbbc3
3 files changed
+78 -26

No files matched your search

@@ -0,0 +1,53 @@
package com.example.aiapp
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.unit.dp
/**
* A chevron, pointing up or down.
*
* Drawn rather than set in a font: a chevron from an icon font is one of the glyphs a system font
* may simply not have, and the reader who gets an empty box instead is never the one who wrote it.
*
* One composable for both directions rather than two that differ by a minus sign -- the pair would
* drift, and the drift would be a bug in exactly one direction.
*
* It draws no label of its own, so every caller owes it a `contentDescription`: this is the whole
* of what assistive technology has to go on, and it is also the answer to "what was that arrow
* for" six months from now.
*/
@Composable
fun Chevron(
pointingUp: Boolean,
modifier: Modifier = Modifier,
colour: Color = MaterialTheme.colorScheme.onSurfaceVariant,
) {
Canvas(modifier.width(20.dp).height(10.dp)) {
val inset = 2.dp.toPx()
val point = if (pointingUp) inset else size.height - inset
val ends = if (pointingUp) size.height - inset else inset
val stroke = 2.dp.toPx()
drawLine(
colour,
Offset(inset, ends),
Offset(size.width / 2, point),
strokeWidth = stroke,
cap = StrokeCap.Round,
)
drawLine(
colour,
Offset(size.width / 2, point),
Offset(size.width - inset, ends),
strokeWidth = stroke,
cap = StrokeCap.Round,
)
}
}