Skip to content
Merged
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
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- Added a Style Switcher block with selectable theme style variations and configurable icon display behaviour.
- Added a Button Icon selector panel for core Button blocks, including left/right positioning and up/down icon options.
- Added a Back to Top option as a `core/button` variation so users inherit native Button styling controls and icon compatibility.
- Added smooth scrolling support for Back to Top button clicks and internal anchor links using vanilla JavaScript.

### Changed
- Changed Back to Top implementation from a standalone custom block to a `core/button` variation.
- Changed Back to Top frontend targeting to use a dedicated wrapper class (`is-back-to-top`) for reliable JS and CSS behaviour.
- Changed Back to Top visibility to always display (removed scroll-threshold hide/show behaviour).

### Deprecated

### Removed
- Removed the standalone Back to Top block source in favour of variation-based implementation.

### Fixed
- Fixed editor runtime errors from invalid React component handling in Back to Top editor integration.
- Fixed strict mode error in Back to Top animation loop by replacing `arguments.callee` with a named animation step.

### Security

Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,16 @@ composer run phpcs

---

## Back to Top variation (how to use)

1. In the editor, insert a Button block.
2. Select the Back to Top variation from block styles/variations.
3. Publish or update the page.

When clicked on the frontend, the button smoothly scrolls to the top of the page.

---

## AI workflows

| Folder | Purpose |
Expand Down
1 change: 1 addition & 0 deletions build/css/back-to-top.asset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => 'd4bf1d0478307697fd97');
1 change: 1 addition & 0 deletions build/css/button-icon.asset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => 'ee8a3fb648b3838658c7');
1 change: 1 addition & 0 deletions build/css/style-back-to-top-rtl.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions build/css/style-back-to-top.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions build/css/style-button-icon-rtl.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions build/css/style-button-icon.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions build/js/back-to-top-view.asset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => '84a35a129b8cf8105805');
1 change: 1 addition & 0 deletions build/js/back-to-top-view.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions build/js/back-to-top.asset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php return array('dependencies' => array('wp-blocks', 'wp-hooks', 'wp-i18n'), 'version' => '9d676336fdab1bdceaa8');
1 change: 1 addition & 0 deletions build/js/back-to-top.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions build/js/button-icon.asset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'd7bb9b5a3d9658d15028');
1 change: 1 addition & 0 deletions build/js/button-icon.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

118 changes: 118 additions & 0 deletions ls-plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,121 @@ function ls_plugin_init() {
$style_switcher->register_hooks();
}
add_action( 'plugins_loaded', 'ls_plugin_init' );

/**
* Enqueues Button Icon editor assets.
*
* @return void
*/
function ls_plugin_enqueue_button_icon_editor_assets() {
$asset_path = LS_PLUGIN_PLUGIN_DIR . 'build/js/button-icon.asset.php';

if ( ! file_exists( $asset_path ) ) {
return;
}

$asset = include $asset_path;

wp_enqueue_script(
'ls-plugin-button-icon',
LS_PLUGIN_PLUGIN_URL . 'build/js/button-icon.js',
$asset['dependencies'] ?? array(),
$asset['version'] ?? LS_PLUGIN_VERSION,
true
);
}
add_action( 'enqueue_block_editor_assets', 'ls_plugin_enqueue_button_icon_editor_assets' );

/**
* Enqueues Button Icon shared styles for front end and editor.
*
* @return void
*/
function ls_plugin_enqueue_button_icon_styles() {
$asset_path = LS_PLUGIN_PLUGIN_DIR . 'build/css/button-icon.asset.php';

if ( ! file_exists( $asset_path ) ) {
return;
}

$asset = include $asset_path;

wp_enqueue_style(
'ls-plugin-button-icon',
LS_PLUGIN_PLUGIN_URL . 'build/css/style-button-icon.css',
$asset['dependencies'] ?? array(),
$asset['version'] ?? LS_PLUGIN_VERSION
);
}
add_action( 'enqueue_block_assets', 'ls_plugin_enqueue_button_icon_styles' );

