Has anyone ever built a table similar the Prismic Compare plan with a slice machine? It looks complicated to build custom types, and I don't know how to achieve it.
Thank you in advance!
Has anyone ever built a table similar the Prismic Compare plan with a slice machine? It looks complicated to build custom types, and I don't know how to achieve it.
Thank you in advance!
Surprise! It’s me again.
I believe for tables, while you CAN do it in Prismic, the “better” solution is to use a service like Airtable. I’ve seen this recommended in other threads.
Thank you for the reply!
I have been learning a lot from you and I appreciate it.
Is AirTable the only solution for this? Can we use both Prismic and AirTable in one project for NextJS?
Did you see this in their FAQ?
Looking at their comparison table that you linked, I have to suspect that this isn't done so that it's editable via Prismic. If I had a client that wanted something like this, I'd create a slice called Table. If the client needed multiple tables, I'd use the variations feature of slices to create the different tables. I'd code the tables as needed. IMHO, this type of data isn't likely to change often enough to need to have it in the Prismic editor.
I totally understand if this doesn't work for your business. Perhaps you deliver a site and then disconnect entirely from the client. This could give you a reason to have them retain you or to contact you again for paid updates.
Thank you for the advice! This was very helpful.
You can also check out the network tab and download the JSON that the page uses - you can see exactly the model/slice structure that Prismic uses. Hope that's helpful
Thank you for the reply!
I don't follow this but I am interested to know more. Do you have a tutorial for this?
Hey!
I built the pricing slice, and indeed it's a bit complex. I'll try to explain. Also, Kris recommendation from above is pretty cool as you can see exactly how it's modelled.
So, for both variations of the pricing slice cards (top of page) and table (the one you refereed to) we have a custom type called "Pricing plan". This custom type consists of fields (a bit simplified) such as:
Then, for the cards variation, it's super simple. It just has a content relationship in the repeatable where you can pick which plans to include.
But for the table, it's a bit more advanced. Looking at the provided screenshot, you can see that we have category titles in the static zone, which defined the labels of the grouping. Then in the repeatable zone, we have:
So, for each row you want to create in the table, you add a new repeatable item, you pick which field you want to pull from the pricing plan, you name it and add additional info.
The only thing hard coded is the grouping of features, which you can only name in the table variations static zone explained above.
I hope this make some kind of sense, and feel free to ask follow up questions!
All the best
Samuel
Thank you for the reply!
How do you render in JSX in terms of content in rows and columns (checkbox/without checkbox)?
This is a table row in the desktop version of the table, tell me if it doesn't make sense, in terms of TypeScript it's far from perfect. Havent revisited this component for a while, but you should get an idea of how it renders at least!
const DesktopFeatureRow = ({
name,
explanation,
field,
full,
plans,
borderBottom,
borderTop,
smallText,
theme
}: DesktopFeatureRowProps) => {
return (
<tr
className={clsx(
"flex text-base lg:text-md font-medium group border-x-2 last:border-b-2 last:rounded-b-xl",
{
"text-gray-50 border-gray-15": theme === "light",
"text-gray-A4 border-gray-50": theme === "dark"
}
)}
>
<td
className={clsx(
"w-[256px] shrink-0 px-6 text-left border-r-2 flex gap-4 justify-between items-center group-last:rounded-bl-[10px]",
{
"py-6": full,
"py-4": !full,
"border-b-2 group-last:border-b-0": borderBottom,
"border-t-2": borderTop,
"bg-gray-F7 border-gray-15": theme === "light",
"bg-gray-1F border-gray-50": theme === "dark"
}
)}
>
<span className="text-base">{name}</span>
{explanation && (
<div className="relative">
<Tooltip placement="right">
<TooltipTrigger>
<QuestionIcon className="h-6 w-6" />
</TooltipTrigger>
<TooltipContent>{explanation}</TooltipContent>
</Tooltip>
</div>
)}
</td>
{plans &&
plans.map(
(plan, index) =>
field && (
<td
key={index}
className={clsx(
"flex-[1_1_100px] w-0 shrink-0 border-r-2 last:border-r-0 flex justify-center items-center group-last:last:rounded-br-[10px] group-last:last:overflow-hidden",
{
"border-b-2 group-last:border-b-0": borderBottom,
"border-t-2": borderTop,
"p-2": smallText,
"py-6 px-4": full && !smallText,
"py-4 px-4": !full && !smallText,
"border-gray-15": theme === "light",
"border-gray-50": theme === "dark"
}
)}
>
{plan.data[field as keyof Content.PricingPlanDocumentData] ===
"Check" ? (
<>
<CheckIcon className="mx-auto text-primary-green h-6 w-6" />
<span className="sr-only">Included</span>
</>
) : (
<span
className={clsx("text-ellipsis overflow-hidden", {
"text-sm font-regular": smallText,
"text-base font-bold": !smallText
})}
>
{
plan.data[
field as keyof Content.PricingPlanDocumentData
] as string
}
</span>
)}
</td>
)
)}
</tr>
);
};
Thank you, Samuel! I will try it out.