+
+
+ onChange({
+ ...editing,
+ config: e.target.value
+ ? { ...editing.config, tosUrl: e.target.value }
+ : (() => {
+ const { tosUrl: _, ...rest } = editing.config ?? {}
+ return Object.keys(rest).length > 0 ? rest : null
+ })(),
+ })
+ }
+ className="mt-1 w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground"
+ placeholder="https://example.com/terms"
+ />
+
+ Link displayed alongside the checkbox so users can review your terms.
+
+
+ )}
)
- case 'tos_acceptance':
+ case 'tos_acceptance': {
+ const tosUrl = typeof field.config?.tosUrl === 'string' ? field.config.tosUrl : null
+ return (
+
+
onChange(e.target.checked)}
+ className="mt-1 h-4 w-4 rounded border-border"
+ />
+
+
+ )
+ }
+
case 'custom_checkbox':
return (
diff --git a/src/components/onboarding-modal.test.tsx b/src/components/onboarding-modal.test.tsx
index e13f946..e1a06a6 100644
--- a/src/components/onboarding-modal.test.tsx
+++ b/src/components/onboarding-modal.test.tsx
@@ -196,6 +196,61 @@ describe('OnboardingModal', () => {
expect(screen.getByRole('button', { name: /continue/i })).toBeEnabled()
})
+ it('renders a ToS link when config.tosUrl is set', () => {
+ render(
+
+ )
+ const link = screen.getByRole('link', { name: /read full terms of service/i })
+ expect(link).toHaveAttribute('href', 'https://example.com/tos')
+ expect(link).toHaveAttribute('target', '_blank')
+ expect(link).toHaveAttribute('rel', 'noopener noreferrer')
+ })
+
+ it('does not render a link when config.tosUrl is absent', () => {
+ render(
+
+ )
+ expect(screen.queryByRole('link')).not.toBeInTheDocument()
+ })
+
+ it('passes axe accessibility check for tos_acceptance with tosUrl', async () => {
+ const { container } = render(
+
+ )
+ const results = await axe(container)
+ expect(results).toHaveNoViolations()
+ })
+
it('passes axe accessibility check', async () => {
const { container } = render()
const results = await axe(container)