Skip to content

smartlabsAT/directus-expandable-blocks

Repository files navigation

Directus Expandable Blocks Interface

npm version npm downloads GitHub release license Directus 11+

A powerful M2A (Many-to-Any) interface for Directus with inline expandable editing that seamlessly integrates with Directus' native save system.

📚 Documentation🐛 Report Bug✨ Request Feature📦 NPM Package

Directus Expandable Blocks Demo

📖 Table of Contents

📚 Documentation

For comprehensive documentation, visit our GitHub Wiki which includes:

  • Detailed installation guide
  • Configuration options
  • Architecture overview
  • API integration guide
  • Development & debugging
  • Security best practices
  • Migration guide
  • And much more!

🎯 Why Expandable Blocks?

Unlike other block editors, this extension works directly with Directus' native form system:

  • No custom API calls - Uses Directus' built-in save/revert functionality
  • Native Save & Stay - Works perfectly with Directus' save options
  • Global Discard - Integrates with Directus' "Discard Changes" button
  • Proper Dirty State - Save button only appears when changes exist
  • No Data Loss - All changes tracked through Directus' form state

This means you get all the benefits of a sophisticated block editor while maintaining full compatibility with Directus' workflow!

✨ Features

Core Interface

  • Inline Expandable Editing: Edit block content directly without opening separate forms
  • Drag & Drop Sorting: Reorder blocks with intuitive drag-and-drop
  • Native Integration: Uses Directus' save system - no custom API calls
  • Smart Dirty State: Only sends changed blocks to the server
  • Status Management: Quick status changes with visual indicators
  • Visual Feedback: See which blocks have unsaved changes
  • Compact & Full View Modes: Adaptive display options
  • Keyboard Navigation: Full keyboard support

Advanced Functionality

  • Nested M2A Support: Handle complex nested relationships
  • Custom Field Filtering: Show only specific fields in edit mode
  • Template System: Pre-configured content templates
  • Status Management: Built-in content status workflows

🚀 Coming Soon: AI-Powered Features

We're actively developing AI integration features that will include:

  • AI Content Generation: Generate content using OpenAI GPT, Claude, or custom APIs
  • Smart Content Improvement: Grammar, style, clarity, and SEO optimization
  • Multi-Language Translation: Instant translation to multiple languages
  • Context-Aware Suggestions: AI that understands your page structure
  • Field-Specific Targeting: Generate content for specific fields only

💡 Early Access: AI features are currently in development on the feature/ai-assistant branch. Follow our GitHub repository for updates!

Configuration Options

  • Enable/disable sorting
  • Show/hide item IDs
  • Accordion mode (one block expanded at a time)
  • Compact display mode
  • Maximum block limits
  • Custom field filtering

📦 Installation

Via NPM (Recommended)

Install directly from the npm registry:

npm install directus-extension-expandable-blocks

The extension will be automatically loaded by Directus when you restart your instance.

Manual Installation

  1. Download the latest release from GitHub Releases
  2. Extract to your Directus extensions/interfaces/ directory
  3. Restart Directus

Docker Installation

For Docker setups, install via npm in your Dockerfile or mount the extension directory:

RUN npm install directus-extension-expandable-blocks
# or mount volume: -v ./extensions:/directus/extensions

🚀 Usage

Basic Setup

1️⃣ Create an M2A (Many-to-Any) Field

  1. Navigate to Settings → Data Model → [Your Collection]
  2. Click "Create Field" button
  3. Choose "Many to Any Relationship (M2A)" field type
  4. Configure the relationship:
    • Field Key: e.g., content_blocks
    • Related Collections: Select which collections can be used as blocks

2️⃣ Select the Expandable Blocks Interface

  1. In the field configuration, go to the "Interface" tab
  2. Click on the interface dropdown (default is "Many to Any")
  3. Select "Expandable Blocks" from the list
  4. The interface will change to show expandable blocks options

3️⃣ Configure Interface Options

In the interface configuration panel, you can set:

  • Display Options

    • ✅ Enable Sorting - Allow drag & drop reordering
    • 📂 Start Expanded - Blocks open by default
    • 🎯 Accordion Mode - Only one block open at a time
    • 📱 Compact Mode - Condensed view for many blocks
  • Permissions

    • 🗑️ Allow Delete - Users can remove blocks
    • 📋 Allow Duplicate - Users can copy blocks
    • 🔢 Max Blocks - Limit number of blocks (empty = unlimited)

