I’ve been using children as a slot with allowedComponents
to do this. I am using registering the sub components though for more specialized cases, but using the default components for things like text. This is a testimonials component registration I’ve done:
export const testimonialsMeta = {
name: 'Testimonials',
props: {
editingSlide: {
displayName: 'Currently edited slide',
type: 'number',
description:
'Switch to the specified slide (first is 0). Only affects the editor, not the final page.',
defaultValueHint: 0,
editOnly: true,
hidden: () => true,
},
title: {
type: 'slot',
hidePlaceholder: true,
defaultValue: {
type: 'text',
value: 'Slider Title',
},
},
addBorder: {
displayName: 'Add Border',
type: 'boolean',
defaultValue: true,
},
variant: {
type: 'choice',
options: ['normal', 'small', 'image'],
},
children: {
type: 'slot',
hidePlaceholder: true,
allowedComponents: [
'testimonialNormalSlide',
'testimonialImageSlide',
'testimonialSmallSlide',
],
},
},
actions: [
{
type: 'custom-action',
control: CurrentSlideDropdown,
},
{
type: 'custom-action',
control: NavigateSlides,
},
{
type: 'button-action',
label: 'Add new testimonial',
onClick: ({ componentProps, studioOps }: any) => {
const slidesCnt = componentProps.children.length;
let slideType;
if (componentProps.variant === 'normal')
slideType = 'testimonialNormalSlide';
if (componentProps.variant === 'small')
slideType = 'testimonialSmallSlide';
if (componentProps.variant === 'image')
slideType = 'testimonialImageSlide';
studioOps.appendToSlot(
{
type: 'component',
name: slideType,
},
'children'
);
studioOps.updateProps({ editingSlide: slidesCnt });
},
},
{
type: 'button-action',
label: 'Delete current testimonial',
onClick: ({ componentProps, contextData, studioOps }: any) => {
const editingSlide = contextData.editingSlide ?? 0;
studioOps.removeFromSlotAt(editingSlide, 'children');
const slidesCnt = componentProps.children.length - 1;
studioOps.updateProps({
editingSlide: (editingSlide - 1 + slidesCnt) % slidesCnt,
});
},
},
],
};
export function registerTestimonials() {
PLASMIC.registerComponent(Testimonials, testimonialsMeta);
}
export const testimonialsImageMeta = {
name: 'testimonialImageSlide',
displayName: 'Testimonial Image Slide',
parentComponentName: 'Testimonials',
props: {
title: {
type: 'slot',
hidePlaceholder: true,
defaultValue: {
type: 'text',
value: 'Slider Title',
},
},
credit: {
type: 'slot',
hidePlaceholder: true,
defaultValue: {
type: 'text',
value: 'Slide Author',
},
},
content: {
type: 'slot',
hidePlaceholder: true,
defaultValue: {
type: 'text',
value:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
},
},
image: {
type: 'imageUrl',
defaultValue:
'<https://site-assets.plasmic.app/0d815cdab8963d4cfecede42adcf7c18.jpg>',
},
},
};
export function registerTestimonialImageSlide() {
PLASMIC.registerComponent(TestimonialImageSlide, testimonialsImageMeta);
}
export const testimonialsNormalMeta = {
name: 'testimonialNormalSlide',
displayName: 'Testimonial Normal Slide',
parentComponentName: 'Testimonials',
props: {
title: {
type: 'slot',
hidePlaceholder: true,
defaultValue: {
type: 'text',
value: 'Slider Title',
},
},
credit: {
type: 'slot',
hidePlaceholder: true,
defaultValue: {
type: 'text',
value: 'Slide Author',
},
},
course: {
type: 'slot',
hidePlaceholder: true,
defaultValue: {
type: 'text',
value: 'Course Ref',
},
},
content: {
type: 'slot',
hidePlaceholder: true,
defaultValue: {
type: 'text',
value:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
},
},
},
};
export function registerTestimonialNormalSlide() {
PLASMIC.registerComponent(TestimonialNormalSlide, testimonialsNormalMeta);
}
export const testimonialsSmallMeta = {
name: 'testimonialSmallSlide',
displayName: 'Testimonial Small Slide',
parentComponentName: 'Testimonials',
props: {
credit: {
type: 'slot',
hidePlaceholder: true,
defaultValue: {
type: 'text',
value: 'Slide Author',
},
},
content: {
type: 'slot',
hidePlaceholder: true,
defaultValue: {
type: 'text',
value:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
},
},
},
};
export function registerTestimonialSmallSlide() {
PLASMIC.registerComponent(TestimonialSmallSlide, testimonialsSmallMeta);
}