Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,9 @@ Follow:
- Keep focus in the inline editor after a failed request and announce the returned message through its status region.
- Disable every editor action while a save or deletion is in progress, then restore the relevant controls on a retryable failure.
- Keep the optional Quicktags toolbar within the editor width and allow its native buttons to wrap on narrow screens.
- Keep controls hidden and outside keyboard navigation until the uncached `sce_get_time_left` AJAX response confirms permission. A failed check must not reveal the editor.
- Retain the default 0.6-second reveal, but skip it when the browser requests `prefers-reduced-motion: reduce` or WP ULike is active (`WP_ULIKE_VERSION`). Plugins can override the latter policy through `sce_skip_control_reveal` (boolean, comment ID); they cannot override the browser preference. No admin setting is added. This changes presentation only, not ownership, nonces, or edit windows, and does not synchronize independent permission requests.
- Do not infer immediate permission from HTML, login state, or unlimited-editing settings: personalized comment pages must bypass shared caches, and an authoritative AJAX round trip is still required.

Avoid:

Expand All @@ -311,6 +314,7 @@ Responsive/accessibility notes:
- Keyboard users must be able to open, cancel, save, and delete through native button behavior.
- When Quicktags is enabled, its native keyboard-accessible toolbar is an enhancement to the textarea, not a replacement for save, cancel, or error feedback.
- The editor's error status is announced immediately; the action preserves its expanded state when a retry is possible.
- Motion preferences must not move focus or change button themes. Preserve the existing stacked save/cancel/delete layout at widths up to 600px; verify the same controls at desktop and mobile widths.

#### Frontend asset loading controls

Expand Down
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,27 @@ See "Styles" section.

## WordPress Filters

### sce_skip_control_reveal - Skip the decorative control animation

SCE normally fades authorized controls in over 0.6 seconds. This filter receives
the default boolean (true when WP ULike is active, detected by `WP_ULIKE_VERSION`)
and the comment ID. There is no admin setting. For example, another plugin can
skip the animation for every comment:

```php
add_filter( 'sce_skip_control_reveal', '__return_true' );
```

Return false to retain the fade even with WP ULike. The browser's
`prefers-reduced-motion: reduce` preference always disables the animation,
regardless of the filter. This affects presentation across all button themes,
not authorization: controls still wait for the server's ownership/time check,
and failed checks keep them hidden. WP ULike's independent rendering can finish
earlier; this removes the extra fade, not the permission round trip. Purge cached
pages after changing the filter or WP ULike activation. Personalized author
pages must bypass shared caches; hidden controls cannot protect private textarea
content in incorrectly cached HTML.

### sce_loading_img - Change the loading image
```php
/**
Expand Down
2 changes: 1 addition & 1 deletion dist/sce-editing.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/sce-frontend.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/sce-frontend.css.map

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ Bundled translations provide the default frontend labels and countdown text when
= Can commenters use an HTML toolbar? =
Yes. Enable Quicktags Toolbar in Settings -> Simple Comment Editing to add WordPress's native Quicktags toolbar to the comment editor. It is disabled by default, does not load TinyMCE or CKEditor, and can be left disabled when another plugin uses the documented JavaScript editor lifecycle.

= Can edit controls appear without the fade-in delay? =
Yes. SCE respects the browser's reduced-motion preference and skips the decorative 0.6-second reveal animation for all button themes. It also skips the animation when WP ULike is active, to avoid an extra fade beside its like buttons. There is no admin setting. Plugins can use `add_filter( 'sce_skip_control_reveal', '__return_true' );` to skip the animation, or return false to opt out of the WP ULike default. The filter receives the default boolean and comment ID. Returning false never overrides the browser's reduced-motion preference. Keyboard behavior and the edit timer are unchanged.

This is a presentation policy, not immediate authorization or a measured network speedup. Controls remain hidden until the server confirms ownership and the remaining edit time, including for logged-in authors with unlimited editing. Independent plugin requests can still finish at different times. Failed permission requests keep controls hidden. Save and Delete still validate permissions and nonces on the server. Personalized pages for logged-in users or guest authors with editing cookies must bypass shared page/CDN caches; hiding controls cannot protect private textarea content already included in incorrectly shared HTML. Purge cached pages after changing the filter or WP ULike activation.

= Can I add custom fields or use a custom comment loop? =
Yes. The integration guide in the GitHub README documents comment-scoped extra fields, safe metadata saving, custom loops that call WordPress's native `comment_text()` path, button HTML, and inline action-row styling. Keep SCE's editor wrappers and controls intact so its nonce, ownership checks, Save, Cancel, and Delete actions continue to work.

Expand Down Expand Up @@ -113,6 +118,7 @@ You can report security bugs through the Patchstack Vulnerability Disclosure Pro
== Changelog ==

= Unreleased =
* New: Respect browser reduced-motion preferences, skip the control reveal when WP ULike is active, and add the sce_skip_control_reveal filter without skipping server permission checks.
* New: Add a repeat-safe, root-scoped initializer for AJAX/lazy-loaded comment controls and an opt-in guest ownership hook for validated AJAX submissions.
* New: Add an optional native Quicktags toolbar and lifecycle hooks for external comment editors.
* Docs: Add supported custom-field, custom-loop, button HTML, and inline action-row integration examples.
Expand Down
13 changes: 13 additions & 0 deletions simple-comment-editing.php
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,19 @@ public function add_edit_interface( $comment_content, $passed_comment = false )
$comment_wrapper = sprintf( '<div id="sce-comment%d" class="sce-comment">%s</div>', $comment_id, $comment_content );

$classes = array( 'sce-edit-comment' );
/**
* Skip the decorative control reveal, not the server permission check.
*
* WP ULike displays its buttons without a fade. Match that presentation
* by default when it is active. CSS always respects reduced motion,
* even when this filter returns false.
*
* @param bool $skip_reveal Whether to skip the reveal animation.
* @param int $comment_id The comment ID.
*/
if ( apply_filters( 'sce_skip_control_reveal', defined( 'WP_ULIKE_VERSION' ), $comment_id ) ) {
$classes[] = 'sce-reduced-motion';
}
/**
* Filter: sce_wrapper_class
*
Expand Down
6 changes: 4 additions & 2 deletions src/js/comment-editing/editing.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,8 @@ const setup = () => {
const { data } = response.data;
let { minutes, seconds } = data;
const { can_edit } = data;
if ( ! can_edit ) {
// Cached markup is not proof of ownership, including for unlimited editing.
if ( true !== can_edit ) {
releaseComment( commentId );
button.parentNode.remove();
return;
Expand Down Expand Up @@ -554,7 +555,8 @@ const setup = () => {
return;
}
delete timers[ commentId ]; // Allow an explicit retry after a failed request.
showEditButton( button );
// A failed permission request must not expose cached author controls.
hideEditButton( button );
showStatus( commentId, error.message || simple_comment_editing.comment_deleted_error, true );
} );

Expand Down
9 changes: 9 additions & 0 deletions src/scss/frontend.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Animation for showing container */
}

.sce-hide {
visibility: hidden;
opacity: 0;
height: 0;
overflow: hidden;
Expand All @@ -29,6 +30,14 @@ Animation for showing container */
opacity: 1;
height: auto;
}
.sce-reduced-motion .sce-show {
animation: none;
}
@media (prefers-reduced-motion: reduce) {
.sce-edit-comment .sce-show {
animation: none;
}
}
.sce-comment-edit-buttons {
.sce-comment-edit-buttons-group {
display: flex;
Expand Down
Loading