AniUI

Kbd

Display keyboard input keys. Useful for iPad keyboard hints and help screens.

CtrlShiftEnterEsc
Web preview — components render natively on iOS & Android
import { Kbd, KbdGroup } from "@/components/ui/kbd";

export function MyScreen() {
  return (
    <KbdGroup>
      <Kbd>Cmd</Kbd>
      <Kbd>C</Kbd>
    </KbdGroup>
  );
}

Installation#

npx @aniui/cli add kbd

Usage#

app/index.tsx
import { Kbd, KbdGroup } from "@/components/ui/kbd";

export function MyScreen() {
  return (
    <KbdGroup>
      <Kbd>Cmd</Kbd>
      <Kbd>C</Kbd>
    </KbdGroup>
  );
}

KbdGroup#

Cmd+C
Cmd+Shift+P
Web preview — components render natively on iOS & Android
import { Kbd, KbdGroup } from "@/components/ui/kbd";

export function MyScreen() {
  return (
    <KbdGroup separator="+">
      <Kbd>Ctrl</Kbd>
      <Kbd>Shift</Kbd>
      <Kbd>P</Kbd>
    </KbdGroup>
  );
}

Sizes#

smmdlg
Web preview — components render natively on iOS & Android
import { Kbd } from "@/components/ui/kbd";

export function MyScreen() {
  return (
    <>
      <Kbd size="sm">Esc</Kbd>
      <Kbd size="md">Tab</Kbd>
      <Kbd size="lg">Enter</Kbd>
    </>
  );
}

Components#

Kbd provides two components:

ComponentDescription
Kbd

A single keyboard key indicator with size variants.

KbdGroup

Groups multiple Kbd elements with a separator character between them.

Props#

Kbd#

PropTypeDefault
size
"sm" | "md" | "lg"
"md"
className
string
-
textClassName
string
-
children
string
required

Also accepts all View props from React Native.

KbdGroup#

PropTypeDefault
separator
string
"+"
className
string
-
children
React.ReactNode
required

Also accepts all View props from React Native.

Accessibility#

  • Uses monospaced font for consistent key display.
  • Pair with descriptive text so screen readers convey the shortcut meaning, not just the key names.
  • Consider using accessibilityLabel on the KbdGroup to describe the full shortcut (e.g. "Copy shortcut: Command plus C").

Source#

components/ui/kbd.tsx
import React from "react";
import { View, Text } from "react-native";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

const kbdVariants = cva(
  "items-center justify-center rounded-md border border-border bg-muted",
  {
    variants: {
      size: {
        sm: "min-h-5 px-1",
        md: "min-h-6 px-1.5",
        lg: "min-h-7 px-2",
      },
    },
    defaultVariants: { size: "md" },
  }
);

const kbdTextVariants = cva("font-mono text-muted-foreground", {
  variants: {
    size: {
      sm: "text-[10px]",
      md: "text-xs",
      lg: "text-sm",
    },
  },
  defaultVariants: { size: "md" },
});

export interface KbdProps
  extends React.ComponentPropsWithoutRef<typeof View>,
    VariantProps<typeof kbdVariants> {
  className?: string;
  textClassName?: string;
  children: string;
}

export function Kbd({ size, className, textClassName, children, ...props }: KbdProps) {
  return (
    <View className={cn(kbdVariants({ size }), className)} {...props}>
      <Text className={cn(kbdTextVariants({ size }), textClassName)}>{children}</Text>
    </View>
  );
}

export interface KbdGroupProps extends React.ComponentPropsWithoutRef<typeof View> {
  className?: string;
  separator?: string;
  children: React.ReactNode;
}

export function KbdGroup({ className, separator = "+", children, ...props }: KbdGroupProps) {
  const items = React.Children.toArray(children);

  return (
    <View className={cn("flex-row items-center gap-1", className)} {...props}>
      {items.map((child, i) => (
        <React.Fragment key={i}>
          {child}
          {i < items.length - 1 && (
            <Text className="text-xs text-muted-foreground">{separator}</Text>
          )}
        </React.Fragment>
      ))}
    </View>
  );
}