EXEPERTAI LAB

Research alpha

Time Machine
EXEPERTAI LAB
GALLERY / COLLECTION
← Browse Astryx gallery
hooks·hook·@astryxdesign/core

useKeyboardHint

Shows an ephemeral "← → to navigate" hint anchored to the focused item the first time a roving-tabindex composite (Toolbar, TabList, SegmentedControl, etc.) receives keyboard focus. It teaches sighted keyboard users that arrow keys move within the group. The hint renders arrow keys with Kbd in the top layer (popover="manual") and is CSS-anchor-positioned to the focused element, so overflow containers never clip it. It auto-dismisses on the first arrow press, on timeout, or on blur, and does not re-show for that instance. Toolbar, TabList, and SegmentedControl wire this in automatically; reach for the hook directly only when building a custom roving-tabindex widget.

Open in Playground @astryxdesign/core/hooks

Signature

Call shape
useKeyboardHint(options: UseKeyboardHintOptions = {}): UseKeyboardHintReturn
Parameters
NameType and behavior
optionsUseKeyboardHintOptions · optional
Configuration object for the keyboard hint.
options.orientation'horizontal' | 'vertical' | 'both' · optional · default 'horizontal'
Which arrow-key axis the composite navigates, controlling which arrow icons the hint shows (← → for horizontal, ↑ ↓ for vertical, all four for both).
options.dismissAfterMsnumber · optional · default 3000
Milliseconds before the hint auto-dismisses after appearing.
options.isEnabledboolean · optional · default true
Whether the hint is enabled. Set to false to suppress it for a specific instance (e.g. a disabled or read-only widget).
Returns
NameType and behavior
hintElementReactNode
The popover hint element to render inside the composite container (as the last child). Portals to the top layer via popover="manual", renders arrow keys with Kbd, and manages its own visibility; render it unconditionally.
onFocus(e: React.FocusEvent) => void
Attach to the container onFocus. Shows the hint on the first keyboard-focus (:focus-visible) entry from outside the composite.
onBlur(e: React.FocusEvent) => void
Attach to the container onBlur. Hides the hint when focus leaves the composite entirely, and re-anchors when focus moves within.
onKeyDown(e: React.KeyboardEvent) => void
Attach to the container onKeyDown. Dismisses the hint on the first arrow press (the user has discovered the interaction). Never prevents default or stops propagation.

Showcases and examples

1 documented example

useKeyboardHint — Arrow-key Hint

Toolbar shows an ephemeral "← → to navigate" hint on first keyboard focus via useKeyboardHint, teaching sighted keyboard users that arrows move within the group.

Preview loads on approachPreview loads on approach
Exact source · use-keyboard-hint-hook-usage
// Copyright (c) Meta Platforms, Inc. and affiliates.

'use client';

import {Toolbar} from '@astryxdesign/core/Toolbar';
import {Button} from '@astryxdesign/core/Button';
import {Icon} from '@astryxdesign/core/Icon';
import {Card} from '@astryxdesign/core/Card';
import {Section} from '@astryxdesign/core/Section';
import {Text} from '@astryxdesign/core/Text';
import {VStack} from '@astryxdesign/core/Layout';
import {BoldIcon, ItalicIcon, UnderlineIcon} from '@heroicons/react/24/outline';

export default function UseKeyboardHintHookUsage() {
  return (
    <Card style={{width: 420}}>
      <Toolbar
        label="Text formatting"
        dividers={['bottom']}
        startContent={
          <>
            <Button
              label="Bold"
              variant="ghost"
              icon={<Icon icon={BoldIcon} />}
              isIconOnly
            />
            <Button
              label="Italic"
              variant="ghost"
              icon={<Icon icon={ItalicIcon} />}
              isIconOnly
            />
            <Button
              label="Underline"
              variant="ghost"
              icon={<Icon icon={UnderlineIcon} />}
              isIconOnly
            />
          </>
        }
      />
      <Section>
        <VStack gap={1}>
          <Text type="body" weight="bold">
            Keyboard-friendly by default
          </Text>
          <Text type="supporting" color="secondary">
            Tab into the toolbar with your keyboard and Toolbar shows an
            ephemeral "← → to navigate" hint — powered by useKeyboardHint — so
            sighted keyboard users learn that arrows move within the group.
          </Text>
        </VStack>
      </Section>
    </Card>
  );
}

Usage

Shows an ephemeral "← → to navigate" hint anchored to the focused item the first time a roving-tabindex composite (Toolbar, TabList, SegmentedControl, etc.) receives keyboard focus. It teaches sighted keyboard users that arrow keys move within the group. The hint renders arrow keys with Kbd in the top layer (popover="manual") and is CSS-anchor-positioned to the focused element, so overflow containers never clip it. It auto-dismisses on the first arrow press, on timeout, or on blur, and does not re-show for that instance. Toolbar, TabList, and SegmentedControl wire this in automatically; reach for the hook directly only when building a custom roving-tabindex widget.

  • Compose the returned onFocus/onKeyDown with your existing focus handlers rather than replacing them: call onKeyDown first (it only dismisses, never prevents), then your navigation handler.
  • Render hintElement as the last child of the composite container; it is position:fixed in the top layer and aria-hidden, so it never affects layout or the accessibility tree.
  • Match orientation to the arrow keys your widget actually responds to so the hint shows the correct icons.
  • Use for single controls or widgets without roving-tabindex navigation; the hint only makes sense where arrows move focus within a group.