All files / components/IconButton IconButton.tsx

83.33% Statements 5/6
96% Branches 24/25
66.66% Functions 2/3
100% Lines 5/5

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86                                                              153x                         1892x           1892x                       1892x             15x                                
import { MaterialSymbol } from 'material-symbols'
import Link from 'next/link'
import { Color } from '../../types/color'
import { Icon } from '../Icon/Icon'
 
type IconButtonProps = {
	/** Specify the icon. */
	icon: MaterialSymbol
	/** Optional property to set the color of the icon button. */
	color?: Color
	/** Optional property to set the background color of the icon button. */
	backgroundColor?: Color
	/** Optional specify an href for your Button to become an `<a>` element. */
	to?: string
	/** Optional callback function to handle click events on the icon button. */
	onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void
	/** Optional class name for custom styling of the icon button. */
	className?: string
	/** Optional class name for custom styling of the icon. */
	iconClassName?: string
	/** Specify whether the Button should be disabled, or not. */
	disabled?: boolean
	/** Optional property to dim the opacity of the icon button when it is disabled. */
	dimOpacityWhenDisabled?: boolean
	/** Optional property to set the datacy attribute for testing purposes. */
	datacy?: string
}
 
/**
 * Button only as Icon. Can be used as a link or with an onClick function.
 */
export const IconButton: React.FC<IconButtonProps> = ({
	icon,
	to,
	onClick,
	datacy,
	iconClassName = '',
	disabled = false,
	className = '',
	color = 'gray',
	backgroundColor,
	dimOpacityWhenDisabled = true,
}) => {
	const innerIcon = (
		<Icon
			icon={icon}
			datacy={`${datacy}-inner-icon`}
			className={`${disabled && dimOpacityWhenDisabled ? 'text-opacity-50 ' : ''}text-${color}-600 ${iconClassName}`}
		/>
	)
	const classes = `text-center ${
		disabled
			? `cursor-default ${
					backgroundColor ? `bg-${backgroundColor}-500 ${dimOpacityWhenDisabled ? `bg-opacity-30` : ``}` : ''
			  }`
			: `cursor-pointer ${
					backgroundColor
						? `bg-${backgroundColor}-500 hover:bg-${backgroundColor}-600 focus:bg-${backgroundColor}-700`
						: `hover:bg-${color}-500 hover:bg-opacity-10 focus:bg-opacity-20`
			  }`
	} rounded-full w-10 h-10 flex items-center justify-center ${className}`
 
	return (
		<>
			{/* Button as link */}
			{to && (
				<Link
					datacy={datacy}
					href={disabled ? '' : to}
					onClick={disabled ? (event) => event.preventDefault() : () => ''}
					className={classes}
				>
					{innerIcon}
				</Link>
			)}
 
			{/* Button with onclick */}
			{!to && (
				<button datacy={datacy} type="button" onClick={onClick} disabled={disabled} className={classes}>
					{innerIcon}
				</button>
			)}
		</>
	)
}