Skip to content

Commit

Permalink
fix(disclosure): 🐛 add collapse for showmore & refactor presence
Browse files Browse the repository at this point in the history
  • Loading branch information
navin-moorthy committed Nov 23, 2021
1 parent d07e019 commit e224e80
Show file tree
Hide file tree
Showing 24 changed files with 631 additions and 433 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"@react-aria/utils": "^3.9.0",
"date-fns": "^2.26.0",
"framer-motion": "^5.3.1",
"raf": "^3.4.1",
"react-remove-scroll": "^2.4.3",
"react-spring": "^9.3.1",
"reakit-system": "^0.15.2",
Expand Down Expand Up @@ -137,6 +138,7 @@
"@types/jest-in-case": "1.0.5",
"@types/mockdate": "3.0.0",
"@types/node": "16.11.9",
"@types/raf": "3.4.0",
"@types/react": "17.0.36",
"@types/react-dom": "17.0.11",
"@types/react-transition-group": "4.4.4",
Expand Down
78 changes: 39 additions & 39 deletions src/dialog/helpers/useDisclosureRef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,50 +10,50 @@ export function useDisclosureRef(
const ref = React.useRef<HTMLElement | null>(null);

React.useEffect(() => {
if (options.visible && !options.present) {
// We get the last focused element before the dialog opens, so we can move
// focus back to it when the dialog closes.
const onFocus = (event: FocusEvent) => {
const target = event.target as HTMLElement;

if ("focus" in target) {
ref.current = target;

if (options.disclosureRef) {
options.disclosureRef.current = target;
}
if (options.visible || options.animating) return undefined;

// We get the last focused element before the dialog opens, so we can move
// focus back to it when the dialog closes.
const onFocus = (event: FocusEvent) => {
const target = event.target as HTMLElement;

if ("focus" in target) {
ref.current = target;

if (options.disclosureRef) {
options.disclosureRef.current = target;
}
};
}
};

const document = getDocument(dialogRef.current);
document.addEventListener("focusin", onFocus);
const document = getDocument(dialogRef.current);
document.addEventListener("focusin", onFocus);

return () => document.removeEventListener("focusin", onFocus);
}
}, [options.visible, options.present, options.disclosureRef, dialogRef]);
return () => document.removeEventListener("focusin", onFocus);
}, [options.visible, options.animating, options.disclosureRef, dialogRef]);

React.useEffect(() => {
if (!options.visible && options.present) {
// Safari and Firefox on MacOS don't focus on buttons on mouse down.
// Instead, they focus on the closest focusable parent (ultimately, the
// body element). This works around that by preventing that behavior and
// forcing focus on the disclosure button. Otherwise, we wouldn't be able
// to close the dialog by clicking again on the disclosure.
const onMouseDown = (event: MouseEvent) => {
const element = event.currentTarget as HTMLElement;

if (!isButton(element)) return;

event.preventDefault();
element.focus();
};

const disclosure = options.disclosureRef?.current || ref.current;
disclosure?.addEventListener("mousedown", onMouseDown);

return () => disclosure?.removeEventListener("mousedown", onMouseDown);
}
}, [options.visible, options.present, options.disclosureRef]);
if (!options.visible || options.animating) return undefined;

// Safari and Firefox on MacOS don't focus on buttons on mouse down.
// Instead, they focus on the closest focusable parent (ultimately, the
// body element). This works around that by preventing that behavior and
// forcing focus on the disclosure button. Otherwise, we wouldn't be able
// to close the dialog by clicking again on the disclosure.
const onMouseDown = (event: MouseEvent) => {
const element = event.currentTarget as HTMLElement;

if (!isButton(element)) return;

event.preventDefault();
element.focus();
};

const disclosure = options.disclosureRef?.current || ref.current;
disclosure?.addEventListener("mousedown", onMouseDown);

return () => disclosure?.removeEventListener("mousedown", onMouseDown);
}, [options.visible, options.animating, options.disclosureRef]);

return options.disclosureRef || ref;
}
5 changes: 3 additions & 2 deletions src/dialog/helpers/useFocusOnHide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ export function useFocusOnHide(

useUpdateEffect(() => {
if (!shouldFocus) return;
if (!options.present) return;
if (options.animating) return;
console.log("%canimating", "color: #ffa280", options.animating);

// Hide was triggered by a click/focus on a tabbable element outside
// the dialog or on another dialog. We won't change focus then.
Expand Down Expand Up @@ -69,5 +70,5 @@ export function useFocusOnHide(
"Can't return focus after closing dialog. Either render a disclosure component or provide a `unstable_finalFocusRef` prop.",
dialogRef.current,
);
}, [shouldFocus, options.present, dialogRef, disclosureRef]);
}, [shouldFocus, options.animating, dialogRef, disclosureRef]);
}
10 changes: 8 additions & 2 deletions src/dialog/helpers/useFocusOnShow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function useFocusOnShow(

if (!shouldFocus) return;
if (!dialog) return;
if (!options.present) return;
if (options.animating) return;

// If there're nested open dialogs, let them handle focus
if (nestedDialogs.some(child => child.current && !child.current.hidden)) {
Expand All @@ -52,5 +52,11 @@ export function useFocusOnShow(
);
}
}
}, [dialogRef, shouldFocus, options.present, nestedDialogs, initialFocusRef]);
}, [
dialogRef,
shouldFocus,
options.animating,
nestedDialogs,
initialFocusRef,
]);
}
7 changes: 1 addition & 6 deletions src/dialog/stories/DialogBasic.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,7 @@ export const DialogBasic: React.FC<DialogBasicProps> = props => {
<>
<DialogDisclosure {...dialog}>Open dialog</DialogDisclosure>
<DialogBackdrop {...dialog} className="backdrop" animationPresent={true}>
<Dialog
{...dialog}
aria-label="Welcome"
className="dialog"
transitionPresent={true}
>
<Dialog {...dialog} aria-label="Welcome" className="dialog">
Welcome to Reakit!
<div>
<label htmlFor="firstName">First Name</label>
Expand Down
Loading

1 comment on commit e224e80

@vercel
Copy link

@vercel vercel bot commented on e224e80 Nov 23, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.