Skip to content

Generically type ButtonProps #290

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

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8c03960
made hook use generic type to allow for any HTML element, updated tes…
caryaharper Nov 16, 2021
7ba49c9
formatting
caryaharper Nov 16, 2021
f2a5670
updated docs to reflect changes
caryaharper Nov 16, 2021
177db00
made docs and readme more specific
caryaharper Nov 17, 2021
c4ea103
reverted yarn.lock
caryaharper Nov 17, 2021
9c215c3
attempting to revert again
caryaharper Nov 17, 2021
4030010
fixed useDropdownMenu not being passed a type
caryaharper Nov 17, 2021
b270f0a
made useDropDownMenu have a default type as well as fixed issues comi…
caryaharper Nov 18, 2021
beeaca5
changed jsx example to use a div as in the above js example
caryaharper Dec 13, 2021
7bb0dd1
removed the example hook being passed a generic type
caryaharper Dec 13, 2021
89df38b
reverted line five due to generic type now being optional
caryaharper Dec 13, 2021
5e6147f
made doc more concise
caryaharper Dec 13, 2021
a193d30
reverted line 14 due to HTMLButtonElement now being the default type
caryaharper Dec 13, 2021
a3ce0a8
replaced the word class with the word type
caryaharper Jan 17, 2022
7261009
replaced all instances of T being used as a type parameter
caryaharper Jan 17, 2022
9752b50
Update website/docs/design/type-parameters.md
caryaharper Jan 17, 2022
b21ca90
Update website/docs/design/type-parameters.md
caryaharper Jan 17, 2022
a939103
changed “the menu” to “a”
caryaharper Jan 17, 2022
08c6d54
Merge branch 'create-type-options-for-button-ref' of github.com:carya…
caryaharper Jan 17, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import useDropdownMenu from 'react-accessible-dropdown-menu-hook';
Call the Hook, telling it how many items your menu will have:

```tsx
const { buttonProps, itemProps, isOpen } = useDropdownMenu(numberOfItems);
const { buttonProps, itemProps, isOpen } = useDropdownMenu<T>(numberOfItems);
```

Spread the `buttonProps` onto a button:
Expand Down
5 changes: 4 additions & 1 deletion src/use-dropdown-menu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ interface Props {

const TestComponent: React.FC<Props> = ({ options }) => {
const [itemCount, setItemCount] = useState(4);
const { buttonProps, itemProps, isOpen, setIsOpen, moveFocus } = useDropdownMenu(itemCount, options);
const { buttonProps, itemProps, isOpen, setIsOpen, moveFocus } = useDropdownMenu<HTMLButtonElement>(
itemCount,
options
);

const clickHandlers: (() => void)[] = [(): void => console.log('Item one clicked'), (): void => setIsOpen(false)];

Expand Down
19 changes: 11 additions & 8 deletions src/use-dropdown-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@
import React, { useState, useRef, createRef, useEffect, useMemo } from 'react';

// Create interface for button properties
interface ButtonProps
interface ButtonProps<T extends HTMLElement>
extends Pick<
React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>,
React.DetailedHTMLProps<React.ButtonHTMLAttributes<T>, T>,
'onKeyDown' | 'onClick' | 'tabIndex' | 'role' | 'aria-haspopup' | 'aria-expanded'
> {
ref: React.RefObject<HTMLButtonElement>;
ref: React.RefObject<T>;
}

// A custom Hook that abstracts away the listeners/controls for dropdown menus
export interface DropdownMenuOptions {
disableFocusFirstItemOnClick?: boolean;
}

interface DropdownMenuResponse {
readonly buttonProps: ButtonProps;
interface DropdownMenuResponse<T extends HTMLElement> {
readonly buttonProps: ButtonProps<T>;
readonly itemProps: {
onKeyDown: (e: React.KeyboardEvent<HTMLAnchorElement>) => void;
tabIndex: number;
Expand All @@ -28,15 +28,18 @@ interface DropdownMenuResponse {
readonly moveFocus: (itemIndex: number) => void;
}

export default function useDropdownMenu(itemCount: number, options?: DropdownMenuOptions): DropdownMenuResponse {
export default function useDropdownMenu<T extends HTMLElement>(
itemCount: number,
options?: DropdownMenuOptions
): DropdownMenuResponse<T> {
// Use state
const [isOpen, setIsOpen] = useState<boolean>(false);
const currentFocusIndex = useRef<number | null>(null);
const firstRun = useRef(true);
const clickedOpen = useRef(false);

// Create refs
const buttonRef = useRef<HTMLButtonElement>(null);
const buttonRef = useRef<T>(null);
const itemRefs = useMemo<React.RefObject<HTMLAnchorElement>[]>(
() => Array.from({ length: itemCount }, () => createRef<HTMLAnchorElement>()),
[itemCount]
Expand Down Expand Up @@ -216,7 +219,7 @@ export default function useDropdownMenu(itemCount: number, options?: DropdownMen
};

// Define spreadable props for button and items
const buttonProps: ButtonProps = {
const buttonProps: ButtonProps<T> = {
onKeyDown: buttonListener,
onClick: buttonListener,
tabIndex: 0,
Expand Down
2 changes: 1 addition & 1 deletion test-projects/browser/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import useDropdownMenu from 'react-accessible-dropdown-menu-hook';
// Functional component
const App: React.FC = () => {
// Use the Hook
const { buttonProps, itemProps, isOpen } = useDropdownMenu(3);
const { buttonProps, itemProps, isOpen } = useDropdownMenu<HTMLButtonElement>(3);

// Return JSX
return (
Expand Down
8 changes: 5 additions & 3 deletions website/docs/getting-started/using.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@
title: Using
---

To use the Hook, first call it, telling it how many items your menu will have:
To use the Hook, first call it, telling it how many items your menu will have along with a valid HTMLElement subtype:

```jsx
const { buttonProps, itemProps, isOpen } = useDropdownMenu(numberOfItems);
const { buttonProps, itemProps, isOpen } = useDropdownMenu<HTMLSubtypeElement>(numberOfItems);
```

Take the `buttonProps` object and spread it onto a button:
Take the `buttonProps` object and spread it onto the corresponding HTML element to your subtype:

```jsx
<button {...buttonProps}>Example</button>

<div {...buttonProps}>Example</div>
```

Create the menu with the `role='menu'` property and spread `itemProps[x]` onto each item:
Expand Down
Loading