From 8b18459dda3845166cf301b924749ba277a319f6 Mon Sep 17 00:00:00 2001
From: unknown
Date: Tue, 21 Jul 2026 09:46:16 +0800
Subject: [PATCH] feat(widgets): Highlights animate + ComboInfo gutters/style
depth
Add scroll-in animation and lazy covers for highlights; combo cards
use row gutters, zibll CSS vars, and optional obs animation.
---
src/AKSRT/Widgets/WidgetComboInfo.php | 33 ++++++++++--
src/AKSRT/Widgets/WidgetHighlights.php | 72 +++++++++++++++++---------
2 files changed, 76 insertions(+), 29 deletions(-)
diff --git a/src/AKSRT/Widgets/WidgetComboInfo.php b/src/AKSRT/Widgets/WidgetComboInfo.php
index 61e6514e..07feca43 100644
--- a/src/AKSRT/Widgets/WidgetComboInfo.php
+++ b/src/AKSRT/Widgets/WidgetComboInfo.php
@@ -44,16 +44,29 @@ class WidgetComboInfo extends \WP_Widget {
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
- $style = sprintf('--aksrt-zci-radius:%dpx;--aksrt-zci-band-h:%dpx;--aksrt-zci-pc:%d;--aksrt-zci-m:%d;', $radius, $band_h, $pc_row, $m_row);
- $wrap = 'aksrt-combo-info' . ($top_band ? ' has-band' : '');
+ $style = sprintf('--aksrt-zci-radius:%dpx;--aksrt-zci-band-h:%dpx;--aksrt-zci-pc:%d;--aksrt-zci-m:%d;--zci-radius:%dpx;--zci-band-h:%dpx;', $radius, $band_h, $pc_row, $m_row, $radius, $band_h);
+ $wrap = 'aksrt-combo-info zib-combo-info-card row gutters-10' . ($top_band ? ' has-band zci-has-band' : '');
+ $anim = sanitize_key((string) ($instance['obs_animation'] ?? ''));
+ $anim_repeat = !empty($instance['animation_repeat']);
+ $pc_span = max(1, (int) floor(12 / $pc_row));
+ $m_span = max(1, (int) floor(12 / $m_row));
+ $col = 'col-sm-' . $pc_span . ' col-xs-' . $m_span;
echo '';
$auto_idx = 0;
+ $ci = 0;
foreach ($cards as $card) {
$html = $this->render_card($card, $cta_default, $auto_idx, $go_link, $top_band);
- if ($html !== '') {
- echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ if ($html === '') {
+ continue;
}
+ $pack = function_exists('aksrt_obs_animate_attrs')
+ ? aksrt_obs_animate_attrs($anim, $anim_repeat, $ci * 0.1)
+ : ['class' => '', 'attr' => ''];
+ echo '
'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ echo '
';
+ $ci++;
}
echo '
';
@@ -219,6 +232,16 @@ class WidgetComboInfo extends \WP_Widget {
+
+
+
max(20, min(160, (int) ($new_instance['top_band_height'] ?? 70))),
'cta_text' => sanitize_text_field((string) ($new_instance['cta_text'] ?? '')),
'go_link' => !empty($new_instance['go_link']) ? 1 : 0,
+ 'obs_animation' => sanitize_key((string) ($new_instance['obs_animation'] ?? '')),
+ 'animation_repeat'=> !empty($new_instance['animation_repeat']) ? 1 : 0,
];
}
}
diff --git a/src/AKSRT/Widgets/WidgetHighlights.php b/src/AKSRT/Widgets/WidgetHighlights.php
index f9f1d12f..a87999a4 100644
--- a/src/AKSRT/Widgets/WidgetHighlights.php
+++ b/src/AKSRT/Widgets/WidgetHighlights.php
@@ -1,6 +1,6 @@
$args
+ * @param array $instance
+ */
public function widget($args, $instance): void {
$cards = $this->normalize($instance['cards'] ?? []);
if (!$cards) {
return;
}
$go_link = !empty($instance['go_link']);
+ $anim = sanitize_key((string) ($instance['obs_animation'] ?? 'slideup'));
+ $anim_repeat = !empty($instance['animation_repeat']);
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base);
@@ -38,30 +44,23 @@ class WidgetHighlights extends \WP_Widget {
$large = array_values(array_filter($cards, static fn($c) => ($c['size'] ?? 'medium') === 'large'));
$medium = array_values(array_filter($cards, static fn($c) => ($c['size'] ?? 'medium') === 'medium'));
$small = array_values(array_filter($cards, static fn($c) => ($c['size'] ?? 'medium') === 'small'));
- // Fallback: if no size tags, treat all as medium.
if (!$large && !$medium && !$small) {
$medium = $cards;
}
echo '';
- if ($large) {
- echo '
';
- foreach ($large as $c) {
- echo $this->card($c, 'large', $go_link); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ $idx = 0;
+ foreach (['large' => $large, 'medium' => $medium, 'small' => $small] as $size => $group) {
+ if (!$group) {
+ continue;
}
- echo '
';
- }
- if ($medium) {
- echo '
';
- foreach ($medium as $c) {
- echo $this->card($c, 'medium', $go_link); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
- }
- echo '
';
- }
- if ($small) {
- echo '
';
- foreach ($small as $c) {
- echo $this->card($c, 'small', $go_link); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ echo '
';
+ foreach ($group as $c) {
+ $pack = function_exists('aksrt_obs_animate_attrs')
+ ? aksrt_obs_animate_attrs($anim, $anim_repeat, $idx * 0.08)
+ : ['class' => '', 'attr' => ''];
+ echo $this->card($c, $size, $go_link, $pack); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+ $idx++;
}
echo '
';
}
@@ -72,8 +71,9 @@ class WidgetHighlights extends \WP_Widget {
/**
* @param array
$c
+ * @param array{class:string,attr:string} $pack
*/
- private function card(array $c, string $size, bool $go_link): string {
+ private function card(array $c, string $size, bool $go_link, array $pack): string {
$color = sanitize_key((string) ($c['color'] ?? 'blue'));
if (!in_array($color, ['blue', 'pink', 'purple', 'green', 'orange', 'cyan'], true)) {
$color = 'blue';
@@ -85,9 +85,11 @@ class WidgetHighlights extends \WP_Widget {
$tag = $url !== '' ? 'a' : 'div';
$href = $url !== '' ? ' href="' . esc_url($url) . '"' : '';
$img = (string) ($c['image'] ?? '');
- $html = '<' . $tag . ' class="aksrt-hl-card size-' . esc_attr($size) . ' color-' . esc_attr($color) . '"' . $href . '>';
+ $cls = 'aksrt-hl-card size-' . esc_attr($size) . ' color-' . esc_attr($color) . $pack['class'];
+ $html = '<' . $tag . ' class="' . esc_attr(trim($cls)) . '"' . $href . $pack['attr'] . '>';
if ($img !== '') {
- $html .= '';
+ $placeholder = get_template_directory_uri() . '/assets/img/placeholder.svg';
+ $html .= '';
}
$html .= '';
if (!empty($c['icon'])) {
@@ -145,6 +147,9 @@ class WidgetHighlights extends \WP_Widget {
return $out;
}
+ /**
+ * @param array
$instance
+ */
public function form($instance): void {
$json = is_string($instance['cards'] ?? null)
? (string) $instance['cards']
@@ -161,17 +166,34 @@ class WidgetHighlights extends \WP_Widget {
+
+
+
$new_instance
+ * @param array $old_instance
+ * @return array
+ */
public function update($new_instance, $old_instance): array {
return [
- 'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
- 'cards' => $this->normalize($new_instance['cards'] ?? []),
- 'go_link' => !empty($new_instance['go_link']) ? 1 : 0,
+ 'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
+ 'cards' => $this->normalize($new_instance['cards'] ?? []),
+ 'go_link' => !empty($new_instance['go_link']) ? 1 : 0,
+ 'obs_animation' => sanitize_key((string) ($new_instance['obs_animation'] ?? 'slideup')),
+ 'animation_repeat' => !empty($new_instance['animation_repeat']) ? 1 : 0,
];
}
}