Show tooltips for sidebar footer actions (#2025)

* fix(app): label sidebar footer actions

* fix(app): translate hosts tooltip
This commit is contained in:
Mohamed Boudra
2026-07-13 02:36:01 +08:00
committed by GitHub
parent a9ba0392b7
commit 18de06c2a4
10 changed files with 60 additions and 58 deletions
+51 -58
View File
@@ -101,9 +101,9 @@ interface SidebarSharedProps {
interface SidebarLabels { interface SidebarLabels {
addProject: string; addProject: string;
newWorkspace: string; newWorkspace: string;
hosts: string;
home: string; home: string;
settings: string; settings: string;
switchHost: string;
searchHosts: string; searchHosts: string;
sessions: string; sessions: string;
schedules: string; schedules: string;
@@ -226,9 +226,9 @@ export const LeftSidebar = memo(function LeftSidebar() {
(): SidebarLabels => ({ (): SidebarLabels => ({
addProject: t("sidebar.actions.addProject"), addProject: t("sidebar.actions.addProject"),
newWorkspace: t("sidebar.actions.newWorkspace"), newWorkspace: t("sidebar.actions.newWorkspace"),
hosts: t("sidebar.actions.hosts"),
home: t("sidebar.actions.home"), home: t("sidebar.actions.home"),
settings: t("sidebar.actions.settings"), settings: t("sidebar.actions.settings"),
switchHost: t("sidebar.host.switchTitle"),
searchHosts: t("sidebar.host.searchPlaceholder"), searchHosts: t("sidebar.host.searchPlaceholder"),
sessions: t("sidebar.sections.sessions"), sessions: t("sidebar.sections.sessions"),
schedules: t("sidebar.sections.schedules"), schedules: t("sidebar.sections.schedules"),
@@ -301,47 +301,58 @@ function FooterIconButton({
buttonRef, buttonRef,
onPress, onPress,
testID, testID,
accessibilityLabel, label,
icon: Icon, icon: Icon,
iconSize, iconSize,
shortcutKeys,
theme, theme,
}: { }: {
onPress: () => void; onPress: () => void;
testID: string; testID: string;
accessibilityLabel: string; label: string;
icon: typeof FolderPlus; icon: typeof FolderPlus;
iconSize?: number; iconSize?: number;
shortcutKeys?: ReturnType<typeof useShortcutKeys>;
theme: SidebarTheme; theme: SidebarTheme;
buttonRef?: RefObject<View | null>; buttonRef?: RefObject<View | null>;
}) { }) {
return ( return (
<Pressable <Tooltip delayDuration={300}>
ref={buttonRef} <TooltipTrigger asChild>
style={styles.footerIconButton} <Pressable
testID={testID} ref={buttonRef}
nativeID={testID} style={styles.footerIconButton}
collapsable={false} testID={testID}
accessible nativeID={testID}
accessibilityLabel={accessibilityLabel} collapsable={false}
accessibilityRole="button" accessible
onPress={onPress} accessibilityLabel={label}
> accessibilityRole="button"
{({ hovered }) => ( onPress={onPress}
<Icon >
size={iconSize ?? theme.iconSize.md} {({ hovered }) => (
color={hovered ? theme.colors.foreground : theme.colors.foregroundMuted} <Icon
/> size={iconSize ?? theme.iconSize.md}
)} color={hovered ? theme.colors.foreground : theme.colors.foregroundMuted}
</Pressable> />
)}
</Pressable>
</TooltipTrigger>
<TooltipContent side="top" align="center" offset={8}>
<IconTooltipContent label={label} shortcutKeys={shortcutKeys} />
</TooltipContent>
</Tooltip>
); );
} }
function SidebarHostPicker({ function SidebarHostPicker({
theme, theme,
label,
onAddHost, onAddHost,
onOpenHostSettings, onOpenHostSettings,
}: { }: {
theme: SidebarTheme; theme: SidebarTheme;
label: string;
onAddHost: () => void; onAddHost: () => void;
onOpenHostSettings: (serverId: string) => void; onOpenHostSettings: (serverId: string) => void;
}) { }) {
@@ -380,7 +391,7 @@ function SidebarHostPicker({
buttonRef={triggerRef} buttonRef={triggerRef}
onPress={handleOpen} onPress={handleOpen}
testID="sidebar-hosts-trigger" testID="sidebar-hosts-trigger"
accessibilityLabel="Hosts" label={label}
icon={Server} icon={Server}
iconSize={theme.iconSize.sm} iconSize={theme.iconSize.sm}
theme={theme} theme={theme}
@@ -389,22 +400,7 @@ function SidebarHostPicker({
); );
} }
function AddProjectTooltipContent({ function IconTooltipContent({
newAgentKeys,
label,
}: {
newAgentKeys: ReturnType<typeof useShortcutKeys>;
label: string;
}) {
return (
<View style={styles.tooltipRow}>
<Text style={styles.tooltipText}>{label}</Text>
{newAgentKeys ? <Shortcut chord={newAgentKeys} /> : null}
</View>
);
}
function HeaderIconTooltipContent({
label, label,
shortcutKeys, shortcutKeys,
}: { }: {
@@ -489,50 +485,47 @@ function SidebarFooter({
handleSettings: () => void; handleSettings: () => void;
labels: { labels: {
addProject: string; addProject: string;
hosts: string;
home: string; home: string;
settings: string; settings: string;
switchHost: string;
searchHosts: string; searchHosts: string;
}; };
handleAddHost: () => void; handleAddHost: () => void;
handleOpenHostSettings: (serverId: string) => void; handleOpenHostSettings: (serverId: string) => void;
}) { }) {
const newAgentKeys = useShortcutKeys("new-agent"); const newAgentKeys = useShortcutKeys("new-agent");
const settingsKeys = useShortcutKeys("toggle-settings");
return ( return (
<View style={styles.sidebarFooter}> <View style={styles.sidebarFooter}>
<View style={styles.footerIconRow}> <View style={styles.footerIconRow}>
<SidebarHostPicker <SidebarHostPicker
theme={theme} theme={theme}
label={labels.hosts}
onAddHost={handleAddHost} onAddHost={handleAddHost}
onOpenHostSettings={handleOpenHostSettings} onOpenHostSettings={handleOpenHostSettings}
/> />
<Tooltip delayDuration={300}> <FooterIconButton
<TooltipTrigger asChild> onPress={handleOpenProject}
<FooterIconButton testID="sidebar-add-project"
onPress={handleOpenProject} label={labels.addProject}
testID="sidebar-add-project" icon={FolderPlus}
accessibilityLabel={labels.addProject} shortcutKeys={newAgentKeys}
icon={FolderPlus} theme={theme}
theme={theme} />
/>
</TooltipTrigger>
<TooltipContent side="top" align="center" offset={8}>
<AddProjectTooltipContent newAgentKeys={newAgentKeys} label={labels.addProject} />
</TooltipContent>
</Tooltip>
<FooterIconButton <FooterIconButton
onPress={handleHome} onPress={handleHome}
testID="sidebar-home" testID="sidebar-home"
accessibilityLabel={labels.home} label={labels.home}
icon={Home} icon={Home}
theme={theme} theme={theme}
/> />
<FooterIconButton <FooterIconButton
onPress={handleSettings} onPress={handleSettings}
testID="sidebar-settings" testID="sidebar-settings"
accessibilityLabel={labels.settings} label={labels.settings}
icon={Settings} icon={Settings}
shortcutKeys={settingsKeys}
theme={theme} theme={theme}
/> />
</View> </View>
@@ -876,7 +869,7 @@ function WorkspacesSectionHeader() {
</Pressable> </Pressable>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent side="bottom" align="center" offset={8}> <TooltipContent side="bottom" align="center" offset={8}>
<HeaderIconTooltipContent label="Search" shortcutKeys={commandCenterKeys} /> <IconTooltipContent label="Search" shortcutKeys={commandCenterKeys} />
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
<Tooltip delayDuration={300}> <Tooltip delayDuration={300}>
@@ -886,7 +879,7 @@ function WorkspacesSectionHeader() {
</View> </View>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent side="bottom" align="center" offset={8}> <TooltipContent side="bottom" align="center" offset={8}>
<HeaderIconTooltipContent label="Display preferences" /> <IconTooltipContent label="Display preferences" />
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
</View> </View>
+1
View File
@@ -370,6 +370,7 @@ describe("translation resources", () => {
expect(en.sidebar.host.switchTitle).toBe("Switch host"); expect(en.sidebar.host.switchTitle).toBe("Switch host");
expect(en.sidebar.host.searchPlaceholder).toBe("Search hosts..."); expect(en.sidebar.host.searchPlaceholder).toBe("Search hosts...");
expect(en.sidebar.actions.addProject).toBe("Add project"); expect(en.sidebar.actions.addProject).toBe("Add project");
expect(en.sidebar.actions.hosts).toBe("Hosts");
expect(en.sidebar.actions.home).toBe("Home"); expect(en.sidebar.actions.home).toBe("Home");
expect(en.sidebar.actions.settings).toBe("Settings"); expect(en.sidebar.actions.settings).toBe("Settings");
expect(en.sidebar.actions.closeSidebar).toBe("Close sidebar"); expect(en.sidebar.actions.closeSidebar).toBe("Close sidebar");
+1
View File
@@ -782,6 +782,7 @@ export const ar: TranslationResources = {
actions: { actions: {
addProject: "إضافة مشروع", addProject: "إضافة مشروع",
newWorkspace: "مساحة عمل جديدة", newWorkspace: "مساحة عمل جديدة",
hosts: "المضيفون",
home: "بيت", home: "بيت",
settings: "إعدادات", settings: "إعدادات",
closeSidebar: "إغلاق الشريط الجانبي", closeSidebar: "إغلاق الشريط الجانبي",
+1
View File
@@ -789,6 +789,7 @@ export const en = {
actions: { actions: {
addProject: "Add project", addProject: "Add project",
newWorkspace: "New workspace", newWorkspace: "New workspace",
hosts: "Hosts",
home: "Home", home: "Home",
settings: "Settings", settings: "Settings",
closeSidebar: "Close sidebar", closeSidebar: "Close sidebar",
+1
View File
@@ -809,6 +809,7 @@ export const es: TranslationResources = {
actions: { actions: {
addProject: "Agregar proyecto", addProject: "Agregar proyecto",
newWorkspace: "Nuevo espacio de trabajo", newWorkspace: "Nuevo espacio de trabajo",
hosts: "Hosts",
home: "Hogar", home: "Hogar",
settings: "Ajustes", settings: "Ajustes",
closeSidebar: "Cerrar barra lateral", closeSidebar: "Cerrar barra lateral",
+1
View File
@@ -808,6 +808,7 @@ export const fr: TranslationResources = {
actions: { actions: {
addProject: "Ajouter un projet", addProject: "Ajouter un projet",
newWorkspace: "Nouvel espace de travail", newWorkspace: "Nouvel espace de travail",
hosts: "Hôtes",
home: "Maison", home: "Maison",
settings: "Paramètres", settings: "Paramètres",
closeSidebar: "Fermer la barre latérale", closeSidebar: "Fermer la barre latérale",
+1
View File
@@ -794,6 +794,7 @@ export const ja: TranslationResources = {
actions: { actions: {
addProject: "プロジェクトを追加", addProject: "プロジェクトを追加",
newWorkspace: "新しいワークスペース", newWorkspace: "新しいワークスペース",
hosts: "ホスト",
home: "ホーム", home: "ホーム",
settings: "設定", settings: "設定",
closeSidebar: "サイドバーを閉じる", closeSidebar: "サイドバーを閉じる",
+1
View File
@@ -800,6 +800,7 @@ export const ptBR: TranslationResources = {
actions: { actions: {
addProject: "Adicionar projeto", addProject: "Adicionar projeto",
newWorkspace: "Novo workspace", newWorkspace: "Novo workspace",
hosts: "Hosts",
home: "Início", home: "Início",
settings: "Configurações", settings: "Configurações",
closeSidebar: "Fechar barra lateral", closeSidebar: "Fechar barra lateral",
+1
View File
@@ -801,6 +801,7 @@ export const ru: TranslationResources = {
actions: { actions: {
addProject: "Добавить проект", addProject: "Добавить проект",
newWorkspace: "Новое рабочее пространство", newWorkspace: "Новое рабочее пространство",
hosts: "Хосты",
home: "Дом", home: "Дом",
settings: "Настройки", settings: "Настройки",
closeSidebar: "Закрыть боковую панель", closeSidebar: "Закрыть боковую панель",
+1
View File
@@ -777,6 +777,7 @@ export const zhCN: TranslationResources = {
actions: { actions: {
addProject: "添加 project", addProject: "添加 project",
newWorkspace: "新建工作区", newWorkspace: "新建工作区",
hosts: "Hosts",
home: "首页", home: "首页",
settings: "设置", settings: "设置",
closeSidebar: "关闭侧边栏", closeSidebar: "关闭侧边栏",