Icon Button
Square button for a single icon. Its accessible name is required by the type, so it can't ship unlabeled.
- required label (types)
- cva
- builds on Button
label is required by the type, so an unlabeled icon button doesn't compile.
Install
npx shadcn@latest add https://tcosta.dev/r/icon-button.jsonOr copy the files below into components/icon-button/. They use the shadcn/ui theme tokens and cn from @/lib/utils, and need class-variance-authority.
Source
icon-button.tsx
import type { ReactElement } from 'react';
import { cn } from '@/lib/utils';
import { Button, type ButtonProps } from '../button';
import { iconButtonVariants } from './icon-button-variants';
type IconButtonProps = Omit<ButtonProps, 'children' | 'aria-label'> & {
/** Accessible name. Required: an icon alone says nothing to a screen reader. */
label: string;
children: ReactElement;
};
export function IconButton({ label, size, className, ...props }: IconButtonProps) {
return (
<Button
aria-label={label}
size={size}
className={cn(iconButtonVariants({ size }), className)}
{...props}
/>
);
}
icon-button-variants.ts
import { cva } from 'class-variance-authority';
export const iconButtonVariants = cva('px-0', {
variants: {
size: {
sm: 'size-8',
md: 'size-9',
lg: 'size-10',
},
},
defaultVariants: {
size: 'md',
},
});
index.ts
export { IconButton } from './icon-button';
export { iconButtonVariants } from './icon-button-variants';