useDescendants
useDescendantsは、子要素を管理するためのカスタムフックです。
Item 0
Item 1
Item 2
Item 3
Item 4
const { useDescendants, useDescendant, DescendantsContext } =
createDescendants()
const ref = useRef<HTMLDivElement>(null)
const descendants = useDescendants()
const onFocus = useCallback(
(ev: FocusEvent<HTMLDivElement>) => {
if (ev.target !== ref.current) return
const descendant = descendants.enabledFirstValue()
if (descendant) {
descendant.node.focus()
if (ref.current) ref.current.tabIndex = -1
}
},
[descendants],
)
const onBlur = useCallback((ev: FocusEvent<HTMLDivElement>) => {
if (contains(ref.current, ev.relatedTarget)) return
if (ref.current) ref.current.tabIndex = 0
}, [])
const Item: FC<{ index: number }> = ({ index }) => {
const { descendants, register } = useDescendant()
const onKeyDown = useCallback(
(ev: KeyboardEvent<HTMLButtonElement>) => {
runKeyAction(ev, {
ArrowDown: () => {
const descendant = descendants.enabledNextValue(index)
if (descendant) descendant.node.focus()
},
ArrowUp: () => {
const descendant = descendants.enabledPrevValue(index)
if (descendant) descendant.node.focus()
},
Home: () => {
const descendant = descendants.enabledFirstValue()
if (descendant) descendant.node.focus()
},
End: () => {
const descendant = descendants.enabledLastValue()
if (descendant) descendant.node.focus()
},
})
},
[descendants],
)
return (
<Center
ref={register}
tabIndex={-1}
onKeyDown={onKeyDown}
bg="bg.contrast"
color="fg.contrast"
p="md"
>
Item {index}
</Center>
)
}
return (
<DescendantsContext value={descendants}>
<VStack
ref={ref}
tabIndex={0}
focusVisibleRing="none"
onFocus={onFocus}
onBlur={onBlur}
>
{Array.from({ length: 5 }).map((_, index) => (
<Item key={index} index={index} />
))}
</VStack>
</DescendantsContext>
)
こちらのコードを使用する場合は、
"use client"をファイルの上部に追加する必要があります。使い方
import { createDescendants } from "@yamada-ui/react"
import { createDescendants } from "@/components/ui"
import { createDescendants } from "@workspaces/ui"
const {
DescendantsContext,
useDescendant,
useDescendantRegister,
useDescendants,
useDescendantsContext,
} = createDescendants()
const descendants = useDescendants()
const { descendants, register } = useDescendant()
無効にする
無効にする場合は、useDescendantのdisabledをtrueに設定します。
Item 0
Item 1
Item 2
Item 3
Item 4
const { useDescendants, useDescendant, DescendantsContext } =
createDescendants()
const ref = useRef<HTMLDivElement>(null)
const descendants = useDescendants()
const onFocus = useCallback(
(ev: FocusEvent<HTMLDivElement>) => {
if (ev.target !== ref.current) return
const descendant = descendants.enabledFirstValue()
if (descendant) {
descendant.node.focus()
if (ref.current) ref.current.tabIndex = -1
}
},
[descendants],
)
const onBlur = useCallback((ev: FocusEvent<HTMLDivElement>) => {
if (contains(ref.current, ev.relatedTarget)) return
if (ref.current) ref.current.tabIndex = 0
}, [])
const Item: FC<{ index: number; disabled?: boolean }> = ({
index,
disabled,
}) => {
const { descendants, register } = useDescendant({ disabled })
const onKeyDown = useCallback(
(ev: KeyboardEvent<HTMLButtonElement>) => {
runKeyAction(ev, {
ArrowDown: () => {
const descendant = descendants.enabledNextValue(index)
if (descendant) descendant.node.focus()
},
ArrowUp: () => {
const descendant = descendants.enabledPrevValue(index)
if (descendant) descendant.node.focus()
},
Home: () => {
const descendant = descendants.enabledFirstValue()
if (descendant) descendant.node.focus()
},
End: () => {
const descendant = descendants.enabledLastValue()
if (descendant) descendant.node.focus()
},
})
},
[descendants],
)
return (
<Center
ref={register}
tabIndex={-1}
onKeyDown={onKeyDown}
bg="bg.contrast"
color="fg.contrast"
p="md"
data-disabled={dataAttr(disabled)}
_disabled={{ layerStyle: "disabled" }}
>
Item {index}
</Center>
)
}
return (
<DescendantsContext value={descendants}>
<VStack
ref={ref}
tabIndex={0}
focusVisibleRing="none"
onFocus={onFocus}
onBlur={onBlur}
>
{Array.from({ length: 5 }).map((_, index) => (
<Item key={index} index={index} disabled={index % 3 === 0} />
))}
</VStack>
</DescendantsContext>
)
こちらのコードを使用する場合は、
"use client"をファイルの上部に追加する必要があります。使用されているコンポーネント・フック
Accordion
Accordionは、情報を展開または折りたたんで表示するリストのコンポーネントです。
Calendar
Calendarは、日付を表示または選択するカレンダーのコンポーネントです。
Menu
Menuは、一般的なドロップダウンメニューを表示するコンポーネントです。
PinInput
PinInputは、ピンコードやOTP(ワンタイムパスワード)の入力を取得するために使用されるコンポーネントです。
SegmentedControl
SegmentedControlは、ユーザーが複数の選択肢の中から1つを選択するために使用されるコンポーネントです。
Steps
Stepsは、複数のステップのプロセスの進行状況を表示するコンポーネントです。
Tabs
Tabsは、異なる表示領域を切り替えるコンポーネントです。