feat(site-builder): basic blocks default to palette tokens

Refs #44

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
shadowdaoandClaude Sonnet 5.5 committed 2026-10-07 11:24:52 -07:00
1 parent 2180f9a776
commit d70f4933af
6 files changed
+41 -8

No files matched your search

@@ -118,3 +118,11 @@ describe('ButtonLink.craft.props exposes target + hover + box-model + animation/
expect(style.opacity).toBe('1');
});
});
describe('ButtonLink.toHtml palette token default (Refs #44)', () => {
test('a new button (craft default props) paints the primary token', () => {
const { html } = toHtml({ ...(ButtonLink as any).craft.props }, '');
expect(html).toContain('background-color:var(--wsb-primary)');
expect(html).not.toContain('#3b82f6');
});
});
+2 -1
View File
@@ -2,6 +2,7 @@ import React, { CSSProperties } from 'react';
import { useNode, UserComponent } from '@craftjs/core';
import { cssPropsToString } from '../../utils/style-helpers';
import { escapeHtml, escapeAttr, safeUrl, cssValue, scopeId } from '../../utils/escape';
import { tokenRef } from '../../utils/tokens';
interface ButtonLinkProps {
text?: string;
@@ -75,7 +76,7 @@ ButtonLink.craft = {
hoverBg: '',
hoverColor: '',
style: {
backgroundColor: '#3b82f6',
backgroundColor: tokenRef('primary'),
color: '#ffffff',
padding: '12px 24px',
borderRadius: '8px',
@@ -70,3 +70,15 @@ describe('Icon.craft.props includes the box-model/animation/visibility rollout p
expect(props).toHaveProperty('hideOnMobile', false);
});
});
describe('Icon.toHtml palette token fallback (Refs #44)', () => {
test('colour absent -> primary token', () => {
const { html } = toHtml({ icon: 'fa-star', size: '32px' }, '');
expect(html).toContain('color:var(--wsb-primary)');
expect(html).not.toContain('#3b82f6');
});
test('an explicit colour still wins', () => {
const { html } = toHtml({ icon: 'fa-star', size: '32px', color: '#ff0000' }, '');
expect(html).toContain('color:#ff0000');
});
});
+4 -3
View File
@@ -2,6 +2,7 @@ import React, { CSSProperties } from 'react';
import { useNode, UserComponent } from '@craftjs/core';
import { cssPropsToString } from '../../utils/style-helpers';
import { escapeAttr, safeUrl } from '../../utils/escape';
import { tokenRef } from '../../utils/tokens';
interface IconProps {
icon?: string;
@@ -29,7 +30,7 @@ function getBgBorderRadius(shape: string): string {
export const Icon: UserComponent<IconProps> = ({
icon = 'fa-star',
size = '32px',
color = '#3b82f6',
color = tokenRef('primary'),
bgColor = 'transparent',
bgShape = 'none',
bgSize = '56px',
@@ -95,7 +96,7 @@ Icon.craft = {
props: {
icon: 'fa-star',
size: '32px',
color: '#3b82f6',
color: tokenRef('primary'),
bgColor: 'transparent',
bgShape: 'none',
bgSize: '56px',
@@ -120,7 +121,7 @@ Icon.craft = {
const {
icon = 'fa-star',
size = '32px',
color = '#3b82f6',
color = tokenRef('primary'),
bgColor = 'transparent',
bgShape = 'none',
bgSize = '56px',
@@ -73,3 +73,13 @@ describe('SearchBar.craft.props includes animation/visibility defaults', () => {
});
});
});
describe('SearchBar.toHtml palette token fallbacks (Refs #44)', () => {
test('button background is the primary token and input text is the text token', () => {
const { html } = toHtml({}, '');
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');
});
});
+5 -4
View File
@@ -2,6 +2,7 @@ import React, { CSSProperties } from 'react';
import { useNode, UserComponent } from '@craftjs/core';
import { cssPropsToString } from '../../utils/style-helpers';
import { escapeHtml, escapeAttr, safeUrl } from '../../utils/escape';
import { tokenRef } from '../../utils/tokens';
interface SearchBarProps {
placeholder?: string;
@@ -73,7 +74,7 @@ export const SearchBar: UserComponent<SearchBarProps> = ({
border: '1px solid #d1d5db',
borderRadius: showButton ? '8px 0 0 8px' : '8px',
backgroundColor: '#ffffff',
color: '#1f2937',
color: tokenRef('text'),
outline: 'none',
boxSizing: 'border-box',
}}
@@ -88,7 +89,7 @@ export const SearchBar: UserComponent<SearchBarProps> = ({
fontWeight: '600',
fontFamily: 'Inter, sans-serif',
color: '#ffffff',
backgroundColor: '#3b82f6',
backgroundColor: tokenRef('primary'),
border: 'none',
borderRadius: '0 8px 8px 0',
cursor: 'pointer',
@@ -147,10 +148,10 @@ SearchBar.craft = {
...style,
});
const inputStyleStr = `width:100%;padding:12px 16px 12px 40px;font-size:15px;font-family:Inter,sans-serif;border:1px solid #d1d5db;border-radius:${showButton ? '8px 0 0 8px' : '8px'};background-color:#ffffff;color:#1f2937;outline:none;box-sizing:border-box`;
const inputStyleStr = `width:100%;padding:12px 16px 12px 40px;font-size:15px;font-family:Inter,sans-serif;border:1px solid #d1d5db;border-radius:${showButton ? '8px 0 0 8px' : '8px'};background-color:#ffffff;color:${tokenRef('text')};outline:none;box-sizing:border-box`;
const btnHtml = showButton
? `<button type="submit" style="padding:12px 20px;font-size:15px;font-weight:600;font-family:Inter,sans-serif;color:#ffffff;background-color:#3b82f6;border:none;border-radius:0 8px 8px 0;cursor:pointer;white-space:nowrap;display:flex;align-items:center;gap:6px"><i class="fa fa-search" style="font-size:13px" aria-hidden="true"></i>${escapeHtml(buttonText)}</button>`
? `<button type="submit" style="padding:12px 20px;font-size:15px;font-weight:600;font-family:Inter,sans-serif;color:#ffffff;background-color:${tokenRef('primary')};border:none;border-radius:0 8px 8px 0;cursor:pointer;white-space:nowrap;display:flex;align-items:center;gap:6px"><i class="fa fa-search" style="font-size:13px" aria-hidden="true"></i>${escapeHtml(buttonText)}</button>`
: '';
// F2: previously a purely decorative <form> -- no action/method/input