feat(ux): accessible confirm dialog replaces window.confirm

- new components/ui/confirm.tsx: ConfirmProvider + useConfirm() built
  on the existing Radix alert-dialog (focus trap, ESC, aria for free)
- wired once into the app layout
- all 13 native window.confirm() delete/remove guards now use the
  styled, accessible confirm with a destructive action button
This commit is contained in:
Moheeb Zara
2026-05-15 22:18:15 -07:00
parent 64d7d626db
commit 1db9434930
14 changed files with 132 additions and 13 deletions
+3 -1
View File
@@ -8,6 +8,7 @@ import { toast } from 'sonner'
import { useRouter } from 'next/navigation'
import type { Tables } from '@/types/database'
import { PageTitle } from '@/components/ui/page-title'
import { useConfirm } from '@/components/ui/confirm'
type Member = Tables<'space_members'>
type AreaLeadRole = { id: string; area_name: string; lead_id: string | null }
@@ -29,6 +30,7 @@ const isAdmin = (role: string) => role === 'admin' || role === 'board'
export function MembersClient({ members: initialMembers, currentRole, areaLeadRoles = [] }: Props) {
const router = useRouter()
const confirm = useConfirm()
const [members, setMembers] = useState<Member[]>(initialMembers)
async function makeAreaLead(memberId: string, areaLeadRoleId: string) {
@@ -105,7 +107,7 @@ export function MembersClient({ members: initialMembers, currentRole, areaLeadRo
}
async function handleRemove(memberId: string) {
if (!confirm('Remove this member from the space?')) return
if (!(await confirm({ title: 'Remove member', description: 'This member will be removed from the space.', confirmText: 'Remove', destructive: true }))) return
const result = await removeMember(memberId)
if (!result.error) {
setMembers(prev => prev.filter(m => m.id !== memberId))