Components

Components are the building blocks of your website. You can drag and drop them into place to build simple pages or complex layouts. Gust comes with a whole bunch of these out of the box, but lets you create new ones or just update the ones we've give you to suit your brand.

Creating components

All components are created by writing JSON and loading them into the site via a hook. All the options are outline below but if you want to get a sense of what it's really like, I suggest you take a look at some of the ones provided for you. You can find these in wp-content/themes/gust/includes/components.

Once you've got your JSON file ready you can add it all in using the following snippet. You'll need to make sure this function is named appropriately, this is just an example.

add_action('gust_register_components', 'register_components');
function register_components( $gust_components )
{
  if (!class_exists('Gust')) return;
  $dir = trailingslashit(plugin_dir_path(__FILE__));
  $string = file_get_contents($dir . 'components/my-component.json');
  $json = json_decode($string, true);
  $gust_components->register_component('my-component', $json);
}

Here's an example component:

{
  "id": "button",
  "displayName": "Button",
  "category": "Buttons",
  "tag": "button",
  "classNames": "font-bold rounded bg-primary text-white p-4 inline-block",
  "content": {
    "type": "value",
    "value": "Click Me!"
  }
}

This creates a very basic, single element component called "Button" which, unsurprisingly, creates a button. You can start to see some obvious properties that go into defining this component.

Component properties

  • Name
    id
    Type
    string
    Required
    Required
    Description

    The ID is not to be confused with the HTML id attribute. This ID is not rendered when the page is built, it is used exclusively in the editor. This must be set on every component and every child of every component. You can leave it off if you want, but things will start to fall apart pretty quickly. We wouldn't recommend it. It can be whatever you want, just make sure that it is unique within the component. And preferably unique to the other components.

  • Name
    displayName
    Type
    string
    Required
    Required: top level only
    Description

    The display name is used to identify a component. It is only needed for the top level, i.e. component children do not need it

  • Name
    category
    Type
    string
    Required
    Required: top level only
    Description

    The category is used to group components in the editor. Like the displayName it is only needed for the top level component

  • Name
    tag
    Type
    string
    Required
    Required
    Description

    The HTML tag that will used

  • Name
    classNames
    Type
    string
    Description

    Any default classes that should appear on the element

  • Name
    content
    Type
    Object
    Description
  • Name
    content.type
    Type
    string
    Required
    Required
    Description

    Can be either value, filter, function, meta, or richtext. See Supported Functions for more info.

  • Name
    content.value
    Type
    string
    Required
    Required
    Description

    This is the value of whatever content.type is set to. E.g if it's a filter then it should be the name of the filter, a function then it's the name of the function, rich text then it's the HTML string

  • Name
    content.defaultValue
    Type
    string
    Description

    When content.type is a filter, this is the default value that gets passed to the filter.

  • Name
    children
    Type
    Component[]
    Description

    Children is an array of component objects. When you start nesting HTML elements, this is where they'll go.

  • Name
    allowChildren
    Type
    boolean
    Description

    In the drag and drop editor, if you want to be able to drag components / elements into this specific element, set this to true

  • Name
    hasRepeater
    Type
    boolean
    Description

    This marks the component as having repeatable content somewhere in its children. For example, a tabs component may have this set to true on the top level, but only implements the repeatable content in one of its children. Only set this on the top level component. There are more examples of this below.

  • Name
    useRepeater
    Type
    boolean
    Description

    This marks a particular node in the component tree as being repeatable. E.g. in a tabs component this might be the tab button that repeats or in a slider component it's the slide element that repeats.

  • Name
    allowRepeaterContent
    Type
    boolean
    Description

    Whether or not the content within this repeated element should be editable. E.g. In a tabs component the tab label itself might set this to true to let the user override the default content.

  • Name
    displayRepeated
    Type
    'single' | ''
    Description

    This controls how repeated content is displayed in the editor. Left undefined it will display the repeated items, however if you set it to single it will only show the currently active item. E.g. in a tabs component you might set the list of tabs as undefined so they are always visible, but you would set the tab content to single so that only one tabs content displayed at a time. Again, this only effects the editor and it's up to the developer to implement this on the front end. We do have some helper classes though, take a look at Repeatable content for more details.

  • Name
    option
    Type
    Option[]
    Description

    Options allow you to "mask" more complex CSS classes or HTML attributes. For example, on an anchor, styled as a button, the user will likely want to add an href. That's fine for developers, but your clients are unlikely to know what an href is. So, you can add an option called "Link" that maps to the href attribute and makes it easy for the user to understand.

  • Name
    option.label
    Type
    string
    Required
    Required
    Description

    The label for your option, shown to the user.

  • Name
    option.name
    Type
    string
    Required
    Required
    Description

    A unique name for your option, this is used by the editor to save the property against. It should be JSON friendly.

  • Name
    option.type
    Type
    'select' | 'text'
    Required
    Required
    Description

    Should the option display as a select box or a free text input.

  • Name
    option.options
    Type
    { label: string; value: string}[]
    Required
    Required: when option.type === 'select'
    Description

    If you set options.type to select you will need to provide options for the user to choose from. It will default to the first option.

  • Name
    option.modify
    Type
    'className' | 'attribute'
    Description

    Should this option add to the CSS class names, or should it set an attribute

  • Name
    option.attributeName
    Type
    string
    Required
    Required: when option.modify === 'attribute'
    Description

    What attribute should be added to the element?

  • Name
    attributes
    Type
    attribute[]
    Description

    You can set default HTML attributes for a tag. Note that the user can override this and set their own.

  • Name
    attribute.type
    Type
    'value' | 'filter' | 'function'
    Required
    Required
    Description

    What type of content should we use for the attribute. See Supported Functions for more info.

  • Name
    attribute.name
    Type
    string
    Required
    Required
    Description

    The HTML attribute name.

  • Name
    attribute.value
    Type
    string
    Required
    Required: when attribute.content is set
    Description

    This is the value of whatever content.type is set to. E.g if it's a filter then it should be the name of the filter, a function then it's the name of the function, rich text then it's the HTML string

  • Name
    styles
    Type
    string[]
    Description

    Add a list of handles that have been registered with wp_register_style. These will be enqueued when the component loads.

  • Name
    scripts
    Type
    string[]
    Description

    Add a list of handles that have been registered with wp_register_script. These will be enqueued when the component loads.

  • Name
    editorStyles
    Type
    React.CSSProperties
    Description

    Add styles here on an element that should be applied only in the editor. This is helpful for things like an accordion which we may want to always show open when editing.

