Sortable
Sortable sắp xếp lại danh sách bằng kéo thả hoặc bàn phím; mỗi bước được đọc cho trình đọc màn hình.
onValueChange chạy cả trong lúc kéo để giao diện theo kịp; lưu thứ tự trong onSortEnd. SortableGroup nối nhiều danh sách (cột Kanban): mục sang được danh sách khác, với bàn phím là phím mũi tên vuông góc với danh sách. Mục đã dùng Space / Enter cho việc khác (nút, menu item, Tag) thì đặt handle để cả mục là tay nắm và shortcuts để Alt + phím mũi tên di chuyển; DataGridColumnPicker và TagPicker (reorderable) làm như vậy. Hướng ngang và lưới theo RTL; khi bật giảm chuyển động, các mục đổi chỗ không trượt. Không phụ thuộc thư viện kéo thả.- Màn hình đăng nhậpHạn thứ Sáu
- Danh sách đơn hàngChờ API
- Thanh toánƯu tiên cao
- Tài liệu phát hànhSau khi phát hành
Import
Cài từ npm, chép mã nguồn vào dự án bằng @yugen-ui/cli hoặc shadcn CLI, hoặc import thẳng khi làm việc trong repo này.
// npm install yugen-uiimport { Sortable, SortableGroup, SortableItem, SortableHandle, arrayMove } from "yugen-ui";Biến thể
Mỗi ô là một mẫu độc lập: hover để Copy, hoặc bấm Code để xem mã nguồn.
Ngang
orientation="horizontal": ← → di chuyển, đảo chiều trong RTL.
Lưới
orientation="grid": mục xuống dòng; ← → sang mục kế bên, ↑ ↓ sang hàng trên / dưới.
Cần làm
Đang làm
Xong
Kanban: SortableGroup
Mỗi cột là một Sortable có listId; SortableGroup giữ thứ tự của mọi cột. Với bàn phím, ← → chuyển thẻ sang cột kế bên. Cột đang nhận thẻ có data-over. onSortEnd chạy một lần khi thả: chỗ để lưu.
- Hoa anh đào
- Mưa tháng Sáu
- Biển đêm
- Gió mùa
Lệnh Lên / Xuống
Thêm lệnh trong menu cho người không nhận ra tay nắm. arrayMove trả về mảng mới; useAnnounce đọc vị trí mới như khi kéo.
Cả mục là tay nắm
Nút đã dùng Space / Enter để mở: handle cho kéo cả nút (bấm không kéo vẫn là bấm; trên màn hình cảm ứng thì giữ một lúc rồi kéo), shortcuts cho Alt + phím mũi tên di chuyển. Nút xuống dòng khi khung hẹp nên dùng orientation="grid".
Cách dùng
- Lưu thứ tự trong onSortEnd; onValueChange chạy cả trong lúc kéo.
- Đặt
labelcho SortableItem khi mục có nhiều chữ, để thông báo ngắn gọn. - Thêm lệnh Lên / Xuống khi người dùng có thể không nhận ra tay nắm.
- Không đặt SortableHandle trong mục có role option hay menuitem: các mục này không chứa được nút. Dùng
handlevàshortcuts. - Không cho kéo danh sách đã có thứ tự tự động (theo ngày, theo tên).
- Không đổi id của mục giữa các lần render:
keyvàvaluephải ổn định.
Props
| Prop · Kiểu | Mặc định | Mô tả |
|---|---|---|
| valuestring[] | Mặc định: — | Thứ tự id các mục. Bỏ trống khi nằm trong SortableGroup. |
| onValueChange(value: string[]) => void | Mặc định: — | Gọi mỗi lần thứ tự đổi, kể cả giữa lúc kéo; Esc gọi lại với thứ tự lúc nhấc lên. |
| onSortStart(data: { item, from }) => void | Mặc định: — | Lúc nhấc mục lên. |
| onSortEnd(data: { item, from, to, canceled }) => void | Mặc định: — | Một lần mỗi lần thả, kể cả khi di chuyển bằng phím tắt. from / to là { list, index }; canceled khi Esc. Lưu thứ tự ở đây. |
| orientation"vertical" | "horizontal" | "grid" | Mặc định: "vertical" | Hướng của danh sách: phím mũi tên nào di chuyển mục và cách tính chỗ thả khi kéo. |
| listIdstring | Mặc định: — | Khoá của danh sách trong value của SortableGroup. |
| labelstring | Mặc định: — | Tên danh sách trong thông báo khi mục chuyển danh sách. Mặc định aria-label / aria-labelledby. |
| disabledboolean | Mặc định: false | Không kéo mục trong danh sách và không thả mục khác vào. |
| asChildboolean | Mặc định: false | Gắn vào phần tử con (List, ul, tbody) thay vì render div. |
| SortableGroup | Mặc định: — | Thứ tự của mọi danh sách, theo listId. |
| SortableGroup | Mặc định: — | Như onValueChange của Sortable, cho cả nhóm. |
| SortableGroup | Mặc định: — | Như của Sortable; from.list / to.list cho biết mục ở danh sách nào. |
| SortableItem | Mặc định: — | Id của mục, có trong value của danh sách. |
| SortableItem | Mặc định: — | Tên mục trong thông báo và nhãn tay nắm. Mặc định là chữ trong mục. |
| SortableItem | Mặc định: false | Không nhấc được; mục vẫn bị đẩy chỗ khi mục khác đi qua. |
| SortableItem | Mặc định: false | Cả mục là tay nắm khi kéo bằng chuột / cảm ứng. |
| SortableItem | Mặc định: false | Alt + phím mũi tên trên mục di chuyển ngay, không cần nhấc lên. |
| SortableItem | Mặc định: false | Gắn vào phần tử con (ListItem, li, tr, Card) thay vì render div. |
| SortableHandle | Mặc định: false | Dùng phần tử con làm tay nắm thay cho nút icon mặc định. |
| arrayMove | Mặc định: — | Mảng mới với phần tử ở from chuyển sang to. |
Messages
Chữ có sẵn của component: nhãn, aria-label, thông báo cho trình đọc màn hình.
Mặc định là tiếng Anh. Đổi qua prop messages của YugenProvider, theo namespace bên dưới; messagesVi chứa bản tiếng Việt. Xem Ngôn ngữ giao diện.
messages.sortable
| Khoá · Kiểu | Mặc định (tiếng Anh) | messagesVi |
|---|---|---|
| handlestring Nhãn tay nắm khi mục không có | Mặc định (tiếng Anh)"Reorder" | messagesVi"Sắp xếp lại" |
| handleItemstring Nhãn tay nắm của mục có | Mặc định (tiếng Anh)"Reorder {item}" | messagesVi"Sắp xếp lại {item}" |
| instructionsstring Hướng dẫn dùng bàn phím, là mô tả (aria-describedby) của tay nắm. | Mặc định (tiếng Anh)"Press Space or Enter to pick up the item, arrow keys to move it, Space or Enter to drop it, Escape to cancel." | messagesVi"Nhấn Space hoặc Enter để nhấc mục lên, dùng phím mũi tên để di chuyển, Space hoặc Enter để thả, Esc để huỷ." |
| liftedstring | Mặc định (tiếng Anh)"Picked up {item}, position {position} of {total}." | messagesVi"Đã nhấc {item}, vị trí {position} trên {total}." |
| movedstring | Mặc định (tiếng Anh)"{item}: position {position} of {total}." | messagesVi"{item}: vị trí {position} trên {total}." |
| movedTostring Mục vừa sang danh sách khác (SortableGroup). | Mặc định (tiếng Anh)"{item}: moved to {list}, position {position} of {total}." | messagesVi"{item}: sang {list}, vị trí {position} trên {total}." |
| droppedstring | Mặc định (tiếng Anh)"Dropped {item} at position {position} of {total}." | messagesVi"Đã thả {item} ở vị trí {position} trên {total}." |
| droppedInstring | Mặc định (tiếng Anh)"Dropped {item} in {list}, position {position} of {total}." | messagesVi"Đã thả {item} vào {list}, vị trí {position} trên {total}." |
| canceledstring | Mặc định (tiếng Anh)"Canceled. {item} is back at position {position} of {total}." | messagesVi"Đã huỷ. {item} về lại vị trí {position} trên {total}." |