Task 15: product detail anchor tabs + per-product custom sections
User report: product detail page was wrong — section titles are
per-product custom data (CMS wppop_sections migration: Packing &
Delivery / Our Exhibition / Our Certifications / Our Company / FAQ),
not fixed headings; they must drive an anchor tab system like the
CMS [locale]/products/[slug].astro detailTabs.
Data side (both layers, task option 1 + 2):
- theme_pro.product_detail_sections: fields.sections
[{title, content}] JSON is the structured source; legacy sync
output that appended sections as trailing body H2 blocks is
recognized by known/data titles and split out (overview keeps the
rest; same-title blocks dedupe to the structured version; Features
body block drops when fields.features renders it)
- sync_cms_data.build_product: store sections/features as structured
fields JSON, stop appending H2 blocks to the body; stats now count
entries with a sections field
- Specifications table no longer leaks structural JSON field keys
(sections/features/specs/gallery/categories) — scalar spec keys
only
Template side (trade-pro product.html, replaces 12a panel
switching):
- tab sequence is fully data-driven and matches the CMS: Product
Details (always) -> custom sections (data titles) ->
Specifications / Features (shown only when data exists)
- tabs are #anchor links, not panel toggles: all sections render
flat with visible titles (readable and crawlable without JS; native
anchor jump), JS adds smooth scrolling + scrollspy highlight +
tab centering in the horizontal scroll row
- section ids are slug-derived (sec-packing-delivery), duplicate
titles get an index suffix; features grid ports the CMS
detail-feature-row
Tests: test_trade_pro_product_layout_structure rewritten for the
anchor-tab contract — sections via fields, legacy body-H2 fallback,
spec/features conditional tabs, no-sections product showing only
Product Details + Specifications, spec table free of JSON key leaks,
updated pro.css needles. 30 passed; the 1 failure
(test_trade_pro_blocks_visual_bridge) fails identically on the
previous commit (pre-existing, unrelated).
Co-Authored-By: Claude Code <noreply@example.com>
This commit is contained in:
@@ -104,8 +104,9 @@
|
||||
.sf-theme-trade-pro .sf-tp-cta h2{margin-block-end:var(--sf-tp-space-2);color:var(--sf-tp-color-text-inverse)}
|
||||
.sf-theme-trade-pro .sf-tp-cta p{color:color-mix(in srgb,var(--sf-tp-color-text-inverse) 83%,transparent);margin:0}
|
||||
|
||||
/* ── 产品详情(Task 12a,[slug].astro 精确对齐重做 10b):hero 画廊/标题 +
|
||||
sticky 选项卡(无 JS 平铺回退)+ rich-body 正文表格 + spec-table + 询盘。
|
||||
/* ── 产品详情(Task 12a,[slug].astro 精确对齐重做 10b;Task 15 选项卡改
|
||||
锚点 Tab + 自定义区块/特性栅格):hero 画廊/标题 + sticky 锚点选项卡 +
|
||||
rich-body 正文表格 + spec-table + detail-features + 询盘。
|
||||
断点映射:cms 900 与 960(询盘堆叠)→ 900;cms 620 → 620。 ── */
|
||||
.sf-theme-trade-pro .sf-tp-product-hero{padding-block:calc(var(--sf-tp-space-8) + var(--sf-tp-space-4)) var(--sf-tp-space-8)}
|
||||
.sf-theme-trade-pro .sf-tp-breadcrumb{display:flex;flex-wrap:wrap;align-items:center;color:var(--sf-tp-color-text-muted);font-size:var(--sf-tp-font-size-sm);margin-block-end:var(--sf-tp-space-6)}
|
||||
@@ -137,13 +138,13 @@
|
||||
/* Tab 单行横滚(数量多不换行);隐藏滚动条 + scroll-snap 贴合(cms .tabs-row) */
|
||||
.sf-theme-trade-pro .sf-tp-tabs-row{display:flex;gap:var(--sf-tp-space-6);overflow-x:auto;scroll-behavior:smooth;scrollbar-width:none;scroll-snap-type:x proximity}
|
||||
.sf-theme-trade-pro .sf-tp-tabs-row::-webkit-scrollbar{display:none}
|
||||
.sf-theme-trade-pro .sf-tp-tab{flex:0 0 auto;white-space:nowrap;padding:var(--sf-tp-space-4) var(--sf-tp-space-1);color:var(--sf-tp-color-text-secondary);font-weight:var(--sf-tp-font-weight-semibold);font-size:var(--sf-tp-font-size-sm);background:none;border:none;border-block-end:var(--sf-tp-border-width-strong) solid transparent;cursor:pointer;scroll-snap-align:center}
|
||||
.sf-theme-trade-pro .sf-tp-tab{flex:0 0 auto;white-space:nowrap;padding:var(--sf-tp-space-4) var(--sf-tp-space-1);color:var(--sf-tp-color-text-secondary);font-weight:var(--sf-tp-font-weight-semibold);font-size:var(--sf-tp-font-size-sm);background:none;border:none;border-block-end:var(--sf-tp-border-width-strong) solid transparent;cursor:pointer;scroll-snap-align:center;text-decoration:none}
|
||||
.sf-theme-trade-pro .sf-tp-tab.active,.sf-theme-trade-pro .sf-tp-tab:hover{color:var(--sf-tp-color-text-link);border-block-end-color:var(--sf-tp-color-border-brand)}
|
||||
/* 面板切换(cms [data-tabbed].tabs-enabled):JS 给容器加 sf-tp-tabs-enabled 后
|
||||
仅显示激活面板并隐藏 panel-title;无 JS 时面板全部平铺可读、标题可见 */
|
||||
.sf-theme-trade-pro .sf-tp-product-tabbed.sf-tp-tabs-enabled .sf-tp-panel{display:none}
|
||||
.sf-theme-trade-pro .sf-tp-product-tabbed.sf-tp-tabs-enabled .sf-tp-panel.active{display:block}
|
||||
.sf-theme-trade-pro .sf-tp-product-tabbed.sf-tp-tabs-enabled .sf-tp-panel-title{display:none}
|
||||
.sf-theme-trade-pro .sf-tp-tab:focus-visible{outline:2px solid var(--sf-tp-color-border-brand);outline-offset:-2px}
|
||||
/* 锚点选项卡(Task 15 重做 12a 面板切换):Tab 是页内锚点链接,区块全部平铺
|
||||
渲染、panel-title 常显(无 JS 原生跳转也可读);JS 平滑滚动 + scrollspy
|
||||
高亮当前 Tab(.sf-tp-tab.active)。区块锚点滚动让位 sticky 条见下方
|
||||
.sf-tp-detail-section 的 scroll-margin-top。 */
|
||||
/* 详情面板(cms .detail-section):区块距 + 锚点滚动让位 sticky 选项卡;
|
||||
区块标题品牌色 3px 下划短线(cms .detail-section > .wrap > h2) */
|
||||
.sf-theme-trade-pro .sf-tp-detail-section{padding-block:calc(var(--sf-tp-space-10) + var(--sf-tp-space-1));scroll-margin-top:calc(var(--sf-tp-space-16) + var(--sf-tp-space-16))}
|
||||
@@ -165,6 +166,13 @@
|
||||
.sf-theme-trade-pro .sf-tp-spec-table{width:100%;border-collapse:collapse;font-size:var(--sf-tp-font-size-sm)}
|
||||
.sf-theme-trade-pro .sf-tp-spec-table th,.sf-theme-trade-pro .sf-tp-spec-table td{border:var(--sf-tp-border-width-hairline) solid var(--sf-tp-color-border-default);padding:calc(var(--sf-tp-space-4) - var(--sf-tp-space-1)) var(--sf-tp-space-4);text-align:start}
|
||||
.sf-theme-trade-pro .sf-tp-spec-table th{background:var(--sf-tp-color-surface-muted);font-weight:var(--sf-tp-font-weight-semibold)}
|
||||
/* 特性栅格(cms .detail-feature-row,fields.features 数据驱动):品牌色星标 +
|
||||
标题/描述两行卡;auto-fit 自适应条目数(cms 固定 4 列,数据条目不定) */
|
||||
.sf-theme-trade-pro .sf-tp-detail-features{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--sf-tp-space-3) var(--sf-tp-space-6)}
|
||||
.sf-theme-trade-pro .sf-tp-detail-feature{display:grid;grid-template-columns:auto 1fr;gap:var(--sf-tp-space-3);align-items:start;padding-block:var(--sf-tp-space-2)}
|
||||
.sf-theme-trade-pro .sf-tp-detail-feature>span{color:var(--sf-tp-color-text-brand);font-size:var(--sf-tp-font-size-xl);line-height:var(--sf-tp-line-height-tight)}
|
||||
.sf-theme-trade-pro .sf-tp-detail-feature h3{font-size:var(--sf-tp-font-size-md);margin-block-end:var(--sf-tp-space-1)}
|
||||
.sf-theme-trade-pro .sf-tp-detail-feature p{margin:0;color:var(--sf-tp-color-text-muted);font-size:var(--sf-tp-font-size-sm)}
|
||||
/* 询盘板块(cms quote-grid 同构):左联系信息 + 右表单卡 */
|
||||
.sf-theme-trade-pro .sf-tp-quote-grid{display:grid;grid-template-columns:0.85fr 1.15fr;gap:calc(var(--sf-tp-space-12) + var(--sf-tp-space-4));align-items:start}
|
||||
.sf-theme-trade-pro .sf-tp-quote-info>p{color:var(--sf-tp-color-text-muted)}
|
||||
|
||||
Reference in New Issue
Block a user