Skip to content

Commit f13600c

Browse files
committed
feat(dialogs): implement neo-brutalism styled alert dialogs for user actions
1 parent 22c9155 commit f13600c

File tree

9 files changed

+560
-98
lines changed

9 files changed

+560
-98
lines changed

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- **Alert Dialog Component**: Installed neo-brutalism styled alert-dialog component from neobrutalism.dev
13+
- **Confirmation Dialogs**: Implemented confirmation dialogs for all major destructive actions across the application
14+
- Post deletion and publishing in PostsTable (mobile and desktop views)
15+
- User account deletion in UserManagement (mobile and desktop views)
16+
- Category and tag deletion in TaxonomyManager
17+
- Comment deletion in CommentsModeration
18+
- Sign out action in UserAccountPanel
19+
- **Improved UX**: Replaced native `window.confirm` dialogs with accessible, styled AlertDialog components
20+
- **Consistent Design**: All confirmation dialogs follow neo-brutalism theme with clear action descriptions
21+
22+
### Changed
23+
24+
- Updated PostsTable to use AlertDialog for delete and publish confirmations
25+
- Updated UserManagement to use AlertDialog for user deletion with proper context
26+
- Updated TaxonomyManager to use AlertDialog for category and tag deletions
27+
- Updated CommentsModeration to use AlertDialog for comment deletion
28+
- Updated UserAccountPanel to use AlertDialog for sign out confirmation
29+
- Removed `window.confirm` usage in favor of accessible AlertDialog components
30+
1031
### Planned - Library Feature
1132
- **User Library System**: Complete Medium-style library feature for saving and organizing content
1233
- Your Library: Central dashboard for all saved content

package-lock.json

Lines changed: 58 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"@hcaptcha/react-hcaptcha": "^1.12.1",
1717
"@modelcontextprotocol/sdk": "^1.19.1",
1818
"@radix-ui/react-accordion": "^1.2.8",
19+
"@radix-ui/react-alert-dialog": "^1.1.15",
1920
"@radix-ui/react-checkbox": "^1.3.3",
2021
"@radix-ui/react-collapsible": "^1.1.12",
2122
"@radix-ui/react-dialog": "^1.1.15",

src/components/admin/CommentsModeration.tsx

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33
import { useMemo } from 'react'
44
import { Check, Loader2, MessageSquareWarning, RefreshCcw, Trash2, XCircle } from 'lucide-react'
55
import { CommentStatus, type AdminCommentSummary } from '@/utils/types'
6+
import {
7+
AlertDialog,
8+
AlertDialogAction,
9+
AlertDialogCancel,
10+
AlertDialogContent,
11+
AlertDialogDescription,
12+
AlertDialogFooter,
13+
AlertDialogHeader,
14+
AlertDialogTitle,
15+
AlertDialogTrigger,
16+
} from '@/components/ui/alert-dialog'
617

718
interface CommentsModerationProps {
819
comments: AdminCommentSummary[]
@@ -163,13 +174,30 @@ export const CommentsModeration = ({
163174
>
164175
<XCircle className="h-4 w-4" aria-hidden="true" /> Reject
165176
</button>
166-
<button
167-
type="button"
168-
onClick={() => onDelete(comment.id)}
169-
className="inline-flex items-center gap-1 rounded-md border-2 border-red-500/40 px-3 py-1 text-sm font-semibold text-red-600 transition hover:bg-red-50"
170-
>
171-
<Trash2 className="h-4 w-4" aria-hidden="true" /> Delete
172-
</button>
177+
<AlertDialog>
178+
<AlertDialogTrigger asChild>
179+
<button
180+
type="button"
181+
className="inline-flex items-center gap-1 rounded-md border-2 border-red-500/40 px-3 py-1 text-sm font-semibold text-red-600 transition hover:bg-red-50"
182+
>
183+
<Trash2 className="h-4 w-4" aria-hidden="true" /> Delete
184+
</button>
185+
</AlertDialogTrigger>
186+
<AlertDialogContent>
187+
<AlertDialogHeader>
188+
<AlertDialogTitle>Delete comment?</AlertDialogTitle>
189+
<AlertDialogDescription>
190+
This will permanently delete this comment from {comment.authorName}. This action cannot be undone.
191+
</AlertDialogDescription>
192+
</AlertDialogHeader>
193+
<AlertDialogFooter>
194+
<AlertDialogCancel>Cancel</AlertDialogCancel>
195+
<AlertDialogAction onClick={() => onDelete(comment.id)}>
196+
Delete Comment
197+
</AlertDialogAction>
198+
</AlertDialogFooter>
199+
</AlertDialogContent>
200+
</AlertDialog>
173201
</div>
174202
</li>
175203
))}

