On this page

Blocks

Blocks are Vue components that allow you to manage website content with fine detail. To create a block, simply add a Vue component in the blocks directory of your project.


Example

Here is an example of a button block:

// blocks/Button.vue

<template>
  <NuxtLink
    :to="link"
    class="inline-block whitespace-nowrap rounded-md bg-blue-600 px-4 py-3 text-white outline-none transition hover:bg-blue-700 focus:bg-blue-800 focus:ring-4"
  >
    {{ label }}
  </NuxtLink>
</template>

<script lang="ts" setup>
import { defineBlock, linkField, textField } from '#pruvious'

defineBlock({ icon: 'Mouse' })

defineProps({
  link: linkField({ required: true }),
  label: textField({ required: true }),
})
</script>

The block UI, with all defined fields, will be automatically included in the dashboard and the component will be rendered when used in your website pages.

Definition

A block is defined by the following properties:

PropertyDescription

name

A unique PascalCase string automatically extracted from your component's name (e.g., Button.vue).

label

The label displayed in the block picker in the dashboard. If not provided, the label is automatically generated from the block name.

description

A brief text displayed as a tooltip in the block picker.

icon

The icon displayed in the block picker in the dashboard. You can find a list of all available icons here.

fields

Used to store block data in the database.

slots

A key-value object that contains the names of component slots and the child blocks allowed within them.

Naming convention

Block names are derived from the Vue component's name without the file extension (e.g., IconBox.vue). Blocks, like other components, should adhere to the PascalCase naming convention.

You can utilize subdirectories to organize your blocks. In this scenario, the parent directory names will be added as a prefix to the block name. For instance, if the block is located in blocks/Gallery/Simple.vue, it will be named GallerySimple.

Fields

Fields are utilized for storing block data in the database. You can assign a wide range of fields either directly in the defineProps Vue macro or in defineBlock if you prefer not to combine them with component props. To import field macros, use the #pruvious alias. The macro names follow the convention of starting with the camelCased field type and ending with Field or Subfield (e.g., textField, imageField, dateTimeSubfield, etc.).

Explore all available Fields.

defineBlock

The defineBlock is an optional compiler macro that allows you to configure your block. It should be placed at the top of your component script if used. The macro is compiled away during the processing of <script setup>.

// blocks/HelloWorld.vue

<template>
  <h1>Hello, World!</h1>
</template>

<script lang="ts" setup>
import { defineBlock } from '#pruvious'

defineBlock({
  // Overrides the automatically generated block label
  label: 'Greeting Block',

  // Text displayed in the block picker
  description: 'This appears in a tooltip',

  // Icon displayed in the block picker (defaults to 'Components')
  icon: 'World',

  // Additional block fields that are not component props
  fields: {},

  // Slot labels and allowed child blocks
  slots: {},
})
</script>

Caveat: Make sure to place the defineBlock macro before your component logic and other Vue macros, like defineProps.

Slots

A block can contain multiple slots for nesting other blocks. Here's an example of a block with two slots:

// blocks/TwoColumns.vue

<template>
  <div class="flex items-center gap-8 tp:flex-col tp:items-stretch">
    <div class="flex-1">
      <slot name="left">
        Default content
      </slot>
    </div>
    <div class="flex-1">
      <slot name="right" />
    </div>
  </div>
</template>

<script lang="ts" setup>
import { defineBlock } from '#pruvious'

defineBlock({
  slots: {
    left: {
      /*
        Default properties:
        - label: 'Left'
        - allowedChildBlocks: '*'
      */
    },
    right: {
      label: 'Image or video', // Displayed in the dashboard
      allowedChildBlocks: ['Image', 'Video'],
    },
  },
})
</script>

Slots are identified by their names. In cases where there is only one slot, it is common not to explicitly name it. In such situations, the slot will be automatically named default.

Last updated on February 10, 2024 at 24:35