Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New Utility]: Sortable #9

Closed
junwen-k opened this issue Nov 17, 2024 · 0 comments · Fixed by #23
Closed

[New Utility]: Sortable #9

junwen-k opened this issue Nov 17, 2024 · 0 comments · Fixed by #23
Assignees
Labels
api-design API needs more thorough consideration enhancement New feature or request

Comments

@junwen-k
Copy link
Owner

Sortable

Utility component that allows sorting of elements.

Description

I've built this component before, which had props like

interface SortableProps<T extends SortableContextProps['items'][number]>
  extends Omit<DndContextProps, 'children'> {
  items?: T[];
  defaultItems?: T[];
  onItemsChange?: (items: T[]) => void;
  onReorder?: (oldIndex: number, newIndex: number) => void;
  children?: React.ReactNode | ((items: T[]) => React.ReactNode);
}

However, I am not sure if we need to support controlled / uncontrolled behavior (internal state of the ordering) for this component. This case is similar to component like DropzoneAccepted in which render props is required to render based on the internal state of the component, albeit most of the time we don't need to use that component.

<DropzoneAccepted>
  {(acceptedFiles) => ...}
</DropzoneAccepted>

This example was taken from my previous Sortable implementation:

<Sortable defaultItems={['id-001', 'id-002', 'id-003', 'id-004']}>
  // Feels a little awkward here, do we need to support this API?
  {(items) => (
    <ul className="grid gap-4">
      {items.map((item) => (
        <SortableItem key={item} id={item}>
          <li className="flex items-center justify-center gap-4 rounded-md border bg-background py-2 pl-2 pr-4">
            <SortableItemActivatorGripIconButton />
            <p className="text-sm text-muted-foreground">{item}</p>
          </li>
        </SortableItem>
      ))}
    </ul>
  )}
</Sortable>

I am wondering if we don't even need to support having items as it's state, and instead just exposes prop like onReorder and allow outside to control the ordering of the list, would be a better choice.

I am currently leaning towards keeping the API simpler by removing the items, defaultItems and onItemsChange API. Axis can also be locked via modifier.

<Sortable.Root onReorder={handleReorder}>
  {items.map((item, index) => (
    <Sortable.Item key={item} id={item}>
      <div className="flex items-center gap-2">
        <Sortable.Handle>
          <GripIcon className="h-4 w-4" />
        </Sortable.Handle>
        {item}
      </div>
    </Sortable.Item>
  ))}
</Sortable.Root>

Anatomy

<Sortable>
  <SortableItem>
    <SortableHandle />
  </SortableItem>
</Sortable>

Libraries / Hooks

@junwen-k junwen-k added enhancement New feature or request api-design API needs more thorough consideration labels Nov 17, 2024
@junwen-k junwen-k self-assigned this Feb 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-design API needs more thorough consideration enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant