Skip to content

Commit fe14893

Browse files
author
Gido Manders
committed
improvement: make error tooltip placement configurable
We want to be able to configure the placement of the error tooltip on fields. The default is bottom, but when using the datepicker that position clashes with the datepicker tooltip. Added tooltipPlacement property to withField.
1 parent b66097c commit fe14893

File tree

1 file changed

+39
-19
lines changed

1 file changed

+39
-19
lines changed

src/form/withField/withField.tsx

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import React from 'react';
2-
import { Field, FieldProps as FieldValidationProps } from '@42.nl/final-form-field-validation';
2+
import {
3+
Field,
4+
FieldProps as FieldValidationProps
5+
} from '@42.nl/final-form-field-validation';
36
import getDisplayName from 'react-display-name';
47
import { merge, omit, pick } from 'lodash';
58

@@ -10,10 +13,11 @@ import { FieldCompatible } from '../types';
1013
import { FieldValidator } from 'final-form';
1114
import { FieldRenderProps } from 'react-final-form';
1215
import { ErrorMode, FieldError } from '../FormError/FieldError';
16+
import { TippyPlacement } from '../../core/types';
1317

1418
// This is a list of props that `withField` will pass to the `final-form`
1519
// Field, but not the wrapper.
16-
const passedFieldProps = [ 'initialValue', 'format', 'formatOnBlur', 'parse' ];
20+
const passedFieldProps = ['initialValue', 'format', 'formatOnBlur', 'parse'];
1721

1822
// These are the props that are managed by `withField` and should not
1923
// be set manually by the user.
@@ -27,20 +31,19 @@ const managedProps = [
2731
'error'
2832
];
2933

30-
export type FieldProps<Value, ChangeValue> = FieldCompatible<Value,
31-
ChangeValue> & {
34+
export type FieldProps<Value, ChangeValue> = FieldCompatible<
35+
Value,
36+
ChangeValue
37+
> & {
3238
errorMode?: ErrorMode;
39+
tooltipPlacement?: TippyPlacement;
3340
};
3441

3542
export type WithFieldProps<Value, P> = FieldValidationProps<Value, any> &
36-
Omit<P,
37-
| 'onFocus'
38-
| 'onBlur'
39-
| 'onChange'
40-
| 'value'
41-
| 'color'
42-
| 'valid'
43-
| 'error'>;
43+
Omit<
44+
P,
45+
'onFocus' | 'onBlur' | 'onChange' | 'value' | 'color' | 'valid' | 'error'
46+
>;
4447

4548
/**
4649
* withField is a Higher Order Component which takes an input element
@@ -58,9 +61,16 @@ export type WithFieldProps<Value, P> = FieldValidationProps<Value, any> &
5861
* @param Wrapper The Component which is `FieldCompatible`.
5962
* @param defaultValidators Optional validators the field should use by default
6063
*/
61-
export function withField<Value,
64+
export function withField<
65+
Value,
6266
ChangeValue,
63-
P extends FieldProps<Value, ChangeValue>>(Wrapper: React.ComponentType<P>, defaultValidators?: (props: WithFieldProps<Value, P>) => FieldValidator<Value>[]) {
67+
P extends FieldProps<Value, ChangeValue>
68+
>(
69+
Wrapper: React.ComponentType<P>,
70+
defaultValidators?: (
71+
props: WithFieldProps<Value, P>
72+
) => FieldValidator<Value>[]
73+
) {
6474
const displayName = `Field${getDisplayName(Wrapper)}`;
6575

6676
WithField.displayName = displayName;
@@ -69,13 +79,19 @@ export function withField<Value,
6979
const illegalProps = managedProps.filter((p) => props[p] !== undefined);
7080

7181
if (illegalProps.length > 0) {
72-
illegalPropsDetected('withField', displayName, illegalProps, managedProps);
82+
illegalPropsDetected(
83+
'withField',
84+
displayName,
85+
illegalProps,
86+
managedProps
87+
);
7388
}
7489

75-
const [ hasErrors, setHasErrors ] = useHasErrors();
90+
const [hasErrors, setHasErrors] = useHasErrors();
7691

7792
const {
7893
errorMode = 'below',
94+
tooltipPlacement = 'bottom',
7995
name,
8096
validators,
8197
asyncValidators,
@@ -86,7 +102,7 @@ export function withField<Value,
86102

87103
// A bit magical this one but this makes TypeScript accept all other
88104
// props as the Props to the wrapped component.
89-
const wrapperProps = (omit(rest, passedFieldProps) as unknown) as P;
105+
const wrapperProps = omit(rest, passedFieldProps) as unknown as P;
90106

91107
const fieldProps = pick(rest, [
92108
'initialValue',
@@ -114,7 +130,11 @@ export function withField<Value,
114130
return (
115131
<Field<Value, any>
116132
name={name}
117-
validators={defaultValidators ? merge(defaultValidators(props), validators) : validators}
133+
validators={
134+
defaultValidators
135+
? merge(defaultValidators(props), validators)
136+
: validators
137+
}
118138
asyncValidators={asyncValidators}
119139
asyncValidatorsDebounce={asyncValidatorsDebounce}
120140
subscription={fieldSubscription}
@@ -124,7 +144,7 @@ export function withField<Value,
124144
content={error}
125145
tag="div"
126146
className="w-100"
127-
placement="bottom"
147+
placement={tooltipPlacement}
128148
>
129149
<Wrapper
130150
{...wrapperProps}

0 commit comments

Comments
 (0)