Skip to content

Commit

Permalink
chore(form-field): post master merge
Browse files Browse the repository at this point in the history
  • Loading branch information
hebernardEquisoft committed Dec 3, 2024
1 parent 5d9fccb commit 5b6ca16
Show file tree
Hide file tree
Showing 21 changed files with 139 additions and 50 deletions.
3 changes: 3 additions & 0 deletions packages/react/src/components/combobox/combobox.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ input + .c2 {
>
<label
class="c2 c3"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -770,6 +771,7 @@ input + .c2 {
>
<label
class="c2 c3"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -1722,6 +1724,7 @@ input + .c2 {
>
<label
class="c2 c3"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/components/combobox/combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const Textbox = styled.input<TextboxProps>`
width: 100%;
${focus};
&::placeholder {
color: ${({ theme }) => theme.component['combobox-placeholder-text-color']};
font-style: italic;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ label + .c3 {
>
<label
class="c1 c2"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -740,6 +741,7 @@ label + .c3 {
>
<label
class="c1 c2"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -1132,6 +1134,7 @@ label + .c3 {
>
<label
class="c1 c2"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -1524,6 +1527,7 @@ label + .c3 {
>
<label
class="c1 c2"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -1944,6 +1948,7 @@ label + .c5 {
>
<label
class="c1 c2"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -2350,6 +2355,7 @@ label + .c3 {
>
<label
class="c1 c2"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -2908,6 +2914,7 @@ label + .c3 {
>
<label
class="c1 c2"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -4209,6 +4216,7 @@ label + .c3 {
>
<label
class="c1 c2"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -5485,6 +5493,7 @@ label + .c3 {
>
<label
class="c1 c2"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ input + .c2 {
>
<label
class="c2 c3"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -665,6 +666,7 @@ input + .c2 {
>
<label
class="c2 c3"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -1139,6 +1141,7 @@ input + .c2 {
>
<label
class="c2 c3"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down Expand Up @@ -2561,6 +2564,7 @@ input + .c2 {
>
<label
class="c2 c3"
data-testid="field-label"
for="uuid2"
id="uuid2_label"
>
Expand Down
24 changes: 19 additions & 5 deletions packages/react/src/components/feedbacks/invalid-field-message.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { PropsWithChildren, VoidFunctionComponent } from 'react';
import { forwardRef, PropsWithChildren, ReactElement, Ref } from 'react';
import styled from 'styled-components';
import { useDataAttributes } from '../../hooks/use-data-attributes';
import { useId } from '../../hooks/use-id';
import { useDeviceContext } from '../device-context-provider/device-context-provider';
import { useFieldControlContext } from '../field-container/context';
import { Icon } from '../icon/icon';
import { InvalidFieldMessageProps } from './types';

Expand All @@ -19,21 +22,32 @@ const StyledIcon = styled(Icon)`
margin-right: var(--spacing-base);
`;

export const InvalidFieldMessage: VoidFunctionComponent<PropsWithChildren<InvalidFieldMessageProps>> = ({
children, id, noInvalidFieldIcon,
}) => {
export const InvalidFieldMessage = forwardRef(({
children,
id: providedId,
noInvalidFieldIcon,
...otherProps
}: PropsWithChildren<InvalidFieldMessageProps>, ref: Ref<HTMLSpanElement>): ReactElement => {
const { isMobile } = useDeviceContext();
const dataAttributes = useDataAttributes(otherProps);
const { slotIds } = useFieldControlContext({});
const id = useId(providedId ?? slotIds?.invalid);

return (
<StyledValidationMessage
data-testid="invalid-field"
id={id}
ref={ref}
$isMobile={isMobile}
{...otherProps /* eslint-disable-line react/jsx-props-no-spreading */}
{...dataAttributes /* eslint-disable-line react/jsx-props-no-spreading */}
>
{!noInvalidFieldIcon && (
<StyledIcon name="alertOctagon" size={isMobile ? '24' : '16'} />
)}
{children}
</StyledValidationMessage>
);
};
});

InvalidFieldMessage.displayName = 'InvalidFieldMessage';
4 changes: 3 additions & 1 deletion packages/react/src/components/feedbacks/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { NativeSpanProps } from '../../types/native-props';
import { FieldContainerProps } from '../field-container/types';

type PartialNativeSpanProps = Omit<NativeSpanProps, 'ref'>;

type CommonFieldContainerProps = Pick<FieldContainerProps, 'noInvalidFieldIcon'>;

export interface InvalidFieldMessageProps extends NativeSpanProps, CommonFieldContainerProps {}
export interface InvalidFieldMessageProps extends PartialNativeSpanProps, CommonFieldContainerProps {}
22 changes: 5 additions & 17 deletions packages/react/src/components/field-container/field-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ export const FieldContainer: FunctionComponent<PropsWithChildren<FieldContainerP
hint,
required,
disabled,
}), [fieldId, ariaLabel, ariaLabelledby, ariaDescribedby, valid, hint, required, disabled]);
slotIds,
}), [fieldId, ariaLabel, ariaLabelledby, ariaDescribedby, valid, hint, required, disabled, slotIds]);

return (
<FieldControlContext.Provider value={contextValues}>
Expand All @@ -75,23 +76,10 @@ export const FieldContainer: FunctionComponent<PropsWithChildren<FieldContainerP
$valid={valid}
{...props /* eslint-disable-line react/jsx-props-no-spreading */}
>
{label && (
<Label
id={slotIds.label}
forId={fieldId}
tooltip={tooltip}
required={required}
>
{label}
</Label>
)}
{hint && (
<Hint id={slotIds.hint}>
{hint}
</Hint>
)}
{label && <Label tooltip={tooltip}>{label}</Label>}
{hint && <Hint>{hint}</Hint>}
{!valid && (
<InvalidFieldMessage id={slotIds.invalid} noInvalidFieldIcon={noInvalidFieldIcon}>
<InvalidFieldMessage noInvalidFieldIcon={noInvalidFieldIcon}>
{validationErrorMessage}
</InvalidFieldMessage>
)}
Expand Down
7 changes: 7 additions & 0 deletions packages/react/src/components/field-container/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { TooltipProps } from '../tooltip/tooltip';

export interface FieldSlotIds {
label?: string;
hint?: string;
invalid?: string;
}

export interface FieldControlProps {
id?: string;
ariaLabel?: string;
Expand All @@ -8,6 +14,7 @@ export interface FieldControlProps {
disabled?: boolean;
required?: boolean;
valid?: boolean;
slotIds?: FieldSlotIds;
}

export interface FieldContainerProps extends FieldControlProps {
Expand Down
7 changes: 1 addition & 6 deletions packages/react/src/components/field-container/utils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { ReactNode } from 'react';
import { devConsole } from '../../utils/dev-console';
import { joinStrings } from '../../utils/string';

interface FieldSlotIds {
label?: string;
hint?: string;
invalid?: string;
}
import { FieldSlotIds } from './types';

export function getSlotId(prop: ReactNode, fieldId: string, propName: string): string | undefined {
return prop ? `${fieldId}_${propName}` : undefined;
Expand Down
23 changes: 18 additions & 5 deletions packages/react/src/components/hint/hint.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { PropsWithChildren, VoidFunctionComponent } from 'react';
import { forwardRef, PropsWithChildren, ReactElement, Ref } from 'react';
import styled from 'styled-components';
import { useDataAttributes } from '../../hooks/use-data-attributes';
import { useId } from '../../hooks/use-id';
import { useDeviceContext } from '../device-context-provider/device-context-provider';
import { useFieldControlContext } from '../field-container/context';
import { HintProps } from './types';

const StyledHint = styled.span<{ $isMobile: boolean }>`
Expand All @@ -12,18 +15,28 @@ const StyledHint = styled.span<{ $isMobile: boolean }>`
line-height: ${({ $isMobile }) => ($isMobile ? '1.5rem' : '1.25rem')};
`;

export const Hint: VoidFunctionComponent<PropsWithChildren<HintProps>> = ({
children, id,
}) => {
export const Hint = forwardRef(({
children,
id: providedId,
...otherProps
}: PropsWithChildren<HintProps>, ref: Ref<HTMLSpanElement>): ReactElement => {
const { isMobile } = useDeviceContext();
const dataAttributes = useDataAttributes(otherProps);
const { slotIds } = useFieldControlContext({});
const id = useId(providedId ?? slotIds?.hint);

return (
<StyledHint
data-testid="field-hint"
id={id}
ref={ref}
$isMobile={isMobile}
{...otherProps /* eslint-disable-line react/jsx-props-no-spreading */}
{...dataAttributes /* eslint-disable-line react/jsx-props-no-spreading */}
>
{children}
</StyledHint>
);
};
});

Hint.displayName = 'Hint';
4 changes: 3 additions & 1 deletion packages/react/src/components/hint/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { NativeSpanProps } from '../../types/native-props';

export interface HintProps extends NativeSpanProps {}
type PartialNativeSpanProps = Omit<NativeSpanProps, 'ref'>

export interface HintProps extends PartialNativeSpanProps {}
6 changes: 3 additions & 3 deletions packages/react/src/components/input/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DetailedHTMLProps, InputHTMLAttributes } from 'react';
import { NativeInputProps } from '../../types/native-props';
import { FieldControlProps } from '../field-container/types';

type BaseInputProps = Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>,
type PartialNativeInputProps = Omit<NativeInputProps,
| 'ref'
>;

Expand All @@ -12,4 +12,4 @@ type CommonFieldControlProps = Pick<FieldControlProps,
| 'valid'
>;

export type InputProps = BaseInputProps & CommonFieldControlProps;
export type InputProps = PartialNativeInputProps & CommonFieldControlProps;
4 changes: 2 additions & 2 deletions packages/react/src/components/label/label.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { Label } from './label';

describe('Label', () => {
test('contains tooltip when tooltip prop is defined', () => {
const wrapper = mountWithTheme(<Label htmlFor="test" tooltip={{ label: 'test' }}>Test</Label>);
const wrapper = mountWithTheme(<Label forId="test" tooltip={{ label: 'test' }}>Test</Label>);

expect(wrapper.find(Tooltip).exists()).toBe(true);
});

test('Matches the snapshot', () => {
const tree = renderWithTheme(
<Label htmlFor="test-id">
<Label forId="test-id">
Children
</Label>,
);
Expand Down
2 changes: 2 additions & 0 deletions packages/react/src/components/label/label.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ input + .c0 {
<label
class="c0 c1"
data-testid="label"
for="test-id"
id="uuid1"
>
Children
</label>
Expand Down
Loading

0 comments on commit 5b6ca16

Please sign in to comment.