{"id":43221738,"url":"https://github.com/rortan134/use-selectify","last_synced_at":"2026-02-01T09:04:27.589Z","repository":{"id":65836384,"uuid":"597882401","full_name":"rortan134/use-selectify","owner":"rortan134","description":"💫 The ultimate drag-to-select solution for React","archived":false,"fork":false,"pushed_at":"2024-01-10T11:45:57.000Z","size":2394,"stargazers_count":3,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-26T12:41:27.886Z","etag":null,"topics":["accessibility","drag","hooks","interactive","mouse","react","selection","state-management","touch","ui-ux"],"latest_commit_sha":null,"homepage":"https://useselectify.js.org/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rortan134.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"github":["rortan134"],"custom":["https://www.buymeacoffee.com/rortan"]}},"created_at":"2023-02-05T22:38:43.000Z","updated_at":"2025-03-20T11:23:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"7f21a944-a5f2-4c3a-b361-5feda872f41c","html_url":"https://github.com/rortan134/use-selectify","commit_stats":{"total_commits":94,"total_committers":2,"mean_commits":47.0,"dds":"0.22340425531914898","last_synced_commit":"97ca17e117777805ae6e3a89c4baca97fd6328e8"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/rortan134/use-selectify","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rortan134%2Fuse-selectify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rortan134%2Fuse-selectify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rortan134%2Fuse-selectify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rortan134%2Fuse-selectify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rortan134","download_url":"https://codeload.github.com/rortan134/use-selectify/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rortan134%2Fuse-selectify/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28974252,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T08:16:14.655Z","status":"ssl_error","status_checked_at":"2026-02-01T08:06:51.373Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accessibility","drag","hooks","interactive","mouse","react","selection","state-management","touch","ui-ux"],"created_at":"2026-02-01T09:03:39.696Z","updated_at":"2026-02-01T09:04:27.581Z","avatar_url":"https://github.com/rortan134.png","language":"TypeScript","readme":"![use-selectify cover image](https://raw.githubusercontent.com/rortan134/use-selectify/master/.github/assets/use-selectify-banner.png)\n\n\u003ch1 align=\"center\"\u003euse-selectify\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003eThe ultimate drag-to-select solution for React. Designed to be fast; Built to be accessible.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/rortan134/use-selectify/blob/main/CONTRIBUTING.md\"\u003e\n    \u003cimg alt=\"PRs Welcome\" src=\"https://img.shields.io/badge/PRs-welcome-blue.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/use-selectify\"\u003e\n    \u003cimg alt=\"Types Included\" src=\"https://badgen.net/npm/types/use-selectify\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://bundlephobia.com/result?p=use-selectify\"\u003e\n    \u003cimg alt=\"Minizipped Size\" src=\"https://img.shields.io/bundlephobia/minzip/use-selectify\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/rortan134/use-selectify/blob/main/LICENSE\"\u003e\n    \u003cimg alt=\"MIT License\" src=\"https://badgen.net/github/license/rortan134/use-selectify\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/use-selectify\"\u003e\n    \u003cimg alt=\"Package Version\" src=\"https://img.shields.io/npm/v/use-selectify.svg?colorB=green\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/use-selectify\"\u003e\n    \u003cimg alt=\"NPM Downloads\" src=\"https://badgen.net/npm/dm/use-selectify\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://twitter.com/meetgilberto\"\u003e\n    \u003cimg alt=\"Follow @meetgilberto on Twitter\" src=\"https://img.shields.io/twitter/follow/meetgilberto.svg?style=social\u0026label=Follow\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cbr /\u003e\n\n## Introduction\n\nDrag interactions are one of the most challenging aspects of the web. Having complete control over the exact behavior of those interactions is essential, yet most available libraries out there still feel like they are not up to the task.\n\nRecognizing this need, I created `use-selectify` aiming to address those issues and provide a powerful starting point for drag interactions while still remaining a robust approach to complex selections of elements in a React application, all done through a hook.\n\nDemo \u0026 Examples: [useselectify.js.org](https://useselectify.js.org/)\n\n## Key Features\n\n✅ Automatic window scrolling\n\n✅ Flexible and [lightweight](https://bundlephobia.com/package/use-selectify) (4kB gzipped)\n\n✅ Accessible by default\n\n✅ Fine-grained control with multiple approaches\n\n✅ Simple \u0026 extensible styling\n\n✅ Works on every device\n\n✅ SSR \u0026 Lazy loading support\n\n✅ Zero dependencies\n\n## Installation\n\nInstall use-selectify from your terminal via npm or yarn.\n\n```sh\nnpm install use-selectify\n```\n\nor\n\n```sh\nyarn add use-selectify\n```\n\n### Import it\n\nImport the `useSelectify` hook. Both default and named imports are supported.\n\n```tsx\nimport { useSelectify } from \"use-selectify\";\n```\n\n## Anatomy\n\n```tsx\nexport default () =\u003e {\n    const {\n        SelectBoxOutlet,\n        selectedElements,\n        isDragging,\n        hasSelected,\n        selectionBox,\n        getSelectableElements,\n        selectAll,\n        clearSelection,\n        mutateSelections,\n        cancelSelectionBox,\n        options,\n    } = useSelectify(ref, options);\n};\n```\n\n-   `ref`: A RefObject containing the parent element that will trigger the selection interactions.\n-   `options` (optional): An [object](#options) containing options that can be used to configure the selection behavior.\n\n\u003cdetails\u003e\n\u003csummary\u003eSee every prop\u003c/summary\u003e\n\n### API Reference\n\n-   `SelectBoxOutlet`: The returned selection box component.\n-   `selectedElements`: A list of every element that has been selected through the hook.\n-   `isDragging`: Whether the user's pointer is dragging or not.\n-   `hasSelected`: Whether there's any element selected. Equal to `selectedElements.length \u003e 0`.\n-   `selectionBox`: A Rect indicating the internal values of the SelectBoxOutlet coordinates.\n-   `getSelectableElements`: An utility function that returns every selectable element relative to the specified [selection criteria](#options)\n-   `selectAll`: An utility function that will select every selectableElement.\n-   `clearSelection`: An utility function that will unselect every selected element.\n-   `mutateSelections`: An utility function, similar to a [setState](https://beta.reactjs.org/reference/react/useState), that allows you to modify internal selections.\n-   `cancelSelectionBox`: An utility function that will instantly cancel the drag-selection without selecting any element.\n-   `options`: A copy of the hook options.\n\u003c/details\u003e\n\n## Getting Started\n\nBegin by defining the element that will contain the drag interaction, then render the selection box outlet in it.\n\n```tsx\nimport * as React from \"react\";\nimport { useSelectify } from \"use-selectify\";\n\nexport default function App() {\n    const selectionContainerRef = React.useRef(null);\n    const { SelectBoxOutlet } = useSelectify(selectionContainerRef, {\n        onSelect: (element) =\u003e {\n            console.log(`selected ${element}`);\n            element.innerHTML = \"Foo bar\";\n        },\n    });\n\n    return (\n        \u003cdiv ref={selectionContainerRef} style={{ position: \"relative\" }}\u003e\n            \u003cdiv\u003eI can be selected!\u003c/div\u003e\n            \u003cSelectBoxOutlet /\u003e\n        \u003c/div\u003e\n    );\n}\n```\n\nBy default every element inside the `selectionContainerRef` is a selectable element. To modify this behavior simply specify a selection criteria using [CSS Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors):\n\n```tsx\nimport * as React from \"react\";\nimport { useSelectify } from \"use-selectify\";\n\nexport default function App() {\n    const selectionContainerRef = React.useRef(null);\n    const { SelectBoxOutlet } = useSelectify(selectionContainerRef, {\n        selectCriteria: \".select-this\", // will only select elements with the \"select-this\" class\n        onSelect: (element) =\u003e {\n            console.log(`selected ${element}`);\n            element.innerHTML = \"Foo bar\";\n        },\n    });\n\n    return (\n        \u003cdiv ref={selectionContainerRef} style={{ position: \"relative\" }}\u003e\n            \u003cdiv className=\"select-this\"\u003eHello World\u003c/div\u003e\n            \u003cdiv\u003eI won't be selected\u003c/div\u003e\n            \u003cSelectBoxOutlet /\u003e\n        \u003c/div\u003e\n    );\n}\n```\n\n### Exclusion Zone\n\nIn order to prevent selection starting from anywhere inside your container, you can also specify an exclusion zone. It supports both `Element`s (such as React refs) or [CSS Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors).\n\n```tsx\nconst selectionContainerRef = React.useRef(null);\nconst exclusionZoneRef = React.useRef(null);\n\nconst { SelectBoxOutlet } = useSelectify(selectionContainerRef, {\n    exclusionZone: exclusionZoneRef.current,\n});\n\nreturn (\n    \u003cdiv ref={selectionContainerRef} style={{ position: \"relative\" }}\u003e\n        \u003cdiv\u003e\n            \u003cp\u003eSelection can start from here\u003c/p\u003e\n        \u003c/div\u003e\n        \u003cdiv ref={exclusionZoneRef}\u003e\n            \u003cp\u003eBut not from here\u003c/p\u003e\n        \u003c/div\u003e\n        \u003cSelectBoxOutlet /\u003e\n    \u003c/div\u003e\n);\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eReadability Tip\u003c/summary\u003e\n\nYou can specify the callback function outside of the hook for further customization:\n\n```tsx\nconst handleSelection = (el: Element) =\u003e {\n    console.log(`selected ${element}`);\n    element.innerHTML = \"Bar\";\n    // ...\n};\n\nconst handleUnselection = (el: Element) =\u003e {\n    console.log(`unselected ${element}`);\n    element.innerHTML = \"Foo\";\n    // ...\n};\n\nconst { SelectBoxOutlet } = useSelectify(selectionContainerRef, {\n    selectCriteria: \".select-this\",\n    onSelect: handleSelection,\n    onUnselect: handleUnselection,\n});\n```\n\n\u003c/details\u003e\n\n### Styling\n\nBy default the selection box comes with some styling. You can override it with the `className` prop and specify how you want your selection box to look through the Outlet Component. For Styled Components or Stitches see [how to render your own selection box](#other-use-cases).\n\n\u003e **Note**\n\u003e\n\u003e The \u003cSelectBoxOutlet /\u003e component can be placed anywhere in your page, just make sure that for the absolute positioning to work properly, the parent element of the outlet should always be relative: `position: relative;`\n\n```tsx\nreturn (\n    \u003cdiv ref={selectionContainerRef} style={{ position: \"relative\" }}\u003e\n        // ...\n        \u003cSelectBoxOutlet className=\"foo bar\" /\u003e\n    \u003c/div\u003e\n);\n```\n\n## Advanced usage\n\n### Mapping reactive components without a callback\n\nWe can check if an element is selected by passing the `selectedElements` down and simply looping accordingly:\n\n```tsx\nimport * as React from \"react\";\nimport { useSelectify } from \"use-selectify\";\n\nconst data = [\n    {\n        id: 1,\n        name: \"foo\",\n        role: \"admin\",\n    },\n    {\n        id: 2,\n        name: \"bar\",\n        role: \"editor\",\n    },\n    {\n        id: 3,\n        name: \"foo-bar\",\n        role: \"author\",\n    },\n    {\n        id: 4,\n        name: \"bar-foo\",\n        role: \"author\",\n    },\n];\n\nconst ListItem = ({\n    selectedElements,\n    children,\n}: {\n    selectedElements: Element[];\n    children: React.ReactNode;\n}) =\u003e {\n    const itemRef = React.useRef(null);\n    const isSelected = selectedElements.includes(itemRef.current);\n\n    return (\n        \u003cli ref={itemRef} className={isSelected ? \"list-item-active\" : \"\"}\u003e\n            {children}\n        \u003c/li\u003e\n    );\n};\n\nexport const List = () =\u003e {\n    const containerRef = React.useRef(null);\n    const { SelectBoxOutlet, selectedElements } = useSelectify(selectionContainerRef);\n\n    return (\n        \u003cdiv ref={containerRef} className=\"container\"\u003e\n            \u003cul className=\"list\"\u003e\n                {data.map((user) =\u003e (\n                    \u003cListItem key={user.id} selectedElements={selectedElements}\u003e\n                        {user.name}\n                    \u003c/ListItem\u003e\n                ))}\n            \u003c/ul\u003e\n            \u003cSelectBoxOutlet /\u003e\n        \u003c/div\u003e\n    );\n};\n```\n\n### Declaratively handling selections\n\nIf you wish to couple the internal hook selections state with your own, you can leverage the `mutateSelections` function. Similarly to a [setState](https://beta.reactjs.org/reference/react/useState), you can modify which elements are internally selected in a declarative way.\n\n```tsx\n// ...\n\nconst selectionContainerRef = React.useRef(null);\nconst { SelectBoxOutlet, selectedElements, mutateSelections } = useSelectify(selectionContainerRef);\n\nconst selectElement = (elementToSelect) =\u003e {\n    mutateSelections((prevSelections) =\u003e [...prevSelections, elementToSelect]);\n};\n\nconst unselectElement = (elementToUnselect) =\u003e {\n    mutateSelections((prevSelections) =\u003e\n        prevSelections.filter((element) =\u003e element !== elementToSelect)\n    );\n};\n```\n\n\u003e Tip:\n\u003e If you think the user won't initially be using drag-selection, consider enabling [lazy-load](https://beta.reactjs.org/reference/react/lazy):\n\n```tsx\nconst { SelectBoxOutlet } = useSelectify(selectionContainerRef, {\n    lazyLoad: true,\n});\n```\n\n### Other use-cases\n\n\u003cdetails\u003e\n\u003csummary\u003e\nDisabling mobile selection\n\u003c/summary\u003e\n\nUse something like [react-device-detect](https://www.npmjs.com/package/react-device-detect) to distinguish if the user-agent is a mobile device or not, then simply disable the hook accordingly.\n\n```tsx\nimport * as React from \"react\";\nimport { isMobile } from \"react-device-detect\";\nimport { useSelectify } from \"use-selectify\";\n\nexport default function App() {\n    const selectionContainerRef = React.useRef(null);\n    const { SelectBoxOutlet } = useSelectify(selectionContainerRef, {\n        disabled: isMobile,\n    });\n\n    return (\n        \u003cdiv ref={selectionContainerRef} style={{ position: \"relative\" }}\u003e\n            \u003cdiv\u003eHello World\u003c/div\u003e\n            \u003cSelectBoxOutlet /\u003e\n        \u003c/div\u003e\n    );\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\nChecking whether to start selecting or not\n\u003c/summary\u003e\nIf you wanted to check whether an user will start a pinch gesture before starting the selection box, you could simply delay the selection: If two fingers are used in the gesture after that time has passed the selection box will be automatically canceled.\n\n```tsx\nconst { SelectBoxOutlet } = useSelectify(selectionContainerRef, {\n    onDragStart: (event) =\u003e {\n        setTimeout(() =\u003e {}, 250); // wait for 250ms for pinch gestures before starting drag-selection\n    },\n});\n```\n\nThe same can be applied to other use cases, if you need to cancel the selection simply return `event.preventDefault()`.\n\n```tsx\nconst { SelectBoxOutlet } = useSelectify(selectionContainerRef, {\n    onDragStart: (event) =\u003e {\n        let shouldCancel = false;\n        setTimeout(() =\u003e {}, 200); // wait 200ms before checking if should cancel selection\n        /**\n         * check if should cancel\n         * ...\n         **/\n        shouldCancel = true;\n        if (shouldCancel) {\n            return event.preventDefault(); // cancel selection\n        }\n    },\n});\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\nDrawing your own selection box\n\u003c/summary\u003e\n\nStart by creating your box component and pass in the provided `selectionBoxRef` from the hook, then apply the `selectionBox` to the styles for the pointer coordinates.\n\n\u003e **Note**\n\u003e\n\u003e You will not have any of the accessibility features included by default.\n\n```tsx\nexport function App() {\n    const selectionContainerRef = React.useRef(null);\n    const { selectionBoxRef, selectionBox } = useSelectify(selectionContainerRef);\n\n    const MyCustomSelectionBoxOutlet = () =\u003e {\n        // Your custom logic...\n        return (\n            \u003cdiv\n                ref={selectionBoxRef}\n                style={{\n                    ...selectionBox,\n                    boxSizing: \"border-box\",\n                    position: \"absolute\",\n                }}\n            /\u003e\n        );\n    };\n\n    return (\n        \u003cdiv ref={selectionContainerRef} style={{ position: \"relative\" }}\u003e\n            \u003cdiv\u003eI can be selected!\u003c/div\u003e\n            \u003cMyCustomSelectionBoxOutlet /\u003e\n        \u003c/div\u003e\n    );\n}\n```\n\n\u003e Make sure you add `position: absolute` and `border-box` for floating-ui calculations.\n\n\u003c/details\u003e\n\n## Options\n\n| Prop                    | Type                                                     | Default          | Description                                                                                                                                             |\n| ----------------------- | -------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| maxSelections           | number \\| false                                          | -                | Maximum number of elements that can be selected. Will stop selecting after reaching that number and keep already selected elements.                     |\n| autoScroll              | boolean                                                  | true             | Automatically try to scroll the window when the pointer approaches the viewport edge while dragging.                                                    |\n| autoScrollEdgeDistance  | number                                                   | 100              | Distance in px from the viewport's edges from which the box will try scrolling the window when the pointer approaches the viewport edge while dragging. |\n| autoScrollStep          | number                                                   | 30               | Auto scroll speed.                                                                                                                                      |\n| disableUnselection      | boolean                                                  | false            | Will keep every item selected after selection. Can be cleared with clearSelection().                                                                    |\n| selectCriteria          | string \\| undefined                                      | \"\\*\"             | The specific CSS Selector criteria to match for selecting elements.                                                                                     |\n| onlySelectOnFullOverlap | boolean                                                  | false            | Will only select the element if the full rect intersects.                                                                                               |\n| onlySelectOnDragEnd     | boolean                                                  | false            | Will only select elements after user has stopped dragging or cursor has left the screen while dragging.                                                 |\n| selectionDelay          | number                                                   | 0                | Specify a delay in miliseconds before elements are selected to prevent accidental selection.                                                            |\n| label                   | string                                                   | \"Drag Selection\" | Accessible label for screen readers.                                                                                                                    |\n| selectionTolerance      | number                                                   | 0                | Distance in px from which elements can be selected even if the selection box is not visually intersecting.                                              |\n| activateOnMetaKey       | boolean                                                  | false            | Only enables the selection box if the user was pressing a meta key while initiating the drag. Included Meta keys are: Shift, Ctrl/Cmd and Alt.          |\n| activateOnKey           | string[]                                                 | []               | Only enables the selection box if the user was pressing a specified key while initiating the drag. Ex: [\"Tab\", \"Control\", \"Alt\"]                        |\n| theme                   | \"default\" \\| \"outline\"                                   | \"default\"        | Included theme options for the selection box appearance.                                                                                                |\n| hideOnScroll            | boolean                                                  | false            | Whether to hide the selection box when the window starts scrolling. Incompatible with autoScroll.                                                       |\n| exclusionZone           | Element \\| Element[] \\| string                           | -                | Won't enable the selection box if the user tries initiating the drag from one of the specified elements.                                                |\n| scrollContext           | HTMLElement \\| Window                                    | `window`         | Sets the scrollable element for the automatic window scrolling to react.                                                                                |\n| exclusionZone           | Element \\| Element[]                                     | -                | Won't enable the selection box if the user tries initiating the drag from one of the specified elements. Supports CSS Selectors.                        |\n| lazyLoad                | boolean                                                  | false            | Defers loading the selection box.                                                                                                                       |\n| disabled                | boolean                                                  | false            | Disables the selection box interaction \u0026 dragging.                                                                                                      |\n| forceMount              | boolean                                                  | false            | Forces the mounting of the selection box on initialization.                                                                                             |\n| onSelect                | (element: Element) =\u003e void                               | -                | Callback function when an element is selected.                                                                                                          |\n| onUnselect              | (unselectedElement: Element) =\u003e void                     | -                | Callback function when an element is unselected.                                                                                                        |\n| onDragStart             | (e: PointerEvent) =\u003e void                                | -                | Callback function when drag starts.                                                                                                                     |\n| onDragMove              | (e: PointerEvent, selectedElements: Element[]) =\u003e void   | -                | Callback function when dragging.                                                                                                                        |\n| onDragEnd               | (e?: PointerEvent, selectedElements?: Element[]) =\u003e void | -                | Callback function when drag ends.                                                                                                                       |\n| onEscapeKeyDown         | (e: KeyboardEvent) =\u003e void                               | -                | Callback function when escape key is pressed.                                                                                                           |\n\n## Accessibility (optional)\n\nBy default use-selectify already follows [WAI-ARIA](https://www.w3.org/WAI/WCAG22/Understanding/dragging-movements.html) best practices. Though to ensure that drag interactions are as accessible as possible, we must consider the following aspects:\n\n1. Add ARIA attributes: To indicate to assistive technology users that the elements are available for selection, we can use an aria-label to each selectable element. This label should be descriptive and informative, indicating either the purpose of selecting that element or how to select it for screen readers. Additionally, we can use the aria-selected attribute to indicate when elements are selected:\n\n    ```tsx\n    const { SelectBoxOutlet } = useSelectify(selectionContainerRef, {\n        onSelect: (el) =\u003e {\n            el.setAttribute(\"aria-selected\", \"true\");\n        },\n    });\n    // ...\n    ```\n\n2. Make elements focusable: To ensure that keyboard-only users can access and select the elements, all functionality should be also operable through the [keyboard alone](http://www.w3.org/TR/WCAG20/#keyboard-operation). Ensure that every selectable element is also focusable. This means either adding a tabindex attribute to the element and setting it to 0 or using an element that is focusable by default.\n\n3. Arrow navigation: Make sure every selectable element can also be selected using the arrow keys.\n\n## FAQ\n\n### How performant is it?\n\nStays decently performant up until a few thousands elements. Open to improvements.\n\n### Can I use this library with an older version of React?\n\nNo, currently the only supported version is ^18.0.0.\n\n### How do I it make mobile friendly\n\nAlthough we support touch interactions, it should be considered the conflict of panning/scrolling and selecting when presented with a single gesture. To effectively support mobile devices in an accessible way you would need to provide a way to switch between panning and drag-selecting like seen in our [figma example](/www/src/app/figma/page.tsx) and even then, such interactions are not recommended in small viewports.\n\n### Does this support React Native?\n\nNo, not currently.\n\n---\n\nLooking forward to seeing how this project and the community evolve and provide feedback. Whether it's a feature request, bug report, or a project to showcase, feel free to get involved!\n\n## Development\n\n1. Clone the repo into a public GitHub repository (or fork \u003chttps://github.com/rortan134/use-selectify/fork\u003e).\n\n    ```sh\n    git clone https://github.com/rortan134/use-selectify.git\n    ```\n\n2. Go to the project folder\n\n    ```sh\n    cd use-selectify\n    ```\n\n3. Install packages with yarn\n\n    ```sh\n    yarn\n    ```\n\n4. Start the Storybook preview for development and modify as you please.\n\n    ```sh\n    yarn storybook\n    ```\n\n## License\n\nDistributed under the MIT License. See LICENSE for more information.\n","funding_links":["https://github.com/sponsors/rortan134","https://www.buymeacoffee.com/rortan"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frortan134%2Fuse-selectify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frortan134%2Fuse-selectify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frortan134%2Fuse-selectify/lists"}