site-builder: fix Menu guided panel (empty Colors) + surface layout/nav colors
The shared NavStylePanel gated its Colors controls on the Navbar's prop names (backgroundColor/textColor/ctaColor), so a Menu -- whose color props are linkColor/linkHoverColor/ctaBgColor/ctaTextColor -- rendered an empty Colors section (customer report: 'nothing to select'). - Add navColorFields() helper: derives the visible color controls from the props actually present, covering both the Navbar and Menu schemas (+ Navbar's hoverColor, which render/toHtml consume but had no control). - Add a Menu Layout section (alignment/orientation/gap/font size), guarded on Menu's own props so it never leaks into Navbar or a standalone Logo. - Unit test (navColorFields.test.ts) locks each component to its real props. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -247,6 +247,35 @@ export const ColorPickerField: React.FC<ColorPickerFieldProps> = ({ label, value
|
||||
</div>
|
||||
);
|
||||
|
||||
/* ---------- Nav-family color fields ----------
|
||||
The Colors section is shared across the whole nav family (Navbar / Logo /
|
||||
Footer / Menu). Those components DON'T share a color-prop schema:
|
||||
Navbar/Logo/Footer use backgroundColor/textColor/ctaColor, while Menu uses
|
||||
linkColor/linkHoverColor/ctaBgColor/ctaTextColor. Deriving the visible fields
|
||||
from whichever props actually exist keeps the section from rendering empty
|
||||
(the "Colors dropdown with nothing to select" bug on Menu). */
|
||||
export interface NavColorField {
|
||||
key: string;
|
||||
label: string;
|
||||
fallback: string;
|
||||
}
|
||||
const NAV_COLOR_FIELDS: NavColorField[] = [
|
||||
// Navbar / Logo / Footer schema
|
||||
{ key: 'backgroundColor', label: 'Background', fallback: '#ffffff' },
|
||||
{ key: 'textColor', label: 'Text Color', fallback: '#18181b' },
|
||||
{ key: 'hoverColor', label: 'Hover Color', fallback: '#3b82f6' },
|
||||
{ key: 'ctaColor', label: 'CTA Color', fallback: '#3b82f6' },
|
||||
// Menu schema (distinct prop names)
|
||||
{ key: 'linkColor', label: 'Link Color', fallback: '#3f3f46' },
|
||||
{ key: 'linkHoverColor', label: 'Hover Color', fallback: '#3b82f6' },
|
||||
{ key: 'ctaBgColor', label: 'CTA Background', fallback: '#3b82f6' },
|
||||
// ctaTextColor is shared: Menu's CTA text AND Navbar's CTA text
|
||||
{ key: 'ctaTextColor', label: 'CTA Text', fallback: '#ffffff' },
|
||||
];
|
||||
export function navColorFields(nodeProps: Record<string, any>): NavColorField[] {
|
||||
return NAV_COLOR_FIELDS.filter((f) => nodeProps[f.key] !== undefined);
|
||||
}
|
||||
|
||||
/* ---------- Collapsible section ---------- */
|
||||
export const CollapsibleSection: React.FC<{ title: string; defaultOpen?: boolean; children: React.ReactNode }> = ({ title, defaultOpen = true, children }) => {
|
||||
const [open, setOpen] = useState(defaultOpen);
|
||||
|
||||
Reference in New Issue
Block a user