Skip to content

Commit 9cf72e1

Browse files
committed
feat: add support for tippy and tooltip in form field label
1 parent 206db95 commit 9cf72e1

File tree

7 files changed

+123
-22
lines changed

7 files changed

+123
-22
lines changed

src/Common/Tooltip/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@
1616

1717
export { default as Tooltip } from './Tooltip'
1818
export { TOOLTIP_CONTENTS } from './constants'
19+
export type { TooltipProps } from './types'

src/Shared/Components/CustomInput/CustomInput.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ const CustomInput = ({
4444
type = 'text',
4545
autoFocus = false,
4646
endIconButtonConfig,
47+
labelTippyCustomizedConfig,
48+
labelTooltipConfig,
4749
...props
4850
}: CustomInputProps) => {
4951
const inputRef = useRef<HTMLInputElement>()
@@ -98,6 +100,8 @@ const CustomInput = ({
98100
fullWidth={fullWidth}
99101
ariaLabel={ariaLabel}
100102
borderRadiusConfig={borderRadiusConfig}
103+
labelTippyCustomizedConfig={labelTippyCustomizedConfig}
104+
labelTooltipConfig={labelTooltipConfig}
101105
>
102106
<>
103107
<input

src/Shared/Components/FormFieldWrapper/FormFieldLabel.tsx

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,80 @@
1-
import { FormFieldLabelProps } from './types'
1+
import { ReactComponent as ICHelpOutline } from '@Icons/ic-help-outline.svg'
2+
import { ReactComponent as ICHelp } from '@Icons/ic-help.svg'
3+
import { TippyCustomized } from '@Common/TippyCustomized'
4+
import { TippyTheme } from '@Common/Types'
5+
import { ConditionalWrap } from '@Common/Helper'
6+
import { ReactElement } from 'react'
7+
import { Tooltip, TooltipProps } from '@Common/Tooltip'
28
import { getFormLabelElementId } from './utils'
9+
import { FormFieldLabelProps } from './types'
310

4-
const FormFieldLabel = ({ label, inputId, required, layout }: FormFieldLabelProps) => {
11+
const FormFieldLabel = ({
12+
label,
13+
inputId,
14+
required,
15+
layout,
16+
labelTooltipConfig,
17+
labelTippyCustomizedConfig,
18+
}: FormFieldLabelProps) => {
519
if (!label) {
620
return null
721
}
822

923
const labelId = getFormLabelElementId(inputId)
1024
const isRowLayout = layout === 'row'
25+
const showTooltip = !!labelTooltipConfig?.content
1126

12-
return (
13-
<label
14-
className={`fs-13 lh-20 fw-4 dc__block mb-0 ${isRowLayout ? 'cn-9' : 'cn-7'}`}
15-
htmlFor={inputId}
16-
id={labelId}
17-
data-testid={labelId}
27+
const wrapWithTooltip = (children: ReactElement) => (
28+
<Tooltip
29+
{...({
30+
placement: 'bottom',
31+
alwaysShowTippyOnHover: true,
32+
...labelTooltipConfig,
33+
} as TooltipProps)}
1834
>
19-
{typeof label === 'string' ? (
20-
<span className={`flex left ${required ? 'dc__required-field' : ''}`}>
21-
<span className="dc__truncate">{label}</span>
22-
{required && <span>&nbsp;</span>}
23-
</span>
24-
) : (
25-
label
35+
{children}
36+
</Tooltip>
37+
)
38+
39+
return (
40+
<div className="flex left dc__gap-4">
41+
<div className={`flex left ${required ? 'dc__required-field' : ''}`}>
42+
<ConditionalWrap condition={showTooltip} wrap={wrapWithTooltip}>
43+
<label
44+
className={`fs-13 lh-20 fw-4 dc__block mb-0 cursor ${isRowLayout ? `cn-9 ${showTooltip ? 'dc__underline' : ''}` : 'cn-7'}`}
45+
htmlFor={inputId}
46+
id={labelId}
47+
data-testid={labelId}
48+
>
49+
{typeof label === 'string' ? (
50+
<span className="flex left">
51+
<span className="dc__truncate">{label}</span>
52+
</span>
53+
) : (
54+
label
55+
)}
56+
</label>
57+
</ConditionalWrap>
58+
{required && <span>&nbsp;</span>}
59+
</div>
60+
{!isRowLayout && labelTippyCustomizedConfig && (
61+
<TippyCustomized
62+
theme={TippyTheme.white}
63+
className="w-400 dc__align-left"
64+
placement="bottom-start"
65+
Icon={ICHelp}
66+
iconClass="fcv-5"
67+
showCloseButton
68+
trigger="click"
69+
interactive
70+
{...labelTippyCustomizedConfig}
71+
>
72+
<div className="flex cursor">
73+
<ICHelpOutline className="fcn-7 icon-dim-16 dc__no-shrink" />
74+
</div>
75+
</TippyCustomized>
2676
)}
27-
</label>
77+
</div>
2878
)
2979
}
3080

src/Shared/Components/FormFieldWrapper/FormFieldWrapper.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const FormFieldWrapper = ({
1212
warningText,
1313
required,
1414
children,
15+
labelTippyCustomizedConfig,
16+
labelTooltipConfig,
1517
}: Required<FormFieldWrapperProps>) => {
1618
const isRowLayout = layout === 'row'
1719
const itemContainerClassName = isRowLayout ? 'dc__mxw-250 w-100 mxh-36 dc__align-self-stretch' : ''
@@ -21,7 +23,19 @@ const FormFieldWrapper = ({
2123
<div className={`flex left top dc__gap-6 ${!isRowLayout ? 'column' : ''} w-100`}>
2224
{label && (
2325
<div className={`${itemContainerClassName} flex left`}>
24-
<FormFieldLabel inputId={inputId} label={label} required={required} layout={layout} />
26+
<FormFieldLabel
27+
inputId={inputId}
28+
label={label}
29+
required={required}
30+
layout={layout}
31+
{...(isRowLayout
32+
? {
33+
labelTooltipConfig,
34+
}
35+
: {
36+
labelTippyCustomizedConfig,
37+
})}
38+
/>
2539
</div>
2640
)}
2741
<div className="w-100 dc__position-rel">{children}</div>

src/Shared/Components/FormFieldWrapper/types.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { TooltipProps } from '@Common/Tooltip'
2+
import { TippyCustomizedProps } from '@Common/Types'
13
import { ReactElement, ReactNode } from 'react'
24

35
export type LabelOrAriaLabelType =
@@ -10,7 +12,9 @@ export type LabelOrAriaLabelType =
1012
ariaLabel: string
1113
}
1214

13-
export type FormFieldLabelProps = LabelOrAriaLabelType & {
15+
type LayoutType = 'row' | 'column'
16+
17+
export type FormFieldLabelProps<Layout extends LayoutType = LayoutType> = LabelOrAriaLabelType & {
1418
/**
1519
* If true, the field is required and * is shown with the label
1620
*/
@@ -22,8 +26,25 @@ export type FormFieldLabelProps = LabelOrAriaLabelType & {
2226
/**
2327
* Layout of the field
2428
*/
25-
layout?: 'row' | 'column'
26-
}
29+
layout?: Layout
30+
} & (Layout extends 'row'
31+
? {
32+
/**
33+
* Tooltip configuration for the label in row layout
34+
*/
35+
labelTooltipConfig?: Omit<TooltipProps, 'alwaysShowTippyOnHover' | 'showOnTruncate' | 'shortcutKeyCombo'>
36+
labelTippyCustomizedConfig?: never
37+
}
38+
: {
39+
labelTooltipConfig?: never
40+
/**
41+
* Tippy configuration for the label in column layout
42+
*/
43+
labelTippyCustomizedConfig?: Pick<
44+
TippyCustomizedProps,
45+
'heading' | 'infoText' | 'documentationLink' | 'documentationLinkText'
46+
>
47+
})
2748

2849
export interface FormFieldInfoProps extends Pick<FormFieldLabelProps, 'inputId'> {
2950
/**
@@ -48,7 +69,10 @@ export interface FormInfoItemProps {
4869
}
4970

5071
export interface FormFieldWrapperProps
51-
extends Pick<FormFieldLabelProps, 'label' | 'required' | 'ariaLabel' | 'layout'>,
72+
extends Pick<
73+
FormFieldLabelProps,
74+
'label' | 'required' | 'ariaLabel' | 'layout' | 'labelTippyCustomizedConfig' | 'labelTooltipConfig'
75+
>,
5276
FormFieldInfoProps {
5377
/**
5478
* If true, the field takes the full width of the parent

src/Shared/Components/SelectPicker/SelectPicker.component.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ const SelectPicker = <OptionValue, IsMulti extends boolean>({
219219
layout,
220220
ariaLabel,
221221
borderRadiusConfig,
222+
labelTippyCustomizedConfig,
223+
labelTooltipConfig,
222224
...props
223225
}: SelectPickerProps<OptionValue, IsMulti>) => {
224226
const [isFocussed, setIsFocussed] = useState(false)
@@ -380,8 +382,10 @@ const SelectPicker = <OptionValue, IsMulti extends boolean>({
380382
required={required}
381383
fullWidth={fullWidth}
382384
ariaLabel={ariaLabel}
383-
// TODO: Add support for custom border radius with CustomInput refactoring
385+
// TODO: Add support for custom border radius with Select refactoring
384386
borderRadiusConfig={borderRadiusConfig}
387+
labelTippyCustomizedConfig={labelTippyCustomizedConfig}
388+
labelTooltipConfig={labelTooltipConfig}
385389
>
386390
<ConditionalWrap condition={isDisabled && !!disabledTippyContent} wrap={renderDisabledTippy}>
387391
<div className="w-100">

src/Shared/Components/Textarea/Textarea.component.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ const Textarea = ({
2727
size = ComponentSizeType.large,
2828
ariaLabel,
2929
borderRadiusConfig,
30+
labelTooltipConfig,
31+
labelTippyCustomizedConfig,
3032
...props
3133
}: TextareaProps) => {
3234
const textareaRef = useRef<HTMLTextAreaElement>(null)
@@ -96,6 +98,8 @@ const Textarea = ({
9698
fullWidth={fullWidth}
9799
ariaLabel={ariaLabel}
98100
borderRadiusConfig={borderRadiusConfig}
101+
labelTooltipConfig={labelTooltipConfig}
102+
labelTippyCustomizedConfig={labelTippyCustomizedConfig}
99103
>
100104
<textarea
101105
{...props}

0 commit comments

Comments
 (0)