/**
* Enqueues Back to Top variation editor assets.
*
* @return void
*/
function ls_plugin_enqueue_back_to_top_editor_assets() {
$asset_path = LS_PLUGIN_PLUGIN_DIR . 'build/js/back-to-top.asset.php';

if ( ! file_exists( $asset_path ) ) {
return;
}

$asset = include $asset_path;

wp_enqueue_script(
'ls-plugin-back-to-top',
LS_PLUGIN_PLUGIN_URL . 'build/js/back-to-top.js',
$asset['dependencies'] ?? array(),
$asset['version'] ?? LS_PLUGIN_VERSION,
true
);
}
add_action( 'enqueue_block_editor_assets', 'ls_plugin_enqueue_back_to_top_editor_assets' );

/**
* Enqueues Back to Top view script for smooth scrolling on front end.
*
* @return void
*/
function ls_plugin_enqueue_back_to_top_view_script() {
$asset_path = LS_PLUGIN_PLUGIN_DIR . 'build/js/back-to-top-view.asset.php';

if ( ! file_exists( $asset_path ) ) {
return;
}

$asset = include $asset_path;

wp_enqueue_script(
'ls-plugin-back-to-top-view',
LS_PLUGIN_PLUGIN_URL . 'build/js/back-to-top-view.js',
$asset['dependencies'] ?? array(),
$asset['version'] ?? LS_PLUGIN_VERSION,
true
);
}
add_action( 'wp_enqueue_scripts', 'ls_plugin_enqueue_back_to_top_view_script' );

/**
* Enqueues Back to Top shared styles for front end and editor.
*
* @return void
*/
function ls_plugin_enqueue_back_to_top_styles() {
$asset_path = LS_PLUGIN_PLUGIN_DIR . 'build/css/back-to-top.asset.php';

if ( ! file_exists( $asset_path ) ) {
return;
}

$asset = include $asset_path;

wp_enqueue_style(
'ls-plugin-back-to-top',
LS_PLUGIN_PLUGIN_URL . 'build/css/style-back-to-top.css',
$asset['dependencies'] ?? array(),
$asset['version'] ?? LS_PLUGIN_VERSION
);
}
add_action( 'enqueue_block_assets', 'ls_plugin_enqueue_back_to_top_styles' );
88 changes: 88 additions & 0 deletions src/plugins/back-to-top/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* Back to Top Variation for core/button
* Registers a "Back to Top" variation of the core Button block with smooth scrolling.
*/

import { addFilter } from '@wordpress/hooks';
import { registerBlockVariation } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';

/**
* Register Back to Top as a core/button variation
*/
registerBlockVariation( 'core/button', {
name: 'back-to-top',
title: __( 'Back to Top', 'ls-plugin' ),
icon: 'arrow-up',
description: __(
'A button that scrolls to the top of the page with smooth animation.',
'ls-plugin'
),
attributes: {
text: __( 'Back to Top', 'ls-plugin' ),
isBackToTop: true,
backToTopPositionMode: 'scroll',
backToTopScrollThreshold: 50,
},
isActive: ( blockAttributes ) => blockAttributes.isBackToTop === true,
} );

/**
* Add back-to-top attributes to core/button
*/
addFilter(
'blocks.registerBlockType',
'ls-plugin/add-back-to-top-attributes',
( settings ) => {
if ( settings.name !== 'core/button' ) {
return settings;
}

return {
...settings,
attributes: {
...settings.attributes,
isBackToTop: {
type: 'boolean',
default: false,
},
backToTopPositionMode: {
type: 'string',
default: 'scroll',
},
backToTopScrollThreshold: {
type: 'number',
default: 50,
},
},
};
}
);

/**
* Add back-to-top inspector controls and editor classes
* We don't need to override BlockEdit - the attributes filter handles everything
*/

/**
* Add back-to-top data attributes to saved button markup
*/
addFilter(
'blocks.getSaveContent.extraProps',
'ls-plugin/back-to-top-save-props',
( extraProps, blockType, attributes ) => {
if ( blockType.name !== 'core/button' || ! attributes.isBackToTop ) {
return extraProps;
}

const classes = [ extraProps.className, 'is-back-to-top' ]
.filter( Boolean )
.join( ' ' );

return {
...extraProps,
className: classes,
'data-back-to-top-mode': attributes.backToTopPositionMode || 'scroll',
};
}
);
Loading