Skip to content

Instantly share code, notes, and snippets.

@rcapeto
Last active July 5, 2024 18:55
Show Gist options
  • Save rcapeto/4064dcc43837a8fba6ed716986f5ea94 to your computer and use it in GitHub Desktop.
Save rcapeto/4064dcc43837a8fba6ed716986f5ea94 to your computer and use it in GitHub Desktop.
VTEX Custom-Component Documentation.

βš›οΈ Custom Component Documentation

Creating a Custom Component

  1. First create a file in /react/components/{filename}
  import React from 'react';

  function CustomComponent() {
    return <div />
  }
  
  export default CustomComponent;
  1. In /react root create a file and import this component
  import CustomComponent from '/components/{filename}'
  export default CustomComponent;
  1. Create file interfaces.json in the blocks.
{
  "custom-component": {
    "component": "{FileName [step 2]}" 
  }
}
  1. Now you can use this custom in your blocks.
{
   "store.home": {
      "blocks": ["custom-component"]
   }
}

Create defaultProps and Schema Object

  • VTEX provides a tool for editing the components called Site-Editor, for that we need to create schema and defaultProps object and the component needs to have props for it to work.
  1. Create Props
  function CustomComponent(props) {
    return(
        <h1>{props.title}</h1>
    );
  }
  1. Create defaultProps and Schema
  function CustomComponent(props) {
    return(
        <h1>{props.title}</h1>
    );
  }
  
  CustomComponent.defaultProps = {
    title: "Title Default"
  }
  CustomComponent.schema = {
    title: "Custom Component",
    type: "object",
    properties: {
      title: {
        type: "string",
        title: "Change title Props",
        default: "Custom Title"
      }
    }
  }
  • Now the developer can change props two ways

JSON File

{
   "store.home": {
      "blocks": ["custom-component#example"]
   },
   
   "custom-component#example": {
       "props": {
          "title: "Change Title Props"
        }
    }
}

Site-Editor

site-editor

πŸ“„ Schema Documentation

  • There are several types of data and we can use the schema to make it easier to style the component
  • The properties key is the configuration of component props

Schema Types

  • string
  • boolean
  • object
  • array

String Examples

  • Here you can use for images, url's, dates and texts props.

Examples:

  1. Images
Component
function CustomComponent({ imageDesktop, imageMobile }) {
   return(
      <div>
         <img src={imageDesktop} />
         <img src={imageMobile} />
      </div>
   );
}
Schema
  • Now has two options to use: One where the user select in computer files or the user paste de image url link.
const schema = {
   title: 'Custom Component',
   type: 'object',
   properties: {
      imageDesktop: {
         type: 'string',
         title: 'Image Desktop',
         default: '',
         description: 'Paste the URL'
      },
      imageMobile: {
         title: 'Image Mobile',
         default: '',
         type: 'string',
         widget: { //here you can choose a file in your computer
            "ui:widget": "image-uploader"
         }
      }
   }
};
Images

site-editor-image-example


  1. Dates
Component
function CustomComponent({ initialDate, finalDate }) {
   return(
      <div>
         <p>{initialDate}</p>
         <p>{finalDate}</p>
      </div>
   );
}
Schema
  • Now has two options to use: One where the user select the date or the user write the date.
const schema = {
   title: 'Custom Component',
   type: 'object',
   properties: {
      initialDate: {
         type: 'string',
         title: 'Initial Date',
         default: '',
         description: '{year}/{month}/{day}'
      },
      finalDate: {
         title: 'Final Date',
         //2022-02-23T02:20:42.074Z
         default: new Date().toISOString(), //Set current date in select input
         type: 'string',
         //to user select a date.
         format: 'date-time',
         widget: {
            "ui:widget": "datetime"
         }
      }
   }
};
Images

site-editor-date-example

  1. Texts/URL's

Schema

const schema = {
   title: 'Custom Component',
   type: 'object',
   properties: {
      textOrUrl: {
         type: 'string',
         title: 'Text or URL',
         default: '',
      }
   }
};

Boolean

Component

function CustomComponent({ active }) {
  if(!active) return;
  
   return(
      <div>
        <h2>Now the component is active!</h2>
      </div>
   );
}

Schema

const schema = {
   title: 'Custom Component',
   type: 'object',
   properties: {
      active: {
         type: 'boolean',
         title: 'Active Component',
         default: true,
      }
   }
};

Images

site-editor-boolean-example

Object

Component

function CustomComponent({ image }) {
   return(
      <div>
        <img
          src={image.url}
          alt={image.alt}
          title={image.title}
        />
      </div>
   );
}

Schema

const schema = {
   title: 'Custom Component',
   type: 'object',
   properties: {
      image: {
         title: 'Image Prop',
         type: 'object',
         properties: {
            url: {
               type: 'string',
               title: 'Image URL',
               description: 'URL image'
            },
            alt: {
               type: 'string',
               title: 'Image Text Alternative',
            },
            title: {
               type: 'string',
               title: 'Attribute title',
            },
         }
      }
   }
};

Images

site-editor-object-example

Array

Component

function CustomComponent({ images }) {
   const isMobile = window.innerWidth < 768;

   return(
      <div>
        {
           images.map((image, index) => (
              <img 
               alt={image.alt}
               key={String(index)}
               src={image[isMobile ? 'src' : 'mobileSrc']}
              />
           ))
        }
      </div>
   );
}

Schema

