diff --git a/.changeset/rich-peaches-yawn.md b/.changeset/rich-peaches-yawn.md new file mode 100644 index 00000000000..e474543fc02 --- /dev/null +++ b/.changeset/rich-peaches-yawn.md @@ -0,0 +1,5 @@ +--- +'@clerk/clerk-js': patch +--- + +Prevent leaking the `data-component-status` attribute for components other than ``. diff --git a/packages/clerk-js/src/ui/customizables/__tests__/FlowRoot.spec.tsx b/packages/clerk-js/src/ui/customizables/__tests__/FlowRoot.spec.tsx new file mode 100644 index 00000000000..146ddc4df64 --- /dev/null +++ b/packages/clerk-js/src/ui/customizables/__tests__/FlowRoot.spec.tsx @@ -0,0 +1,59 @@ +import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; + +import { AppearanceProvider } from '../AppearanceContext'; +import { Flow } from '../Flow'; + +describe('Flow.Root data-component-status behavior', () => { + it('does not set data-component-status if prop is omitted', () => { + const { container } = render( + + +
+ + , + , + ); + + const host = container as HTMLElement | null; + expect(host).toBeTruthy(); + // Attribute should not be present + expect(host?.getAttribute('data-component-status')).toBeNull(); + }); + + it('sets data-component-status="awaiting-data" when isFlowReady=false', async () => { + const { container } = render( + + +
+ + , + , + ); + + const host = container as HTMLElement | null; + expect(host).toBeTruthy(); + expect(host?.getAttribute('data-component-status')).toBe('awaiting-data'); + }); + + it('sets data-component-status="ready" when isFlowReady=true', () => { + const { container } = render( + + +
+ + , + , + ); + + const host = container as HTMLElement | null; + expect(host).toBeTruthy(); + expect(host?.getAttribute('data-component-status')).toBe('ready'); + }); +}); diff --git a/packages/clerk-js/src/ui/elements/InvisibleRootBox.tsx b/packages/clerk-js/src/ui/elements/InvisibleRootBox.tsx index 0cae2f62602..609a7829edd 100644 --- a/packages/clerk-js/src/ui/elements/InvisibleRootBox.tsx +++ b/packages/clerk-js/src/ui/elements/InvisibleRootBox.tsx @@ -18,7 +18,9 @@ const _InvisibleRootBox = React.memo((props: RootBoxProps & { isFlowReady?: bool } parent.setAttribute('class', props.className); - parent.setAttribute('data-component-status', props.isFlowReady ? 'ready' : 'awaiting-data'); + if ('isFlowReady' in props) { + parent.setAttribute('data-component-status', props.isFlowReady ? 'ready' : 'awaiting-data'); + } }, [props.className, props.isFlowReady]); return ( diff --git a/packages/clerk-js/src/ui/elements/contexts/index.tsx b/packages/clerk-js/src/ui/elements/contexts/index.tsx index b449c95a93b..84aa3211f39 100644 --- a/packages/clerk-js/src/ui/elements/contexts/index.tsx +++ b/packages/clerk-js/src/ui/elements/contexts/index.tsx @@ -129,7 +129,7 @@ const [FlowMetadataCtx, useFlowMetadata] = createContextAndHook('F export const FlowMetadataProvider = (props: React.PropsWithChildren) => { const { flow, part } = props; - const value = React.useMemo(() => ({ value: { ...props } }), [flow, part]); + const value = React.useMemo(() => ({ value: props }), [flow, part]); return {props.children}; };