feat: refine detail catalog component layouts
This commit is contained in:
parent
2f1eff956a
commit
54f02be0f5
@ -45,10 +45,17 @@ function collectRenderableScreenComponents(surface: UiSurfaceSnapshot, parentId:
|
|||||||
component.type === "detail_card" ||
|
component.type === "detail_card" ||
|
||||||
component.type === "detail_badge" ||
|
component.type === "detail_badge" ||
|
||||||
component.type === "detail_feature_card" ||
|
component.type === "detail_feature_card" ||
|
||||||
|
component.type === "detail_feature_tag" ||
|
||||||
component.type === "detail_spec_table" ||
|
component.type === "detail_spec_table" ||
|
||||||
|
component.type === "detail_table_label" ||
|
||||||
|
component.type === "detail_table_value" ||
|
||||||
component.type === "detail_comparison_strip" ||
|
component.type === "detail_comparison_strip" ||
|
||||||
|
component.type === "detail_compare_before" ||
|
||||||
|
component.type === "detail_compare_after" ||
|
||||||
component.type === "detail_proof_bar" ||
|
component.type === "detail_proof_bar" ||
|
||||||
component.type === "detail_cta_banner"
|
component.type === "detail_cta_banner" ||
|
||||||
|
component.type === "detail_cta_button" ||
|
||||||
|
component.type === "detail_cta_support"
|
||||||
) {
|
) {
|
||||||
result.push(component);
|
result.push(component);
|
||||||
continue;
|
continue;
|
||||||
@ -73,10 +80,17 @@ export function DetailSurfaceInspectorPanel(params: {
|
|||||||
countUiSurfaceComponents(surface, "detail_card") +
|
countUiSurfaceComponents(surface, "detail_card") +
|
||||||
countUiSurfaceComponents(surface, "detail_badge") +
|
countUiSurfaceComponents(surface, "detail_badge") +
|
||||||
countUiSurfaceComponents(surface, "detail_feature_card") +
|
countUiSurfaceComponents(surface, "detail_feature_card") +
|
||||||
|
countUiSurfaceComponents(surface, "detail_feature_tag") +
|
||||||
countUiSurfaceComponents(surface, "detail_spec_table") +
|
countUiSurfaceComponents(surface, "detail_spec_table") +
|
||||||
|
countUiSurfaceComponents(surface, "detail_table_label") +
|
||||||
|
countUiSurfaceComponents(surface, "detail_table_value") +
|
||||||
countUiSurfaceComponents(surface, "detail_comparison_strip") +
|
countUiSurfaceComponents(surface, "detail_comparison_strip") +
|
||||||
|
countUiSurfaceComponents(surface, "detail_compare_before") +
|
||||||
|
countUiSurfaceComponents(surface, "detail_compare_after") +
|
||||||
countUiSurfaceComponents(surface, "detail_proof_bar") +
|
countUiSurfaceComponents(surface, "detail_proof_bar") +
|
||||||
countUiSurfaceComponents(surface, "detail_cta_banner");
|
countUiSurfaceComponents(surface, "detail_cta_banner") +
|
||||||
|
countUiSurfaceComponents(surface, "detail_cta_button") +
|
||||||
|
countUiSurfaceComponents(surface, "detail_cta_support");
|
||||||
const totalSections = countUiSurfaceComponents(surface, "detail_section");
|
const totalSections = countUiSurfaceComponents(surface, "detail_section");
|
||||||
const totalScreens = screenComponents.length;
|
const totalScreens = screenComponents.length;
|
||||||
|
|
||||||
|
|||||||
@ -161,10 +161,17 @@ function collectRenderableSurfaceComponents(params: {
|
|||||||
component.type === "detail_badge" ||
|
component.type === "detail_badge" ||
|
||||||
component.type === "detail_text_block" ||
|
component.type === "detail_text_block" ||
|
||||||
component.type === "detail_feature_card" ||
|
component.type === "detail_feature_card" ||
|
||||||
|
component.type === "detail_feature_tag" ||
|
||||||
component.type === "detail_spec_table" ||
|
component.type === "detail_spec_table" ||
|
||||||
|
component.type === "detail_table_label" ||
|
||||||
|
component.type === "detail_table_value" ||
|
||||||
component.type === "detail_comparison_strip" ||
|
component.type === "detail_comparison_strip" ||
|
||||||
|
component.type === "detail_compare_before" ||
|
||||||
|
component.type === "detail_compare_after" ||
|
||||||
component.type === "detail_proof_bar" ||
|
component.type === "detail_proof_bar" ||
|
||||||
component.type === "detail_cta_banner"
|
component.type === "detail_cta_banner" ||
|
||||||
|
component.type === "detail_cta_button" ||
|
||||||
|
component.type === "detail_cta_support"
|
||||||
) {
|
) {
|
||||||
collected.push(component);
|
collected.push(component);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -82,10 +82,17 @@ function createStyledSurfaceTextComponent(params: {
|
|||||||
| "detail_badge"
|
| "detail_badge"
|
||||||
| "detail_text_block"
|
| "detail_text_block"
|
||||||
| "detail_feature_card"
|
| "detail_feature_card"
|
||||||
|
| "detail_feature_tag"
|
||||||
| "detail_spec_table"
|
| "detail_spec_table"
|
||||||
|
| "detail_table_label"
|
||||||
|
| "detail_table_value"
|
||||||
| "detail_comparison_strip"
|
| "detail_comparison_strip"
|
||||||
|
| "detail_compare_before"
|
||||||
|
| "detail_compare_after"
|
||||||
| "detail_proof_bar"
|
| "detail_proof_bar"
|
||||||
| "detail_cta_banner";
|
| "detail_cta_banner"
|
||||||
|
| "detail_cta_button"
|
||||||
|
| "detail_cta_support";
|
||||||
parentId: string;
|
parentId: string;
|
||||||
frame: { x: number; y: number; width: number; height: number };
|
frame: { x: number; y: number; width: number; height: number };
|
||||||
zIndex?: number;
|
zIndex?: number;
|
||||||
@ -135,37 +142,63 @@ function buildCatalogStrings(params: {
|
|||||||
const layoutNote = String(params.screen.layoutNote || "").replace(/\s+/g, " ").trim();
|
const layoutNote = String(params.screen.layoutNote || "").replace(/\s+/g, " ").trim();
|
||||||
const catalogTitle = primaryTitle || "核心卖点";
|
const catalogTitle = primaryTitle || "核心卖点";
|
||||||
|
|
||||||
|
const featureCards = (highlights.length > 0
|
||||||
|
? highlights
|
||||||
|
: [subtitle || catalogTitle].filter(Boolean)
|
||||||
|
)
|
||||||
|
.slice(0, 3)
|
||||||
|
.map((item, index) => ({
|
||||||
|
tag:
|
||||||
|
index === 0
|
||||||
|
? "核心升级"
|
||||||
|
: index === 1
|
||||||
|
? "场景收益"
|
||||||
|
: "舒适证明",
|
||||||
|
title: item,
|
||||||
|
detail:
|
||||||
|
index === 0
|
||||||
|
? subtitle || objective || "围绕核心体验完成升级"
|
||||||
|
: index === 1
|
||||||
|
? objective || layoutNote || "匹配真实使用场景"
|
||||||
|
: layoutNote || subtitle || "用可感知结果证明价值",
|
||||||
|
accent: index === 0 ? "primary" : index === 1 ? "secondary" : "neutral",
|
||||||
|
}));
|
||||||
|
|
||||||
const specRows = [
|
const specRows = [
|
||||||
`核心卖点|${catalogTitle || "舒适支撑"}`,
|
{ label: "核心卖点", value: catalogTitle || "舒适支撑" },
|
||||||
objective ? `适用场景|${objective}` : "",
|
...(objective ? [{ label: "适用场景", value: objective }] : []),
|
||||||
subtitle ? `结果表达|${subtitle}` : "",
|
...(subtitle ? [{ label: "结果表达", value: subtitle }] : []),
|
||||||
layoutNote ? `设计要求|${layoutNote}` : "",
|
...(layoutNote ? [{ label: "设计要求", value: layoutNote }] : []),
|
||||||
].filter(Boolean);
|
];
|
||||||
|
|
||||||
const comparisonText = [
|
const comparison = {
|
||||||
"旧方式",
|
beforeTitle: "旧方式",
|
||||||
highlights[0] || "久坐容易疲劳、支撑不足",
|
beforeBody: highlights[0] || "久坐容易疲劳、支撑不足、使用场景不聚焦",
|
||||||
"",
|
afterTitle: "现在",
|
||||||
"现在",
|
afterBody: highlights[1] || subtitle || "围绕护腰/舒适/效率完成体验升级",
|
||||||
highlights[1] || subtitle || "围绕护腰/舒适/效率完成升级",
|
};
|
||||||
]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join("\n");
|
|
||||||
|
|
||||||
const proofText = layoutNote || objective || subtitle || catalogTitle;
|
const proof = {
|
||||||
|
label: params.screen.screenType === "A" ? "技术证明" : "结果证明",
|
||||||
|
value: layoutNote || objective || subtitle || catalogTitle,
|
||||||
|
};
|
||||||
const shouldShowCta =
|
const shouldShowCta =
|
||||||
params.screenIndex === (params.totalScreens || 0) ||
|
params.screenIndex === (params.totalScreens || 0) ||
|
||||||
/下单|购买|收口|转化|cta|call to action/i.test(layoutNote);
|
/下单|购买|收口|转化|cta|call to action/i.test(layoutNote);
|
||||||
const ctaText = shouldShowCta
|
const cta = shouldShowCta
|
||||||
? `立即聚焦:${catalogTitle}${subtitle ? `\n${subtitle}` : ""}`
|
? {
|
||||||
: "";
|
buttonLabel: params.screen.screenType === "C" ? "立即对比体验" : "立即了解详情",
|
||||||
|
supportText: subtitle || objective || "继续查看完整卖点与场景说明",
|
||||||
|
highlightText: catalogTitle,
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
highlights,
|
featureCards,
|
||||||
specTableText: specRows.join("\n"),
|
specRows,
|
||||||
comparisonText,
|
comparison,
|
||||||
proofText,
|
proof,
|
||||||
ctaText,
|
cta,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,9 +437,16 @@ function buildSectionedTextComponents(params: {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const supportingCards =
|
const supportingCards =
|
||||||
catalog.highlights.length > 0
|
catalog.featureCards.length > 0
|
||||||
? catalog.highlights.slice(0, 3)
|
? catalog.featureCards
|
||||||
: [String(params.screen.copy || "").trim()].filter(Boolean);
|
: [
|
||||||
|
{
|
||||||
|
tag: "核心信息",
|
||||||
|
title: String(params.screen.copy || "").trim() || catalog.proof.value,
|
||||||
|
detail: catalog.proof.value,
|
||||||
|
accent: "primary",
|
||||||
|
},
|
||||||
|
];
|
||||||
const cardGap = 14;
|
const cardGap = 14;
|
||||||
const supportColumns = variant === "split_bottom" ? Math.min(3, supportingCards.length) : Math.min(2, Math.max(1, supportingCards.length));
|
const supportColumns = variant === "split_bottom" ? Math.min(3, supportingCards.length) : Math.min(2, Math.max(1, supportingCards.length));
|
||||||
const supportCardWidth = Math.floor(
|
const supportCardWidth = Math.floor(
|
||||||
@ -418,6 +458,55 @@ function buildSectionedTextComponents(params: {
|
|||||||
const row = supportColumns === 0 ? 0 : Math.floor(index / supportColumns);
|
const row = supportColumns === 0 ? 0 : Math.floor(index / supportColumns);
|
||||||
const x = safeArea.left + column * (supportCardWidth + cardGap);
|
const x = safeArea.left + column * (supportCardWidth + cardGap);
|
||||||
const y = supportingSectionY + row * 116;
|
const y = supportingSectionY + row * 116;
|
||||||
|
|
||||||
|
components.push(
|
||||||
|
createStyledSurfaceTextComponent({
|
||||||
|
id: `${params.screenId}-feature-tag-${index + 1}`,
|
||||||
|
type: "detail_feature_tag",
|
||||||
|
parentId: `${params.screenId}-section-supporting`,
|
||||||
|
frame: {
|
||||||
|
x: x + 16,
|
||||||
|
y: y + 8,
|
||||||
|
width: Math.min(112, Math.max(76, highlight.tag.length * 17)),
|
||||||
|
height: 26,
|
||||||
|
},
|
||||||
|
zIndex: 3,
|
||||||
|
content: `✦ ${highlight.tag}`,
|
||||||
|
role: "feature_tag",
|
||||||
|
style: {
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: "700",
|
||||||
|
color:
|
||||||
|
highlight.accent === "primary"
|
||||||
|
? "#1d4ed8"
|
||||||
|
: highlight.accent === "secondary"
|
||||||
|
? "#7c3aed"
|
||||||
|
: "#334155",
|
||||||
|
textAlign: "center",
|
||||||
|
lineHeight: 1.1,
|
||||||
|
backgroundColor:
|
||||||
|
highlight.accent === "primary"
|
||||||
|
? "rgba(219,234,254,0.96)"
|
||||||
|
: highlight.accent === "secondary"
|
||||||
|
? "rgba(237,233,254,0.96)"
|
||||||
|
: "rgba(241,245,249,0.96)",
|
||||||
|
borderColor:
|
||||||
|
highlight.accent === "primary"
|
||||||
|
? "rgba(59,130,246,0.24)"
|
||||||
|
: highlight.accent === "secondary"
|
||||||
|
? "rgba(124,58,237,0.24)"
|
||||||
|
: "rgba(148,163,184,0.24)",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 999,
|
||||||
|
padding: 6,
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
screenIndex: params.screenIndex,
|
||||||
|
componentRole: "feature_tag",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
components.push(
|
components.push(
|
||||||
createStyledSurfaceTextComponent({
|
createStyledSurfaceTextComponent({
|
||||||
id: `${params.screenId}-support-card-${index + 1}`,
|
id: `${params.screenId}-support-card-${index + 1}`,
|
||||||
@ -425,28 +514,32 @@ function buildSectionedTextComponents(params: {
|
|||||||
parentId: `${params.screenId}-section-supporting`,
|
parentId: `${params.screenId}-section-supporting`,
|
||||||
frame: {
|
frame: {
|
||||||
x,
|
x,
|
||||||
y,
|
y: y + 20,
|
||||||
width: supportCardWidth,
|
width: supportCardWidth,
|
||||||
height: variant === "split_bottom" ? 102 : 96,
|
height: variant === "split_bottom" ? 116 : 110,
|
||||||
},
|
},
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
content: highlight,
|
content: `${index + 1}. ${highlight.title}${highlight.detail ? `\n${highlight.detail}` : ""}`,
|
||||||
role: "support_card",
|
role: "support_card",
|
||||||
style: {
|
style: {
|
||||||
fontSize: bodyBlock ? Math.max(18, Number(bodyBlock.style.fontSize || 22)) : 20,
|
fontSize: bodyBlock ? Math.max(18, Number(bodyBlock.style.fontSize || 22)) : 20,
|
||||||
fontWeight: "600",
|
fontWeight: "600",
|
||||||
color: "#111827",
|
color: "#111827",
|
||||||
textAlign: "left",
|
textAlign: "left",
|
||||||
lineHeight: 1.32,
|
lineHeight: 1.34,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
variant === "split_bottom"
|
variant === "split_bottom"
|
||||||
? "rgba(255,255,255,0.92)"
|
? "rgba(255,255,255,0.92)"
|
||||||
: "rgba(248,250,252,0.82)",
|
: "rgba(248,250,252,0.82)",
|
||||||
borderColor:
|
borderColor:
|
||||||
index === 0 ? "rgba(59,130,246,0.42)" : "rgba(148,163,184,0.28)",
|
highlight.accent === "primary"
|
||||||
|
? "rgba(59,130,246,0.42)"
|
||||||
|
: highlight.accent === "secondary"
|
||||||
|
? "rgba(124,58,237,0.34)"
|
||||||
|
: "rgba(148,163,184,0.28)",
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
padding: 18,
|
padding: 20,
|
||||||
boxShadow: "0 18px 42px rgba(15,23,42,0.12)",
|
boxShadow: "0 18px 42px rgba(15,23,42,0.12)",
|
||||||
backdropBlur: 12,
|
backdropBlur: 12,
|
||||||
},
|
},
|
||||||
@ -458,84 +551,182 @@ function buildSectionedTextComponents(params: {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (catalog.specTableText && params.screen.screenType === "A") {
|
if (catalog.specRows.length > 0 && params.screen.screenType === "A") {
|
||||||
|
const tableX = safeArea.left;
|
||||||
|
const tableY =
|
||||||
|
variant === "split_bottom"
|
||||||
|
? supportingSectionY - 140
|
||||||
|
: supportingSectionY + supportingSectionHeight - 220;
|
||||||
|
const tableWidth = Math.min(contentWidth, 396);
|
||||||
|
const labelWidth = 106;
|
||||||
|
const rowGap = 10;
|
||||||
|
|
||||||
components.push(
|
components.push(
|
||||||
createStyledSurfaceTextComponent({
|
createSectionComponent({
|
||||||
id: `${params.screenId}-spec-table`,
|
id: `${params.screenId}-section-spec-table`,
|
||||||
type: "detail_spec_table",
|
|
||||||
parentId: `${params.screenId}-section-supporting`,
|
parentId: `${params.screenId}-section-supporting`,
|
||||||
|
role: "spec_table_section",
|
||||||
frame: {
|
frame: {
|
||||||
x: safeArea.left,
|
x: tableX,
|
||||||
y:
|
y: tableY,
|
||||||
variant === "split_bottom"
|
width: tableWidth,
|
||||||
? supportingSectionY - 122
|
height: 196,
|
||||||
: supportingSectionY + supportingSectionHeight - 204,
|
|
||||||
width: Math.min(contentWidth, 360),
|
|
||||||
height: 188,
|
|
||||||
},
|
},
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
content: catalog.specTableText,
|
|
||||||
role: "spec_table",
|
|
||||||
style: {
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: "600",
|
|
||||||
color: "#0f172a",
|
|
||||||
textAlign: "left",
|
|
||||||
lineHeight: 1.48,
|
|
||||||
backgroundColor: "rgba(255,255,255,0.94)",
|
|
||||||
borderColor: "rgba(59,130,246,0.18)",
|
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 24,
|
|
||||||
padding: 20,
|
|
||||||
boxShadow: "0 18px 42px rgba(15,23,42,0.12)",
|
|
||||||
backdropBlur: 12,
|
|
||||||
},
|
|
||||||
metadata: {
|
metadata: {
|
||||||
screenIndex: params.screenIndex,
|
screenIndex: params.screenIndex,
|
||||||
componentRole: "spec_table",
|
componentRole: "spec_table_section",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
catalog.specRows.slice(0, 4).forEach((row, index) => {
|
||||||
|
const rowY = tableY + index * (38 + rowGap);
|
||||||
|
components.push(
|
||||||
|
createStyledSurfaceTextComponent({
|
||||||
|
id: `${params.screenId}-table-label-${index + 1}`,
|
||||||
|
type: "detail_table_label",
|
||||||
|
parentId: `${params.screenId}-section-spec-table`,
|
||||||
|
frame: {
|
||||||
|
x: tableX,
|
||||||
|
y: rowY,
|
||||||
|
width: labelWidth,
|
||||||
|
height: 38,
|
||||||
|
},
|
||||||
|
zIndex: 3,
|
||||||
|
content: row.label,
|
||||||
|
role: "table_label",
|
||||||
|
style: {
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: "700",
|
||||||
|
color: "#334155",
|
||||||
|
textAlign: "center",
|
||||||
|
lineHeight: 1.15,
|
||||||
|
backgroundColor: "rgba(241,245,249,0.96)",
|
||||||
|
borderColor: "rgba(148,163,184,0.22)",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 14,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
screenIndex: params.screenIndex,
|
||||||
|
componentRole: "table_label",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
components.push(
|
||||||
|
createStyledSurfaceTextComponent({
|
||||||
|
id: `${params.screenId}-table-value-${index + 1}`,
|
||||||
|
type: "detail_table_value",
|
||||||
|
parentId: `${params.screenId}-section-spec-table`,
|
||||||
|
frame: {
|
||||||
|
x: tableX + labelWidth + 10,
|
||||||
|
y: rowY,
|
||||||
|
width: tableWidth - labelWidth - 10,
|
||||||
|
height: 38,
|
||||||
|
},
|
||||||
|
zIndex: 3,
|
||||||
|
content: row.value,
|
||||||
|
role: "table_value",
|
||||||
|
style: {
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: "600",
|
||||||
|
color: "#0f172a",
|
||||||
|
textAlign: "left",
|
||||||
|
lineHeight: 1.18,
|
||||||
|
backgroundColor: "rgba(255,255,255,0.94)",
|
||||||
|
borderColor: "rgba(59,130,246,0.16)",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 14,
|
||||||
|
padding: 12,
|
||||||
|
boxShadow: "0 8px 22px rgba(15,23,42,0.08)",
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
screenIndex: params.screenIndex,
|
||||||
|
componentRole: "table_value",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (catalog.comparisonText && params.screen.screenType === "C") {
|
if ((catalog.comparison.beforeBody || catalog.comparison.afterBody) && params.screen.screenType === "C") {
|
||||||
|
const compareY = supportingSectionY - 126;
|
||||||
|
const compareWidth = Math.min(contentWidth, 430);
|
||||||
|
const compareColumnWidth = Math.floor((compareWidth - 12) / 2);
|
||||||
components.push(
|
components.push(
|
||||||
createStyledSurfaceTextComponent({
|
createStyledSurfaceTextComponent({
|
||||||
id: `${params.screenId}-comparison-strip`,
|
id: `${params.screenId}-compare-before`,
|
||||||
type: "detail_comparison_strip",
|
type: "detail_compare_before",
|
||||||
parentId: `${params.screenId}-section-supporting`,
|
parentId: `${params.screenId}-section-supporting`,
|
||||||
frame: {
|
frame: {
|
||||||
x: safeArea.left,
|
x: safeArea.left,
|
||||||
y: supportingSectionY - 112,
|
y: compareY,
|
||||||
width: Math.min(contentWidth, 420),
|
width: compareColumnWidth,
|
||||||
height: 158,
|
height: 170,
|
||||||
},
|
},
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
content: catalog.comparisonText,
|
content: `${catalog.comparison.beforeTitle}\n${catalog.comparison.beforeBody}`,
|
||||||
role: "comparison_strip",
|
role: "comparison_before",
|
||||||
style: {
|
style: {
|
||||||
fontSize: 17,
|
fontSize: 17,
|
||||||
fontWeight: "700",
|
fontWeight: "700",
|
||||||
color: "#f8fafc",
|
color: "#334155",
|
||||||
textAlign: "left",
|
textAlign: "left",
|
||||||
lineHeight: 1.4,
|
lineHeight: 1.4,
|
||||||
backgroundColor: "rgba(15,23,42,0.88)",
|
backgroundColor: "rgba(255,255,255,0.92)",
|
||||||
|
borderColor: "rgba(148,163,184,0.20)",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 26,
|
||||||
|
padding: 20,
|
||||||
|
boxShadow: "0 18px 44px rgba(15,23,42,0.10)",
|
||||||
|
backdropBlur: 10,
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
screenIndex: params.screenIndex,
|
||||||
|
componentRole: "comparison_before",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
components.push(
|
||||||
|
createStyledSurfaceTextComponent({
|
||||||
|
id: `${params.screenId}-compare-after`,
|
||||||
|
type: "detail_compare_after",
|
||||||
|
parentId: `${params.screenId}-section-supporting`,
|
||||||
|
frame: {
|
||||||
|
x: safeArea.left + compareColumnWidth + 12,
|
||||||
|
y: compareY,
|
||||||
|
width: compareColumnWidth,
|
||||||
|
height: 170,
|
||||||
|
},
|
||||||
|
zIndex: 2,
|
||||||
|
content: `${catalog.comparison.afterTitle}\n${catalog.comparison.afterBody}`,
|
||||||
|
role: "comparison_after",
|
||||||
|
style: {
|
||||||
|
fontSize: 17,
|
||||||
|
fontWeight: "800",
|
||||||
|
color: "#eff6ff",
|
||||||
|
textAlign: "left",
|
||||||
|
lineHeight: 1.4,
|
||||||
|
backgroundColor: "rgba(37,99,235,0.88)",
|
||||||
borderColor: "rgba(255,255,255,0.18)",
|
borderColor: "rgba(255,255,255,0.18)",
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderRadius: 26,
|
borderRadius: 26,
|
||||||
padding: 20,
|
padding: 20,
|
||||||
boxShadow: "0 20px 48px rgba(15,23,42,0.18)",
|
boxShadow: "0 20px 48px rgba(37,99,235,0.22)",
|
||||||
backdropBlur: 12,
|
backdropBlur: 12,
|
||||||
},
|
},
|
||||||
metadata: {
|
metadata: {
|
||||||
screenIndex: params.screenIndex,
|
screenIndex: params.screenIndex,
|
||||||
componentRole: "comparison_strip",
|
componentRole: "comparison_after",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (catalog.proofText) {
|
if (catalog.proof.value) {
|
||||||
const noteY = Math.min(
|
const noteY = Math.min(
|
||||||
params.screenSize.height - 116,
|
params.screenSize.height - 116,
|
||||||
supportingSectionY + supportingSectionHeight - 74,
|
supportingSectionY + supportingSectionHeight - 74,
|
||||||
@ -555,7 +746,7 @@ function buildSectionedTextComponents(params: {
|
|||||||
height: 62,
|
height: 62,
|
||||||
},
|
},
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
content: catalog.proofText,
|
content: `${catalog.proof.label}|${catalog.proof.value}`,
|
||||||
role: "proof_bar",
|
role: "proof_bar",
|
||||||
style: {
|
style: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
@ -579,34 +770,106 @@ function buildSectionedTextComponents(params: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (catalog.ctaText) {
|
if (catalog.cta) {
|
||||||
|
components.push(
|
||||||
|
createStyledSurfaceTextComponent({
|
||||||
|
id: `${params.screenId}-cta-support`,
|
||||||
|
type: "detail_cta_support",
|
||||||
|
parentId: params.textStackId,
|
||||||
|
frame: {
|
||||||
|
x: safeArea.left,
|
||||||
|
y: Math.min(params.screenSize.height - 198, supportingSectionY + supportingSectionHeight + 4),
|
||||||
|
width: Math.min(contentWidth, 430),
|
||||||
|
height: 70,
|
||||||
|
},
|
||||||
|
zIndex: 2,
|
||||||
|
content: catalog.cta.highlightText,
|
||||||
|
role: "cta_support",
|
||||||
|
style: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "800",
|
||||||
|
color: "#0f172a",
|
||||||
|
textAlign: "left",
|
||||||
|
lineHeight: 1.2,
|
||||||
|
backgroundColor: "rgba(255,255,255,0.88)",
|
||||||
|
borderColor: "rgba(37,99,235,0.14)",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 24,
|
||||||
|
padding: 18,
|
||||||
|
boxShadow: "0 14px 40px rgba(15,23,42,0.10)",
|
||||||
|
backdropBlur: 10,
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
screenIndex: params.screenIndex,
|
||||||
|
componentRole: "cta_support",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
components.push(
|
||||||
|
createStyledSurfaceTextComponent({
|
||||||
|
id: `${params.screenId}-cta-button`,
|
||||||
|
type: "detail_cta_button",
|
||||||
|
parentId: params.textStackId,
|
||||||
|
frame: {
|
||||||
|
x: safeArea.left,
|
||||||
|
y: Math.min(params.screenSize.height - 118, supportingSectionY + supportingSectionHeight + 76),
|
||||||
|
width: Math.min(268, contentWidth * 0.62),
|
||||||
|
height: 58,
|
||||||
|
},
|
||||||
|
zIndex: 3,
|
||||||
|
content: `${catalog.cta.buttonLabel} →`,
|
||||||
|
role: "cta_button",
|
||||||
|
style: {
|
||||||
|
fontSize: 19,
|
||||||
|
fontWeight: "800",
|
||||||
|
color: "#f8fafc",
|
||||||
|
textAlign: "center",
|
||||||
|
lineHeight: 1.05,
|
||||||
|
letterSpacing: 0.2,
|
||||||
|
backgroundColor: "rgba(37,99,235,0.94)",
|
||||||
|
borderColor: "rgba(255,255,255,0.24)",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 999,
|
||||||
|
padding: 18,
|
||||||
|
boxShadow: "0 22px 58px rgba(37,99,235,0.28)",
|
||||||
|
backdropBlur: 12,
|
||||||
|
textTransform: "uppercase",
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
screenIndex: params.screenIndex,
|
||||||
|
componentRole: "cta_button",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
components.push(
|
components.push(
|
||||||
createStyledSurfaceTextComponent({
|
createStyledSurfaceTextComponent({
|
||||||
id: `${params.screenId}-cta-banner`,
|
id: `${params.screenId}-cta-banner`,
|
||||||
type: "detail_cta_banner",
|
type: "detail_cta_banner",
|
||||||
parentId: params.textStackId,
|
parentId: params.textStackId,
|
||||||
frame: {
|
frame: {
|
||||||
x: safeArea.left,
|
x: safeArea.left + Math.min(268, contentWidth * 0.62) + 12,
|
||||||
y: Math.min(params.screenSize.height - 164, supportingSectionY + supportingSectionHeight + 8),
|
y: Math.min(params.screenSize.height - 118, supportingSectionY + supportingSectionHeight + 76),
|
||||||
width: Math.min(contentWidth, 430),
|
width: Math.max(140, Math.min(430, contentWidth) - Math.min(268, contentWidth * 0.62) - 12),
|
||||||
height: 104,
|
height: 58,
|
||||||
},
|
},
|
||||||
zIndex: 3,
|
zIndex: 2,
|
||||||
content: catalog.ctaText,
|
content: catalog.cta.supportText,
|
||||||
role: "cta_banner",
|
role: "cta_banner",
|
||||||
style: {
|
style: {
|
||||||
fontSize: 20,
|
fontSize: 15,
|
||||||
fontWeight: "800",
|
fontWeight: "600",
|
||||||
color: "#f8fafc",
|
color: "#eff6ff",
|
||||||
textAlign: "left",
|
textAlign: "left",
|
||||||
lineHeight: 1.28,
|
lineHeight: 1.22,
|
||||||
backgroundColor: "rgba(37,99,235,0.88)",
|
backgroundColor: "rgba(15,23,42,0.74)",
|
||||||
borderColor: "rgba(255,255,255,0.24)",
|
borderColor: "rgba(255,255,255,0.16)",
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderRadius: 28,
|
borderRadius: 22,
|
||||||
padding: 22,
|
padding: 16,
|
||||||
boxShadow: "0 22px 58px rgba(37,99,235,0.28)",
|
boxShadow: "0 18px 42px rgba(15,23,42,0.18)",
|
||||||
backdropBlur: 12,
|
backdropBlur: 10,
|
||||||
},
|
},
|
||||||
metadata: {
|
metadata: {
|
||||||
screenIndex: params.screenIndex,
|
screenIndex: params.screenIndex,
|
||||||
|
|||||||
@ -12,10 +12,17 @@ export type UiSurfaceComponentType =
|
|||||||
| "detail_card"
|
| "detail_card"
|
||||||
| "detail_badge"
|
| "detail_badge"
|
||||||
| "detail_feature_card"
|
| "detail_feature_card"
|
||||||
|
| "detail_feature_tag"
|
||||||
| "detail_spec_table"
|
| "detail_spec_table"
|
||||||
|
| "detail_table_label"
|
||||||
|
| "detail_table_value"
|
||||||
| "detail_comparison_strip"
|
| "detail_comparison_strip"
|
||||||
|
| "detail_compare_before"
|
||||||
|
| "detail_compare_after"
|
||||||
| "detail_proof_bar"
|
| "detail_proof_bar"
|
||||||
| "detail_cta_banner";
|
| "detail_cta_banner"
|
||||||
|
| "detail_cta_button"
|
||||||
|
| "detail_cta_support";
|
||||||
|
|
||||||
export type UiSurfaceTextBindingKey = "title" | "subtitle" | "copy";
|
export type UiSurfaceTextBindingKey = "title" | "subtitle" | "copy";
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user