Token-based sections (21 total across four families) with tests covering insert, export (no stray hex, alt on images, relative links) and tree shape. Refs #52
157 lines
8.5 KiB
TypeScript
157 lines
8.5 KiB
TypeScript
import type { SectionDef } from '../catalog';
|
|
import type { TemplateComponent } from '../../templates/definitions';
|
|
import { tokenRef } from '../../utils/tokens';
|
|
|
|
/** Services sections. Content tasks append to SERVICES_SECTIONS only. */
|
|
const pad = (v: string, h = '20px') => ({ paddingTop: v, paddingBottom: v, paddingLeft: h, paddingRight: h });
|
|
const title = (text: string): TemplateComponent => ({
|
|
type: 'Heading',
|
|
props: { text, level: 'h2', style: { textAlign: 'center', color: tokenRef('text'), fontFamily: tokenRef('heading-font'), marginBottom: '32px' } },
|
|
});
|
|
const h3 = (text: string, align = 'left'): TemplateComponent => ({
|
|
type: 'Heading',
|
|
props: { text, level: 'h3', style: { textAlign: align, color: tokenRef('text'), fontFamily: tokenRef('heading-font'), fontSize: '22px', marginBottom: '8px' } },
|
|
});
|
|
const p = (text: string, align = 'left'): TemplateComponent => ({
|
|
type: 'TextBlock',
|
|
props: { text, style: { textAlign: align, color: tokenRef('muted'), fontFamily: tokenRef('body-font'), lineHeight: '1.6', marginBottom: '8px' } },
|
|
});
|
|
const emoji = (e: string): TemplateComponent => ({
|
|
type: 'TextBlock',
|
|
props: { text: e, style: { fontSize: '36px', lineHeight: '1.2', marginBottom: '8px' } },
|
|
});
|
|
const card = (children: TemplateComponent[]): TemplateComponent => ({
|
|
type: 'Container',
|
|
props: { style: { paddingTop: '28px', paddingBottom: '28px', paddingLeft: '28px', paddingRight: '28px', minHeight: '0px', border: `1px solid ${tokenRef('border')}`, borderRadius: '12px', backgroundColor: tokenRef('bg') } },
|
|
children,
|
|
});
|
|
const plain = (children: TemplateComponent[]): TemplateComponent => ({
|
|
type: 'Container', props: { style: { padding: '0px', minHeight: '0px' } }, children,
|
|
});
|
|
|
|
const BTN = { backgroundColor: tokenRef('primary'), color: tokenRef('bg'), padding: '12px 24px', borderRadius: '8px', fontWeight: '600', fontSize: '16px', border: 'none' };
|
|
|
|
export const SERVICES_SECTIONS: SectionDef[] = [
|
|
{
|
|
id: 'services-grid',
|
|
name: 'Services grid',
|
|
family: 'services',
|
|
keywords: ['features', 'offerings', 'what we do', 'benefits'],
|
|
tree: {
|
|
type: 'Section',
|
|
props: { aiName: 'Services', anchorId: '', style: { padding: '72px 20px', backgroundColor: tokenRef('bg') } },
|
|
children: [
|
|
{ type: 'Heading', props: { text: 'Our Services', level: 'h2', style: { textAlign: 'center', color: tokenRef('text'), fontFamily: tokenRef('heading-font'), marginBottom: '24px' } } },
|
|
{
|
|
type: 'FeaturesGrid',
|
|
props: {
|
|
features: [
|
|
{ title: 'Service one', description: 'A short description of what this service includes.', icon: '⭐' },
|
|
{ title: 'Service two', description: 'A short description of what this service includes.', icon: '🛠️' },
|
|
{ title: 'Service three', description: 'A short description of what this service includes.', icon: '💬' },
|
|
],
|
|
style: { backgroundColor: tokenRef('bg') },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
id: 'services-icon-cards',
|
|
name: 'Services - icon cards',
|
|
family: 'services',
|
|
keywords: ['icons', 'cards', 'three column', 'what we do', 'benefits'],
|
|
tree: {
|
|
type: 'Section',
|
|
props: { aiName: 'Services', anchorId: '', style: { ...pad('72px'), backgroundColor: tokenRef('bg') } },
|
|
children: [
|
|
title('Our Services'),
|
|
{ type: 'ColumnLayout', props: { columns: 3, split: '33-33-33', gap: '24px' }, children: [
|
|
card([emoji('⭐'), h3('Service one'), p('A short description of what this service includes.')]),
|
|
card([emoji('🛠️'), h3('Service two'), p('A short description of what this service includes.')]),
|
|
card([emoji('💬'), h3('Service three'), p('A short description of what this service includes.')]),
|
|
] },
|
|
],
|
|
},
|
|
},
|
|
{
|
|
id: 'services-cards-2x2',
|
|
name: 'Services - 2x2 cards',
|
|
family: 'services',
|
|
keywords: ['cards', 'four', 'grid', 'offerings', 'what we do'],
|
|
tree: {
|
|
type: 'Section',
|
|
props: { aiName: 'Services', anchorId: '', style: { ...pad('72px'), backgroundColor: tokenRef('bg') } },
|
|
children: [
|
|
title('What we do'),
|
|
{ type: 'ColumnLayout', props: { columns: 2, split: '50-50', gap: '24px' }, children: [
|
|
card([emoji('🔧'), h3('Repairs and maintenance'), p('Fast, tidy work to keep everything running as it should.')]),
|
|
card([emoji('📋'), h3('Planning and advice'), p('Clear recommendations and honest quotes before we start.')]),
|
|
] },
|
|
{ type: 'Spacer', props: { height: '24px' } },
|
|
{ type: 'ColumnLayout', props: { columns: 2, split: '50-50', gap: '24px' }, children: [
|
|
card([emoji('🏠'), h3('On-site visits'), p('We come to you, on a day and time that suits you.')]),
|
|
card([emoji('🤝'), h3('Ongoing support'), p('Regular check-ins and a friendly voice when you need one.')]),
|
|
] },
|
|
],
|
|
},
|
|
},
|
|
{
|
|
id: 'services-alternating-rows',
|
|
name: 'Services - alternating rows',
|
|
family: 'services',
|
|
keywords: ['rows', 'image', 'detail', 'alternating', 'zigzag'],
|
|
tree: {
|
|
type: 'Section',
|
|
props: { aiName: 'Services', anchorId: '', style: { ...pad('72px'), backgroundColor: tokenRef('bg') } },
|
|
children: [
|
|
title('How we can help'),
|
|
{ type: 'ColumnLayout', props: { columns: 2, split: '50-50', gap: '48px', style: { alignItems: 'center' } }, children: [
|
|
{ type: 'ImageBlock', props: { alt: 'First service', style: { width: '100%', height: 'auto', aspectRatio: '4 / 3', objectFit: 'cover', borderRadius: '12px' } } },
|
|
plain([h3('Our main service'), p('Describe the service, who it is for and the result customers can expect.'), { type: 'ButtonLink', props: { text: 'Learn more', href: 'contact', style: BTN } }]),
|
|
] },
|
|
{ type: 'Spacer', props: { height: '48px' } },
|
|
{ type: 'ColumnLayout', props: { columns: 2, split: '50-50', gap: '48px', style: { alignItems: 'center' } }, children: [
|
|
plain([h3('Our second service'), p('Explain what is included and what makes your approach different.'), { type: 'ButtonLink', props: { text: 'Learn more', href: 'contact', style: BTN } }]),
|
|
{ type: 'ImageBlock', props: { alt: 'Second service', style: { width: '100%', height: 'auto', aspectRatio: '4 / 3', objectFit: 'cover', borderRadius: '12px' } } },
|
|
] },
|
|
],
|
|
},
|
|
},
|
|
{
|
|
id: 'services-steps',
|
|
name: 'Services - how it works steps',
|
|
family: 'services',
|
|
keywords: ['process', 'steps', 'how it works', 'numbered'],
|
|
tree: {
|
|
type: 'Section',
|
|
props: { aiName: 'Process', anchorId: '', style: { ...pad('72px'), backgroundColor: tokenRef('bg') } },
|
|
children: [
|
|
title('How it works'),
|
|
{ type: 'ColumnLayout', props: { columns: 3, split: '33-33-33', gap: '32px' }, children: [
|
|
plain([{ type: 'Heading', props: { text: '1', level: 'h3', style: { color: tokenRef('primary'), fontFamily: tokenRef('heading-font'), fontSize: '40px', textAlign: 'center', marginBottom: '4px' } } }, h3('Get in touch', 'center'), p('Tell us what you need and we will reply quickly.', 'center')]),
|
|
plain([{ type: 'Heading', props: { text: '2', level: 'h3', style: { color: tokenRef('primary'), fontFamily: tokenRef('heading-font'), fontSize: '40px', textAlign: 'center', marginBottom: '4px' } } }, h3('We make a plan', 'center'), p('A clear quote and a date that works for you.', 'center')]),
|
|
plain([{ type: 'Heading', props: { text: '3', level: 'h3', style: { color: tokenRef('primary'), fontFamily: tokenRef('heading-font'), fontSize: '40px', textAlign: 'center', marginBottom: '4px' } } }, h3('Job done', 'center'), p('We finish on time and check you are happy.', 'center')]),
|
|
] },
|
|
],
|
|
},
|
|
},
|
|
{
|
|
id: 'services-list-columns',
|
|
name: 'Services - simple list',
|
|
family: 'services',
|
|
keywords: ['list', 'compact', 'offerings', 'two column'],
|
|
tree: {
|
|
type: 'Section',
|
|
props: { aiName: 'Services', anchorId: '', innerMaxWidth: '900px', style: { ...pad('64px'), backgroundColor: tokenRef('bg') } },
|
|
children: [
|
|
title('Services we offer'),
|
|
{ type: 'ColumnLayout', props: { columns: 2, split: '50-50', gap: '40px' }, children: [
|
|
plain([h3('Service one'), p('One line about this service.'), h3('Service two'), p('One line about this service.'), h3('Service three'), p('One line about this service.')]),
|
|
plain([h3('Service four'), p('One line about this service.'), h3('Service five'), p('One line about this service.'), h3('Service six'), p('One line about this service.')]),
|
|
] },
|
|
],
|
|
},
|
|
},
|
|
];
|