site-builder: dynamic CTAs, section anchors, edit-with-Sitesmith
Three related features: 1. Dynamic CTA buttons on HeroSimple, CTASection, CallToAction. New shared ctas[] array (text + href + variant + target) replaces the primary/secondary pair. Settings panel gets add/remove/reorder controls. Legacy fields stay readable for backwards compat — first user edit migrates the section onto the new array. 2. Anchor IDs on all layout/section components (Container, Section, BackgroundSection, ColumnLayout, plus 6 section blocks done by parallel subagent, plus Hero/CTA/CallToAction). Anchor input lives in the settings panel with an "auto from heading" button that walks the subtree for the first Heading.text. Renders as id="..." on the outermost element so #anchor URLs resolve. 3. Edit-with-Sitesmith targeted invocation. Right-click → "Ask Sitesmith" and a button at the top of the right-side settings panel both open the modal pre-targeted at the selected node. The node's serialized subtree is sent to the server; system prompt is augmented to require a patch with replace_node. Editor lifts modal state into a new SitesmithContext. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import React, { CSSProperties, useState } from 'react';
|
||||
import { useNode, UserComponent } from '@craftjs/core';
|
||||
import { cssPropsToString } from '../../utils/style-helpers';
|
||||
import { AnchorIdField } from '../../ui/AnchorIdField';
|
||||
|
||||
interface Testimonial {
|
||||
quote: string;
|
||||
@@ -16,6 +17,7 @@ interface TestimonialsProps {
|
||||
style?: CSSProperties;
|
||||
cardBg?: string;
|
||||
starColor?: string;
|
||||
anchorId?: string;
|
||||
}
|
||||
|
||||
const defaultTestimonials: Testimonial[] = [
|
||||
@@ -52,6 +54,7 @@ export const Testimonials: UserComponent<TestimonialsProps> = ({
|
||||
style = {},
|
||||
cardBg = '#f8fafc',
|
||||
starColor = '#f59e0b',
|
||||
anchorId,
|
||||
}) => {
|
||||
const {
|
||||
connectors: { connect, drag },
|
||||
@@ -86,6 +89,7 @@ export const Testimonials: UserComponent<TestimonialsProps> = ({
|
||||
return (
|
||||
<section
|
||||
ref={(ref: HTMLElement | null): void => { if (ref) connect(drag(ref)); }}
|
||||
id={anchorId || undefined}
|
||||
style={{
|
||||
padding: '80px 20px',
|
||||
backgroundColor: '#ffffff',
|
||||
@@ -187,6 +191,7 @@ const TestimonialsSettings: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div style={{ padding: '12px', display: 'flex', flexDirection: 'column', gap: '14px' }}>
|
||||
<AnchorIdField />
|
||||
{/* Layout */}
|
||||
<div>
|
||||
<label style={labelStyle}>Layout</label>
|
||||
@@ -357,6 +362,7 @@ Testimonials.craft = {
|
||||
style: { backgroundColor: '#ffffff' },
|
||||
cardBg: '#f8fafc',
|
||||
starColor: '#f59e0b',
|
||||
anchorId: '',
|
||||
},
|
||||
rules: {
|
||||
canDrag: () => true,
|
||||
@@ -388,6 +394,7 @@ Testimonials.craft = {
|
||||
backgroundColor: '#ffffff',
|
||||
...style,
|
||||
});
|
||||
const idAttr = props.anchorId ? ` id="${esc(props.anchorId)}"` : '';
|
||||
|
||||
const cardCss = `background-color:${cardBg};border-radius:12px;padding:32px 24px;text-align:center;border:1px solid #e2e8f0`;
|
||||
|
||||
@@ -403,7 +410,7 @@ Testimonials.craft = {
|
||||
if (layout === 'single') {
|
||||
// For single layout, export as grid with 1 column (simpler static export)
|
||||
return {
|
||||
html: `<section${sectionStyle ? ` style="${sectionStyle}"` : ''}>
|
||||
html: `<section${idAttr}${sectionStyle ? ` style="${sectionStyle}"` : ''}>
|
||||
<div style="max-width:600px;margin:0 auto;display:grid;grid-template-columns:1fr;gap:24px">
|
||||
${cards}
|
||||
</div>
|
||||
@@ -412,7 +419,7 @@ Testimonials.craft = {
|
||||
}
|
||||
|
||||
return {
|
||||
html: `<section${sectionStyle ? ` style="${sectionStyle}"` : ''}>
|
||||
html: `<section${idAttr}${sectionStyle ? ` style="${sectionStyle}"` : ''}>
|
||||
<div style="max-width:1100px;margin:0 auto;display:grid;grid-template-columns:repeat(${columns},1fr);gap:24px">
|
||||
${cards}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user