Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export function ActionSelector({
hasSteps,
numSteps,
showSubmitButton,
canSubmitOrAdvance,
allOptions,
showInlineEdit,
moveUp,
Expand Down Expand Up @@ -284,6 +285,10 @@ export function ActionSelector({
const isSelected = selectedIndex === index;

const isHovered = hoveredIndex === index;
const isDisabled =
isSubmitOption(option.id) &&
showSubmitButton &&
!canSubmitOrAdvance;
return (
<OptionRow
key={option.id}
Expand All @@ -298,6 +303,7 @@ export function ActionSelector({
customInputPlaceholder=""
isEditing={false}
submitLabel={getSubmitLabel()}
disabled={isDisabled}
onCustomInputChange={setCustomInput}
onNavigateUp={handleNavigateUp}
onNavigateDown={handleNavigateDown}
Expand Down
37 changes: 21 additions & 16 deletions apps/code/src/renderer/components/action-selector/OptionRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface OptionRowProps {
customInputPlaceholder: string;
isEditing: boolean;
submitLabel: string;
disabled?: boolean;
onCustomInputChange: (value: string) => void;
onNavigateUp: () => void;
onNavigateDown: () => void;
Expand All @@ -52,6 +53,7 @@ export function OptionRow({
customInputPlaceholder,
isEditing,
submitLabel,
disabled = false,
onCustomInputChange,
onNavigateUp,
onNavigateDown,
Expand All @@ -63,34 +65,37 @@ export function OptionRow({
}: OptionRowProps) {
if (isSubmitOption(option.id) || isCancelOption(option.id)) {
const isCancel = isCancelOption(option.id);
const submitBg = disabled
? "bg-(--gray-4)"
: isSelected
? "bg-(--blue-8)"
: isHovered
? "bg-(--blue-4)"
: "bg-(--blue-3)";
return (
<Flex
align="center"
justify="center"
gap="2"
onClick={onClick}
onClick={disabled ? undefined : onClick}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
px="2"
className={`inline-flex h-[28px] cursor-pointer rounded-(--radius-2) ${
isCancel
? isSelected
? "bg-(--gray-6)"
: "bg-(--gray-3)"
: isSelected
? "bg-(--blue-8)"
: isHovered
? "bg-(--blue-4)"
: "bg-(--blue-3)"
className={`inline-flex h-[28px] rounded-(--radius-2) ${
disabled ? "cursor-not-allowed" : "cursor-pointer"
} ${
isCancel ? (isSelected ? "bg-(--gray-6)" : "bg-(--gray-3)") : submitBg
}`}
>
<Text
className={`font-medium text-[13px] ${
isSelected
? isCancel
? "text-gray-12"
: "text-blue-12"
: "text-gray-12"
disabled
? "text-gray-9"
: isSelected
? isCancel
? "text-gray-12"
: "text-blue-12"
: "text-gray-12"
}`}
>
{isCancel ? option.label : submitLabel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ export function useActionSelectorState({
);
const containerRef = useRef<HTMLDivElement>(null);
const prevActiveStepRef = useRef(currentStep);
const customInputRef = useRef("");
customInputRef.current = customInput;

const activeStep = internalStep;
const hasSteps = steps !== undefined && steps.length > 1;
Expand All @@ -99,6 +101,7 @@ export function useActionSelectorState({
const selectedOption = allOptions[selectedIndex];
const showInlineEdit =
isEditing && selectedOption && needsCustomInput(selectedOption);
const canSubmitOrAdvance = checkedOptions.size > 0;

useEffect(() => {
if (!isInteractiveElementInDifferentCell(containerRef)) {
Expand Down Expand Up @@ -164,12 +167,17 @@ export function useActionSelectorState({
}, [activeStep, restoreStepAnswer]);

useEffect(() => {
if (selectedOption && needsCustomInput(selectedOption)) {
setIsEditing(true);
} else {
setIsEditing(false);
const isCustom = !!selectedOption && needsCustomInput(selectedOption);
setIsEditing(isCustom);
if (isCustom && showSubmitButton && customInputRef.current.trim()) {
setCheckedOptions((prev) => {
if (prev.has(selectedOption.id)) return prev;
const next = multiSelect ? new Set(prev) : new Set<string>();
next.add(selectedOption.id);
return next;
});
}
}, [selectedOption]);
}, [selectedOption, showSubmitButton, multiSelect]);

const moveUp = useCallback(() => {
setHoveredIndex(null);
Expand Down Expand Up @@ -249,6 +257,7 @@ export function useActionSelectorState({
onSelect(selected.id);
return;
}
if (!canSubmitOrAdvance) return;
if (hasSteps && activeStep < numSteps - 1) {
saveCurrentStepAnswer();
setStep(activeStep + 1);
Expand Down Expand Up @@ -294,6 +303,7 @@ export function useActionSelectorState({
saveCurrentStepAnswer,
setStep,
isEditing,
canSubmitOrAdvance,
]);

const selectByIndex = useCallback(
Expand All @@ -306,6 +316,7 @@ export function useActionSelectorState({
onSelect(selected.id);
return;
}
if (!canSubmitOrAdvance) return;
if (hasSteps && activeStep < numSteps - 1) {
saveCurrentStepAnswer();
setStep(activeStep + 1);
Expand Down Expand Up @@ -340,6 +351,7 @@ export function useActionSelectorState({
onSelect,
saveCurrentStepAnswer,
setStep,
canSubmitOrAdvance,
],
);

Expand All @@ -355,6 +367,7 @@ export function useActionSelectorState({
onSelect(selected.id);
return;
}
if (!canSubmitOrAdvance) return;
if (hasSteps && activeStep < numSteps - 1) {
saveCurrentStepAnswer();
setStep(activeStep + 1);
Expand Down Expand Up @@ -396,6 +409,7 @@ export function useActionSelectorState({
onSelect,
saveCurrentStepAnswer,
setStep,
canSubmitOrAdvance,
],
);

Expand Down Expand Up @@ -451,16 +465,53 @@ export function useActionSelectorState({

const handleInlineSubmit = useCallback(() => {
if (!selectedOption) return;
if (showSubmitButton) {
if (customInput.trim()) {
ensureChecked(selectedOption.id);
const trimmed = customInput.trim();

if (!showSubmitButton) {
if (trimmed) {
onSelect(selectedOption.id, trimmed);
}
setIsEditing(false);
return;
}

if (trimmed) {
ensureChecked(selectedOption.id);
}
setIsEditing(false);

if (!trimmed && !canSubmitOrAdvance) {
containerRef.current?.focus();
} else if (customInput.trim()) {
onSelect(selectedOption.id, customInput.trim());
return;
}
}, [showSubmitButton, ensureChecked, selectedOption, customInput, onSelect]);

if (hasSteps && activeStep < numSteps - 1) {
saveCurrentStepAnswer();
setStep(activeStep + 1);
containerRef.current?.focus();
return;
}

if (multiSelect) {
handleSubmitMulti();
} else {
handleSubmitSingle();
}
}, [
showSubmitButton,
ensureChecked,
selectedOption,
customInput,
onSelect,
hasSteps,
activeStep,
numSteps,
saveCurrentStepAnswer,
setStep,
multiSelect,
handleSubmitMulti,
handleSubmitSingle,
canSubmitOrAdvance,
]);

const handleNavigateUp = useCallback(() => {
if (
Expand Down Expand Up @@ -503,6 +554,7 @@ export function useActionSelectorState({
hasSteps,
numSteps,
showSubmitButton,
canSubmitOrAdvance,
allOptions,
selectedOption,
showInlineEdit,
Expand Down
Loading