fix(header): 1:1 zibll overlay icon cards for top multifunc component
Rebuild header-slider card DOM/CSS against zib_header_slide + zib_icon_cover_card so shared/individual backgrounds, flex gutters, and badge icons match the reference theme.
This commit is contained in:
1 parent
bbdeeafc80
commit
e35011f2c0
7 files changed
+384
-463
No files matched your search
@@ -135,103 +135,165 @@ if (!function_exists('aksrt_icon_cover_card')) :
|
||||
* @param bool $echo
|
||||
*/
|
||||
function aksrt_icon_cover_card(array $args = [], bool $echo = false): string {
|
||||
$defaults = [
|
||||
'class' => 'zib-widget',
|
||||
'icon' => '',
|
||||
'icon_size' => 25,
|
||||
'customize_icon' => '',
|
||||
'icon_image' => '',
|
||||
'link' => [
|
||||
'url' => '',
|
||||
'target' => '',
|
||||
],
|
||||
'icon_radius' => false,
|
||||
'icon_color' => '',
|
||||
'icon_custom_color' => '',
|
||||
'icon_class' => '',
|
||||
'title' => '',
|
||||
'desc' => '',
|
||||
];
|
||||
$args = wp_parse_args($args, $defaults);
|
||||
$defaults = [
|
||||
'class' => 'zib-widget',
|
||||
'icon' => '',
|
||||
'icon_size' => 25,
|
||||
'customize_icon' => '',
|
||||
'custom_icon' => '',
|
||||
'icon_image' => '',
|
||||
'link' => [
|
||||
'url' => '',
|
||||
'target' => '',
|
||||
],
|
||||
// Flat keys used by header_components_icon_cards admin schema.
|
||||
'url' => '',
|
||||
'target' => '',
|
||||
'icon_radius' => false,
|
||||
'icon_color' => '',
|
||||
'icon_custom_color' => '',
|
||||
'icon_class' => '',
|
||||
'title' => '',
|
||||
'desc' => '',
|
||||
];
|
||||
$args = wp_parse_args($args, $defaults);
|
||||
|
||||
$icon_fa = sanitize_text_field((string) $args['icon']);
|
||||
$icon_img = esc_url_raw(trim((string) ($args['icon_image'] !== '' ? $args['icon_image'] : '')));
|
||||
$custom_html = '';
|
||||
if ($icon_img === '' && is_string($args['customize_icon']) && str_contains((string) $args['customize_icon'], '<')) {
|
||||
$custom_html = wp_kses((string) $args['customize_icon'], [
|
||||
'i' => ['class' => true, 'aria-hidden' => true],
|
||||
'img' => ['src' => true, 'alt' => true, 'class' => true, 'loading' => true],
|
||||
'span'=> ['class' => true],
|
||||
]);
|
||||
} elseif ($icon_img === '' && is_string($args['customize_icon']) && filter_var((string) $args['customize_icon'], FILTER_VALIDATE_URL)) {
|
||||
$icon_img = esc_url_raw((string) $args['customize_icon']);
|
||||
}
|
||||
if ($icon_fa === '' && $icon_img === '' && $custom_html === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$link = $args['link'];
|
||||
if (is_string($link)) {
|
||||
$link = ['url' => $link, 'target' => ''];
|
||||
}
|
||||
if (!is_array($link)) {
|
||||
$link = ['url' => '', 'target' => ''];
|
||||
}
|
||||
$url = esc_url(trim((string) ($link['url'] ?? '')));
|
||||
$target = sanitize_text_field((string) ($link['target'] ?? ''));
|
||||
$tgt = $target !== '' ? ' target="' . esc_attr($target) . '" rel="noopener noreferrer"' : '';
|
||||
|
||||
$icon_class = trim('icon-cover-icon badg cir ' . sanitize_html_class((string) $args['icon_class']) . ' ' . sanitize_html_class((string) $args['icon_color']));
|
||||
if (!empty($args['icon_radius'])) {
|
||||
$icon_class .= ' radius4';
|
||||
}
|
||||
$icon_size = max(14, min(64, (int) $args['icon_size']));
|
||||
$style = 'font-size:' . $icon_size . 'px;';
|
||||
$custom_color = sanitize_hex_color((string) $args['icon_custom_color']);
|
||||
if ($custom_color) {
|
||||
$style .= 'color:' . $custom_color . ';';
|
||||
}
|
||||
|
||||
if ($custom_html !== '') {
|
||||
$icon_inner = $custom_html;
|
||||
} elseif ($icon_img !== '') {
|
||||
$icon_inner = '<img src="' . esc_url($icon_img) . '" alt="" loading="lazy" />';
|
||||
} else {
|
||||
if ($icon_fa !== '' && !str_contains($icon_fa, 'fa-') && !str_contains($icon_fa, ' ')) {
|
||||
$icon_fa = 'fa fa-' . $icon_fa;
|
||||
// Normalize link: accept nested link[] or flat url/target (SPA schema).
|
||||
$link = $args['link'];
|
||||
if (is_string($link)) {
|
||||
$link = ['url' => $link, 'target' => (string) $args['target']];
|
||||
}
|
||||
if (!is_array($link)) {
|
||||
$link = ['url' => '', 'target' => ''];
|
||||
}
|
||||
if (trim((string) ($link['url'] ?? '')) === '' && trim((string) $args['url']) !== '') {
|
||||
$link['url'] = (string) $args['url'];
|
||||
}
|
||||
if (trim((string) ($link['target'] ?? '')) === '' && trim((string) $args['target']) !== '') {
|
||||
$link['target'] = (string) $args['target'];
|
||||
}
|
||||
$icon_inner = '<i class="' . esc_attr($icon_fa) . ' em09" aria-hidden="true"></i>';
|
||||
}
|
||||
$icon = '<div class="' . esc_attr(trim($icon_class)) . '" style="' . esc_attr($style) . '">' . $icon_inner . '</div>';
|
||||
|
||||
$title = trim((string) $args['title']);
|
||||
$desc = trim((string) $args['desc']);
|
||||
$text = '';
|
||||
if ($title !== '') {
|
||||
$text .= '<div class="em12 text-ellipsis font-bold">' . esc_html($title) . '</div>';
|
||||
}
|
||||
if ($desc !== '') {
|
||||
$text .= '<div class="muted-color mt6 text-ellipsis">' . esc_html($desc) . '</div>';
|
||||
}
|
||||
$icon_fa = trim((string) $args['icon']);
|
||||
// custom_icon (SPA) + customize_icon (zibll) + icon_image URL.
|
||||
$custom_src = (string) ($args['custom_icon'] !== '' ? $args['custom_icon'] : $args['customize_icon']);
|
||||
$icon_img = esc_url_raw(trim((string) ($args['icon_image'] !== '' ? $args['icon_image'] : '')));
|
||||
$custom_html = '';
|
||||
if ($icon_img === '' && $custom_src !== '' && str_contains($custom_src, '<')) {
|
||||
$custom_html = wp_kses($custom_src, [
|
||||
'i' => ['class' => true, 'aria-hidden' => true],
|
||||
'img' => ['src' => true, 'alt' => true, 'class' => true, 'loading' => true, 'width' => true, 'height' => true],
|
||||
'span' => ['class' => true],
|
||||
'svg' => ['class' => true, 'viewbox' => true, 'viewBox' => true, 'width' => true, 'height' => true, 'fill' => true, 'xmlns' => true, 'aria-hidden' => true],
|
||||
'path' => ['d' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true],
|
||||
'use' => ['href' => true, 'xlink:href' => true],
|
||||
]);
|
||||
} elseif ($icon_img === '' && $custom_src !== '' && filter_var($custom_src, FILTER_VALIDATE_URL)) {
|
||||
$icon_img = esc_url_raw($custom_src);
|
||||
}
|
||||
if ($icon_fa === '' && $icon_img === '' && $custom_html === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$html = '';
|
||||
if ($url !== '') {
|
||||
$html .= '<a class="main-color" href="' . esc_url($url) . '"' . $tgt . '>';
|
||||
}
|
||||
$html .= '<div class="icon-cover-card flex ac ' . esc_attr((string) $args['class']) . '">';
|
||||
$html .= $icon;
|
||||
$html .= $text !== '' ? '<div class="icon-cover-desc ml10 flex1 px12-sm">' . $text . '</div>' : '';
|
||||
$html .= '</div>';
|
||||
if ($url !== '') {
|
||||
$html .= '</a>';
|
||||
}
|
||||
$url = esc_url(trim((string) ($link['url'] ?? '')));
|
||||
$target = sanitize_text_field((string) ($link['target'] ?? ''));
|
||||
// zibll only adds target= when non-empty; keep same for 1:1.
|
||||
$tgt = ($target !== '' && $target !== '_self') ? ' target="' . esc_attr($target) . '"' : '';
|
||||
|
||||
if ($echo) {
|
||||
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
return '';
|
||||
// zibll: class = "icon-cover-icon badg cir" + optional icon_class (may include radius4 / c-* / jb-*).
|
||||
// Do NOT sanitize_html_class on the whole string — it collapses multi-token classes.
|
||||
$icon_class_extra = trim(preg_replace('/\s+/', ' ', (string) $args['icon_class']));
|
||||
$icon_class = 'icon-cover-icon badg cir';
|
||||
if ($icon_class_extra !== '') {
|
||||
$tokens = preg_split('/\s+/', $icon_class_extra) ?: [];
|
||||
$safe = [];
|
||||
foreach ($tokens as $tok) {
|
||||
$tok = preg_replace('/[^a-zA-Z0-9_-]/', '', $tok);
|
||||
if ($tok !== '') {
|
||||
$safe[] = $tok;
|
||||
}
|
||||
}
|
||||
if ($safe) {
|
||||
$icon_class .= ' ' . implode(' ', $safe);
|
||||
}
|
||||
}
|
||||
if (!empty($args['icon_radius']) && !str_contains($icon_class, 'radius4')) {
|
||||
$icon_class .= ' radius4';
|
||||
}
|
||||
$icon_color = trim((string) $args['icon_color']);
|
||||
if ($icon_color !== '' && !str_contains($icon_class, $icon_color)) {
|
||||
$icon_class .= ' ' . preg_replace('/[^a-zA-Z0-9_-]/', '', $icon_color);
|
||||
}
|
||||
|
||||
$icon_size = max(14, min(64, (int) $args['icon_size']));
|
||||
// zibll always sets font-size on the icon badge.
|
||||
$style = 'font-size: ' . $icon_size . 'px;';
|
||||
$custom_color = sanitize_hex_color((string) $args['icon_custom_color']);
|
||||
if ($custom_color) {
|
||||
$style .= 'color:' . $custom_color . ';';
|
||||
}
|
||||
|
||||
if ($custom_html !== '') {
|
||||
$icon_inner = $custom_html;
|
||||
} elseif ($icon_img !== '') {
|
||||
$icon_inner = '<img src="' . esc_url($icon_img) . '" alt="" loading="lazy" />';
|
||||
} else {
|
||||
// zibll: zib_get_cfs_icon($args['icon'], 'em09') — keep FA class + em09.
|
||||
if ($icon_fa !== '' && !str_contains($icon_fa, 'fa-') && !str_contains($icon_fa, ' ') && !str_starts_with($icon_fa, 'zibsvg-')) {
|
||||
$icon_fa = 'fa fa-' . $icon_fa;
|
||||
}
|
||||
if (str_contains($icon_fa, '<')) {
|
||||
$icon_inner = wp_kses($icon_fa, [
|
||||
'i' => ['class' => true, 'aria-hidden' => true],
|
||||
'svg' => ['class' => true, 'viewbox' => true, 'viewBox' => true, 'width' => true, 'height' => true, 'fill' => true, 'xmlns' => true, 'aria-hidden' => true],
|
||||
'path' => ['d' => true, 'fill' => true],
|
||||
'use' => ['href' => true, 'xlink:href' => true],
|
||||
]);
|
||||
} else {
|
||||
$icon_inner = '<i class="' . esc_attr($icon_fa) . ' em09" aria-hidden="true"></i>';
|
||||
}
|
||||
}
|
||||
$icon = '<div class="' . esc_attr(trim($icon_class)) . '" style="' . esc_attr($style) . '">' . $icon_inner . '</div>';
|
||||
|
||||
// zibll allows HTML in title/desc (admin stores badges etc.).
|
||||
$title = (string) $args['title'];
|
||||
$desc = (string) $args['desc'];
|
||||
$allow = [
|
||||
'badge' => ['class' => true],
|
||||
'span' => ['class' => true],
|
||||
'i' => ['class' => true, 'aria-hidden' => true],
|
||||
'em' => ['class' => true],
|
||||
'strong' => ['class' => true],
|
||||
'b' => [],
|
||||
'small' => ['class' => true],
|
||||
'br' => [],
|
||||
];
|
||||
$text = '';
|
||||
if (trim(wp_strip_all_tags($title)) !== '' || str_contains($title, '<')) {
|
||||
$text .= '<div class="em12 text-ellipsis font-bold"> ' . wp_kses($title, $allow) . '</div>';
|
||||
}
|
||||
if (trim(wp_strip_all_tags($desc)) !== '' || str_contains($desc, '<')) {
|
||||
$text .= '<div class="muted-color mt6 text-ellipsis"> ' . wp_kses($desc, $allow) . '</div>';
|
||||
}
|
||||
|
||||
$html = '';
|
||||
if ($url !== '') {
|
||||
// zibll: <a class="main-color" [target] href="...">
|
||||
$html .= '<a class="main-color" ' . ($tgt !== '' ? ltrim($tgt) . ' ' : '') . 'href="' . esc_url($url) . '">';
|
||||
}
|
||||
$html .= '<div class="icon-cover-card flex ac ' . esc_attr((string) $args['class']) . '">';
|
||||
$html .= $icon;
|
||||
$html .= $text !== '' ? '<div class="icon-cover-desc ml10 flex1 px12-sm"> ' . $text . '</div>' : '';
|
||||
$html .= '</div>';
|
||||
if ($url !== '') {
|
||||
$html .= '</a>';
|
||||
}
|
||||
|
||||
if ($echo) {
|
||||
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
return '';
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
endif;
|
||||
|
||||
if (!function_exists('aksrt_obs_animate_attrs')) :
|
||||
|
||||
@@ -495,45 +495,46 @@ if (!function_exists('aksrt_render_icon_cover_card')):
|
||||
* @return string HTML
|
||||
*/
|
||||
function aksrt_render_icon_cover_card(array $card): string {
|
||||
$icon = $card['icon'] ?? 'fas fa-star';
|
||||
$custom_icon = $card['custom_icon'] ?? '';
|
||||
$icon_class = $card['icon_class'] ?? 'c-blue';
|
||||
$icon_shape = ($card['icon_shape'] ?? 'circle') === 'square' ? 'radius4' : '';
|
||||
$title = $card['title'] ?? '';
|
||||
$desc = $card['desc'] ?? '';
|
||||
$url = $card['url'] ?? '';
|
||||
$target = ($card['target'] ?? '_self') === '_blank' ? ' target="_blank" rel="noopener"' : '';
|
||||
// Prefer canonical zibll-aligned renderer.
|
||||
if (function_exists('aksrt_icon_cover_card')) {
|
||||
return aksrt_icon_cover_card($card);
|
||||
}
|
||||
|
||||
// 图标 HTML
|
||||
$icon_html = $custom_icon
|
||||
? $custom_icon
|
||||
: '<i class="' . esc_attr($icon) . '"></i>';
|
||||
$icon = $card['icon'] ?? 'fas fa-star';
|
||||
$custom_icon = $card['custom_icon'] ?? ($card['customize_icon'] ?? '');
|
||||
$icon_class = trim((string) ($card['icon_class'] ?? 'c-blue'));
|
||||
if (($card['icon_shape'] ?? '') === 'square' && !str_contains($icon_class, 'radius4')) {
|
||||
$icon_class .= ' radius4';
|
||||
}
|
||||
$title = $card['title'] ?? '';
|
||||
$desc = $card['desc'] ?? '';
|
||||
$url = $card['url'] ?? ($card['link']['url'] ?? '');
|
||||
$target = $card['target'] ?? ($card['link']['target'] ?? '');
|
||||
$tgt = ($target !== '' && $target !== '_self') ? ' target="' . esc_attr((string) $target) . '"' : '';
|
||||
|
||||
// 图标容器
|
||||
$icon_container = '<div class="icon-cover-icon ' . esc_attr($icon_class) . ' ' . esc_attr($icon_shape) . '">' . $icon_html . '</div>';
|
||||
$icon_html = $custom_icon !== ''
|
||||
? wp_kses_post((string) $custom_icon)
|
||||
: '<i class="' . esc_attr((string) $icon) . ' em09" aria-hidden="true"></i>';
|
||||
|
||||
// 文字区
|
||||
$text_html = '<div class="icon-cover-desc">';
|
||||
if ($title) {
|
||||
$text_html .= '<div class="icon-cover-title">' . wp_kses_post($title) . '</div>';
|
||||
}
|
||||
if ($desc) {
|
||||
$text_html .= '<div class="icon-cover-subtitle">' . wp_kses_post($desc) . '</div>';
|
||||
}
|
||||
$text_html .= '</div>';
|
||||
$icon_container = '<div class="icon-cover-icon badg cir ' . esc_attr($icon_class) . '" style="font-size: 25px;">' . $icon_html . '</div>';
|
||||
|
||||
// 卡片内容
|
||||
$card_inner = $icon_container . $text_html;
|
||||
$text_html = '<div class="icon-cover-desc ml10 flex1 px12-sm">';
|
||||
if ($title !== '') {
|
||||
$text_html .= '<div class="em12 text-ellipsis font-bold"> ' . wp_kses_post((string) $title) . '</div>';
|
||||
}
|
||||
if ($desc !== '') {
|
||||
$text_html .= '<div class="muted-color mt6 text-ellipsis"> ' . wp_kses_post((string) $desc) . '</div>';
|
||||
}
|
||||
$text_html .= '</div>';
|
||||
|
||||
// 包裹标签
|
||||
if ($url) {
|
||||
$html = '<a href="' . esc_url($url) . '" class="icon-cover-card"' . $target . '>' . $card_inner . '</a>';
|
||||
} else {
|
||||
$html = '<div class="icon-cover-card">' . $card_inner . '</div>';
|
||||
}
|
||||
$card_inner = $icon_container . $text_html;
|
||||
$cls = 'icon-cover-card flex ac ' . esc_attr((string) ($card['class'] ?? 'zib-widget'));
|
||||
|
||||
return $html;
|
||||
}
|
||||
if ($url !== '') {
|
||||
return '<a class="main-color" ' . ($tgt !== '' ? ltrim($tgt) . ' ' : '') . 'href="' . esc_url((string) $url) . '"><div class="' . $cls . '">' . $card_inner . '</div></a>';
|
||||
}
|
||||
return '<div class="' . $cls . '">' . $card_inner . '</div>';
|
||||
}
|
||||
endif;
|
||||
|
||||
// ============================================================
|
||||
|
||||
Reference in new issue
Block a user