Skip to content
This repository has been archived by the owner on Jan 2, 2025. It is now read-only.

Commit

Permalink
rework arrow navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
anastasiya1155 committed Jan 29, 2024
1 parent a8dcf91 commit 9f53f6e
Show file tree
Hide file tree
Showing 37 changed files with 373 additions and 246 deletions.
40 changes: 16 additions & 24 deletions client/src/CommandBar/Body/Item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,23 @@ import {
} from '../../services/storage';

type Props = CommandBarItemGeneralType & {
isFocused?: boolean;
i: number;
index: string;
focusedIndex: string;
isFirst?: boolean;
isWithCheckmark?: boolean;
setFocusedIndex: Dispatch<SetStateAction<number>>;
setFocusedIndex: Dispatch<SetStateAction<string>>;
customRightElement?: ReactElement;
focusedItemProps?: Record<string, any>;
disableKeyNav?: boolean;
itemKey: string;
onlyOneClickable?: string;
};

const CommandBarItem = ({
isFocused,
focusedIndex,
Icon,
label,
shortcut,
i,
index,
setFocusedIndex,
id,
footerBtns,
Expand All @@ -54,7 +53,6 @@ const CommandBarItem = ({
isWithCheckmark,
closeOnClick,
itemKey,
onlyOneClickable,
}: Props) => {
const ref = useRef<HTMLButtonElement>(null);
const shortcutKeys = useShortcuts(shortcut);
Expand All @@ -63,29 +61,26 @@ const CommandBarItem = ({
);

useEffect(() => {
if (isFocused) {
if (focusedIndex === index) {
setFocusedItem({
footerHint,
footerBtns,
focusedItemProps,
});
ref.current?.scrollIntoView({ block: 'nearest' });
}
}, [isFocused, footerBtns, footerHint, focusedItemProps]);
}, [focusedIndex, index, footerBtns, footerHint, focusedItemProps]);

const handleMouseMove = useCallback(
(e: React.MouseEvent) => {
if (e.movementX || e.movementY) {
setFocusedIndex(i);
setFocusedIndex(index);
}
},
[i, setFocusedIndex],
[index, setFocusedIndex],
);

const handleClick = useCallback(() => {
if (onlyOneClickable && onlyOneClickable !== itemKey) {
return;
}
if (onClick) {
onClick();
if (closeOnClick) {
Expand All @@ -101,44 +96,41 @@ const CommandBarItem = ({
});
}
updateArrayInStorage(RECENT_COMMANDS_KEY, itemKey);
}, [id, onClick, closeOnClick, itemKey, onlyOneClickable]);
}, [id, onClick, closeOnClick, itemKey]);

const handleKeyEvent = useCallback(
(e: KeyboardEvent) => {
const shortAction = footerBtns.find((b) => checkEventKeys(e, b.shortcut));
if (
(isFocused && shortAction && !shortAction.action) ||
(focusedIndex === index && shortAction && !shortAction.action) ||
checkEventKeys(e, shortcut)
) {
e.preventDefault();
e.stopPropagation();
handleClick();
return;
}
if (isFocused && shortAction?.action) {
if (focusedIndex === index && shortAction?.action) {
e.preventDefault();
e.stopPropagation();
shortAction.action();
}
},
[isFocused, shortcut, footerBtns, handleClick],
);
useKeyboardNavigation(
handleKeyEvent,
disableKeyNav || (!!onlyOneClickable && onlyOneClickable !== itemKey),
[focusedIndex === index, shortcut, footerBtns, handleClick],
);
useKeyboardNavigation(handleKeyEvent, disableKeyNav);

return (
<button
className={`flex items-center gap-3 rounded-md px-2 h-10 ${
isFocused && !(onlyOneClickable && onlyOneClickable !== itemKey)
focusedIndex === index
? 'bg-bg-base-hover text-label-title'
: 'text-label-base'
} text-left ${isFirst ? 'scroll-mt-8' : ''}`}
onMouseMove={handleMouseMove}
onClick={handleClick}
data-node-index={index}
ref={ref}
disabled={!!onlyOneClickable && onlyOneClickable !== itemKey}
>
<div
className={`rounded-6 w-6 h-6 flex items-center justify-center relative ${
Expand Down
20 changes: 8 additions & 12 deletions client/src/CommandBar/Body/Section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,19 @@ import Item from './Item';
type Props = {
title?: string;
items: (CommandBarItemCustomType | CommandBarItemGeneralType)[];
focusedIndex: number;
setFocusedIndex: Dispatch<SetStateAction<number>>;
offset: number;
focusedIndex: string;
setFocusedIndex: Dispatch<SetStateAction<string>>;
disableKeyNav?: boolean;
onlyOneClickable?: string;
index: string;
};

const CommandBarBodySection = ({
title,
items,
setFocusedIndex,
offset,
focusedIndex,
disableKeyNav,
onlyOneClickable,
index,
}: Props) => {
return (
<div className="flex flex-col select-none">
Expand All @@ -33,24 +31,22 @@ const CommandBarBodySection = ({
<Rest.Component
{...Rest.componentProps}
key={key}
isFocused={focusedIndex === i + offset}
focusedIndex={focusedIndex}
setFocusedIndex={setFocusedIndex}
isFirst={i === 0}
i={i + offset}
index={`${index}-${key}`}
disableKeyNav={disableKeyNav}
onlyOneClickable={onlyOneClickable}
/>
) : (
<Item
key={key}
{...Rest}
i={i + offset}
isFocused={focusedIndex === i + offset}
index={`${index}-${key}`}
focusedIndex={focusedIndex}
setFocusedIndex={setFocusedIndex}
isFirst={i === 0}
disableKeyNav={disableKeyNav}
itemKey={key}
onlyOneClickable={onlyOneClickable}
/>
),
)}
Expand Down
62 changes: 11 additions & 51 deletions client/src/CommandBar/Body/index.tsx
Original file line number Diff line number Diff line change
@@ -1,85 +1,45 @@
import { memo, useCallback, useEffect, useState } from 'react';
import { memo, useEffect } from 'react';
import { CommandBarSectionType } from '../../types/general';
import useKeyboardNavigation from '../../hooks/useKeyboardNavigation';
import { useArrowNavigation } from '../../hooks/useArrowNavigation';
import Section from './Section';

type Props = {
sections: CommandBarSectionType[];
disableKeyNav?: boolean;
onlyOneClickable?: string;
onFocusedIndexChange?: (i: number) => void;
onFocusedIndexChange?: (i: string) => void;
};

const CommandBarBody = ({
sections,
disableKeyNav,
onlyOneClickable,
onFocusedIndexChange,
}: Props) => {
const [focusedIndex, setFocusedIndex] = useState(0);

useEffect(() => {
if (onlyOneClickable) {
let itemIndex = -1;
const clickableSectionIndex = sections.findIndex((s) => {
itemIndex = s.items.findIndex((i) => i.key === onlyOneClickable);
return itemIndex > -1;
});
if (itemIndex > -1) {
setFocusedIndex(
sections[clickableSectionIndex].itemsOffset + itemIndex,
);
}
}
}, [onlyOneClickable, sections]);
const { focusedIndex, setFocusedIndex, handleArrowKey, navContainerRef } =
useArrowNavigation();

useEffect(() => {
if (onFocusedIndexChange) {
onFocusedIndexChange(focusedIndex);
}
}, [focusedIndex]);

useEffect(() => {
setFocusedIndex(0);
}, [sections]);

const handleKeyEvent = useCallback(
(e: KeyboardEvent) => {
if (e.key === 'ArrowDown') {
e.preventDefault();
e.stopPropagation();
setFocusedIndex((prev) =>
prev <
sections.reduce((prev, curr) => prev + curr.items.length, 0) - 1
? prev + 1
: 0,
);
} else if (e.key === 'ArrowUp') {
e.preventDefault();
e.stopPropagation();
setFocusedIndex((prev) =>
prev > 0
? prev - 1
: sections.reduce((prev, curr) => prev + curr.items.length, 0) - 1,
);
}
},
[sections],
);
useKeyboardNavigation(handleKeyEvent, disableKeyNav || !!onlyOneClickable);
useKeyboardNavigation(handleArrowKey, disableKeyNav);

return (
<div className="flex flex-col gap-1 flex-1 w-full p-2 overflow-auto show-scrollbar">
<div
className="flex flex-col gap-1 flex-1 w-full p-2 overflow-auto show-scrollbar"
ref={navContainerRef}
>
{sections.map((s) => (
<Section
key={s.key}
title={s.label}
items={s.items}
focusedIndex={focusedIndex}
setFocusedIndex={setFocusedIndex}
offset={s.itemsOffset}
disableKeyNav={disableKeyNav}
onlyOneClickable={onlyOneClickable}
index={s.key}
/>
))}
</div>
Expand Down
4 changes: 0 additions & 4 deletions client/src/CommandBar/steps/AddToStudio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,6 @@ const AddToStudio = (props: Props) => {
newSectionsToShow.push({
...s,
items,
itemsOffset: newSectionsToShow[newSectionsToShow.length - 1]
? newSectionsToShow[newSectionsToShow.length - 1].itemsOffset +
newSectionsToShow[newSectionsToShow.length - 1].items.length
: 0,
});
}
});
Expand Down
1 change: 0 additions & 1 deletion client/src/CommandBar/steps/Documentation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ const Documentation = ({}: Props) => {
setSections([
addItem,
{
itemsOffset: 1,
key: 'indexed-docs',
label: t('Indexed documentation web pages'),
items: mapped,
Expand Down
19 changes: 0 additions & 19 deletions client/src/CommandBar/steps/Initial.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,6 @@ const InitialCommandBar = ({ shouldShowTutorial }: Props) => {
? [
{
items: newTabItems,
itemsOffset: 0,
key: 'new-tab-items',
},
]
Expand All @@ -384,7 +383,6 @@ const InitialCommandBar = ({ shouldShowTutorial }: Props) => {
? [
{
items: tabItems,
itemsOffset: newTabItems.length,
key: 'tab-items',
},
]
Expand All @@ -394,35 +392,22 @@ const InitialCommandBar = ({ shouldShowTutorial }: Props) => {
{
label: t('Recent conversations'),
items: chatItems,
itemsOffset: newTabItems.length + tabItems.length,
key: 'chat-items',
},
]
: []),
{
items: contextItems,
itemsOffset: newTabItems.length + tabItems.length + chatItems.length,
label: t('Manage context'),
key: 'context-items',
},
{
items: projectItems,
itemsOffset:
newTabItems.length +
tabItems.length +
chatItems.length +
contextItems.length,
label: t('Recent projects'),
key: 'recent-projects',
},
{
items: commandsItems,
itemsOffset:
newTabItems.length +
tabItems.length +
chatItems.length +
contextItems.length +
projectItems.length,
label: t('Commands'),
key: 'general-commands',
},
Expand Down Expand Up @@ -456,10 +441,6 @@ const InitialCommandBar = ({ shouldShowTutorial }: Props) => {
newSections.push({
...s,
items: newItems,
itemsOffset: newSections[newSections.length - 1]
? newSections[newSections.length - 1].items.length +
newSections[newSections.length - 1].itemsOffset
: 0,
});
}
});
Expand Down
1 change: 0 additions & 1 deletion client/src/CommandBar/steps/LocalRepos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ const LocalRepos = ({}: Props) => {
setSections([
addItem,
{
itemsOffset: 1,
key: 'indexed-repos',
label: t('Indexed local repositories'),
items: mapped,
Expand Down
4 changes: 0 additions & 4 deletions client/src/CommandBar/steps/ManageRepos/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,6 @@ const ManageRepos = ({ shouldShowTutorial }: Props) => {
newSectionsToShow.push({
...s,
items,
itemsOffset: newSectionsToShow[newSectionsToShow.length - 1]
? newSectionsToShow[newSectionsToShow.length - 1].itemsOffset +
newSectionsToShow[newSectionsToShow.length - 1].items.length
: 0,
});
}
});
Expand Down
4 changes: 0 additions & 4 deletions client/src/CommandBar/steps/PrivateRepos/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,6 @@ const PrivateReposStep = ({ shouldShowTutorial }: Props) => {
newSectionsToShow.push({
...s,
items,
itemsOffset: newSectionsToShow[newSectionsToShow.length - 1]
? newSectionsToShow[newSectionsToShow.length - 1].itemsOffset +
newSectionsToShow[newSectionsToShow.length - 1].items.length
: 0,
});
}
});
Expand Down
Loading

0 comments on commit 9f53f6e

Please sign in to comment.