feat(app): unify task list status styling

Use one task-row presentation across message and composer lists so running, pending, and completed states keep the same hierarchy and status language.
This commit is contained in:
Mohamed Boudra
2026-08-13 18:52:15 +02:00
parent 9c195feb9b
commit 0f27230746
4 changed files with 188 additions and 136 deletions
+2 -80
View File
@@ -1,4 +1,5 @@
import { LoadingSpinner } from "@/components/ui/loading-spinner";
import { TaskListRow } from "@/components/task-list-row";
import {
View,
Text,
@@ -166,7 +167,6 @@ const MARKDOWN_ALLOWED_IMAGE_HANDLERS = [
const MARKDOWN_TOP_LEVEL_MAX_EXCEEDED_ITEM = <Text key="dotdotdot">...</Text>;
const ThemedMicVocal = withUnistyles(MicVocal);
const ThemedTodoCheckIcon = withUnistyles(Check);
const ThemedFileSymlinkIcon = withUnistyles(FileSymlink);
const ThemedTriangleAlertIcon = withUnistyles(TriangleAlertIcon);
const ThemedChevronRightIcon = withUnistyles(ChevronRight);
@@ -179,9 +179,6 @@ const foregroundMutedColorMapping = (theme: Theme) => ({
const mutedForegroundColorMapping = (theme: Theme) => ({
color: theme.colors.mutedForeground,
});
const primaryForegroundColorMapping = (theme: Theme) => ({
color: theme.colors.primaryForeground,
});
const destructiveColorMapping = (theme: Theme) => ({ color: theme.colors.destructive });
const WEB_TOOLCALL_SHIMMER_KEYFRAME_CSS = `
@keyframes ${WEB_TOOLCALL_SHIMMER_ANIMATION_NAME} {
@@ -2239,12 +2236,6 @@ interface TodoListCardProps {
disableOuterSpacing?: boolean;
}
interface TodoListItemRowProps {
text: string;
completed: boolean;
status?: TodoEntry["status"];
}
function taskActivityIcon(activity: TaskActivity) {
switch (activity.type) {
case "added":
@@ -2260,34 +2251,6 @@ function taskActivityIcon(activity: TaskActivity) {
}
}
function TodoListItemRow({ text, completed, status }: TodoListItemRowProps) {
const badgeStyle = useMemo(
() => [
todoListCardStylesheet.radioBadge,
completed
? todoListCardStylesheet.radioBadgeComplete
: todoListCardStylesheet.radioBadgeIncomplete,
],
[completed],
);
const textStyle = useMemo(
() => [todoListCardStylesheet.itemText, completed && todoListCardStylesheet.itemTextCompleted],
[completed],
);
return (
<View style={todoListCardStylesheet.itemRow}>
<View
style={[badgeStyle, status === "in_progress" && todoListCardStylesheet.radioBadgeActive]}
>
{completed ? (
<ThemedTodoCheckIcon size={12} uniProps={primaryForegroundColorMapping} />
) : null}
</View>
<Text style={textStyle}>{text}</Text>
</View>
);
}
const todoListCardStylesheet = StyleSheet.create((theme) => ({
detailsWrapper: {
padding: theme.spacing[2],
@@ -2295,40 +2258,6 @@ const todoListCardStylesheet = StyleSheet.create((theme) => ({
list: {
gap: theme.spacing[1],
},
itemRow: {
flexDirection: "row",
alignItems: "center",
gap: theme.spacing[2],
},
radioBadge: {
width: 16,
height: 16,
borderRadius: 8,
backgroundColor: theme.colors.foregroundMuted,
alignItems: "center",
justifyContent: "center",
},
radioBadgeIncomplete: {
opacity: 0.55,
},
radioBadgeComplete: {
opacity: 0.95,
},
radioBadgeActive: {
borderWidth: 2,
borderColor: theme.colors.primary,
backgroundColor: "transparent",
opacity: 1,
},
itemText: {
flex: 1,
color: theme.colors.foreground,
fontSize: theme.fontSize.base,
},
itemTextCompleted: {
color: theme.colors.foregroundMuted,
textDecorationLine: "line-through",
},
emptyText: {
color: theme.colors.foregroundMuted,
fontSize: theme.fontSize.base,
@@ -2366,14 +2295,7 @@ export const TodoListCard = memo(function TodoListCard({
{items.length === 0 ? (
<Text style={todoListCardStylesheet.emptyText}>{t("message.todo.empty")}</Text>
) : (
items.map((item) => (
<TodoListItemRow
key={item.id ?? item.text}
text={item.text}
completed={item.completed}
status={item.status}
/>
))
items.map((item) => <TaskListRow key={item.id ?? item.text} task={item} />)
)}
</View>
</View>