Skip to content

Commit

Permalink
fix: w3c validation + position text validation IF-1684
Browse files Browse the repository at this point in the history
  • Loading branch information
mshatikhin committed Jul 23, 2024
1 parent 523e191 commit 87569f9
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 135 deletions.
2 changes: 1 addition & 1 deletion contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ function foo() {}
Стоит избегать общих слов, таких как "change". Вместо этого опишите в чем конкретно произошло изменение.

Примеры:
- validationsRemoveExtraSpans - Избавиться от обертки span в ValidationContainer, ValidationWrapper и ValidationText
- validationsDivWrapper - Поменять обертку span на div c 'display: inline' чтобы соответсвовать w3c стандарту в ValidationContainer, ValidationWrapper и ValidationText
- tokenInputRemoveWhitespaceFromDefaultDelimiters - В TokenInput изменили разделитель по умолчанию

2) Добавьте флаг в ReactUIFeatureFlags в файл ReactUIFeatureFlagsContext.tsx и в документацию FEATUREFLAGSCONTEXT.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Доступные флаги

export interface ValidationsFeatureFlags {
validationsRemoveExtraSpans?: boolean;
validationsDivWrapper?: boolean;
fixedValidationTextColors?: boolean;
darkTheme?: boolean;
}
Expand All @@ -14,16 +14,16 @@

import { ValidationsFeatureFlagsContext } from '@skbkontur/react-ui-validations'

<ValidationsFeatureFlagsContext.Provider value={{ validationsRemoveExtraSpans: true }}>{/* ... */}</ValidationsFeatureFlagsContext.Provider>;
<ValidationsFeatureFlagsContext.Provider value={{ validationsDivWrapper: true }}>{/* ... */}</ValidationsFeatureFlagsContext.Provider>;

## Использование

### validationsRemoveExtraSpans
### validationsDivWrapper

В ValidationContainer, ValidationWrapper и ValidationText из корня удалён лишний span.
В Validations 2.0 фича будет применена по умолчанию.

!!DemoWithCode!!FeatureFlagsExamplevalidationsRemoveExtraSpans
!!DemoWithCode!!FeatureFlagsExampleValidationsRemoveDivWrapper


### fixedValidationTextColors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface CheckboxState {
checked: boolean;
}

