feat: add inline confirm dialog and always-visible actions options#2024
Open
lauralesteves wants to merge 4 commits into
Open
feat: add inline confirm dialog and always-visible actions options#2024lauralesteves wants to merge 4 commits into
lauralesteves wants to merge 4 commits into
Conversation
…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.
There was a problem hiding this comment.
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_confirmandactions_always_visibleconfiguration options and parse them from iframe query params. - Introduce an inline
ConfirmDialogcomponent and wire it into comment actions that previously usedwindow.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 }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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):
After:
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
New component
ConfirmDialog— a lightweight inline confirmation dialog that:react-intl(confirm-dialog.confirm,confirm-dialog.cancel)role="alertdialog"for accessibilityFiles changed
app/typings/global.d.tsinline_confirmandactions_always_visibletoRemarkConfigapp/common/settings.tsapp/components/confirm-dialog/ConfirmDialogcomponent (tsx + CSS module + index)app/components/comment/comment.tsxwindow.confirm()withconfirmWithMessage()helperapp/components/comment/comment-actions.tsxalwaysVisibleclass based on configapp/components/comment/comment-actions.module.css.alwaysVisiblemodifier to skip hover behaviorapp/components/settings/settings.tsxconfirmWithMessage()patternBackwards compatibility
Both options default to
false, preserving the current behavior. No changes for existing users unless they explicitly opt in.Test plan
window.confirm()works as beforeinline_confirm=true: inline dialog appears for delete, pin, block, etc.inline_confirm=trueon iOS Safari: confirm dialog works inside iframeactions_always_visible=true: actions visible without hoveractions_always_visible=false: actions hidden until hover (default)pnpm run buildandpnpm run type-checksucceed