Skip to content

Commit 0fa5660

Browse files
committed
feat: add support for icon button
1 parent 9375c5b commit 0fa5660

File tree

5 files changed

+109
-26
lines changed

5 files changed

+109
-26
lines changed

src/Shared/Components/Button/Button.component.tsx

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import { Progressing } from '@Common/Progressing'
44
import { Tooltip } from '@Common/Tooltip'
55
import { ComponentSizeType } from '@Shared/constants'
66
import { ButtonComponentType, ButtonProps, ButtonStyleType, ButtonVariantType } from './types'
7-
import { BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP, BUTTON_SIZE_TO_LOADER_SIZE_MAP } from './constants'
8-
import { getButtonDerivedClass } from './utils'
7+
import { getButtonDerivedClass, getButtonIconClassName, getButtonLoaderSize } from './utils'
98
import './button.scss'
109

1110
const ButtonElement = ({
@@ -27,9 +26,11 @@ const ButtonElement = ({
2726
| 'tooltipProps'
2827
| 'dataTestId'
2928
| 'isLoading'
29+
| 'ariaLabel'
3030
> & {
3131
className: string
3232
'data-testid': ButtonProps['dataTestId']
33+
'aria-label': ButtonProps['ariaLabel']
3334
}
3435
>) => {
3536
if (component === ButtonComponentType.link) {
@@ -126,24 +127,43 @@ const Button = ({
126127
isLoading = false,
127128
showTooltip = false,
128129
tooltipProps = {},
130+
icon = null,
131+
ariaLabel = null,
129132
...props
130133
}: ButtonProps) => {
131134
const isDisabled = disabled || isLoading
132-
const iconClass = `dc__no-shrink flex dc__fill-available-space ${BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP[size]}`
135+
const iconClass = `dc__no-shrink flex dc__fill-available-space ${getButtonIconClassName({
136+
size,
137+
icon,
138+
})}`
133139

134140
return (
135141
<Tooltip {...tooltipProps} alwaysShowTippyOnHover={showTooltip && !!tooltipProps?.content}>
136142
<div>
137143
<ButtonElement
138144
{...props}
139145
disabled={isDisabled}
140-
className={`br-4 flex cursor dc__mnw-100 dc__tab-focus dc__position-rel dc__capitalize ${getButtonDerivedClass({ size, variant, style, isLoading })} ${isDisabled ? 'dc__disabled' : ''}`}
146+
className={`br-4 flex cursor dc__tab-focus dc__position-rel dc__capitalize ${getButtonDerivedClass({ size, variant, style, isLoading, icon })} ${isDisabled ? 'dc__disabled' : ''}`}
141147
data-testid={dataTestId}
148+
aria-label={ariaLabel}
142149
>
143-
{startIcon && <span className={iconClass}>{startIcon}</span>}
144-
<span className="dc__mxw-150 dc__align-left dc__truncate">{text}</span>
145-
{endIcon && <span className={iconClass}>{endIcon}</span>}
146-
{isLoading && <Progressing size={BUTTON_SIZE_TO_LOADER_SIZE_MAP[size]} />}
150+
{icon ? (
151+
<span className={iconClass}>{icon}</span>
152+
) : (
153+
<>
154+
{startIcon && <span className={iconClass}>{startIcon}</span>}
155+
<span className="dc__mxw-150 dc__align-left dc__truncate">{text}</span>
156+
{endIcon && <span className={iconClass}>{endIcon}</span>}
157+
</>
158+
)}
159+
{isLoading && (
160+
<Progressing
161+
size={getButtonLoaderSize({
162+
size,
163+
icon,
164+
})}
165+
/>
166+
)}
147167
</ButtonElement>
148168
</div>
149169
</Tooltip>

src/Shared/Components/Button/button.scss

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
color: $text-color;
88
}
99

10-
// Only stroke icons are supposed to be used with button
11-
svg,
12-
svg * {
10+
svg *[stroke^="#"] {
1311
stroke: $text-color;
1412
}
1513

14+
svg *[fill^="#"] {
15+
fill: $text-color;
16+
}
17+
1618
// Custom state for loader
1719
// Added using css to ensure using the respective text-color
1820
.loader {

src/Shared/Components/Button/constants.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ export const BUTTON_SIZE_TO_CLASS_NAME_MAP: Record<ButtonProps['size'], string>
1010
[ComponentSizeType.xl]: 'px-15 py-9 fs-14 lh-20 fw-6 dc__gap-12',
1111
} as const
1212

13+
export const ICON_BUTTON_SIZE_TO_CLASS_NAME_MAP: Record<ButtonProps['size'], string> = {
14+
[ComponentSizeType.xs]: 'p-3',
15+
[ComponentSizeType.small]: 'p-5',
16+
[ComponentSizeType.medium]: 'p-7',
17+
[ComponentSizeType.large]: 'p-7',
18+
[ComponentSizeType.xl]: 'p-7',
19+
} as const
20+
1321
export const BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP: Record<ButtonProps['size'], string> = {
1422
[ComponentSizeType.xs]: 'icon-dim-12',
1523
[ComponentSizeType.small]: 'icon-dim-12',
@@ -18,10 +26,26 @@ export const BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP: Record<ButtonProps['size'], str
1826
[ComponentSizeType.xl]: 'icon-dim-20',
1927
} as const
2028

29+
export const ICON_BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP: Record<ButtonProps['size'], string> = {
30+
[ComponentSizeType.xs]: 'icon-dim-16',
31+
[ComponentSizeType.small]: 'icon-dim-16',
32+
[ComponentSizeType.medium]: 'icon-dim-16',
33+
[ComponentSizeType.large]: 'icon-dim-20',
34+
[ComponentSizeType.xl]: 'icon-dim-24',
35+
} as const
36+
2137
export const BUTTON_SIZE_TO_LOADER_SIZE_MAP: Record<ButtonProps['size'], ProgressingProps['size']> = {
2238
[ComponentSizeType.xs]: 12,
2339
[ComponentSizeType.small]: 12,
2440
[ComponentSizeType.medium]: 16,
2541
[ComponentSizeType.large]: 16,
2642
[ComponentSizeType.xl]: 20,
2743
} as const
44+
45+
export const ICON_BUTTON_SIZE_TO_LOADER_SIZE_MAP: Record<ButtonProps['size'], ProgressingProps['size']> = {
46+
[ComponentSizeType.xs]: 16,
47+
[ComponentSizeType.small]: 16,
48+
[ComponentSizeType.medium]: 16,
49+
[ComponentSizeType.large]: 20,
50+
[ComponentSizeType.xl]: 24,
51+
} as const

src/Shared/Components/Button/types.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,6 @@ export type ButtonProps = (
7070
* @default ButtonStyleType.default
7171
*/
7272
style?: ButtonStyleType
73-
/**
74-
* Text to be displayed in the button
75-
*/
76-
text: string
77-
/**
78-
* If provided, icon to be displayed at the start of the button
79-
*/
80-
startIcon?: ReactElement
81-
/**
82-
* If provided, icon to be displayed at the end of the button
83-
*/
84-
endIcon?: ReactElement
8573
/**
8674
* If true, the loading state is shown for the button with disabled
8775
*/
@@ -111,4 +99,29 @@ export type ButtonProps = (
11199
showTooltip?: never
112100
tooltipProps?: never
113101
}
102+
) &
103+
(
104+
| {
105+
icon?: never
106+
ariaLabel?: never
107+
/**
108+
* Text to be displayed in the button
109+
*/
110+
text: string
111+
/**
112+
* If provided, icon to be displayed at the start of the button
113+
*/
114+
startIcon?: ReactElement
115+
/**
116+
* If provided, icon to be displayed at the end of the button
117+
*/
118+
endIcon?: ReactElement
119+
}
120+
| {
121+
icon: ReactElement
122+
ariaLabel: string
123+
text?: never
124+
startIcon?: never
125+
endIcon?: never
126+
}
114127
)

src/Shared/Components/Button/utils.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,34 @@
1-
import { BUTTON_SIZE_TO_CLASS_NAME_MAP } from './constants'
1+
import {
2+
BUTTON_SIZE_TO_CLASS_NAME_MAP,
3+
BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP,
4+
BUTTON_SIZE_TO_LOADER_SIZE_MAP,
5+
ICON_BUTTON_SIZE_TO_CLASS_NAME_MAP,
6+
ICON_BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP,
7+
ICON_BUTTON_SIZE_TO_LOADER_SIZE_MAP,
8+
} from './constants'
29
import { ButtonProps } from './types'
310

11+
export const getButtonIconClassName = ({ size, icon }: Pick<ButtonProps, 'size' | 'icon'>) => {
12+
if (icon) {
13+
return ICON_BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP[size]
14+
}
15+
16+
return BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP[size]
17+
}
18+
19+
export const getButtonLoaderSize = ({ size, icon }: Pick<ButtonProps, 'size' | 'icon'>) => {
20+
if (icon) {
21+
return ICON_BUTTON_SIZE_TO_LOADER_SIZE_MAP[size]
22+
}
23+
24+
return BUTTON_SIZE_TO_LOADER_SIZE_MAP[size]
25+
}
26+
427
export const getButtonDerivedClass = ({
528
size,
629
variant,
730
style,
831
isLoading,
9-
}: Pick<ButtonProps, 'variant' | 'size' | 'style' | 'isLoading'>) =>
10-
`button button__${variant}--${style} ${BUTTON_SIZE_TO_CLASS_NAME_MAP[size]} ${isLoading ? 'button--loading' : ''}`
32+
icon,
33+
}: Pick<ButtonProps, 'variant' | 'size' | 'style' | 'isLoading' | 'icon'>) =>
34+
`button button__${variant}--${style} ${icon ? ICON_BUTTON_SIZE_TO_CLASS_NAME_MAP[size] : `${BUTTON_SIZE_TO_CLASS_NAME_MAP[size]} dc__mnw-100`} ${isLoading ? 'button--loading' : ''}`

0 commit comments

Comments
 (0)