Skip to content

feat: add inline confirm dialog and always-visible actions options#2024

Open
lauralesteves wants to merge 4 commits into
umputun:masterfrom
lauralesteves:feature/inline-confirm-and-ux-improvements
Open

feat: add inline confirm dialog and always-visible actions options#2024
lauralesteves wants to merge 4 commits into
umputun:masterfrom
lauralesteves:feature/inline-confirm-and-ux-improvements

Conversation

@lauralesteves

Copy link
Copy Markdown

Summary

This PR adds two new opt-in configuration options to improve the comment widget UX, especially on mobile devices.

Problem

window.confirm() is blocked by iOS Safari inside iframes. This means users on iPhones cannot delete their own comments when the Remark42 widget is embedded via iframe — the confirm dialog never appears and the action silently fails.

Additionally, comment actions (Copy, Pin, Block, Delete) require hover to be visible, which doesn't work on touch devices.

Solution

Two new backwards-compatible config options:

1. inline_confirm (default: false)

Replaces window.confirm() with an inline confirmation dialog rendered directly in the comment component.

Before (broken on iOS):

User taps "Delete" → window.confirm() → blocked by Safari → nothing happens

After:

User taps "Delete" → inline dialog appears below actions → user confirms/cancels

Affected methods in comment.tsx:

  • deleteComment(), togglePin(), toggleVerify(), blockUser(), unblockUser(), hideUser()

Also updated in settings.tsx:

  • block(), unblock()

2. actions_always_visible (default: false)

Shows comment actions (Copy, Pin, Block, Delete) without requiring hover. Improves usability on touch devices.

Usage

var remark_config = {
  host: '...',
  site_id: '...',
  inline_confirm: true,
  actions_always_visible: true,
};

New component

ConfirmDialog — a lightweight inline confirmation dialog that:

  • Renders in-place below the comment actions
  • Uses existing CSS custom properties (works in both dark and light themes)
  • Supports i18n via react-intl (confirm-dialog.confirm, confirm-dialog.cancel)
  • Has role="alertdialog" for accessibility
  • Animates in with a subtle slide-in effect

Files changed

File Change
app/typings/global.d.ts Added inline_confirm and actions_always_visible to RemarkConfig
app/common/settings.ts Parse new config options from query params
app/components/confirm-dialog/ NewConfirmDialog component (tsx + CSS module + index)
app/components/comment/comment.tsx Replace window.confirm() with confirmWithMessage() helper
app/components/comment/comment-actions.tsx Apply alwaysVisible class based on config
app/components/comment/comment-actions.module.css Add .alwaysVisible modifier to skip hover behavior
app/components/settings/settings.tsx Use confirmWithMessage() pattern

Backwards compatibility

Both options default to false, preserving the current behavior. No changes for existing users unless they explicitly opt in.

Test plan

  • Default behavior: window.confirm() works as before
  • inline_confirm=true: inline dialog appears for delete, pin, block, etc.
  • inline_confirm=true on iOS Safari: confirm dialog works inside iframe
  • actions_always_visible=true: actions visible without hover
  • actions_always_visible=false: actions hidden until hover (default)
  • Dark theme: dialog styled correctly
  • Light theme: dialog styled correctly
  • Build passes: pnpm run build and pnpm run type-check succeed
  • Lint passes: stylelint and eslint clean

…options

Replace window.confirm() with an inline ConfirmDialog component when
inline_confirm=true is set. This fixes iOS Safari blocking confirm()
inside iframes, preventing users from deleting their own comments on
mobile devices.

Also add actions_always_visible option to show comment actions (copy,
pin, block, delete) without requiring hover, improving accessibility
on touch devices.

Both options are opt-in via remark_config parameters:
- inline_confirm: uses inline dialog instead of window.confirm()
- actions_always_visible: shows actions without hover

These are backwards-compatible — default behavior is unchanged.
Copilot AI review requested due to automatic review settings May 24, 2026 22:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces two new optional frontend configuration flags to improve widget UX on mobile/touch devices: replacing window.confirm() with an inline confirmation UI (to work around iOS Safari iframe limitations) and optionally keeping comment action buttons visible without hover. It also adds a new GitHub Actions workflow to build and publish Docker images.

Changes:

  • Add inline_confirm and actions_always_visible configuration options and parse them from iframe query params.
  • Introduce an inline ConfirmDialog component and wire it into comment actions that previously used window.confirm().
  • Add a new Docker image build/push workflow under .github/workflows/.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
frontend/apps/remark42/app/typings/global.d.ts Extends RemarkConfig typings with the new opt-in flags.
frontend/apps/remark42/app/common/settings.ts Parses inline_confirm and actions_always_visible from query params.
frontend/apps/remark42/app/components/confirm-dialog/index.ts Exports the new ConfirmDialog component.
frontend/apps/remark42/app/components/confirm-dialog/confirm-dialog.tsx Adds the inline confirmation dialog UI and ARIA attributes.
frontend/apps/remark42/app/components/confirm-dialog/confirm-dialog.module.css Styles and animation for the inline dialog.
frontend/apps/remark42/app/components/comment/comment.tsx Replaces window.confirm() usage with an inline-confirm helper and renders ConfirmDialog.
frontend/apps/remark42/app/components/comment/comment-actions.tsx Adds config-driven class toggle for always-visible actions.
frontend/apps/remark42/app/components/comment/comment-actions.module.css Updates hover-only visibility behavior to allow an always-visible modifier.
frontend/apps/remark42/app/components/settings/settings.tsx Refactors block/unblock confirmations through a helper tied to inlineConfirm.
.github/workflows/build-docker.yml New workflow to build and push Docker images to GHCR.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +67 to +72
confirmWithMessage = (message: string, action: () => void) => {
if (inlineConfirm) {
// For settings page, use inline confirm by replacing the action with a pending state
// For simplicity in settings context, we still use window.confirm as fallback
// since settings page is not inside an iframe
if (window.confirm(message)) {
const intl = useIntl();

return (
<div className={styles.root} role="alertdialog" aria-label={message}>
push:
branches:
- master
- 'feature/**'
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
Comment on lines +172 to +175
if (confirmAction) {
confirmAction.action();
}
this.setState({ confirmAction: null });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants