Skip to content

Options Reference

Options are the heart of BlocksWeb - they define what properties your components expose to the visual editor. This comprehensive guide covers all 12 option types and their configurations.

Overview

Every option has these common properties:

typescript
{
  type: string;        // The option type
  name: string;        // The prop name in your component
  label: string;       // Display name in the editor
  default?: any;       // Default value
  required?: boolean;  // Whether the field is required
  help?: string;       // Help text shown to users
}

Text Option

Simple single-line text input.

Type Definition

typescript
{
  type: 'text';
  name: string;
  label: string;
  default?: string;
  placeholder?: string;
  maxLength?: number;
  pattern?: string; // Regex pattern
}

Example

typescript
Hero.schema = {
  displayName: 'Hero',
  options: [
    {
      type: 'text',
      name: 'title',
      label: 'Page Title',
      default: 'Welcome to Our Website',
      placeholder: 'Enter title...',
      maxLength: 60,
      help: 'Keep it under 60 characters for best SEO'
    }
  ]
};

Number Option

Numeric input with optional min/max constraints.

Type Definition

typescript
{
  type: 'number';
  name: string;
  label: string;
  default?: number;
  min?: number;
  max?: number;
  step?: number;
}

Example

typescript
{
  type: 'number',
  name: 'columns',
  label: 'Number of Columns',
  default: 3,
  min: 1,
  max: 6,
  step: 1
}

Rich Text Option

Full rich text editor with formatting, links, lists, and more.

Type Definition

typescript
{
  type: 'richtext';
  name: string;
  label: string;
  default?: string; // HTML string
}

Usage in Component

typescript
import { RichText } from '@blocksweb/core/client';

const MyComponent: IBlockswebComponent = ({ content }) => {
  return (
    <div>
      <RichText
        propName="content"
        text={content}
        defaultText="<p>Default content</p>"
      />
    </div>
  );
};

MyComponent.schema = {
  displayName: 'Content Block',
  options: [
    {
      type: 'richtext',
      name: 'content',
      label: 'Content',
      default: '<p>Enter your content here</p>'
    }
  ]
};

Image Option

Image picker with asset manager integration.

Type Definition

typescript
{
  type: 'image';
  name: string;
  label: string;
  default?: string; // URL
}

Usage in Component

typescript
import { Image } from '@blocksweb/core/client';

const MyComponent: IBlockswebComponent = ({ heroImage }) => {
  return (
    <Image
      propName="heroImage"
      asset={heroImage}
      default="/placeholder.jpg"
      alt="Hero image"
    />
  );
};

MyComponent.schema = {
  displayName: 'Image Block',
  options: [
    {
      type: 'image',
      name: 'heroImage',
      label: 'Hero Image',
      default: '/default-hero.jpg'
    }
  ]
};

Color Option

Color picker with hex, RGB, and preset support.

Type Definition

typescript
{
  type: 'color';
  name: string;
  label: string;
  default?: string; // Hex color
  presets?: string[]; // Preset color options
}

Example

typescript
{
  type: 'color',
  name: 'backgroundColor',
  label: 'Background Color',
  default: '#ffffff',
  presets: ['#ffffff', '#f3f4f6', '#1f2937', '#3b82f6']
}

Select Option

Dropdown selection from predefined options.

Type Definition

typescript
{
  type: 'select';
  name: string;
  label: string;
  options: Array<{ label: string; value: string }>;
  default?: string;
}

Example

typescript
{
  type: 'select',
  name: 'alignment',
  label: 'Text Alignment',
  options: [
    { label: 'Left', value: 'left' },
    { label: 'Center', value: 'center' },
    { label: 'Right', value: 'right' }
  ],
  default: 'center'
}

Checkbox Option

Boolean toggle switch.

Type Definition

typescript
{
  type: 'checkbox';
  name: string;
  label: string;
  default?: boolean;
}

Example

typescript
{
  type: 'checkbox',
  name: 'showButton',
  label: 'Show Call-to-Action Button',
  default: true
}

Component Option

Nested component slot for composition.

Type Definition

typescript
{
  type: 'component';
  name: string;
  label: string;
  allowedComponents?: string[]; // Restrict to specific components
}

Usage in Component

typescript
import { BlockOutlet } from '@blocksweb/core/client';

const Container: IBlockswebComponent = ({ children }) => {
  return (
    <div className="container">
      <BlockOutlet propName="children" blocks={children} />
    </div>
  );
};

Container.schema = {
  displayName: 'Container',
  options: [
    {
      type: 'component',
      name: 'children',
      label: 'Content',
      allowedComponents: ['Hero', 'FeatureCard', 'RichContent']
    }
  ]
};

Entity Option

Reference to a single entity from a collection.

Type Definition

typescript
{
  type: 'entity';
  name: string;
  label: string;
  collectionName: string; // Which collection to query
  default?: string; // Entity ID
}

Example

typescript
import { useCollectionRecord } from '@blocksweb/core/client';

const ProductShowcase: IBlockswebComponent = ({ productId }) => {
  const { data: product } = useCollectionRecord('products', productId);

  if (!product) return <div>Loading...</div>;

  return (
    <div>
      <h2>{product.name}</h2>
      <p>{product.price}</p>
    </div>
  );
};

ProductShowcase.schema = {
  displayName: 'Product Showcase',
  options: [
    {
      type: 'entity',
      name: 'productId',
      label: 'Select Product',
      collectionName: 'products'
    }
  ]
};

Entity Multiple Option

References to multiple entities from a collection.

Type Definition

typescript
{
  type: 'entity-multiple';
  name: string;
  label: string;
  collectionName: string;
  default?: string[]; // Array of entity IDs
  max?: number; // Maximum selections
}

Example

typescript
import { useCollectionRecords } from '@blocksweb/core/client';

const ProductGrid: IBlockswebComponent = ({ productIds }) => {
  const { data: products } = useCollectionRecords('products', productIds);

  return (
    <div className="grid grid-cols-3 gap-4">
      {products?.map(product => (
        <div key={product.id}>
          <h3>{product.name}</h3>
          <p>${product.price}</p>
        </div>
      ))}
    </div>
  );
};

ProductGrid.schema = {
  displayName: 'Product Grid',
  options: [
    {
      type: 'entity-multiple',
      name: 'productIds',
      label: 'Select Products',
      collectionName: 'products',
      max: 6
    }
  ]
};

Page Option

Link to a single page in the site.

Type Definition

typescript
{
  type: 'page';
  name: string;
  label: string;
  default?: string; // Page ID or slug
}

Example

typescript
{
  type: 'page',
  name: 'linkedPage',
  label: 'Link to Page',
  default: '/'
}

Page Multiple Option

Links to multiple pages in the site.

Type Definition

typescript
{
  type: 'page-multiple';
  name: string;
  label: string;
  default?: string[]; // Array of page IDs/slugs
  max?: number;
}

Example

typescript
const Navigation: IBlockswebComponent = ({ pages }) => {
  return (
    <nav>
      {pages.map(page => (
        <a key={page.id} href={page.slug}>
          {page.name}
        </a>
      ))}
    </nav>
  );
};

Navigation.schema = {
  displayName: 'Navigation',
  options: [
    {
      type: 'page-multiple',
      name: 'pages',
      label: 'Navigation Pages',
      max: 10
    }
  ]
};

Collection Option

Reference to developer-defined collection records. BlocksWeb automatically resolves the IDs to full objects.

How It Works

When a user selects collection records in the editor, BlocksWeb stores the record IDs. When your component renders, BlocksWeb automatically fetches and resolves those IDs to full record objects. You receive complete data, not IDs!

Type Definition

typescript
{
  type: 'collection';
  name: string;
  label: string;
  collectionName: string;        // Which collection to use
  multiple?: boolean;             // Single or multiple selection (default: false)
  default?: string | string[] | null;
}

Single Selection Example

typescript
const BlogPostCard: IBlockswebComponent = ({ selectedPost }) => {
  // selectedPost is the FULL OBJECT, not an ID!
  // BlocksWeb automatically resolved it for you

  if (!selectedPost) {
    return <div>No post selected</div>;
  }

  return (
    <article>
      <h2>{selectedPost.title}</h2>
      <p>By {selectedPost.author}</p>
      <div>{selectedPost.content}</div>
    </article>
  );
};

