diff --git a/src/components/ContactBook/AddContact.test.tsx b/src/components/ContactBook/AddContact.test.tsx
new file mode 100644
index 0000000..23ee260
--- /dev/null
+++ b/src/components/ContactBook/AddContact.test.tsx
@@ -0,0 +1,23 @@
+import React from 'react'
+import { describe, it, expect, vi } from 'vitest'
+import { render, screen, fireEvent } from '@testing-library/react'
+import { AddContact } from './AddContact'
+
+describe('AddContact accessible labeling', () => {
+ it('associates inputs with accessible labels', () => {
+ render()
+
+ expect(screen.getByLabelText(/contact name/i)).toBeInTheDocument()
+ expect(screen.getByLabelText(/stellar address/i)).toBeInTheDocument()
+ })
+
+ it('validates required fields on submit', () => {
+ const onAdd = vi.fn()
+ render()
+
+ fireEvent.click(screen.getByRole('button', { name: /add/i }))
+ expect(screen.getByText(/name is required/i)).toBeInTheDocument()
+ expect(screen.getByText(/invalid stellar address/i)).toBeInTheDocument()
+ expect(onAdd).not.toHaveBeenCalled()
+ })
+})
diff --git a/src/components/ContactBook/AddContact.tsx b/src/components/ContactBook/AddContact.tsx
index 2d5094c..711a10d 100644
--- a/src/components/ContactBook/AddContact.tsx
+++ b/src/components/ContactBook/AddContact.tsx
@@ -1,5 +1,6 @@
import React, { useState } from 'react'
import { isValidStellarAddress } from '../../utils/stellar'
+import { VisuallyHidden } from '../common/VisuallyHidden'
import type { Contact } from './ContactItem'
interface Props {
@@ -23,16 +24,36 @@ export function AddContact({ onAdd, onCancel }: Props) {
return (
Add contact
-
setName(e.target.value)}
- placeholder="Name" className="input w-full"
- />
- {errors.name &&
{errors.name}
}
-
setAddress(e.target.value.trim())}
- placeholder="G... address" className="input w-full font-mono"
- />
- {errors.address &&
{errors.address}
}
+
+
+
setName(e.target.value)}
+ placeholder="Name"
+ className="input w-full"
+ aria-invalid={!!errors.name}
+ aria-describedby={errors.name ? "contact-name-error" : undefined}
+ />
+ {errors.name &&
{errors.name}
}
+
+
+
+
setAddress(e.target.value.trim())}
+ placeholder="G... address"
+ className="input w-full font-mono"
+ aria-invalid={!!errors.address}
+ aria-describedby={errors.address ? "contact-address-error" : undefined}
+ />
+ {errors.address &&
{errors.address}
}
+