Skip to content

Commit

Permalink
fix(useList): added isDraggep prop to TreeListItemView and fixed issu…
Browse files Browse the repository at this point in the history
…e with keyboard dnd
  • Loading branch information
IsaevAlexandr committed Mar 18, 2024
1 parent 08f906e commit d6ebede
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 14 deletions.
14 changes: 11 additions & 3 deletions src/components/TreeList/__stories__/stories/WithDndListStory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,13 @@ export interface WithDndListStoryProps

export const WithDndListStory = (storyProps: WithDndListStoryProps) => {
const [items, setItems] = React.useState(randomItems);
const containerRef = React.useRef<HTMLDivElement>(null);
const listState = useListState();

React.useLayoutEffect(() => {
containerRef?.current?.focus();
}, []);

const renderContainer: TreeListRenderContainer<CustomDataType> = ({
renderItem,
visibleFlattenIds,
Expand All @@ -58,6 +63,8 @@ export const WithDndListStory = (storyProps: WithDndListStoryProps) => {
setItems((currentItems) =>
reorderArray(currentItems, source.index, destination.index),
);

listState.setActiveItemId(`${destination.index}`);
}
};

Expand All @@ -75,7 +82,7 @@ export const WithDndListStory = (storyProps: WithDndListStoryProps) => {
rubric.source.index,
{
provided,
active: snapshot.isDragging,
isDragging: snapshot.isDragging,
},
);
}}
Expand Down Expand Up @@ -126,7 +133,7 @@ export const WithDndListStory = (storyProps: WithDndListStoryProps) => {
<DraggableListItem
provided={provided}
{...commonProps}
active={snapshot.isDragging || commonProps.active}
isDragging={snapshot.isDragging}
/>
)}
</Draggable>
Expand All @@ -135,9 +142,10 @@ export const WithDndListStory = (storyProps: WithDndListStoryProps) => {

return (
<TreeList
containerRef={containerRef}
{...storyProps}
{...listState}
items={items}
{...listState}
getItemContent={({someRandomKey}) => ({title: someRandomKey})}
// you can omit this prop here. If prop `id` passed, TreeSelect would take it by default
getId={({id}) => id}
Expand Down
14 changes: 9 additions & 5 deletions src/components/TreeSelect/TreeSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const b = block('tree-select');
export const TreeSelect = React.forwardRef(function TreeSelect<T>(
{
id,
qa,
placement,
slotBeforeListBody,
slotAfterListBody,
size,
Expand Down Expand Up @@ -51,8 +53,7 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
renderItem,
renderContainer,
onItemClick,
placement,
qa,
setActiveItemId: propsSetActiveItemId,
getItemContent,
}: TreeSelectProps<T>,
ref: React.Ref<HTMLButtonElement>,
Expand Down Expand Up @@ -80,6 +81,8 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
selectedById: selected,
});

const setActiveItemId = propsSetActiveItemId ?? listState.setActiveItemId;

const listParsedState = useList({
items,
getId,
Expand Down Expand Up @@ -112,7 +115,7 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
if (listState.disabledById[listItemId]) return;

// always activate selected item
listState.setActiveItemId(listItemId);
setActiveItemId(listItemId);

if (isGroup && groupsBehavior === 'expandable') {
listState.setExpanded((state) => ({
Expand Down Expand Up @@ -145,6 +148,7 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
[
onItemClick,
listState,
setActiveItemId,
groupsBehavior,
multiple,
handleMultipleSelection,
Expand All @@ -159,7 +163,7 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
const lastSelectedItemId = value[value.length - 1];
containerRef.current?.focus();

listState.setActiveItemId(lastSelectedItemId);
setActiveItemId(lastSelectedItemId);

if (lastSelectedItemId) {
scrollToListItem(lastSelectedItemId, containerRef.current);
Expand Down Expand Up @@ -255,7 +259,7 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
selectedById: listState.selectedById,
expandedById: listState.expandedById,
activeItemId: listState.activeItemId,
setActiveItemId: listState.setActiveItemId,
setActiveItemId,
onItemClick: handleItemClick,
items,
renderContainer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const randomItems: CustomDataType[] = createRandomizedData({

export const WithDndListExample = (storyProps: WithDndListExampleProps) => {
const [items, setItems] = React.useState(randomItems);
const [activeItemId, setActiveItemId] = React.useState<string | undefined>(undefined);
const [value, setValue] = React.useState<string[]>([]);

const renderContainer: TreeSelectRenderContainer<CustomDataType> = ({
Expand All @@ -63,6 +64,8 @@ export const WithDndListExample = (storyProps: WithDndListExampleProps) => {
setItems((currentItems) =>
reorderArray(currentItems, source.index, destination.index),
);

setActiveItemId(`${destination.index}`);
}
};

Expand All @@ -80,7 +83,7 @@ export const WithDndListExample = (storyProps: WithDndListExampleProps) => {
rubric.source.index,
{
provided,
active: snapshot.isDragging,
isDragging: snapshot.isDragging,
},
);
}}
Expand Down Expand Up @@ -131,7 +134,7 @@ export const WithDndListExample = (storyProps: WithDndListExampleProps) => {
<DraggableListItem
provided={provided}
{...commonProps}
active={snapshot.isDragging || commonProps.active}
isDragging={snapshot.isDragging}
/>
)}
</Draggable>
Expand All @@ -144,6 +147,8 @@ export const WithDndListExample = (storyProps: WithDndListExampleProps) => {
{...storyProps}
value={value}
items={items}
activeItemId={activeItemId}
setActiveItemId={setActiveItemId}
// you can omit this prop here. If prop `id` passed, TreeSelect would take it by default
getId={({id}) => id}
getItemContent={({someRandomKey}) => ({
Expand All @@ -152,6 +157,7 @@ export const WithDndListExample = (storyProps: WithDndListExampleProps) => {
onItemClick={({id, isGroup, disabled}) => {
if (!isGroup && !disabled) {
setValue([id]);
setActiveItemId(id);
}
}}
renderContainer={renderContainer}
Expand Down
3 changes: 2 additions & 1 deletion src/components/TreeSelect/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export interface TreeSelectProps<T> extends QAProps, Partial<Omit<ListState, 'se
* In other situations use `renderContainer` method
*/
slotAfterListBody?: React.ReactNode;
items: ListItemType<T>[];
/**
* Define custom id depended on item data value to use in controlled state component variant
*/
Expand All @@ -102,5 +103,5 @@ export interface TreeSelectProps<T> extends QAProps, Partial<Omit<ListState, 'se
* Map item data to view props
*/
getItemContent: TreeListRenderContent<T>;
items: ListItemType<T>[];
setActiveItemId?(listItemId?: ListItemId): void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export const ListWithDnd = ({size, itemsCount}: ListWithDndProps) => {
{...data}
{...provided.draggableProps}
{...provided.dragHandleProps}
active={snapshot.isDragging}
isDragging={snapshot.isDragging}
ref={provided.innerRef}
endSlot={<Icon data={Grip} size={16} />}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ $block: '.#{variables.$ns}list-item-view';
}

&_selected,
&_selected#{$block}_active, // if active and selected selected bgc more priority
&_selected:not(#{$block}_isDragging)#{$block}_active, // if active and selected selected bgc more priority
&_selected:hover#{$block}_activeOnHover {
background: var(--g-color-base-selection);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ export interface ListItemViewProps extends QAProps {
className?: string;
role?: React.AriaRole;
expanded?: boolean;
/**
* Add active styles and change selection behavior during dnd is performing
*/
isDragging?: boolean;
/**
* `[${LIST_ITEM_DATA_ATR}="${id}"]` data attribute to find element.
* For example for scroll to
Expand Down Expand Up @@ -105,6 +109,7 @@ export const ListItemView = React.forwardRef(
height,
expanded,
style,
isDragging,
role = 'option',
onClick: _onClick,
...rest
Expand All @@ -121,10 +126,11 @@ export const ListItemView = React.forwardRef(
onClick={onClick}
className={b(
{
active,
active: isDragging || active,
selected: selected && !hasSelectionIcon,
activeOnHover,
radius: size,
isDragging,
clickable: Boolean(onClick),
},
spacing({px: 2}, className),
Expand Down

0 comments on commit d6ebede

Please sign in to comment.