Skip to content

Commit f73fd82

Browse files
committed
chore: Add dnd drag buttons to list
1 parent d531c83 commit f73fd82

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

pages/list/sortable-permutations.page.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ const items: Item[] = [
2525
{ content: 'Item 4', description: 'Description', timestamp: 'January 1 2025' },
2626
];
2727

28+
const ControlledList = (props: ListProps<Item>) => {
29+
const [items, setItems] = React.useState(props.items);
30+
return <List {...props} items={items} onSortingChange={e => setItems(e.detail.items)} />;
31+
};
32+
2833
const permutations = createPermutations<ListProps<Item> & { viewportWidth: number; _sortable: boolean | 'disabled' }>([
2934
{
3035
viewportWidth: [200, 400],
@@ -57,7 +62,7 @@ export default function ListItemPermutations() {
5762
permutations={permutations}
5863
render={({ viewportWidth, _sortable, ...permutation }) => (
5964
<div style={{ width: viewportWidth, borderRight: '1px solid red', padding: '4px', overflow: 'hidden' }}>
60-
<List {...permutation} sortable={!!_sortable} sortDisabled={_sortable === 'disabled'} />
65+
<ControlledList {...permutation} sortable={!!_sortable} sortDisabled={_sortable === 'disabled'} />
6166
</div>
6267
)}
6368
/>

src/internal/components/sortable-area/__tests__/sortable-area.test.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ test('renders all items with correct attributes', () => {
4545
disabled: false,
4646
onPointerDown: expect.anything(),
4747
onKeyDown: expect.anything(),
48+
onDirectionClick: expect.anything(),
49+
triggerMode: 'keyboard-activate',
50+
directions:
51+
i === 0
52+
? {
53+
'block-start': 'disabled',
54+
'block-end': 'active',
55+
}
56+
: {
57+
'block-start': 'active',
58+
'block-end': 'disabled',
59+
},
4860
},
4961
})
5062
);

src/internal/components/sortable-area/index.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Portal } from '@cloudscape-design/component-toolkit/internal';
1111

1212
import { fireNonCancelableEvent } from '../../events';
1313
import { joinStrings } from '../../utils/strings';
14+
import { Direction } from '../drag-handle-wrapper/interfaces';
1415
import { SortableAreaProps } from './interfaces';
1516
import useDragAndDropReorder from './use-drag-and-drop-reorder';
1617
import useLiveAnnouncements from './use-live-announcements';
@@ -65,14 +66,23 @@ export default function SortableArea<Item>({
6566
items={items.map(item => itemDefinition.id(item))}
6667
strategy={verticalListSortingStrategy}
6768
>
68-
{items.map(item => (
69+
{items.map((item, index) => (
6970
<DraggableItem
7071
key={itemDefinition.id(item)}
7172
item={item}
7273
itemDefinition={itemDefinition}
74+
isFirst={index === 0}
75+
isLast={index === items.length - 1}
7376
renderItem={renderItem}
7477
onKeyDown={handleKeyDown}
7578
dragHandleAriaLabel={i18nStrings?.dragHandleAriaLabel}
79+
onDirectionClick={direction => {
80+
const movedItem = item;
81+
const oldIndex = items.indexOf(item);
82+
const newIndex = direction === 'block-end' ? oldIndex + 1 : oldIndex - 1;
83+
fireNonCancelableEvent(onItemsChange, { items: arrayMove([...items], oldIndex, newIndex), movedItem });
84+
i18nStrings?.liveAnnouncementDndItemCommitted?.(oldIndex + 1, newIndex + 1, items.length);
85+
}}
7686
/>
7787
))}
7888
</SortableContext>
@@ -126,13 +136,19 @@ function DraggableItem<Item>({
126136
item,
127137
itemDefinition,
128138
dragHandleAriaLabel,
139+
isFirst,
140+
isLast,
129141
onKeyDown,
142+
onDirectionClick,
130143
renderItem,
131144
}: {
132145
item: Item;
133146
itemDefinition: SortableAreaProps.ItemDefinition<Item>;
134147
dragHandleAriaLabel?: string;
148+
isFirst: boolean;
149+
isLast: boolean;
135150
onKeyDown: (event: React.KeyboardEvent) => void;
151+
onDirectionClick: (direction: Direction) => void;
136152
renderItem: (props: SortableAreaProps.RenderItemProps<Item>) => React.ReactNode;
137153
}) {
138154
const id = itemDefinition.id(item);
@@ -173,6 +189,12 @@ function DraggableItem<Item>({
173189
ariaLabel: joinStrings(dragHandleAriaLabel, itemDefinition.label(item)) ?? '',
174190
ariaDescribedby: attributes['aria-describedby'],
175191
disabled: attributes['aria-disabled'],
192+
directions: {
193+
'block-start': isFirst ? 'disabled' : 'active',
194+
'block-end': isLast ? 'disabled' : 'active',
195+
},
196+
triggerMode: 'keyboard-activate',
197+
onDirectionClick,
176198
},
177199
})}
178200
</>

0 commit comments

Comments
 (0)