feat(site-builder): form blocks default to palette tokens
Refs #44 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d70f4933af
commit
af43af7dc1
6 files changed
+53
-14
No files matched your search
@@ -286,3 +286,17 @@ describe('ContactForm.toHtml destination marker', () => {
|
||||
expect(out.html).toContain('name="_gotcha"');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ContactForm.toHtml palette token fallbacks (Refs #44)', () => {
|
||||
test('submitColor empty -> primary token; input text -> text token', () => {
|
||||
const { html } = toHtml({ recipientEmail: 'a@b.com', fields: [{ type: 'text', label: 'Name', name: 'name' }], submitColor: '' }, '');
|
||||
expect(html).toContain('background-color:var(--wsb-primary)');
|
||||
expect(html).toContain('color:var(--wsb-text)');
|
||||
expect(html).not.toContain('#3b82f6');
|
||||
expect(html).not.toContain('#1f2937');
|
||||
});
|
||||
test('explicit submitColor wins', () => {
|
||||
const { html } = toHtml({ recipientEmail: 'a@b.com', fields: [], submitColor: '#ff0000' }, '');
|
||||
expect(html).toContain('background-color:#ff0000');
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,7 @@ import { useNode, UserComponent } from '@craftjs/core';
|
||||
import { cssPropsToString } from '../../utils/style-helpers';
|
||||
import { relayFormWiring } from '../../utils/form-relay-wiring';
|
||||
import { escapeHtml, escapeAttr, slugId, cssValue, sanitizeInputType } from '../../utils/escape';
|
||||
import { tokenRef } from '../../utils/tokens';
|
||||
|
||||
// The allowlist enforced at export time lives in `sanitizeInputType`
|
||||
// (utils/escape.ts) -- this union is a superset (it also covers 'textarea'
|
||||
@@ -61,7 +62,7 @@ const defaultFields: ContactFormField[] = [
|
||||
export const ContactForm: UserComponent<ContactFormProps> = ({
|
||||
fields = defaultFields,
|
||||
submitText = 'Send Message',
|
||||
submitColor = '#3b82f6',
|
||||
submitColor = tokenRef('primary'),
|
||||
formAction = '#',
|
||||
successMessage = 'Thank you! We\'ll get back to you soon.',
|
||||
style = {},
|
||||
@@ -84,7 +85,7 @@ export const ContactForm: UserComponent<ContactFormProps> = ({
|
||||
border: `1px solid ${inputBorder}`,
|
||||
borderRadius: '6px',
|
||||
backgroundColor: inputBg,
|
||||
color: '#1f2937',
|
||||
color: tokenRef('text'),
|
||||
boxSizing: 'border-box',
|
||||
outline: 'none',
|
||||
};
|
||||
@@ -168,7 +169,7 @@ ContactForm.craft = {
|
||||
props: {
|
||||
fields: defaultFields,
|
||||
submitText: 'Send Message',
|
||||
submitColor: '#3b82f6',
|
||||
submitColor: tokenRef('primary'),
|
||||
formAction: '#',
|
||||
successMessage: 'Thank you! We\'ll get back to you soon.',
|
||||
style: {
|
||||
@@ -215,7 +216,7 @@ ContactForm.craft = {
|
||||
const labelColor = cssValue(props.labelColor) || '#374151';
|
||||
const inputBg = cssValue(props.inputBg) || '#ffffff';
|
||||
const inputBorder = cssValue(props.inputBorder) || '#d1d5db';
|
||||
const inputStyleStr = `width:100%;padding:10px 14px;font-size:14px;font-family:Inter,sans-serif;border:1px solid ${inputBorder};border-radius:6px;background-color:${inputBg};color:#1f2937;box-sizing:border-box;outline:none`;
|
||||
const inputStyleStr = `width:100%;padding:10px 14px;font-size:14px;font-family:Inter,sans-serif;border:1px solid ${inputBorder};border-radius:6px;background-color:${inputBg};color:${tokenRef('text')};box-sizing:border-box;outline:none`;
|
||||
|
||||
const fieldsHtml = (props.fields || defaultFields).map((field, i) => {
|
||||
const reqStar = field.required ? '<span style="color:#ef4444;margin-left:2px">*</span>' : '';
|
||||
@@ -242,7 +243,7 @@ ContactForm.craft = {
|
||||
fontWeight: '600',
|
||||
fontFamily: 'Inter, sans-serif',
|
||||
color: '#ffffff',
|
||||
backgroundColor: props.submitColor || '#3b82f6',
|
||||
backgroundColor: cssValue(props.submitColor) || tokenRef('primary'),
|
||||
border: 'none',
|
||||
borderRadius: '8px',
|
||||
cursor: 'pointer',
|
||||
|
||||
@@ -38,3 +38,11 @@ describe('FormButton.craft.props includes animation/visibility defaults', () =>
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('FormButton.toHtml palette token default (Refs #44)', () => {
|
||||
test('a new form button (craft default props) paints the primary token', () => {
|
||||
const { html } = toHtml({ ...(FormButton as any).craft.props }, '');
|
||||
expect(html).toContain('background-color:var(--wsb-primary)');
|
||||
expect(html).not.toContain('#3b82f6');
|
||||
});
|
||||
});
|
||||
@@ -2,6 +2,7 @@ import React, { CSSProperties } from 'react';
|
||||
import { useNode, UserComponent } from '@craftjs/core';
|
||||
import { cssPropsToString } from '../../utils/style-helpers';
|
||||
import { escapeHtml } from '../../utils/escape';
|
||||
import { tokenRef } from '../../utils/tokens';
|
||||
|
||||
interface FormButtonProps {
|
||||
text?: string;
|
||||
@@ -31,7 +32,7 @@ export const FormButton: UserComponent<FormButtonProps> = ({
|
||||
onClick={(e) => e.preventDefault()}
|
||||
style={{
|
||||
padding: '12px 32px',
|
||||
backgroundColor: '#3b82f6',
|
||||
backgroundColor: tokenRef('primary'),
|
||||
color: '#ffffff',
|
||||
border: 'none',
|
||||
borderRadius: '6px',
|
||||
@@ -55,7 +56,7 @@ FormButton.craft = {
|
||||
props: {
|
||||
text: 'Submit',
|
||||
style: {
|
||||
backgroundColor: '#3b82f6',
|
||||
backgroundColor: tokenRef('primary'),
|
||||
color: '#ffffff',
|
||||
padding: '12px 32px',
|
||||
borderRadius: '6px',
|
||||
|
||||
@@ -79,3 +79,17 @@ describe('SubscribeForm.craft.props includes animation/visibility defaults', ()
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('SubscribeForm.toHtml palette token fallbacks (Refs #44)', () => {
|
||||
test('buttonColor absent -> primary token; heading/input text -> text token', () => {
|
||||
const { html } = toHtml({ heading: 'Join us' }, '');
|
||||
expect(html).toContain('background-color:var(--wsb-primary)');
|
||||
expect(html).toContain('color:var(--wsb-text)');
|
||||
expect(html).not.toContain('#3b82f6');
|
||||
expect(html).not.toContain('#1f2937');
|
||||
});
|
||||
test('explicit buttonColor wins', () => {
|
||||
const { html } = toHtml({ buttonColor: '#ff0000' }, '');
|
||||
expect(html).toContain('background-color:#ff0000');
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,7 @@ import { useNode, UserComponent } from '@craftjs/core';
|
||||
import { cssPropsToString } from '../../utils/style-helpers';
|
||||
import { relayFormWiring } from '../../utils/form-relay-wiring';
|
||||
import { escapeHtml, escapeAttr } from '../../utils/escape';
|
||||
import { tokenRef } from '../../utils/tokens';
|
||||
|
||||
interface SubscribeFormProps {
|
||||
heading?: string;
|
||||
@@ -28,7 +29,7 @@ export const SubscribeForm: UserComponent<SubscribeFormProps> = ({
|
||||
heading = 'Subscribe to our newsletter',
|
||||
placeholder = 'Enter your email',
|
||||
buttonText = 'Subscribe',
|
||||
buttonColor = '#3b82f6',
|
||||
buttonColor = tokenRef('primary'),
|
||||
layout = 'inline',
|
||||
style = {},
|
||||
}) => {
|
||||
@@ -55,7 +56,7 @@ export const SubscribeForm: UserComponent<SubscribeFormProps> = ({
|
||||
<h3 style={{
|
||||
fontSize: '22px',
|
||||
fontWeight: '600',
|
||||
color: '#1f2937',
|
||||
color: tokenRef('text'),
|
||||
marginBottom: '20px',
|
||||
fontFamily: 'Inter, sans-serif',
|
||||
}}>
|
||||
@@ -84,7 +85,7 @@ export const SubscribeForm: UserComponent<SubscribeFormProps> = ({
|
||||
border: '1px solid #d1d5db',
|
||||
borderRadius: isInline ? '8px 0 0 8px' : '8px',
|
||||
backgroundColor: '#ffffff',
|
||||
color: '#1f2937',
|
||||
color: tokenRef('text'),
|
||||
outline: 'none',
|
||||
boxSizing: 'border-box',
|
||||
}}
|
||||
@@ -119,7 +120,7 @@ SubscribeForm.craft = {
|
||||
heading: 'Subscribe to our newsletter',
|
||||
placeholder: 'Enter your email',
|
||||
buttonText: 'Subscribe',
|
||||
buttonColor: '#3b82f6',
|
||||
buttonColor: tokenRef('primary'),
|
||||
layout: 'inline',
|
||||
style: { backgroundColor: '#f8fafc' },
|
||||
recipientEmail: '',
|
||||
@@ -144,7 +145,7 @@ SubscribeForm.craft = {
|
||||
heading = 'Subscribe to our newsletter',
|
||||
placeholder = 'Enter your email',
|
||||
buttonText = 'Subscribe',
|
||||
buttonColor = '#3b82f6',
|
||||
buttonColor = tokenRef('primary'),
|
||||
layout = 'inline',
|
||||
style = {},
|
||||
} = props;
|
||||
@@ -158,7 +159,7 @@ SubscribeForm.craft = {
|
||||
});
|
||||
|
||||
const headingHtml = heading
|
||||
? `<h3 style="font-size:22px;font-weight:600;color:#1f2937;margin-bottom:20px;font-family:Inter,sans-serif">${escapeHtml(heading)}</h3>`
|
||||
? `<h3 style="font-size:22px;font-weight:600;color:${tokenRef('text')};margin-bottom:20px;font-family:Inter,sans-serif">${escapeHtml(heading)}</h3>`
|
||||
: '';
|
||||
|
||||
const formStyle = cssPropsToString({
|
||||
@@ -170,7 +171,7 @@ SubscribeForm.craft = {
|
||||
alignItems: 'stretch',
|
||||
});
|
||||
|
||||
const inputStyleStr = `flex:1;padding:12px 16px;font-size:15px;font-family:Inter,sans-serif;border:1px solid #d1d5db;border-radius:${isInline ? '8px 0 0 8px' : '8px'};background-color:#ffffff;color:#1f2937;outline:none;box-sizing:border-box`;
|
||||
const inputStyleStr = `flex:1;padding:12px 16px;font-size:15px;font-family:Inter,sans-serif;border:1px solid #d1d5db;border-radius:${isInline ? '8px 0 0 8px' : '8px'};background-color:#ffffff;color:${tokenRef('text')};outline:none;box-sizing:border-box`;
|
||||
|
||||
const btnStyle = cssPropsToString({
|
||||
padding: '12px 24px',
|
||||
|
||||
Reference in new issue
Block a user