Skip to content

Commit 5b87b06

Browse files
authored
feat(force-value) - improve to use form description component (#984)
* feat(force-value) - improve to use form description component * fix description * fix(force-value-fields) - fix semantics a bit * fix semantics
1 parent f99d7a6 commit 5b87b06

4 files changed

Lines changed: 55 additions & 61 deletions

File tree

example/src/Onboarding.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,10 @@ const OnboardingWithProps = ({
436436
// Nigeria
437437
contract_details: 2,
438438
},
439+
NLD: {
440+
// Netherlands
441+
contract_details: 2,
442+
},
439443
NOR: {
440444
// Norway
441445
contract_details: 2,
Lines changed: 30 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,9 @@
11
import { useFormContext } from 'react-hook-form';
22
import { sanitizeHtml } from '@/src/lib/utils';
33
import { useEffect } from 'react';
4-
import { ZendeskTriggerButton } from '@/src/components/shared/zendesk-drawer/ZendeskTriggerButton';
5-
6-
const Description = ({
7-
name,
8-
description,
9-
helpCenter,
10-
}: {
11-
name: string;
12-
description: string;
13-
helpCenter?: {
14-
callToAction: string;
15-
id: number;
16-
url: string;
17-
label: string;
18-
};
19-
}) => {
20-
return (
21-
<span>
22-
<span
23-
className={`text-xs RemoteFlows__ForcedValue__Description__${name}`}
24-
dangerouslySetInnerHTML={{ __html: sanitizeHtml(description) }}
25-
/>
26-
{helpCenter?.callToAction && helpCenter?.id && (
27-
<ZendeskTriggerButton
28-
className='RemoteFlows__ForcedValue__HelpCenterLink'
29-
zendeskId={helpCenter.id}
30-
>
31-
{helpCenter.callToAction}
32-
</ZendeskTriggerButton>
33-
)}
34-
</span>
35-
);
36-
};
4+
import { HelpCenterDataProps } from '@/src/types/fields';
5+
import { BaseFormDescription as Description } from '@/src/components/ui/form';
6+
import { HelpCenter } from '@/src/components/shared/zendesk-drawer/HelpCenter';
377

388
export type ForcedValueFieldProps = {
399
name: string;
@@ -44,12 +14,7 @@ export type ForcedValueFieldProps = {
4414
description?: string;
4515
};
4616
label: string;
47-
helpCenter?: {
48-
callToAction: string;
49-
id: number;
50-
url: string;
51-
label: string;
52-
};
17+
helpCenter?: HelpCenterDataProps;
5318
};
5419

5520
export function ForcedValueField({
@@ -61,40 +26,54 @@ export function ForcedValueField({
6126
helpCenter,
6227
}: ForcedValueFieldProps) {
6328
const { setValue } = useFormContext();
64-
const descriptionSanitized = sanitizeHtml(
65-
statement?.description || description,
66-
);
29+
const forcedValueDescription = statement?.description || description;
6730

68-
const titleSanitized = statement?.title
31+
const forcedValueTitle = statement?.title
6932
? sanitizeHtml(statement?.title)
7033
: sanitizeHtml(label);
7134

35+
const titleId = `forced-value-${name}-title`;
36+
const descriptionId = `forced-value-${name}-description`;
37+
7238
useEffect(() => {
7339
setValue(name, value);
7440
// eslint-disable-next-line react-hooks/exhaustive-deps
7541
}, []);
7642

77-
const isHiddenValue = !descriptionSanitized && !statement?.title;
43+
const isHiddenValue = !forcedValueDescription && !statement?.title;
7844

7945
if (isHiddenValue) {
8046
return null;
8147
}
8248

8349
return (
84-
<div>
85-
{titleSanitized && (
50+
<div
51+
role='group'
52+
aria-labelledby={forcedValueTitle ? titleId : undefined}
53+
aria-describedby={forcedValueDescription ? descriptionId : undefined}
54+
>
55+
{forcedValueTitle && (
8656
<p
57+
id={titleId}
8758
className={`text-sm RemoteFlows__ForcedValue__Title__${name}`}
8859
dangerouslySetInnerHTML={{
89-
__html: titleSanitized,
60+
__html: forcedValueTitle,
9061
}}
9162
/>
9263
)}
9364
<Description
94-
name={name}
95-
description={descriptionSanitized}
96-
helpCenter={helpCenter}
97-
/>
65+
as='span'
66+
id={descriptionId}
67+
className={`text-xs RemoteFlows__ForcedValue__Description__${name}`}
68+
helpCenter={
69+
<HelpCenter
70+
className='RemoteFlows__ForcedValue__HelpCenterLink'
71+
helpCenter={helpCenter}
72+
/>
73+
}
74+
>
75+
{forcedValueDescription}
76+
</Description>
9877
</div>
9978
);
10079
}

src/components/shared/zendesk-drawer/HelpCenter.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ import { HelpCenterDataProps } from '@/src/types/fields';
33

44
type HelpCenterProps = {
55
helpCenter?: HelpCenterDataProps;
6+
className?: string;
67
};
78

8-
export function HelpCenter({ helpCenter }: HelpCenterProps) {
9+
export function HelpCenter({ helpCenter, className }: HelpCenterProps) {
910
if (!helpCenter || !helpCenter.id || !helpCenter.callToAction) {
1011
return null;
1112
}
1213

1314
return (
14-
<ZendeskTriggerButton zendeskId={helpCenter.id}>
15+
<ZendeskTriggerButton zendeskId={helpCenter.id} className={className}>
1516
{helpCenter.callToAction}
1617
</ZendeskTriggerButton>
1718
);

src/components/ui/form.tsx

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -131,26 +131,26 @@ const FormControl = React.forwardRef<
131131

132132
FormControl.displayName = 'FormControl';
133133

134-
function FormDescription<T extends React.ElementType = 'p'>({
134+
export function BaseFormDescription<T extends React.ElementType = 'p'>({
135135
helpCenter,
136136
className,
137137
children,
138138
as,
139+
id,
139140
...props
140141
}: React.ComponentProps<'p'> & {
141142
helpCenter?: React.ReactNode;
142143
children?: React.ReactNode | (() => React.ReactNode);
143144
as?: T;
144-
} & Omit<React.ComponentPropsWithoutRef<T>, 'children' | 'className'>) {
145-
const { formDescriptionId } = useFormField();
145+
id?: string;
146+
} & Omit<React.ComponentPropsWithoutRef<T>, 'children' | 'className' | 'id'>) {
146147
const Component = as || 'p';
147-
148148
if (typeof children === 'string') {
149149
return (
150150
<>
151151
<Component
152152
data-slot='form-description'
153-
id={formDescriptionId}
153+
id={id}
154154
className={cn('text-base-color text-xs', className)}
155155
data-sanitized='true'
156156
{...props}
@@ -161,13 +161,12 @@ function FormDescription<T extends React.ElementType = 'p'>({
161161
</>
162162
);
163163
}
164-
165164
return (
166165
<Component
167166
data-slot='form-description'
168-
id={formDescriptionId}
169-
data-sanitized='false'
167+
id={id}
170168
className={cn('text-base-color text-xs', className)}
169+
data-sanitized='false'
171170
{...props}
172171
>
173172
{typeof children === 'function' ? children() : children}
@@ -176,6 +175,17 @@ function FormDescription<T extends React.ElementType = 'p'>({
176175
);
177176
}
178177

178+
function FormDescription<T extends React.ElementType = 'p'>({
179+
...props
180+
}: React.ComponentProps<'p'> & {
181+
helpCenter?: React.ReactNode;
182+
children?: React.ReactNode | (() => React.ReactNode);
183+
as?: T;
184+
} & Omit<React.ComponentPropsWithoutRef<T>, 'children' | 'className' | 'id'>) {
185+
const { formDescriptionId } = useFormField();
186+
return <BaseFormDescription id={formDescriptionId} {...props} />;
187+
}
188+
179189
function FormMessage({ className, ...props }: React.ComponentProps<'p'>) {
180190
const { error, formMessageId } = useFormField();
181191
const body = error ? String(error?.message ?? '') : props.children;

0 commit comments

Comments
 (0)