|
1 | | -import React, { useState } from 'react'; |
| 1 | +import React from 'react'; |
2 | 2 | import { |
3 | 3 | Button as MuiButton, |
4 | 4 | ButtonProps as MuiButtonProps, |
5 | | - Stack, |
6 | 5 | IconButton as MuiIconButton, |
7 | 6 | useTheme, |
8 | 7 | } from '@mui/material'; |
9 | 8 | import { globalFocusShadow, colors, elevations } from '../../common'; |
10 | 9 | import { isDarkColor } from 'utils'; |
11 | | -import { IconProp } from '@fortawesome/fontawesome-svg-core'; |
| 10 | +import { IconParams, IconProp } from '@fortawesome/fontawesome-svg-core'; |
12 | 11 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; |
13 | | -import { styled } from '@mui/system'; |
14 | 12 | import { RouterLinkRenderer } from '../Navigation/Link'; |
15 | 13 |
|
16 | 14 | const buttonStyles = { |
@@ -213,7 +211,7 @@ const TertiaryButton = ({ |
213 | 211 | }: ButtonProps) => { |
214 | 212 | const height: string = sizeMap[size]; |
215 | 213 | const customColor = colors.notification[color as keyof typeof colors.notification]?.shade ?? color; |
216 | | - const activeColor = color !== 'default' ? `color-mix(in srgb, ${customColor}, white 90%)` : colors.surface.blue[10]; |
| 214 | + const activeColor = color == 'default' ? colors.surface.blue[10] : `color-mix(in srgb, ${customColor}, white 90%)`; |
217 | 215 |
|
218 | 216 | return ( |
219 | 217 | <MuiButton |
@@ -284,58 +282,77 @@ type IconButtonProps = { |
284 | 282 | icon: IconProp; |
285 | 283 | onClick?: () => void; |
286 | 284 | title?: string; |
287 | | - sx?: React.CSSProperties; // Add sx prop |
| 285 | + sx?: React.CSSProperties; |
| 286 | + size?: string; |
| 287 | + iconSize?: string; |
| 288 | + color?: string; |
288 | 289 | backgroundColor?: string; |
| 290 | + hoverBackgroundColor?: string; |
| 291 | + disabled?: boolean; |
| 292 | + iconProps?: IconParams; |
289 | 293 | }; |
290 | 294 |
|
291 | | -const StyledIconButton = styled(MuiIconButton)(() => ({ |
292 | | - color: '#494949', |
293 | | - borderRadius: '50%', // Make it round |
294 | | - width: '40px', // Set width to maintain circle shape |
295 | | - height: '40px', // Set height to maintain circle shape |
296 | | -})); |
297 | | - |
298 | 295 | /** |
299 | 296 | * IconButton component that renders a circular button with an icon. |
300 | | - * It supports focus styles and hover effects. |
| 297 | + * Provides full customization of size, colors, and positioning while maintaining |
| 298 | + * consistent focus and hover behavior. |
| 299 | + * |
301 | 300 | * @param {IconButtonProps} props - The properties for the icon button. |
302 | 301 | * @param {IconProp} props.icon - The icon to display in the button. |
303 | 302 | * @param {() => void} props.onClick - The function to call when the button is clicked. |
304 | 303 | * @param {string} props.title - The title for the button, used for accessibility. |
305 | 304 | * @param {React.CSSProperties} props.sx - Additional styles to apply to the button. |
306 | | - * @param {string} props.backgroundColor - Optional background color for the button. |
| 305 | + * @param {string} props.size - Button diameter (e.g., '40px', '3rem'). Default is '40px'. |
| 306 | + * @param {string} props.iconSize - Icon font size (e.g., '20px', '1.5rem'). Default is '20px'. |
| 307 | + * @param {string} props.color - Icon color. Default is '#494949'. |
| 308 | + * @param {string} props.backgroundColor - Button background color. Default is colors.focus.regular.inner. |
| 309 | + * @param {string} props.hoverBackgroundColor - Background color on hover/focus. Default is '#F2F2F2'. |
| 310 | + * @param {boolean} props.disabled - Whether the button is disabled. |
| 311 | + * @param {IconParams} props.iconProps - Additional properties for the FontAwesomeIcon. |
307 | 312 | * @returns A styled icon button component. |
308 | 313 | */ |
309 | | -export const IconButton: React.FC<IconButtonProps> = ({ icon, onClick, title, sx, backgroundColor }) => { |
310 | | - const [focused, setFocused] = useState(false); |
311 | | - |
| 314 | +export const IconButton: React.FC<IconButtonProps> = ({ |
| 315 | + icon, |
| 316 | + onClick, |
| 317 | + title, |
| 318 | + sx, |
| 319 | + size = '40px', |
| 320 | + iconSize = '20px', |
| 321 | + color = '#494949', |
| 322 | + backgroundColor = colors.focus.regular.inner, |
| 323 | + hoverBackgroundColor = '#F2F2F2', |
| 324 | + disabled = false, |
| 325 | + iconProps, |
| 326 | +}) => { |
312 | 327 | return ( |
313 | | - <Stack |
314 | | - direction="row" |
315 | | - justifyContent="center" |
316 | | - alignItems="center" |
| 328 | + <MuiIconButton |
| 329 | + onClick={onClick} |
| 330 | + title={title} |
| 331 | + aria-label={title} |
| 332 | + disabled={disabled} |
317 | 333 | sx={{ |
318 | | - backgroundColor: backgroundColor ?? `${colors.focus.regular.inner}`, |
319 | | - cursor: 'pointer', |
| 334 | + width: size, |
| 335 | + height: size, |
320 | 336 | borderRadius: '50%', |
321 | | - boxShadow: focused ? `0 0 0 2px white, 0 0 0 4px ${colors.focus.regular.outer}` : 'none', |
| 337 | + backgroundColor: backgroundColor, |
| 338 | + color: color, |
322 | 339 | '&:hover': { |
323 | | - backgroundColor: '#F2F2F2', |
| 340 | + backgroundColor: hoverBackgroundColor, |
324 | 341 | }, |
325 | 342 | '&:focus-visible': { |
326 | | - backgroundColor: '#F2F2F2', |
327 | | - outline: 'white 2px dashed', // Remove default outline |
| 343 | + backgroundColor: hoverBackgroundColor, |
| 344 | + outline: `2px solid ${colors.focus.regular.outer}`, |
328 | 345 | outlineOffset: '2px', |
| 346 | + boxShadow: globalFocusShadow, |
| 347 | + }, |
| 348 | + '&:disabled': { |
| 349 | + backgroundColor: colors.surface.gray[40], |
| 350 | + color: colors.type.regular.disabled, |
329 | 351 | }, |
330 | 352 | ...sx, |
331 | 353 | }} |
332 | | - onFocus={() => setFocused(true)} |
333 | | - onBlur={() => setFocused(false)} |
334 | | - tabIndex={focused ? 0 : -1} // Set tabIndex to -1 when not focused |
335 | 354 | > |
336 | | - <StyledIconButton onClick={onClick} title={title} aria-label={title}> |
337 | | - <FontAwesomeIcon icon={icon} style={{ fontSize: '20px', color: '#494949' }} /> |
338 | | - </StyledIconButton> |
339 | | - </Stack> |
| 355 | + <FontAwesomeIcon icon={icon} style={{ fontSize: iconSize }} {...iconProps} /> |
| 356 | + </MuiIconButton> |
340 | 357 | ); |
341 | 358 | }; |
0 commit comments