Supported functions

When setting the content or attribute type as function, Gust supports a few functions out of the box. These are:

  • get_the_title
  • get_the_content
  • get_the_permalink
  • get_the_post_thumbnail
  • get_the_post_thumbnail_url
  • get_the_excerpt
  • get_post_status
  • get_the_ID

Note that these functions are all using the get_ counterparts so that the result is not immediately echo'd by PHP.

Repeatable content

When it comes to components, repeatable content is not the same as context and looping over content. Repeatable content exposes UI controls to the user and allows users to repeat the same UI elements with different data, all within one component. Some examples of elements requiring repeatable content are:

  • Tabs
  • Accordions
  • Slideshows

All of the above need to share common UI elements and generally have some shared state ( e.g. when one tab is open, close the others ).

Developers can also filter the repeatable content. See the gust_repeater_items filter on the WordPress hooks page.

Example component

The below example is an example of how you can create your components with an example of using one of every option. We're going to be making a tabbed component and there are comments throughout the definition to help clear up some of the more obscure properties. Some key things to note here are:

  • how repeatable items are used
  • how options are used in the
{
  "id": "tabs",
  "displayName": "Tabs",
  "category": "Content",
  "tag": "div",
  // this lets the editor know that users should be able to add items, or in this case "tabs"
  "hasRepeater": true,
  "children": [
    {
      "id": "tabLabelsContainer",
      "tag": "ul",
      // class set to "flex" ( see tailwind CSS ) to make all the tabs sit inline
      "classNames": "flex",
      "children": [
        {
          "id": "tabLabel",
          "tag": "li",
          // when a new item ( i.e. tab ) is added by the user in the UI, this whole element will repeat
          "useRepeater": true,
          "classNames": "group",
          "children": [
            {
              "id": "tabButton",
              "tag": "button",
              // adds some padding and borders
              // note the group-gust-active-item:border-primary class
              // there's more detail on that in the Repeatable Content doc
              "classNames": "p-2 border-b-2 group-gust-active-item:border-primary",
              // allows the content of this element to be overwritten on a per-item basis
              // without this, every tab label would display "Tab" and the user would not be able to change it
              "allowRepeaterContent": true,
              // sets up a default value for tab label
              "content": {
                "type": "value",
                "value": "Tab"
              }
            }
          ],
          // let's the user choose whether their button has a white or primary background
          "options": [
            {
              "label": "Label Colour",
              "name": "labelColour",
              // adds the selected value to the class name list
              "modify": "className",
              "type": "select",
              "options": [
                {
                  "label": "White",
                  "value": "bg-white"
                },
                {
                  "label": "Primary",
                  "value": "bg-primary text-white"
                }
              ]
            }
          ],
          "attributes": [
            {
              // not really needed in this scenario
              // but sets the type="button" attribute on the button
              "name": "type",
              // this attribute is a "value"
              // so it gets its value from the below value property and not from a filter or function
              "type": "value",
              "value": "button"
            },
            {
              // this attribute sets a "data-post-id" attribute on the button which is the return value of calling get_the_ID()
              // See the supported functions above
              "name": "data-post-id",
              "type": "function",
              "value": "get_the_ID"
            }
          ]
        }
      ]
    },
    {
      "id": "tabContentContainer",
      "tag": "div",
      "classNames": "border-t p-4",
      "children": [
        {
          "id": "tabContent",
          "tag": "div",
          // same as above, this element will be repeated when new items are added
          "useRepeater": true,
          // in the editor only show the currently active item
          "displayRepeated": "single",
          // allow the user to drop elements into this one
          "allowChildren": true
        }
      ]
    }
  ]
}

Subscribe

No spam, just product updates.