Sections
Jessica Walsh
Created: Aug 28, 2024
One of the most common tasks is to create new sections. In this example I'm going to create a "Gallery Opening" component to capture the details including title, description, images and a list of opening times.
Create content types
Now we have our wireframe design we can construct the content types in Headlesshost. Navigate to the staging site you are working on and select the "Types" option from the left hand menu.
Custom type
The opening times list will have a day of the week and hours open field. We will use a select component for the day of the week and a simple text field for the hours.
Enter the days of the week as a static list in the select field.
Section creation
Now we have all the types required, we can define the section. We can re-use the custom heading type used in other sections and add two image and one long text type. Finally we can add our opening times type and check the option for it to be a list.
For the images, we want the size to be exactly 250px square, so set the aspect ratio to 1 and min/max width to 250px
Code setup
Now we have our type setup in Headlesshost it's time to add the code to our Next.js application.
Section code
Create a new file called galleryOpening.tsx in the components/sections folder and add the following code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import React from "react";
import { Heading, ImageDetails, Section } from "@/app/lib/types";
import StandardHeading from "./standardHeading";
import Image from "next/image";
interface OpeningHour {
day: string;
hours: string;
}
interface GalleryOpeningSection extends Section {
heading: Heading;
openingHours: OpeningHour[];
description: string;
imageTop: ImageDetails;
imageBottom: ImageDetails;
}
interface GalleryOpeningProps {
section: GalleryOpeningSection;
}
const GalleryOpening: React.FC<GalleryOpeningProps> = ({ section }) => {
return (
<div className="flex">
<div className="pe-2">
<StandardHeading section={section} />
<div className="text-md text-slate-600 whitespace-pre-wrap mb-4">{section.description}</div>
<div className="font-bold font-xl mb-4">Opening Hours</div>
{section.openingHours.map((openingHour, index) => (
<div key={index} className="mb-4">
<div className="font-bold">{openingHour.day}</div>
<div>{openingHour.hours}</div>
</div>
))}
</div>
<div className="min-w-[250px]">
{section.imageTop && <Image src={section.imageTop.url} alt={section.imageTop.alt} width={section.imageTop.width} height={section.imageTop.height} className="rounded-t-md" />}
{section.imageBottom && <Image src={section.imageBottom.url} alt={section.imageBottom.alt} width={section.imageBottom.width} height={section.imageBottom.height} className="rounded-b-md" />}
</div>
</div>
);
};
export default GalleryOpening;
Modify section.tsx
Modify the section.tsx file inside the components folder.
1
2
3
import GalleryOpening from "./sections/galleryOpening";
GALLERY_OPENING: GalleryOpening
Complete file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import React from "react";
import TextBlockWithHeader from "./sections/textBlockWithHeader";
import InfoBox from "./sections/infoBox";
import CodeDisplay from "./sections/codeDisplay";
import ActionBox from "./sections/actionBox";
import NavLink from "./sections/navLink";
import CmsImage from "./sections/cmsImage";
import Video from "./sections/video";
import PageHeader from "./sections/pageHeader";
import TextBlock from "./sections/textBlock";
import OrderedList from "./sections/orderedList";
import AuthorTable from "./sections/authorTable";
import StandardHeading from "./sections/standardHeading";
import ContactForm from "./sections/contactForm";
import GalleryOpening from "./sections/galleryOpening";
interface SectionProps {
section: any;
instanceId: string;
}
const sections: { [key: string]: React.FC<any> } = {
PAGE_HEADER: PageHeader,
CODE_BLOCK: CodeDisplay,
TEXT_BLOCK_WITH_HEADER: TextBlockWithHeader,
TEXT_BLOCK: TextBlock,
INFO_BOX: InfoBox,
ACTION_BOX: ActionBox,
NAV_LINK: NavLink,
IMAGE: CmsImage,
VIDEO: Video,
ORDERED_LIST: OrderedList,
AUTHOR_TABLE: AuthorTable,
STANDARD_HEADING: StandardHeading,
CONTACT_FORM: ContactForm,
GALLERY_OPENING: GalleryOpening,
};
const Section: React.FC<SectionProps> = ({ section, instanceId }) => {
const SectionComponent = sections[section.type];
if (!SectionComponent) {
return null;
}
return <SectionComponent section={section} instanceId={instanceId} siteId={process.env.HEADLESSHOST_SITEID} />;
};
export default Section;
Test the section
With the code added you should now be able to test the section. Click "Insert new section" on any page and select the new Gallery Opening section.
Complete the form and save your changes.
Your staging site should hot reload with your new design.