4️⃣ Save and Use

  1. Click "Save" to apply the configuration
  2. Navigate to your collection items
  3. The M2A field will now use the Expandable Blocks interface!

Example M2A Structure

# Main Collection (e.g., "pages")
Page Collection:
  - id: primary key
  - title: string
  - slug: string
  - content_blocks: M2A field → Uses "Expandable Blocks" interface
  - status: string
  - date_created: timestamp

# Junction Collection (auto-created by Directus)
pages_blocks:
  - id: primary key
  - pages_id: foreign key → pages.id
  - collection: string (which block type)
  - item: foreign key → block item id
  - sort: integer (for ordering)

# Block Collections (your content types)
content_text:
  - id: primary key
  - headline: string
  - subheadline: string
  - content: text (rich text editor)
  - alignment: string

content_hero:
  - id: primary key
  - headline: string
  - subheadline: string
  - button_text: string
  - button_link: string
  - image: file (image)
  - overlay: boolean

content_gallery:
  - id: primary key
  - title: string
  - images: O2M → gallery_images
  - columns: integer
  - spacing: string

Visual Guide

📸 Click to see setup screenshots
  1. Creating M2A Field

    • Select M2A relationship type
    • Configure related collections
  2. Selecting Interface

    • Change from default "Many to Any"
    • Select "Expandable Blocks"
  3. Interface in Action

    • Inline editing capability
    • Drag & drop sorting
    • Visual status indicators

🔧 How It Works

Native Save Integration

The extension integrates seamlessly with Directus' form system:

// Traditional approach (what we DON'T do):
async function saveBlock(block) {
  await api.post('/items/content_blocks', block) // ❌ Custom API call
  await refreshData() // ❌ Manual sync
  updateUI() // ❌ Manual UI update
}

// Our approach (native integration):
function handleBlockChange(blocks) {
  emit('input', blocks) // ✅ Let Directus handle everything
}

Smart Change Detection

Only modified blocks are sent to the server:

// Example: 3 blocks, only middle one edited
[
  "block-1-id",                    // ✅ Unchanged - send ID only
  { id: "block-2-id", title: "New" }, // ✅ Changed - send full object
  "block-3-id"                     // ✅ Unchanged - send ID only  
]

This means:

  • 🚀 Faster saves - Less data transmitted
  • 🛡️ Conflict prevention - Unchanged blocks aren't touched
  • 📊 Better performance - Server processes only what changed

⚙️ Configuration Options

Option Type Default Description
enableSorting boolean true Allow drag & drop reordering
showItemId boolean true Display item IDs in headers
startExpanded boolean false Start with all blocks expanded
accordionMode boolean false Only one block expanded at a time
compactMode boolean false Use compact display
maxBlocks number null Maximum number of blocks
isAllowedDelete boolean true Allow block deletion
isAllowedDuplicate boolean true Allow block duplication

🧪 Testing

The extension includes comprehensive test coverage:

# Unit tests
npm run test

# E2E tests  
npm run test:e2e

# Test coverage
npm run test:coverage

# Watch mode
npm run dev

📝 Development

# Install dependencies
npm install

# Development build with watching
npm run dev

# Production build
npm run build

# Link for local development
npm run link

📚 Architecture Documentation

For detailed information about the data flow, state management, and debugging techniques, see our comprehensive Architecture Documentation. This includes:

  • Complete data flow lifecycle with visual diagrams
  • Detailed state management explanations
  • Store interactions and timing
  • Debugging techniques and helpers
  • Common issues and solutions
  • Performance optimization tips

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details on:

  • Development setup
  • Testing procedures
  • Pull request process
  • Code standards
  • Issue templates

📄 License

MIT License - see LICENSE file for details

🐛 Issues & Support

Report issues on GitHub Issues

🔄 Changelog

See CHANGELOG.md for detailed version history.

🗺️ Roadmap

Check out our Development Roadmap to see what's coming next:

  • 🤖 AI-Powered Content Generation (v1.1.0)
  • 🎨 Enhanced UI/UX Features
  • 🔧 Developer Tools & CLI
  • 🚀 Performance Optimizations

📖 Documentation

📚 Wiki Documentation

For comprehensive documentation, visit our GitHub Wiki:

📄 Quick Links

🐛 Issue Templates


Made with ❤️ for the Directus community