const schema = {
   title: 'Custom Component',
   type: 'object',
   properties: {
      images: {
         type: 'array',
         title: 'Images',
         default: [
            {
               src: '',
               alt: 'Text alternative',
               mobileSrc: ''
            }
         ],
         items: { //item configuration
            type: 'object',
            title: 'Image',
            properties: {
               src: {
                  type: 'string',
                  title: 'Image SRC',
                  description: 'Image URL [desktop]'
               },
               alt: {
                  type: 'string',
                  title: 'Image Text Alternative',
                  description: 'Image URL'
               },
               mobileSrc: {
                  type: 'string',
                  title: 'Image SRC [mobile]',
                  description: 'Image URL'
               },
            }
         }
      }
   }
};

Images

site-editor-array-example site-editor-array-item-example

One more thing:

  • You can change Item array name with __editorItemTitle property

Usage:

const schema = {
   title: 'Custom Component',
   type: 'object',
   properties: {
      images: {
         type: 'array',
         title: 'Images',
         default: [
            {
               src: '',
               alt: 'Text alternative',
               mobileSrc: ''
            }
         ],
         items: { //item configuration
            type: 'object',
            title: 'Image',
            properties: {
             __editorItemTitle: { // now change name is available
                  default: 'Image Item',
                  title: 'Change item name',
                  type: 'string'
               },
               src: {
                  type: 'string',
                  title: 'Image SRC',
                  description: 'Image URL [desktop]'
               },
               alt: {
                  type: 'string',
                  title: 'Image Text Alternative',
                  description: 'Image URL'
               },
               mobileSrc: {
                  type: 'string',
                  title: 'Image SRC [mobile]',
                  description: 'Image URL'
               },
            }
         }
      }
   }
};

Images

change-array-item-name-example-1 change-array-item-name-example-2 change-array-item-name-example-3

Enum and EnumNames properties

Enum

  • The function of the enum is for the prop to have specific values.
  • For example: I've a prop colors and the possible values are: red, blue or black.
const schema = {
   title: 'Custom Component',
   type: 'object',
   properties: {
      colors: {
         type: 'string',
         title: 'Color',
         default: 'red',
         enum: ['red', 'blue', 'black']
      }
   }
};

Images

site-editor-enum-example-1 site-editor-enum-example-2

EnumNames with Enum

  • The function of the enumName is for change names in enum.
  • For example: I've a prop colors and the possible values are: #0ff102, #1038c9 or #000000, but for the user I need to show de names: green, blue or black
  • If user select the value green, the prop returns #0ff102
const schema = {
   title: 'Custom Component',
   type: 'object',
   properties: {
      colors: {
         type: 'string',
         title: 'Color',
         default: 'red',
         enumNames: ['green', 'blue', 'black'],
         enum: [`#0ff102`,`#1038c9`, `#000000`]
      }
   }
};

Images

site-editor-enumNames-example-1 site-editor-enumNames-example-2

πŸš€ TypeScript

  • TypeScript is an open source programming language developed by Microsoft. It is a strict syntactic superset of JavaScript and adds optional static typing to the language.
  • For more informations, click here
  • With TypeScript we can create our own types to help with development

For example:

  • Using react types.
import React from 'react';

interface Props {
   title: string;
};

const CustomComponent: React.FC<Props> = props => {
   const { title } = props;
   return(
      <div>
         <h1>{title}</h1>
      </div>
   );
};
  • Using our own types:

Schema Interface

declare global {
   interface Schema {
      title: string;
      type: Extract<SchemaType, 'object'>;
      properties: SchemaProperties;
      dependencies?: SchemaDependencies;
   }
}

export type SchemaType = 'array' | 'object' | 'string' | 'boolean' | 'number';
export type UiWidget = 'image-uploader' | 'textarea' | 'datetime' | 'select' | 'color';

export interface SchemaDependencies {
   [key: string]: {
      oneOf: {
         properties: {
            [key: string]: Partial<SchemaItemProperty>;
         }
      }[];
   }
}

export interface SchemaProperties {
  __editorItemTitle?: {
    default: string
    title: string
    type: Extract<SchemaType, 'string'>
  },
   [key: string]: SchemaItemProperty;
}

export interface SchemaItemProperty {
   type: SchemaType;
   enumNames?: string[]; //esse funciona junto com o enum
   enum?: string[];
   default?: any;
   title?: string;
   description?: string;
   properties?: SchemaProperties;
   format?: 'date-time',
   widget?: {
      "ui:widget"?: UiWidget;
   },
   items?: {
      type: SchemaType;
      title?: string;
      properties?: SchemaProperties;
      default?: any;
   }
};

Component Interface

declare global {
  interface VTEXCustomComponent<Props ={}> extends FunctionComponent<Props> {
    getSchema?: (props: Props) => Schema;
    schema?: Schema;
    defaultProps?: Props;    
  }
}

Now we can use the created inteface

interface Props {
   title: string;
};

const CustomComponent: VTEXCustomComponent<Props> = ({ title }) => {
   return(
      <div>
         <h1>{title}</h1>
      </div>
   );
};

CustomComponent.defaultProps = {
   title: 'Default value'
}
CustomComponent.schema = {
   title: 'Custom Component',
   type: 'object',
   properties: { 
      title: {
         type: 'string',
         default: 'Default value',
         title: 'Title prop'
      }
   }
};

πŸ‘¨πŸ»β€πŸ’» Developers


Raphael Capeto

πŸ’»

Gabriel Cintra

πŸ’»

Gabriel Martins

πŸ’»

Made with πŸ–€ by Developers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment