Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/itchy-cycles-sell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/clerk-js': patch
---

Fixes issue where `FormFeedback` was rendering two elements with the same `id` attribute leading to invalid markup.
3 changes: 2 additions & 1 deletion packages/clerk-js/src/ui/elements/FieldControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,12 @@ const FieldLabelRow = (props: PropsWithChildren) => {
};

const FieldFeedback = (props: Pick<FormFeedbackProps, 'elementDescriptors' | 'center'>) => {
const { fieldId, debouncedFeedback } = useFormField();
const { fieldId, debouncedFeedback, errorMessageId } = useFormField();

return (
<FormFeedback
center={props.center}
errorMessageId={errorMessageId}
{...{
...debouncedFeedback,
elementDescriptors: props.elementDescriptors,
Expand Down
7 changes: 6 additions & 1 deletion packages/clerk-js/src/ui/elements/FormControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,14 @@ export type FormFeedbackDescriptorsKeys = 'error' | 'warning' | 'info' | 'succes
type Feedback = { feedback?: string; feedbackType?: FeedbackType; shouldEnter: boolean };

export type FormFeedbackProps = Partial<ReturnType<typeof useFormControlFeedback>['debounced'] & { id: FieldId }> & {
errorMessageId?: string;
elementDescriptors?: Partial<Record<FormFeedbackDescriptorsKeys, ElementDescriptor>>;
center?: boolean;
sx?: ThemableCssProp;
};

export const FormFeedback = (props: FormFeedbackProps) => {
const { id, elementDescriptors, sx, feedback, feedbackType = 'info', center = false } = props;
const { id, elementDescriptors, sx, feedback, feedbackType = 'info', center = false, errorMessageId } = props;
const feedbacksRef = useRef<{
a?: Feedback;
b?: Feedback;
Expand Down Expand Up @@ -142,6 +143,10 @@ export const FormFeedback = (props: FormFeedbackProps) => {
return {
elementDescriptor: descriptor,
elementId: id ? descriptor?.setId?.(id) : undefined,
// We only want the id applied when the feedback type is an error
// to avoid having multiple elements in the dom with the same id attribute.
// We also only have aria-describedby applied to the input when it is an error.
id: type === 'error' ? errorMessageId : undefined,
};
};

Expand Down