Skip to content

Commit

Permalink
feat: replace unstable_getPreferredChildOnFocusReceive prop with getP…
Browse files Browse the repository at this point in the history
…referredChildOnFocus

BREAKING CHANGE: `unstable_getPreferredChildOnFocusReceive` prop is removed from SunbeamProvider and
Focusable components, `getPreferredChildOnFocus` is introduced instead
  • Loading branch information
vovacodes committed Sep 6, 2020
1 parent dc16272 commit d5a1138
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 18 deletions.
24 changes: 24 additions & 0 deletions packages/react-sunbeam/src/focus/components/Focusable.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,28 @@ describe("Focusable", () => {
act(() => focusManager.moveRight())
expect(focusManager.getFocusPath()).toEqual(["right"])
})

describe("getPreferredChildOnFocus", () => {
it("selects which child to focus on when SunbeamProvider becomes focused", () => {
const focusManager = new FocusManager()

render(
<SunbeamProvider focusManager={focusManager}>
<Focusable
getPreferredChildOnFocus={({ focusableChildren }) => {
return focusableChildren.get("middleChild")
}}
focusKey="leftParent"
>
<Focusable focusKey="topChild">Left Top</Focusable>
<Focusable focusKey="middleChild">Left Middle</Focusable>
<Focusable focusKey="bottomChild">Left Bottom</Focusable>
</Focusable>
<Focusable focusKey="right">Right</Focusable>
</SunbeamProvider>
)

expect(focusManager.getFocusPath()).toEqual(["leftParent", "middleChild"])
})
})
})
16 changes: 8 additions & 8 deletions packages/react-sunbeam/src/focus/components/Focusable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ interface Props {
lock?: Direction | Direction[]
style?: React.CSSProperties
className?: string
unstable_getPreferredChildOnFocusReceive?: (args: {
onKeyPress?: KeyPressListener
onFocus?: (event: FocusEvent) => void
onBlur?: (event: FocusEvent) => void
getPreferredChildOnFocus?: (args: {
focusableChildren: FocusableNodesMap
focusOrigin?: FocusableTreeNode
direction?: Direction
}) => FocusableTreeNode | undefined
onKeyPress?: KeyPressListener
onFocus?: (event: FocusEvent) => void
onBlur?: (event: FocusEvent) => void
}

/* eslint-disable @typescript-eslint/camelcase */
Expand All @@ -34,7 +34,7 @@ export function Focusable({
focusKey,
focusable = true,
lock = [],
unstable_getPreferredChildOnFocusReceive,
getPreferredChildOnFocus,
onKeyPress,
onFocus,
onBlur,
Expand All @@ -59,15 +59,15 @@ export function Focusable({
const getChildren = useCallback(() => focusableChildrenRef.current, [])
const getPreferredChild = useCallback(
(focusOrigin?: FocusableTreeNode, direction?: Direction) => {
return unstable_getPreferredChildOnFocusReceive
? unstable_getPreferredChildOnFocusReceive({
return getPreferredChildOnFocus
? getPreferredChildOnFocus({
focusableChildren: focusableChildrenRef.current,
focusOrigin,
direction,
})
: getPreferredNode({ nodes: focusableChildrenRef.current, focusOrigin, direction })
},
[unstable_getPreferredChildOnFocusReceive]
[getPreferredChildOnFocus]
)
const {
addFocusableToMap,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,26 @@ describe("<SunbeamProvider>", () => {
spy.mockRestore()
})

describe("getPreferredChildOnFocus", () => {
it("selects which child to focus on when SunbeamProvider becomes focused", () => {
const focusManager = new FocusManager()

render(
<SunbeamProvider
focusManager={focusManager}
getPreferredChildOnFocus={({ focusableChildren }) => {
return focusableChildren.get("right")
}}
>
<Focusable>left</Focusable>
<Focusable focusKey="right">right</Focusable>
</SunbeamProvider>
)

expect(focusManager.getFocusPath()).toEqual(["right"])
})
})

describe("keyPressManager", () => {
it("should allow to provide a custom instance of KeyPressManager", () => {
function enterKeyHandler(event: KeyboardEvent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,9 @@ type Props = {
focusManager: FocusManager
keyPressManager?: KeyPressManager
children: React.ReactNode
// unstable_passFocusBetweenChildren?: (args: {
// focusableChildren: FocusableNodesMap
// focusOrigin: FocusableTreeNode
// direction: Direction
// }) => FocusableTreeNode | "KEEP_FOCUS_UNCHANGED" | "CANDIDATE_NOT_FOUND"
onFocusUpdate?: (event: { focusPath: FocusPath }) => void
onKeyPress?: KeyPressListener
unstable_getPreferredChildOnFocusReceive?: (args: {
getPreferredChildOnFocus?: (args: {
focusableChildren: FocusableNodesMap
focusOrigin?: FocusableTreeNode
direction?: Direction
Expand All @@ -41,7 +36,7 @@ export function SunbeamProvider({
children,
onFocusUpdate,
onKeyPress,
unstable_getPreferredChildOnFocusReceive,
getPreferredChildOnFocus,
}: Props) {
const focusPath = useFocusPath(focusManager, onFocusUpdate)
const wrapperRef = useRef<HTMLDivElement | null>(null)
Expand All @@ -61,15 +56,15 @@ export function SunbeamProvider({
const getChildren = useCallback(() => focusableChildrenRef.current, [])
const getPreferredChild = useCallback(
(focusOrigin?: FocusableTreeNode, direction?: Direction) => {
return unstable_getPreferredChildOnFocusReceive
? unstable_getPreferredChildOnFocusReceive({
return getPreferredChildOnFocus
? getPreferredChildOnFocus({
focusableChildren: focusableChildrenRef.current,
focusOrigin,
direction,
})
: getPreferredNode({ nodes: focusableChildrenRef.current, focusOrigin, direction })
},
[unstable_getPreferredChildOnFocusReceive]
[getPreferredChildOnFocus]
)
const path = useMemo(() => [], [])
const focusableTreeRoot = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useState } from "react"
import nanoid from "nanoid"

export function useGeneratedFocusKey(): string {
// Using useState here to get a reliably-memoized value
const [focusKey] = useState(() => `focusable:${nanoid()}`)
return focusKey
}

0 comments on commit d5a1138

Please sign in to comment.