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.
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.
id
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.
displayName
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
category
The category is used to group components in the editor. Like the
displayName
it is only needed for the top level component
tag
The HTML tag that will used
classNames
Any default classes that should appear on the element
content
content.type
Can be either value
, filter
, function
, meta
, or richtext
. See
Supported Functions for more info.
content.value
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
content.defaultValue
When content.type
is a filter, this is the default value that gets passed
to the filter.
children
Children is an array of component objects. When you start nesting HTML elements, this is where they'll go.
allowChildren
In the drag and drop editor, if you want to be able to drag components /
elements into this specific element, set this to true
hasRepeater
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.
useRepeater
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.
allowRepeaterContent
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.
displayRepeated
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.
option
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.
option.label
The label for your option, shown to the user.
option.name
A unique name for your option, this is used by the editor to save the property against. It should be JSON friendly.
option.type
Should the option display as a select box or a free text input.
option.options
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.
option.modify
Should this option add to the CSS class names, or should it set an attribute
option.attributeName
What attribute should be added to the element?
attributes
You can set default HTML attributes for a tag. Note that the user can override this and set their own.
attribute.type
What type of content should we use for the attribute. See Supported Functions for more info.
attribute.name
The HTML attribute name.
attribute.value
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
styles
Add a list of handles that have been registered with wp_register_style
.
These will be enqueued when the component loads.
scripts
Add a list of handles that have been registered with wp_register_script
.
These will be enqueued when the component loads.
editorStyles
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.
When setting the content or attribute type as function
, Gust supports a few functions out of the box. These are:
Note that these functions are all using the get_
counterparts so that the result is not immediately echo'd by PHP.
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:
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.
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:
{
"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
}
]
}
]
}