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 kbdUsage#
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
KbdA single keyboard key indicator with size variants.
KbdGroupGroups multiple Kbd elements with a separator character between them.
Props#
Kbd#
PropTypeDefault
size"sm" | "md" | "lg""md"classNamestring-textClassNamestring-childrenstringrequiredAlso accepts all View props from React Native.
KbdGroup#
PropTypeDefault
separatorstring"+"classNamestring-childrenReact.ReactNoderequiredAlso 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
accessibilityLabelon theKbdGroupto 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>
);
}