BlogPostCard.schema = {
  displayName: 'Blog Post Card',
  options: [
    {
      type: 'collection',
      name: 'selectedPost',       // Receives full object, not ID
      label: 'Select Blog Post',
      collectionName: 'blogPosts',
      multiple: false,            // Single selection
      default: null
    }
  ]
};

Multiple Selection Example

typescript
const ProductGrid: IBlockswebComponent = ({ selectedProducts = [] }) => {
  // selectedProducts is array of FULL OBJECTS, not IDs!
  // BlocksWeb automatically resolved them for you

  return (
    <div className="grid grid-cols-3 gap-4">
      {selectedProducts.map(product => (
        <div key={product.id}>
          <img src={product.image} alt={product.name} />
          <h3>{product.name}</h3>
          <p>${product.price}</p>
          <span>{product.inStock ? 'In Stock' : 'Out of Stock'}</span>
        </div>
      ))}
    </div>
  );
};

ProductGrid.schema = {
  displayName: 'Product Grid',
  options: [
    {
      type: 'collection',
      name: 'selectedProducts',   // Receives array of full objects
      label: 'Select Products',
      collectionName: 'products',
      multiple: true,             // Multiple selection
      default: []
    }
  ]
};

Behind the Scenes

1. Editor UI: User selects records
   → IDs stored: ["1", "2", "3"]

2. Page renders (server or client)
   → BlocksWeb automatically fetches records

3. Your component receives:
   → Full objects: [{ id: "1", name: "...", ... }, ...]

No hooks needed! Just use the data.

Advanced Patterns

Conditional Options

Show/hide options based on other values:

typescript
options: [
  {
    type: 'checkbox',
    name: 'showImage',
    label: 'Show Image',
    default: true
  },
  {
    type: 'image',
    name: 'image',
    label: 'Image',
    // Only show if showImage is true
    condition: { field: 'showImage', value: true }
  }
]

Option Groups

Group related options together:

typescript
options: [
  {
    group: 'Content',
    items: [
      { type: 'text', name: 'title', label: 'Title' },
      { type: 'richtext', name: 'description', label: 'Description' }
    ]
  },
  {
    group: 'Styling',
    items: [
      { type: 'color', name: 'bgColor', label: 'Background' },
      { type: 'select', name: 'alignment', label: 'Alignment' }
    ]
  }
]

Dynamic Default Values

Use functions for dynamic defaults:

typescript
{
  type: 'text',
  name: 'id',
  label: 'Component ID',
  default: () => `component-${Date.now()}`
}

Best Practices

1. Provide Sensible Defaults

Always set defaults so components look good immediately:

typescript
{
  type: 'text',
  name: 'title',
  label: 'Title',
  default: 'Welcome' // ✅ Good
}

{
  type: 'text',
  name: 'title',
  label: 'Title'
  // ❌ Bad - No default
}

2. Use Clear Labels

typescript
// ✅ Good
{ label: 'Call-to-Action Button Text' }

// ❌ Bad
{ label: 'CTA Btn Txt' }

3. Add Help Text

typescript
{
  type: 'text',
  name: 'metaDescription',
  label: 'Meta Description',
  help: 'Keep between 150-160 characters for best SEO results',
  maxLength: 160
}

4. Limit Choices

Don't overwhelm users with too many options:

typescript
// ✅ Good - 3-5 options
{
  type: 'select',
  name: 'size',
  options: [
    { label: 'Small', value: 'sm' },
    { label: 'Medium', value: 'md' },
    { label: 'Large', value: 'lg' }
  ]
}

// ❌ Bad - Too many options
{
  type: 'select',
  name: 'fontSize',
  options: Array.from({ length: 50 }, (_, i) => ({
    label: `${i + 10}px`,
    value: `${i + 10}px`
  }))
}

5. Use TypeScript

Type your props to match your options:

typescript
type MyComponentProps = {
  title: string;           // type: 'text'
  count: number;           // type: 'number'
  visible: boolean;        // type: 'checkbox'
  bgColor: string;         // type: 'color'
  alignment: 'left' | 'center' | 'right'; // type: 'select'
};

Next Steps

Reference

See the complete TypeScript types in @blocksweb/core/types.