src/components/admin/PostsTable.tsx

Lines changed: 113 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@ import {
99
RotateCcw,
1010
} from 'lucide-react'
1111
import { AdminPost, PostStatus } from '../../utils/types'
12+
import {
13+
AlertDialog,
14+
AlertDialogAction,
15+
AlertDialogCancel,
16+
AlertDialogContent,
17+
AlertDialogDescription,
18+
AlertDialogFooter,
19+
AlertDialogHeader,
20+
AlertDialogTitle,
21+
AlertDialogTrigger,
22+
} from '@/components/ui/alert-dialog'
1223

1324
interface PostsTableProps {
1425
posts: AdminPost[]
@@ -144,28 +155,65 @@ export const PostsTable = ({
144155
</div>
145156
<div className="flex flex-wrap gap-2 pt-2">
146157
<button
158+
type="button"
147159
onClick={() => onEdit(post)}
148160
className="flex flex-1 items-center justify-center gap-1 rounded-md bg-[#6C63FF] px-3 py-2 text-sm font-semibold text-white shadow-sm transition hover:opacity-90"
149161
title="Edit"
150162
>
151163
<Pencil className="h-4 w-4" /> Edit
152164
</button>
153165
{post.status !== PostStatus.PUBLISHED && (
154-
<button
155-
onClick={() => onPublish(post.id)}
156-
className="flex flex-1 items-center justify-center gap-1 rounded-md bg-[#06D6A0] px-3 py-2 text-sm font-semibold text-white shadow-sm transition hover:opacity-90"
157-
title="Publish"
158-
>
159-
<ArrowUpRight className="h-4 w-4" /> Publish
160-
</button>
166+
<AlertDialog>
167+
<AlertDialogTrigger asChild>
168+
<button
169+
type="button"
170+
className="flex flex-1 items-center justify-center gap-1 rounded-md bg-[#06D6A0] px-3 py-2 text-sm font-semibold text-white shadow-sm transition hover:opacity-90"
171+
title="Publish"
172+
>
173+
<ArrowUpRight className="h-4 w-4" /> Publish
174+
</button>
175+
</AlertDialogTrigger>
176+
<AlertDialogContent>
177+
<AlertDialogHeader>
178+
<AlertDialogTitle>Publish this post?</AlertDialogTitle>
179+
<AlertDialogDescription>
180+
This will make &quot;{post.title}&quot; visible to all readers. You can unpublish it later if needed.
181+
</AlertDialogDescription>
182+
</AlertDialogHeader>
183+
<AlertDialogFooter>
184+
<AlertDialogCancel>Cancel</AlertDialogCancel>
185+
<AlertDialogAction onClick={() => onPublish(post.id)}>
186+
Publish Now
187+
</AlertDialogAction>
188+
</AlertDialogFooter>
189+
</AlertDialogContent>
190+
</AlertDialog>
161191
)}
162-
<button
163-
onClick={() => onDelete(post.id)}
164-
className="flex flex-1 items-center justify-center gap-1 rounded-md bg-[#FF5252] px-3 py-2 text-sm font-semibold text-white shadow-sm transition hover:opacity-90"
165-
title="Delete"
166-
>
167-
<Trash2 className="h-4 w-4" /> Delete
168-
</button>
192+
<AlertDialog>
193+
<AlertDialogTrigger asChild>
194+
<button
195+
type="button"
196+
className="flex flex-1 items-center justify-center gap-1 rounded-md bg-[#FF5252] px-3 py-2 text-sm font-semibold text-white shadow-sm transition hover:opacity-90"
197+
title="Delete"
198+
>
199+
<Trash2 className="h-4 w-4" /> Delete
200+
</button>
201+
</AlertDialogTrigger>
202+
<AlertDialogContent>
203+
<AlertDialogHeader>
204+
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
205+
<AlertDialogDescription>
206+
This will permanently delete &quot;{post.title}&quot;. This action cannot be undone and will remove all associated data.
207+
</AlertDialogDescription>
208+
</AlertDialogHeader>
209+
<AlertDialogFooter>
210+
<AlertDialogCancel>Cancel</AlertDialogCancel>
211+
<AlertDialogAction onClick={() => onDelete(post.id)}>
212+
Delete Post
213+
</AlertDialogAction>
214+
</AlertDialogFooter>
215+
</AlertDialogContent>
216+
</AlertDialog>
169217
</div>
170218
</div>
171219
</article>
@@ -232,28 +280,65 @@ export const PostsTable = ({
232280
<td className="p-4">
233281
<div className="flex items-center justify-end gap-2">
234282
<button
283+
type="button"
235284
onClick={() => onEdit(post)}
236285
className="rounded-md bg-[#6C63FF] p-2 text-white transition hover:opacity-90"
237286
title="Edit"
238287
>
239288
<Pencil className="h-4 w-4" />
240289
</button>
241290
{post.status !== PostStatus.PUBLISHED && (
242-
<button
243-
onClick={() => onPublish(post.id)}
244-
className="rounded-md bg-[#06D6A0] p-2 text-white transition hover:opacity-90"
245-
title="Publish"
246-
>
247-
<ArrowUpRight className="h-4 w-4" />
248-
</button>
291+
<AlertDialog>
292+
<AlertDialogTrigger asChild>
293+
<button
294+
type="button"
295+
className="rounded-md bg-[#06D6A0] p-2 text-white transition hover:opacity-90"
296+
title="Publish"
297+
>
298+
<ArrowUpRight className="h-4 w-4" />
299+
</button>
300+
</AlertDialogTrigger>
301+
<AlertDialogContent>
302+
<AlertDialogHeader>
303+
<AlertDialogTitle>Publish this post?</AlertDialogTitle>
304+
<AlertDialogDescription>
305+
This will make &quot;{post.title}&quot; visible to all readers. You can unpublish it later if needed.
306+
</AlertDialogDescription>
307+
</AlertDialogHeader>
308+
<AlertDialogFooter>
309+
<AlertDialogCancel>Cancel</AlertDialogCancel>
310+
<AlertDialogAction onClick={() => onPublish(post.id)}>
311+
Publish Now
312+
</AlertDialogAction>
313+
</AlertDialogFooter>
314+
</AlertDialogContent>
315+
</AlertDialog>
249316
)}
250-
<button
251-
onClick={() => onDelete(post.id)}
252-
className="rounded-md bg-[#FF5252] p-2 text-white transition hover:opacity-90"
253-
title="Delete"
254-
>
255-
<Trash2 className="h-4 w-4" />
256-
</button>
317+
<AlertDialog>
318+
<AlertDialogTrigger asChild>
319+
<button
320+
type="button"
321+
className="rounded-md bg-[#FF5252] p-2 text-white transition hover:opacity-90"
322+
title="Delete"
323+
>
324+
<Trash2 className="h-4 w-4" />
325+
</button>
326+
</AlertDialogTrigger>
327+
<AlertDialogContent>
328+
<AlertDialogHeader>
329+
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
330+
<AlertDialogDescription>
331+
This will permanently delete &quot;{post.title}&quot;. This action cannot be undone and will remove all associated data.
332+
</AlertDialogDescription>
333+
</AlertDialogHeader>
334+
<AlertDialogFooter>
335+
<AlertDialogCancel>Cancel</AlertDialogCancel>
336+
<AlertDialogAction onClick={() => onDelete(post.id)}>
337+
Delete Post
338+
</AlertDialogAction>
339+
</AlertDialogFooter>
340+
</AlertDialogContent>
341+
</AlertDialog>
257342
</div>
258343
</td>
259344
</tr>

0 commit comments

Comments
 (0)