chore(lint): hoist jsx-as-prop in workspace/new-workspace screens

This commit is contained in:
Mohamed Boudra
2026-04-24 05:47:45 +07:00
parent 3f079aa987
commit 36a40e9729
3 changed files with 112 additions and 45 deletions

View File

@@ -50,6 +50,55 @@ interface PickerSelection {
const BRANCH_OPTION_PREFIX = "branch:";
const PR_OPTION_PREFIX = "github-pr:";
function PickerOptionItem({
testID,
label,
description,
selected,
active,
disabled,
onPress,
isBranch,
iconColor,
iconSize,
}: {
testID: string;
label: string;
description: string | undefined;
selected: boolean;
active: boolean;
disabled: boolean;
onPress: () => void;
isBranch: boolean;
iconColor: string;
iconSize: number;
}) {
const leadingSlot = useMemo(
() => (
<View style={styles.rowIconBox}>
{isBranch ? (
<GitBranch size={iconSize} color={iconColor} />
) : (
<GitPullRequest size={iconSize} color={iconColor} />
)}
</View>
),
[isBranch, iconSize, iconColor],
);
return (
<ComboboxItem
testID={testID}
label={label}
description={description}
selected={selected}
active={active}
disabled={disabled}
onPress={onPress}
leadingSlot={leadingSlot}
/>
);
}
function branchOptionId(name: string): string {
return `${BRANCH_OPTION_PREFIX}${name}`;
}
@@ -433,16 +482,6 @@ export function NewWorkspaceScreen({
const isBranch = item.kind === "branch";
const leadingSlot = (
<View style={styles.rowIconBox}>
{isBranch ? (
<GitBranch size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
) : (
<GitPullRequest size={theme.iconSize.sm} color={theme.colors.foregroundMuted} />
)}
</View>
);
const testID = isBranch
? `new-workspace-ref-picker-branch-${item.name}`
: `new-workspace-ref-picker-pr-${item.item.number}`;
@@ -451,7 +490,7 @@ export function NewWorkspaceScreen({
!isBranch && item.item.baseRefName ? `into ${item.item.baseRefName}` : undefined;
return (
<ComboboxItem
<PickerOptionItem
testID={testID}
label={pickerItemLabel(item)}
description={description}
@@ -459,7 +498,9 @@ export function NewWorkspaceScreen({
active={active}
disabled={isPending}
onPress={onPress}
leadingSlot={leadingSlot}
isBranch={isBranch}
iconColor={theme.colors.foregroundMuted}
iconSize={theme.iconSize.sm}
/>
);
},

View File

@@ -52,6 +52,7 @@ import {
import {
buildWorkspaceDesktopTabActions,
type WorkspaceDesktopTabActions,
type WorkspaceTabMenuEntry,
} from "@/screens/workspace/workspace-tab-menu";
import type { WorkspaceTabDescriptor } from "@/screens/workspace/workspace-tabs-types";
@@ -62,6 +63,50 @@ function newTabActionButtonStyle({ hovered, pressed }: PressableStateCallbackTyp
return [styles.newTabActionButton, (hovered || pressed) && styles.newTabActionButtonHovered];
}
function TabContextMenuItem({
entry,
iconColor,
}: {
entry: Extract<WorkspaceTabMenuEntry, { kind: "item" }>;
iconColor: string;
}) {
const leading = useMemo(() => {
switch (entry.icon) {
case "copy":
return <Copy size={16} color={iconColor} />;
case "rotate-cw":
return <RotateCw size={16} color={iconColor} />;
case "arrow-left-to-line":
return <ArrowLeftToLine size={16} color={iconColor} />;
case "arrow-right-to-line":
return <ArrowRightToLine size={16} color={iconColor} />;
case "copy-x":
return <CopyX size={16} color={iconColor} />;
case "x":
return <X size={16} color={iconColor} />;
default:
return undefined;
}
}, [entry.icon, iconColor]);
const trailing = useMemo(
() => (entry.hint ? <Text style={styles.menuItemHint}>{entry.hint}</Text> : undefined),
[entry.hint],
);
return (
<ContextMenuItem
testID={entry.testID}
disabled={entry.disabled}
destructive={entry.destructive}
onSelect={entry.onSelect}
tooltip={entry.tooltip}
leading={leading}
trailing={trailing}
>
{entry.label}
</ContextMenuItem>
);
}
function tabKeyExtractor(tab: WorkspaceDesktopTabRowItem) {
return `${tab.tab.key}:${tab.tab.kind}`;
}
@@ -366,38 +411,11 @@ function TabChip({
entry.kind === "separator" ? (
<ContextMenuSeparator key={entry.key} />
) : (
<ContextMenuItem
<TabContextMenuItem
key={entry.key}
testID={entry.testID}
disabled={entry.disabled}
destructive={entry.destructive}
onSelect={entry.onSelect}
tooltip={entry.tooltip}
leading={(() => {
const iconColor = theme.colors.foregroundMuted;
switch (entry.icon) {
case "copy":
return <Copy size={16} color={iconColor} />;
case "rotate-cw":
return <RotateCw size={16} color={iconColor} />;
case "arrow-left-to-line":
return <ArrowLeftToLine size={16} color={iconColor} />;
case "arrow-right-to-line":
return <ArrowRightToLine size={16} color={iconColor} />;
case "copy-x":
return <CopyX size={16} color={iconColor} />;
case "x":
return <X size={16} color={iconColor} />;
default:
return undefined;
}
})()}
trailing={
entry.hint ? <Text style={styles.menuItemHint}>{entry.hint}</Text> : undefined
}
>
{entry.label}
</ContextMenuItem>
entry={entry}
iconColor={theme.colors.foregroundMuted}
/>
),
)}
</ContextMenuContent>

View File

@@ -38,11 +38,19 @@ interface EditorMenuItemProps {
function EditorMenuItem({ editor, isPreferred, onOpen, foregroundMuted }: EditorMenuItemProps) {
const handleSelect = useCallback(() => onOpen(editor.id), [onOpen, editor.id]);
const leading = useMemo(
() => <EditorAppIcon editorId={editor.id} size={16} color={foregroundMuted} />,
[editor.id, foregroundMuted],
);
const trailing = useMemo(
() => (isPreferred ? <Check size={16} color={foregroundMuted} /> : undefined),
[isPreferred, foregroundMuted],
);
return (
<DropdownMenuItem
testID={`workspace-open-in-editor-item-${editor.id}`}
leading={<EditorAppIcon editorId={editor.id} size={16} color={foregroundMuted} />}
trailing={isPreferred ? <Check size={16} color={foregroundMuted} /> : undefined}
leading={leading}
trailing={trailing}
onSelect={handleSelect}
>
{editor.label}