export default class FeatureFlagsExampleValidationsWrapperAndContainerRemoveExtraSpan extends React.Component {
export default class FeatureFlagsExampleValidationsWrapperAndContainerDivWrapper extends React.Component {
public state: CheckboxState = {
checked: false,
};
Expand All @@ -31,9 +31,7 @@ export default class FeatureFlagsExampleValidationsWrapperAndContainerRemoveExtr

render() {
return (
<ValidationsFeatureFlagsContext.Provider
value={{ validationsRemoveExtraSpans: true }}
>
<ValidationsFeatureFlagsContext.Provider value={{ validationsDivWrapper: true }}>
<ValidationContainer ref={this.refContainer}>
<ValidationWrapper validationInfo={this.validateSex()}>
<Checkbox
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ValidationWrapperInternal } from './ValidationWrapperInternal';
import type { ScrollOffset, ValidateArgumentType } from './ValidationContainer';
import { isNullable } from './utils/isNullable';
import { FocusMode } from './FocusMode';
import { InlineDiv } from './utils/InlineDiv';

export interface ValidationContextSettings {
scrollOffset: ScrollOffset;
Expand Down Expand Up @@ -165,8 +166,8 @@ export class ValidationContextWrapper extends React.Component<ValidationContextW
private featureFlags!: ValidationsFeatureFlags;

private children = (flags: ValidationsFeatureFlags) => {
if (flags.validationsRemoveExtraSpans) {
return this.props.children;
if (flags.validationsDivWrapper) {
return <InlineDiv>{this.props.children}</InlineDiv>;
}

return <span>{this.props.children}</span>;
Expand Down
19 changes: 4 additions & 15 deletions packages/react-ui-validations/src/ValidationText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,13 @@ export const ValidationText = ({ pos, children, validation, 'data-tid': dataTid
const color = getValidationTextColor(featureFlags, theme, validation?.level);

if (pos === 'right') {
const childrenAndValidationText = (
<>
return (
<span style={{ display: 'inline-block' }}>
{children}
<span data-tid={dataTid} data-validation-message="text" style={{ marginLeft: '10px', color }}>
{(validation && validation.message) || ''}
</span>
</>
);

return featureFlags.validationsRemoveExtraSpans ? (
childrenAndValidationText
) : (
<span style={{ display: 'inline-block' }}>{childrenAndValidationText}</span>
</span>
);
}

Expand All @@ -54,12 +48,7 @@ export const ValidationText = ({ pos, children, validation, 'data-tid': dataTid
</span>
);

return featureFlags.validationsRemoveExtraSpans ? (
<>
{children}
<span style={{ position: 'absolute', display: 'block' }}>{validationText}</span>
</>
) : (
return (
<span style={{ position: 'relative', display: 'inline-block' }}>
{children}
<span style={{ position: 'absolute', bottom: 0, left: 0, height: 0 }}>{validationText}</span>
Expand Down
34 changes: 10 additions & 24 deletions packages/react-ui-validations/src/ValidationTooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import React from 'react';

import {
ValidationsFeatureFlags,
ValidationsFeatureFlagsContext,
getFullValidationsFlagsContext,
} from './utils/featureFlagsContext';
import { ReactUiDetection, Tooltip } from './ReactUiDetection';

export type TooltipPosition =
Expand Down Expand Up @@ -33,31 +28,22 @@ export class ValidationTooltip extends React.Component<ValidationTooltipProps> {
public static __KONTUR_REACT_UI__ = 'ValidationTooltip';
public static displayName = 'ValidationTooltip';

private featureFlags!: ValidationsFeatureFlags;
public render() {
const { children, pos, error, render, ...rest } = this.props;

const onlyChild = React.Children.only(children);
const child = onlyChild && onlyChild.props ? onlyChild.props.children : null;

return (
<ValidationsFeatureFlagsContext.Consumer>
{(flags) => {
this.featureFlags = getFullValidationsFlagsContext(flags);
return !this.featureFlags.validationsRemoveExtraSpans &&
(ReactUiDetection.isRadioGroup(child) ||
ReactUiDetection.isTokenInput(child) ||
ReactUiDetection.isSwitcher(child)) ? (
<Tooltip useWrapper={false} pos={pos} render={error && render} trigger={'hover&focus'} {...rest}>
{child}
</Tooltip>
) : (
<Tooltip pos={pos} render={error && render} trigger={'hover&focus'} {...rest}>
{children}
</Tooltip>
);
}}
</ValidationsFeatureFlagsContext.Consumer>
return ReactUiDetection.isRadioGroup(child) ||
ReactUiDetection.isTokenInput(child) ||
ReactUiDetection.isSwitcher(child) ? (
<Tooltip useWrapper={false} pos={pos} render={error && render} trigger={'hover&focus'} {...rest}>
{child}
</Tooltip>
) : (
<Tooltip pos={pos} render={error && render} trigger={'hover&focus'} {...rest}>
{children}
</Tooltip>
);
}
}
27 changes: 3 additions & 24 deletions packages/react-ui-validations/src/ValidationWrapperInternal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@ import warning from 'warning';

import { Nullable } from '../typings/Types';

import {
ValidationsFeatureFlags,
ValidationsFeatureFlagsContext,
getFullValidationsFlagsContext,
} from './utils/featureFlagsContext';
import { getRootNode } from './utils/getRootNode';
import { isBrowser } from './utils/utils';
import { smoothScrollIntoView } from './smoothScrollIntoView';
Expand Down Expand Up @@ -70,8 +65,6 @@ export class ValidationWrapperInternal extends React.Component<
public static contextType = ValidationContext;
public context: ValidationContextType = this.context;

private featureFlags!: ValidationsFeatureFlags;

public componentDidMount() {
warning(
this.context,
Expand Down Expand Up @@ -150,23 +143,9 @@ export class ValidationWrapperInternal extends React.Component<
});
}

return (
<ValidationsFeatureFlagsContext.Consumer>
{(flags) => {
this.featureFlags = getFullValidationsFlagsContext(flags);
return React.cloneElement(
this.props.errorMessage(
this.featureFlags.validationsRemoveExtraSpans ? clonedChild : <span>{clonedChild}</span>,
!!validation,
validation,
),
{
'data-tid': dataTid,
},
);
}}
</ValidationsFeatureFlagsContext.Consumer>
);
return React.cloneElement(this.props.errorMessage(clonedChild, !!validation, validation), {
'data-tid': dataTid,
});
}

private customRef = (instance: Nullable<ReactInstance>) => {
Expand Down
8 changes: 8 additions & 0 deletions packages/react-ui-validations/src/utils/InlineDiv.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react';
import type { FC, PropsWithChildren } from 'react';

export const InlineDiv: FC<PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>> = ({ children, ...rest }) => (
<div style={{ display: 'inline' }} {...rest}>
{children}
</div>
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type FeatureFlags = 'validationsRemoveExtraSpans' | 'fixedValidationTextC
export type ValidationsFeatureFlags = Partial<Record<FeatureFlags, boolean>>;

export const validationsFeatureFlagsDefault: ValidationsFeatureFlags = {
validationsRemoveExtraSpans: false,
validationsDivWrapper: false,
fixedValidationTextColors: false,
};

Expand Down
28 changes: 13 additions & 15 deletions packages/react-ui-validations/stories/Checkbox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Meta } from '@storybook/react';
import { Button } from '@skbkontur/react-ui/components/Button';
import { Checkbox } from '@skbkontur/react-ui/components/Checkbox/Checkbox';

import { ValidationContainer, ValidationInfo, ValidationWrapper, ValidationsFeatureFlagsContext } from '../src';
import { ValidationContainer, ValidationInfo, ValidationWrapper } from '../src';
import { Nullable } from '../typings/Types';

export default {
Expand All @@ -22,19 +22,17 @@ export const Required = () => {
};

return (
<ValidationsFeatureFlagsContext.Provider value={{ validationsRemoveExtraSpans: true }}>
<div style={{ padding: 20 }}>
<ValidationContainer ref={refContainer}>
<ValidationWrapper validationInfo={validateSex()}>
<Checkbox checked={checked ? checked : false} onValueChange={setChecked}>
Checkbox
</Checkbox>
</ValidationWrapper>
<div style={{ padding: '20px 0' }}>
<Button onClick={() => refContainer.current?.validate()}>Check</Button>
</div>
</ValidationContainer>
</div>
</ValidationsFeatureFlagsContext.Provider>
<div style={{ padding: 20 }}>
<ValidationContainer ref={refContainer}>
<ValidationWrapper validationInfo={validateSex()}>
<Checkbox checked={checked ? checked : false} onValueChange={setChecked}>
Checkbox
</Checkbox>
</ValidationWrapper>
<div style={{ padding: '20px 0' }}>
<Button onClick={() => refContainer.current?.validate()}>Check</Button>
</div>
</ValidationContainer>
</div>
);
};
68 changes: 28 additions & 40 deletions packages/react-ui-validations/stories/Input.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,7 @@ import { Select } from '@skbkontur/react-ui/components/Select';
import { Gapped } from '@skbkontur/react-ui';
import { Story } from '@skbkontur/react-ui/typings/stories';

import {
text,
tooltip,
ValidationBehaviour,
ValidationContainer,
ValidationInfo,
ValidationWrapper,
ValidationsFeatureFlagsContext,
} from '../src';
import { text, tooltip, ValidationBehaviour, ValidationContainer, ValidationInfo, ValidationWrapper } from '../src';
import { Nullable } from '../typings/Types';

export default {
Expand Down Expand Up @@ -179,23 +171,21 @@ export const SelectFirstControlForValidation = () => {
};

return (
<ValidationsFeatureFlagsContext.Provider value={{ validationsRemoveExtraSpans: true }}>
<ValidationContainer ref={refContainer}>
<div style={{ padding: 50, height: 200, position: 'relative' }}>
<div style={{ position: 'absolute', top: 100 }}>
<ValidationWrapper validationInfo={validateValue1()}>
<Input value={value1} onValueChange={setValue1} />
</ValidationWrapper>
</div>
<div style={{ position: 'absolute', top: 20 }}>
<ValidationWrapper validationInfo={validateValue2()}>
<Input value={value2} onValueChange={setValue2} />
</ValidationWrapper>
</div>
<ValidationContainer ref={refContainer}>
<div style={{ padding: 50, height: 200, position: 'relative' }}>
<div style={{ position: 'absolute', top: 100 }}>
<ValidationWrapper validationInfo={validateValue1()}>
<Input value={value1} onValueChange={setValue1} />
</ValidationWrapper>
</div>
<Button onClick={() => refContainer.current?.submit()}>Отправить</Button>
</ValidationContainer>
</ValidationsFeatureFlagsContext.Provider>
<div style={{ position: 'absolute', top: 20 }}>
<ValidationWrapper validationInfo={validateValue2()}>
<Input value={value2} onValueChange={setValue2} />
</ValidationWrapper>
</div>
</div>
<Button onClick={() => refContainer.current?.submit()}>Отправить</Button>
</ValidationContainer>
);
};

Expand Down Expand Up @@ -382,21 +372,19 @@ export const SetPercentageWidth = () => {
refContainer.current?.submit();
}}
>
<ValidationsFeatureFlagsContext.Provider value={{ validationsRemoveExtraSpans: true }}>
<ValidationContainer ref={refContainer}>
<ValidationWrapper
renderMessage={tooltip('left middle')}
validationInfo={{ message: 'Ошибка!', type: 'submit' }}
>
<Input width="100%" placeholder={'Валидация'} />
</ValidationWrapper>
<br />
<br />
<ValidationWrapper renderMessage={text('bottom')} validationInfo={{ message: 'Ошибка!', type: 'submit' }}>
<Input width="100%" placeholder={'Валидация'} />
</ValidationWrapper>
</ValidationContainer>
</ValidationsFeatureFlagsContext.Provider>
<ValidationContainer ref={refContainer}>
<ValidationWrapper
renderMessage={tooltip('left middle')}
validationInfo={{ message: 'Ошибка!', type: 'submit' }}
>
<Input width="100%" placeholder={'Валидация'} />
</ValidationWrapper>
<br />
<br />
<ValidationWrapper renderMessage={text('bottom')} validationInfo={{ message: 'Ошибка!', type: 'submit' }}>
<Input width="100%" placeholder={'Валидация'} />
</ValidationWrapper>
</ValidationContainer>
<br />
<br />
<br />
Expand Down
10 changes: 5 additions & 5 deletions packages/react-ui-validations/tests/ValidationContainer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ describe('ValidationContainer', () => {
expect(screen.getByTestId('passed-container')).toBeInTheDocument();
});

it('renders passed data-tid on container when validationsRemoveExtraSpans enabled', () => {
it('renders passed data-tid on container when validationsDivWrapper enabled', () => {
render(
<ValidationsFeatureFlagsContext.Provider value={{ validationsRemoveExtraSpans: true }}>
<ValidationsFeatureFlagsContext.Provider value={{ validationsDivWrapper: true }}>
<ValidationContainer data-tid="passed-container">
<div />
</ValidationContainer>
Expand All @@ -45,17 +45,17 @@ describe('ValidationContainer', () => {
expect(screen.getByTestId('passed-container')).toBeInTheDocument();
});

it('not renders passed data-tid on container when validationsRemoveExtraSpans enabled', () => {
it('renders passed data-tid on container when validationsDivWrapper enabled', () => {
render(
<ValidationsFeatureFlagsContext.Provider value={{ validationsRemoveExtraSpans: true }}>
<ValidationsFeatureFlagsContext.Provider value={{ validationsDivWrapper: true }}>
<ValidationContainer data-tid="passed-container">
<div />
<div />
</ValidationContainer>
</ValidationsFeatureFlagsContext.Provider>,
);

expect(screen.queryByTestId('passed-container')).toBeNull();
expect(screen.queryByTestId('passed-container')).toBeInTheDocument();
});

it('renders passed children', () => {
Expand Down

0 comments on commit 87569f9

Please sign in to comment.