Show project icons in status-grouped sidebar rows (#2416)

* feat: show project icons in sidebar status view

* test(sidebar): keep status icon regression active

The ten-second mock can finish during app startup, removing the Working bucket before the icon assertion. Keep the seeded workspace active for the full scenario.

---------

Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
This commit is contained in:
nikuscs
2026-07-31 14:44:31 +02:00
committed by GitHub
co-authored by Mohamed Boudra
parent d9b72e1c76
commit 87ef631ac4
6 changed files with 207 additions and 22 deletions
@@ -0,0 +1,74 @@
import { View } from "react-native";
import { StyleSheet } from "react-native-unistyles";
import { ProjectIconView } from "@/components/project-icon-view";
import { projectIconPlaceholderLabelFromDisplayName } from "@/utils/project-display-name";
/**
* Decorative project marker for a sidebar row's subtitle line. Status mode breaks
* the project grouping, so the icon is what makes two same-named branches from
* different projects tell apart at a glance — the project name next to it carries
* the meaning, so the icon itself stays out of the accessibility tree.
*/
export function SidebarSubtitleProjectIcon({
projectKey,
projectName,
iconDataUri,
testID,
}: {
projectKey: string;
projectName: string;
iconDataUri: string | null;
testID?: string;
}) {
const placeholderInitial = projectIconPlaceholderLabelFromDisplayName(projectName)
.charAt(0)
.toUpperCase();
if (!iconDataUri && !placeholderInitial) {
return null;
}
return (
<View
style={styles.slot}
testID={testID}
accessibilityElementsHidden
importantForAccessibility="no-hide-descendants"
>
<ProjectIconView
iconDataUri={iconDataUri}
initial={placeholderInitial}
projectKey={projectKey}
imageStyle={styles.icon}
fallbackStyle={styles.fallback}
textStyle={styles.fallbackText}
/>
</View>
);
}
const styles = StyleSheet.create((theme) => ({
slot: {
width: 12,
// Match the 14px subtitle line so the icon does not change row density.
height: 14,
flexShrink: 0,
alignItems: "center",
justifyContent: "center",
},
icon: {
width: 12,
height: 12,
borderRadius: theme.borderRadius.sm,
},
fallback: {
width: 12,
height: 12,
borderRadius: theme.borderRadius.sm,
alignItems: "center",
justifyContent: "center",
},
fallbackText: {
fontSize: 8,
lineHeight: 12,
},
}));