Skip to content

Commit

Permalink
refactor(accordion): ♻️ accordion state actions
Browse files Browse the repository at this point in the history
  • Loading branch information
navin-moorthy committed Sep 3, 2020
1 parent 39c7c57 commit 414991d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 72 deletions.
4 changes: 1 addition & 3 deletions src/accordion/AccordionItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ export const useAccordionItem = createHook<
compose: unstable_useId,
keys: ACCORDION_KEYS,

useProps(options, { ref: htmlRef, ...htmlProps }) {
const { id, registerItem } = options;

useProps({ id, registerItem }, { ref: htmlRef, ...htmlProps }) {
const ref = React.useRef<HTMLElement>(null);

React.useLayoutEffect(() => {
Expand Down
114 changes: 45 additions & 69 deletions src/accordion/AccordionState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,40 @@ export function useAccordionState(

const idState = unstable_useIdState(sealed);

const { buttons } = state;
const total = buttons.length;
const buttonIds = buttons.map(({ id }) => id);

const next = React.useCallback(
(id: string) => {
const currentIndex = buttonIds.indexOf(id);
const nextIndex = (currentIndex + 1) % total;

if (!loop && nextIndex === 0) return;
moveFocus(nextIndex, buttons);
},
[buttonIds, buttons, loop, total],
);

const prev = React.useCallback(
(id: string) => {
const currentIndex = buttonIds.indexOf(id);
const prevIndex = (currentIndex - 1 + total) % total;

if (!loop && prevIndex === total - 1) return;
moveFocus(prevIndex, buttons);
},
[buttonIds, buttons, loop, total],
);

const first = React.useCallback(() => {
moveFocus(0, buttons);
}, [buttons]);

const last = React.useCallback(() => {
moveFocus(total - 1, buttons);
}, [buttons, total]);

React.useEffect(() => {
if (defaultActiveId) {
dispatch({ type: "addActiveItem", id: defaultActiveId });
Expand All @@ -102,18 +136,10 @@ export function useAccordionState(
registerItem: React.useCallback(item => {
dispatch({ type: "registerItem", item });
}, []),
next: React.useCallback(id => {
dispatch({ type: "next", id });
}, []),
prev: React.useCallback(id => {
dispatch({ type: "prev", id });
}, []),
first: React.useCallback(() => {
dispatch({ type: "first" });
}, []),
last: React.useCallback(() => {
dispatch({ type: "last" });
}, []),
next,
prev,
first,
last,
};
}

Expand All @@ -122,20 +148,13 @@ export type AccordionReducerAction =
| { type: "registerButton"; button: Button }
| { type: "registerPanel"; panel: Panel }
| { type: "addActiveItem"; id: string }
| { type: "removeActiveItem"; id: string }
| { type: "next"; id: string }
| { type: "prev"; id: string }
| { type: "first" }
| { type: "last" };
| { type: "removeActiveItem"; id: string };

function reducer(
state: AccordionState,
action: AccordionReducerAction,
): AccordionState {
const { items, activeItems, buttons, allowMultiple, loop } = state;

const total = buttons.length;
const buttonIds = buttons.map(({ id }) => id);
const { items, activeItems, buttons, allowMultiple } = state;

switch (action.type) {
case "addActiveItem": {
Expand Down Expand Up @@ -190,54 +209,6 @@ function reducer(
return { ...state, items: [...items, item] };
}

case "next": {
const { id } = action;

const currentIndex = buttonIds.indexOf(id);
const nextIndex = (currentIndex + 1) % total;

if (!loop && nextIndex === 0) {
return { ...state };
}

const nextItem = buttons[nextIndex];
nextItem.ref?.current?.focus();

return { ...state };
}

case "prev": {
const { id } = action;

const currentIndex = buttonIds.indexOf(id);
const prevIndex = (currentIndex - 1 + total) % total;

if (!loop && prevIndex === total - 1) {
return { ...state };
}

const prevItem = buttons[prevIndex];
prevItem.ref?.current?.focus();

return { ...state };
}

case "first": {
const firstItem = buttons[0];
firstItem.ref?.current?.focus();

return { ...state };
}

case "last": {
const total = buttons.length;

const lastItem = buttons[total - 1];
lastItem.ref?.current?.focus();

return { ...state };
}

default:
throw new Error();
}
Expand All @@ -254,3 +225,8 @@ function getNextItem(type: string, currentItem: Button | Panel, items: Item[]) {

return { nextItem, nextItems };
}

function moveFocus(index: number, buttons: Button[]) {
const item = buttons[index];
item.ref?.current?.focus();
}

0 comments on commit 414991d

Please sign in to comment.