refactor(header): unify top icon-cards on single zib-widget path
This commit is contained in:
@@ -37,15 +37,6 @@ body {
|
||||
background-color: var(--surface-page);
|
||||
}
|
||||
|
||||
/* Shared horizontal icon-card contract.
|
||||
* Header components and widget areas use different layout wrappers, but the
|
||||
* card itself must retain the compact Zibll proportions in every context. */
|
||||
.icon-cover-card.aksrt-icon-cover-card {
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* zibll compat: global link composite transition */
|
||||
a[href] {
|
||||
transition: color 0.2s, background 0.3s, opacity 0.3s, box-shadow 0.3s, transform 0.3s;
|
||||
@@ -100,8 +91,7 @@ main.container,
|
||||
|
||||
/* Header multifunc icon cards need horizontal gutter (zibll content rows).
|
||||
* Global .container padding is 0 for dual-column float math. */
|
||||
.header-slider-card.container,
|
||||
.header-components-card.container {
|
||||
.header-slider-card.container {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/* ============================================================
|
||||
* Header icon cards — unified geometry (zibll 1:1)
|
||||
*
|
||||
* The top multi-function component ("顶部多功能组件") renders its icon
|
||||
* cards through one path: aksrt_header_slide() →
|
||||
* aksrt_icon_cover_card() (see inc/helpers/homepage/header-components.php
|
||||
* and inc/helpers/aksrt-icon-cards.php). This file is the single source of
|
||||
* truth for their size/layout, loaded after Zibll main.min.css on every
|
||||
* page so cards stay identical across home / archive / single / search.
|
||||
*
|
||||
* DOM: .header-slider-card.container
|
||||
* > (.zib-widget.padding-10 | div)
|
||||
* > .flex.jse.flex-row.gutters-5.flex-col-sm-2
|
||||
* > (.flex1 | .relative-h)
|
||||
* > [.main-color] .icon-cover-card.aksrt-icon-cover-card.flex.ac.(zib-widget|padding-10)
|
||||
* > .icon-cover-icon.badg.cir.(c-*|jb-*)[.radius4] (the badge)
|
||||
* > .icon-cover-desc.ml10.flex1.px12-sm
|
||||
* ============================================================ */
|
||||
|
||||
/* --- Equal-width cells + zibll gutters (both header wrapper aliases) --- */
|
||||
.header-slider-card .flex,
|
||||
.header-components-card .flex {
|
||||
display: flex;
|
||||
}
|
||||
.header-slider-card .flex.jse,
|
||||
.header-components-card .flex.jse,
|
||||
.header-slider-card .jse,
|
||||
.header-components-card .jse {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
.header-slider-card .flex-row,
|
||||
.header-components-card .flex-row {
|
||||
flex-direction: row;
|
||||
}
|
||||
.header-slider-card .flex.ac,
|
||||
.header-components-card .flex.ac,
|
||||
.header-slider-card .ac,
|
||||
.header-components-card .ac {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-slider-card .gutters-5,
|
||||
.header-components-card .gutters-5,
|
||||
.header-slider-card .flex.jse.flex-row,
|
||||
.header-components-card .flex.jse.flex-row {
|
||||
margin: -5px;
|
||||
}
|
||||
.header-slider-card .gutters-5 > *,
|
||||
.header-components-card .gutters-5 > *,
|
||||
.header-slider-card .flex.jse.flex-row > *,
|
||||
.header-components-card .flex.jse.flex-row > * {
|
||||
padding: 5px !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Higher-specificity scope selector wins over the single-post-only
|
||||
* zibll-utilities.css `.flex1{flex:1 1 auto}` so every card is equal-width:
|
||||
* zibll uses `flex:1; overflow:hidden`. */
|
||||
.header-slider-card .flex1,
|
||||
.header-components-card .flex1,
|
||||
.header-slider-card .flex .flex1,
|
||||
.header-components-card .flex .flex1 {
|
||||
flex: 1 1 0;
|
||||
overflow: hidden;
|
||||
min-width: 0;
|
||||
}
|
||||
.header-slider-card .relative-h,
|
||||
.header-components-card .relative-h {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.header-slider-card,
|
||||
.header-components-card {
|
||||
position: relative;
|
||||
margin-top: -40px;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header-slider-card .zib-widget,
|
||||
.header-components-card .zib-widget {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* --- Card box: compact zibll proportions in every context --- */
|
||||
.icon-cover-card.aksrt-icon-cover-card {
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* --- Icon badge: fixed size so a custom (non-FA) icon cannot stretch it --- */
|
||||
.icon-cover-card .icon-cover-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
min-width: 45px;
|
||||
font-size: 25px;
|
||||
flex: 0 0 auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.icon-cover-card .icon-cover-icon > img,
|
||||
.icon-cover-card .icon-cover-icon > svg {
|
||||
width: 1.6em;
|
||||
height: 1.6em;
|
||||
max-width: 1.6em;
|
||||
max-height: 1.6em;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
/* --- Text column: equal truncation --- */
|
||||
.icon-cover-card .icon-cover-desc {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* --- Mobile: two columns + zibll padding overrides --- */
|
||||
@media (max-width: 767px) {
|
||||
.header-slider-card,
|
||||
.header-components-card {
|
||||
margin-top: -35px;
|
||||
}
|
||||
.header-slider-card .flex.flex-row.flex-col-sm-2,
|
||||
.header-components-card .flex.flex-row.flex-col-sm-2 {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.header-slider-card .flex.flex-row.flex-col-sm-2 > *,
|
||||
.header-components-card .flex.flex-row.flex-col-sm-2 > * {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
.header-slider-card .icon-cover-card.zib-widget,
|
||||
.header-components-card .icon-cover-card.zib-widget {
|
||||
padding: 10px;
|
||||
}
|
||||
.header-slider-card .icon-cover-card.padding-10,
|
||||
.header-components-card .icon-cover-card.padding-10 {
|
||||
padding: 2px;
|
||||
}
|
||||
}
|
||||
@@ -282,7 +282,7 @@ if (!function_exists('aksrt_icon_cover_card')) :
|
||||
}
|
||||
// Keep every horizontal icon card on the same compact visual contract,
|
||||
// regardless of the page-specific wrapper that renders it.
|
||||
$html .= '<div class="icon-cover-card aksrt-icon-cover-card flex ac ' . esc_attr((string) $args['class']) . '">';
|
||||
$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>';
|
||||
|
||||
@@ -415,27 +415,24 @@ if (!function_exists('aksrt_header_slide')) {
|
||||
$card_count = 0;
|
||||
if (aksrt_header_slider_device_is_visible($args['header_slider_card_s'] ?? [])) {
|
||||
$card_options = wp_parse_args((array) ($args['header_slider_card_option'] ?? []), [
|
||||
'show_widget_bg' => false, 'icon_radius4' => false, 'cards' => [],
|
||||
'icon_radius4' => false, 'cards' => [],
|
||||
]);
|
||||
$items = '';
|
||||
foreach ((array) $card_options['cards'] as $card) {
|
||||
if (!is_array($card) || (empty($card['icon']) && empty($card['customize_icon']) && empty($card['custom_icon']) && empty($card['icon_image']))) {
|
||||
continue;
|
||||
}
|
||||
$card['class'] = !empty($card_options['show_widget_bg']) ? 'padding-10' : 'zib-widget';
|
||||
$card['icon_class'] = trim((string) ($card['icon_class'] ?? '') . (!empty($card_options['icon_radius4']) ? ' radius4' : ''));
|
||||
$inner = function_exists('aksrt_icon_cover_card') ? aksrt_icon_cover_card($card) : '';
|
||||
if ($inner === '') {
|
||||
continue;
|
||||
}
|
||||
$items .= !empty($card_options['show_widget_bg']) ? '<div class="relative-h">' : '<div class="flex1">';
|
||||
$items .= $inner . '</div>';
|
||||
$items .= '<div class="flex1">' . $inner . '</div>';
|
||||
$card_count++;
|
||||
}
|
||||
if ($items !== '') {
|
||||
$cards_html = '<div class="header-slider-card container">'
|
||||
. (!empty($card_options['show_widget_bg']) ? '<div class="zib-widget padding-10">' : '<div class="">')
|
||||
. '<div class="flex jse flex-row gutters-5 flex-col-sm-2">' . $items . '</div></div></div>';
|
||||
. '<div class="flex jse flex-row gutters-5 flex-col-sm-2">' . $items . '</div></div>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -262,7 +262,7 @@ final class PageConfigMetaBox {
|
||||
],
|
||||
];
|
||||
}
|
||||
return ['show_widget_bg' => !empty($value['show_widget_bg']), 'icon_radius4' => !empty($value['icon_radius4']), 'cards' => $cards];
|
||||
return ['icon_radius4' => !empty($value['icon_radius4']), 'cards' => $cards];
|
||||
}
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
@@ -293,7 +293,7 @@ final class PageConfigMetaBox {
|
||||
|
||||
/** @return array<string,mixed> */
|
||||
private static function card_defaults(): array {
|
||||
return ['show_widget_bg' => false, 'icon_radius4' => false, 'cards' => [
|
||||
return ['icon_radius4' => false, 'cards' => [
|
||||
['icon' => 'zibsvg-vip_1', 'customize_icon' => '', 'icon_class' => 'c-yellow', 'link' => [], 'title' => '图标卡片', 'desc' => '这是一个图标卡片示例'],
|
||||
['icon' => 'zibsvg-vip_2', 'customize_icon' => '', 'icon_class' => 'c-blue-2', 'link' => [], 'title' => '原创作品', 'desc' => '这是一个图标卡片示例'],
|
||||
['icon' => 'zibsvg-hot', 'customize_icon' => '', 'icon_class' => 'jb-pink', 'link' => [], 'title' => '灵感来源<badge class="ml6 jb-yellow">NEW</badge>', 'desc' => '这是一个图标卡片示例'],
|
||||
|
||||
@@ -183,7 +183,7 @@ class SchemaPageDisplay {
|
||||
}
|
||||
|
||||
private static function card_fields(): array {
|
||||
return [self::field('show_widget_bg', '模块背景', 'switcher', false), self::field('icon_radius4', '方形图标', 'switcher', false), self::field('cards', '添加卡片', 'group', [], ['button_title' => '添加内容', 'fields' => [self::field('title', '文案标题', 'textarea', '', ['sanitize_type' => 'html']), self::field('desc', '文案简介', 'textarea', '', ['sanitize_type' => 'html']), self::field('icon', '选择图标', 'icon', 'fa fa-magic'), self::field('customize_icon', '自定义图标', 'textarea', '', ['sanitize_type' => 'html']), self::field('icon_class', '图标颜色', 'palette', 'c-yellow', ['options' => self::zib_palette(true)]), self::field('link', '跳转链接', 'link', [])]])];
|
||||
return [self::field('icon_radius4', '方形图标', 'switcher', false), self::field('cards', '添加卡片', 'group', [], ['button_title' => '添加内容', 'fields' => [self::field('title', '文案标题', 'textarea', '', ['sanitize_type' => 'html']), self::field('desc', '文案简介', 'textarea', '', ['sanitize_type' => 'html']), self::field('icon', '选择图标', 'icon', 'fa fa-magic'), self::field('customize_icon', '自定义图标', 'textarea', '', ['sanitize_type' => 'html']), self::field('icon_class', '图标颜色', 'palette', 'c-yellow', ['options' => self::zib_palette(true)]), self::field('link', '跳转链接', 'link', [])]])];
|
||||
}
|
||||
|
||||
private static function orderby_fields(): array { return [self::field('lists', '显示排序方式', 'select', ['modified', 'views', 'like', 'comment_count'], ['multiple' => true, 'sortable' => true, 'options' => self::post_order_options(false)]), self::field('dropdown', '更多排序方式', 'switcher', false)]; }
|
||||
@@ -192,7 +192,7 @@ class SchemaPageDisplay {
|
||||
private static function header_slider_defaults(): array { $img = self::asset('assets/vendor/zibll/img/'); return [['background' => $img . 'slider-bg.jpg', 'link' => ['url' => 'https://www.zibll.com/', 'target' => '_blank'], 'text' => ['title' => '', 'desc' => ''], 'text_align' => 'left-bottom', 'text_parallax' => 30, 'text_size_m' => 20, 'text_size_pc' => 30], ['background' => $img . 'user_t.jpg', 'link' => ['url' => 'https://www.zibll.com/', 'target' => '_blank'], 'text' => ['title' => '', 'desc' => ''], 'text_align' => 'left-bottom', 'text_parallax' => 30, 'text_size_m' => 20, 'text_size_pc' => 30]]; }
|
||||
private static function slider_options_defaults(): array { return ['direction' => 'horizontal', 'loop' => true, 'button' => true, 'pagination' => true, 'effect' => 'slide', 'scale_height' => false, 'auto_height' => false, 'pc_height' => 550, 'm_height' => 280, 'spacebetween' => 0, 'speed' => 0, 'autoplay' => true, 'interval' => 6]; }
|
||||
private static function search_defaults(): array { return ['show_keywords' => true, 'popular_limit' => 6, 'show_input_cat' => false, 'in_cat' => '', 'more_cats' => '', 'show_type' => false, 'in_type' => 'post', 'before_html' => '<div class="em16 font-bold mb10">更优雅的Wordpress主题</div>' . "\n" . '<div>这是导航栏幻灯片多功能组件,可在后台进行配置</div>', 'after_html' => '']; }
|
||||
private static function card_defaults(): array { return ['show_widget_bg' => false, 'icon_radius4' => false, 'cards' => [['icon' => 'zibsvg-vip_1', 'customize_icon' => '', 'icon_class' => 'c-yellow', 'link' => [], 'title' => '图标卡片', 'desc' => '这是一个图标卡片示例'], ['icon' => 'zibsvg-vip_2', 'customize_icon' => '', 'icon_class' => 'c-blue-2', 'link' => [], 'title' => '原创作品', 'desc' => '这是一个图标卡片示例'], ['icon' => 'zibsvg-hot', 'customize_icon' => '', 'icon_class' => 'jb-pink', 'link' => [], 'title' => '灵感来源<badge class="ml6 jb-yellow">NEW</badge>', 'desc' => '这是一个图标卡片示例'], ['icon' => 'fa fa-ioxhost', 'customize_icon' => '', 'icon_class' => 'jb-cyan', 'link' => [], 'title' => '系统工具 <badge class="ml6 jb-blue">GO <span class="fa fa-angle-right em12"></span></badge>', 'desc' => '这是一个图标卡片示例']]]; }
|
||||
private static function card_defaults(): array { return ['icon_radius4' => false, 'cards' => [['icon' => 'zibsvg-vip_1', 'customize_icon' => '', 'icon_class' => 'c-yellow', 'link' => [], 'title' => '图标卡片', 'desc' => '这是一个图标卡片示例'], ['icon' => 'zibsvg-vip_2', 'customize_icon' => '', 'icon_class' => 'c-blue-2', 'link' => [], 'title' => '原创作品', 'desc' => '这是一个图标卡片示例'], ['icon' => 'zibsvg-hot', 'customize_icon' => '', 'icon_class' => 'jb-pink', 'link' => [], 'title' => '灵感来源<badge class="ml6 jb-yellow">NEW</badge>', 'desc' => '这是一个图标卡片示例'], ['icon' => 'fa fa-ioxhost', 'customize_icon' => '', 'icon_class' => 'jb-cyan', 'link' => [], 'title' => '系统工具 <badge class="ml6 jb-blue">GO <span class="fa fa-angle-right em12"></span></badge>', 'desc' => '这是一个图标卡片示例']]]; }
|
||||
|
||||
private static function field(string $key, string $label, string $type, $default = null, array $extra = []): array { return array_merge(['key' => $key, 'label' => $label, 'type' => $type, 'default' => $default], $extra); }
|
||||
private static function notice(string $content): array { return ['key' => '_notice_' . md5($content), 'type' => 'notice', 'content' => $content, 'tone' => 'warning']; }
|
||||
|
||||
@@ -106,7 +106,6 @@ trait ScriptsPart1b {
|
||||
// AKSRT domain styles load after Zibll main.css. The old aggregate is
|
||||
// intentionally not used because it contains the removed navigation CSS.
|
||||
$enqueue_module('base');
|
||||
$enqueue_module('header-cards');
|
||||
$enqueue_module('card-primitives');
|
||||
$enqueue_module('overlay-primitives');
|
||||
$enqueue_module('layout');
|
||||
|
||||
@@ -132,7 +132,6 @@ trait DisplayPageGroups {
|
||||
/** @return array<string,mixed> */
|
||||
private static function header_slider_card_defaults(): array {
|
||||
return [
|
||||
'show_widget_bg' => false,
|
||||
'icon_radius4' => false,
|
||||
'cards' => [
|
||||
['icon' => 'zibsvg-vip_1', 'customize_icon' => '', 'icon_class' => 'c-yellow', 'link' => [], 'title' => '图标卡片', 'desc' => '这是一个图标卡片示例'],
|
||||
|
||||
@@ -14,25 +14,24 @@ test('icon card renderers keep vertical and horizontal Zibll DOM contracts separ
|
||||
const header = read('inc/helpers/homepage/header-components.php');
|
||||
|
||||
assert.match(helper, /<div class="icon-card /);
|
||||
assert.match(helper, /<div class="icon-cover-card aksrt-icon-cover-card flex ac /);
|
||||
assert.match(helper, /<div class="icon-cover-card flex ac /);
|
||||
assert.match(helper, /icon-cover-icon badg cir/);
|
||||
assert.match(helper, /icon-cover-desc ml10 flex1 px12-sm/);
|
||||
assert.match(helper, /aksrt-icon-cover-card/);
|
||||
assert.doesNotMatch(helper, /aksrt-icon-cover-card/);
|
||||
assert.match(widgets, /'customize_icon' => \$card\['customize_icon'\] \?\? ''/);
|
||||
assert.match(widgets, /'custom_icon'\s+=> \$card\['custom_icon'\] \?\? ''/);
|
||||
assert.match(widgets, /'icon_image'\s+=> \$card\['icon_image'\] \?\? ''/);
|
||||
assert.match(header, /empty\(\$card\['custom_icon'\]\)/);
|
||||
});
|
||||
|
||||
test('homepage horizontal cards use the shared compact card contract and retain Zibll responsive rules', () => {
|
||||
const css = read('assets/css/frontend/header-cards.css');
|
||||
test('homepage horizontal cards render fully from Zibll CSS with no dedicated stylesheet', () => {
|
||||
const baseCss = read('assets/css/frontend/base.css');
|
||||
const widgetCss = read('assets/widgets/frontend.css');
|
||||
const scripts = read('src/Core/ScriptsPart1b.php');
|
||||
|
||||
assert.match(baseCss, /\.icon-cover-card\.aksrt-icon-cover-card\s*\{\s*padding:\s*10px;\s*font-size:\s*16px;/);
|
||||
assert.match(css, /\.icon-cover-card\.zib-widget[\s\S]*?padding:\s*10px;/);
|
||||
assert.match(css, /\.icon-cover-card\.padding-10[\s\S]*?padding:\s*2px;/);
|
||||
assert.doesNotMatch(css, /\.header-slider-card \.icon-cover-icon\.badg\.cir/);
|
||||
assert.doesNotMatch(css, /\.header-slider-card \.icon-cover-icon img/);
|
||||
assert.equal(fs.existsSync(path.join(root, 'assets/css/frontend/header-cards.css')), false);
|
||||
assert.doesNotMatch(baseCss, /\.icon-cover-card\.aksrt-icon-cover-card/);
|
||||
assert.doesNotMatch(baseCss, /\.header-components-card/);
|
||||
assert.doesNotMatch(scripts, /header-cards/);
|
||||
assert.doesNotMatch(widgetCss, /aksrt-widget-icon-cards \.icon-cover-card/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user