`s
* Ensure contrast, focusability, and proper labels
* Use `alt` text and avoid relying on color alone
* Test your sections with real assistive tools
Design for everyone. Accessible sections create better experiences — for every shopper.
---
---
url: /building-theme/adding-blocks/overview.md
---
# Adding Blocks - Overview
Blocks are the atomic building units of Bagisto Visual. This guide will walk you through creating custom blocks for your theme.
## What You'll Learn
This section covers everything you need to know about building blocks:
* **[Creating a Block](/building-theme/adding-blocks/creating-block)**: Step-by-step guide to creating your first block
* **[Block Attributes](/building-theme/adding-blocks/block-schema)**: Configuring settings, presets, and nested blocks
* **[Static Blocks](/building-theme/adding-blocks/static-blocks)**: Rendering blocks in Blade templates
* **[Container Blocks](/building-theme/adding-blocks/container-blocks)**: Creating blocks that accept child blocks
## When to Create Custom Blocks
Create custom blocks when you need:
* **Reusable components** that appear across multiple sections (buttons, testimonials, badges)
* **E-commerce elements** specific to your store (custom product cards, pricing displays)
* **Branded components** that reflect your design system (CTAs, social proof, icons)
* **Content types** that merchants will manage repeatedly (team members, features, FAQs)
## Block Types Overview
Bagisto Visual provides three base block types to extend:
### BladeBlock
The most common block type. Uses Blade templates for rendering.
**Best for:**
* Standard content blocks (text, images, buttons)
* Blocks with settings but no complex logic
* Most use cases
### LivewireBlock
Dynamic blocks powered by Livewire components.
**Best for:**
* Interactive blocks (forms, calculators, live search)
* Blocks that need real-time updates
* AJAX-based functionality
### SimpleBlock
Minimal blocks without settings or logic.
**Best for:**
* Structural elements (dividers, spacers)
* Static content
* Pure presentation blocks
## Quick Example
Here's a simple block to get you started:
**PHP Class** (`src/Blocks/Testimonial.php`):
```php
namespace Themes\YourTheme\Blocks;
use BagistoPlus\Visual\Block\BladeBlock;
use BagistoPlus\Visual\Settings\Text;
use BagistoPlus\Visual\Settings\Textarea;
use BagistoPlus\Visual\Settings\Image;
class Testimonial extends BladeBlock
{
protected static string $view = 'shop::blocks.testimonial';
public static function settings(): array
{
return [
Text::make('name', 'Customer name'),
Textarea::make('quote', 'Testimonial quote'),
Image::make('photo', 'Customer photo'),
];
}
}
```
**Blade View** (`resources/views/blocks/testimonial.blade.php`):
```blade
@if($block->settings->photo)
@endif
{{ $block->settings->quote }}
{{ $block->settings->name }}
```
That's it! This Testimonial block can now be used in any section that accepts it.
## Directory Structure
```plaintext
/theme/
├── src/
│ └── Blocks/
│ ├── Button.php
│ ├── Testimonial.php
│ ├── ProductCard.php
│ └── Columns.php # Container block
├── resources/
│ └── views/
│ └── blocks/
│ ├── button.blade.php
│ ├── testimonial.blade.php
│ ├── product-card.blade.php
│ └── columns.blade.php
```
**Key points:**
* PHP classes go in `src/Blocks/`
* Blade views go in `resources/views/blocks/`
* One PHP class per block, one Blade view per block
* Class names should be PascalCase, view names should be kebab-case
## Development Workflow
1. **Plan your block**: Decide what settings it needs and where it will be used
2. **Create the PHP class**: Extend BladeBlock, LivewireBlock, or SimpleBlock
3. **Define settings**: Use the settings() method to configure merchant-editable options
4. **Create the Blade view**: Implement the block's HTML and styling
5. **Test in sections**: Add your block to sections and test in the theme editor
6. **Refine**: Iterate based on how merchants use it
## Best Practices
✅ **Keep blocks focused**: One purpose per block (button, testimonial, image)
✅ **Make them reusable**: Design for multiple contexts, not one specific section
✅ **Provide sensible defaults**: Settings should have good default values
✅ **Use clear naming**: Block names should clearly describe their purpose
✅ **Document settings**: Use descriptive labels for merchant-facing settings
✅ **Test responsiveness**: Blocks should work on all screen sizes
## Next Steps
Ready to create your first block? Start with **[Creating a Block](/building-theme/adding-blocks/creating-block)** to build a block step-by-step.
---
---
url: /building-theme/adding-layouts.md
---
# Adding Layouts
In Bagisto Visual, layouts define the **main HTML structure** of your pages.
Layouts are Blade files that act as **wrappers** for all templates and sections.
They typically include shared elements like the header, footer, meta tags, and asset loading.
## Creating the `default` Layout
The most important layout file is **`default.blade.php`**.
Create the file inside:
```text
resources/views/layouts/default.blade.php
```
Example content for a basic `default.blade.php`:
```blade
Awesome Theme
@bagistoVite(['resources/assets/css/app.css', 'resources/assets/js/app.js'])
@stack('meta')
@stack('styles')
@visualRegion('header')
@visual_layout_content
@visualRegion('footer')
@stack('scripts')
```
* `@visualRegion('header')` renders the header region (customizable by merchants).
* `@visualRegion('footer')` renders the footer region (customizable by merchants).
* `@visual_layout_content` renders the page content (templates and sections).
* `@bagistoVite([...])` includes theme assets correctly.
## Header and Footer Regions
Regions are customizable zones that merchants can control through the Visual Editor. Create header and footer regions:
```text
resources/views/regions/header.visual.php
resources/views/regions/footer.visual.php
```
Basic `header.visual.php` example:
```php
id('header')
->name('Header')
->sections([
// Merchants can add sections here through the Visual Editor
]);
```
Basic `footer.visual.php` example:
```php
id('footer')
->name('Footer')
->sections([
// Merchants can add sections here through the Visual Editor
]);
```
✅ Regions allow merchants to customize header and footer areas without touching code. Learn more about [Regions](../core-concepts/regions.md).
## Views Namespace
All views inside your theme are automatically registered under two namespaces:
* `shop::` (default and recommended)
* `awesome-theme::` (theme code namespace)
For example:
* `resources/views/layouts/default.blade.php` → `shop::layouts.default`
* `resources/views/sections/hero.blade.php` → `shop::sections.hero`
* `resources/views/components/button.blade.php` → `
`
You could also use the `awesome-theme::` namespace (example: `shop::layouts.default` becomes `awesome-theme::layouts.default`),
but to keep it **simple and standard**, we always use the **`shop::` namespace** in this documentation.
## Checking Your Layout
After setting up your layout and regions:
1. Make sure you have created:
* `resources/views/layouts/default.blade.php`
* `resources/views/regions/header.visual.php`
* `resources/views/regions/footer.visual.php`
2. Go to your store **homepage**.
You should now see the default layout rendered —
showing your **header region**, **main area**, and **footer region**.
✅
If you see this, it means your layout setup is working correctly!
Merchants can now customize the header and footer regions through the Visual Editor by adding sections.
# Next Steps
Now that your layout is ready, you can move on to:
* [Creating Templates](./adding-templates.md)
* [Creating Sections](./adding-sections/overview.md)
---
---
url: /building-theme/adding-templates.md
---
# Adding Templates
Templates define the structure of store pages in Bagisto Visual.
They control how sections are arranged and rendered inside the main layout.
Templates can be created using multiple formats:
* **Blade templates** (`.blade.php`) — simple static content or basic Blade directives
* **JSON/YAML templates** (`.json` or `.yaml`) — fully dynamic, section-driven layouts for the Visual Editor
* **PHP templates** (`.visual.php`) — programmatic templates with IDE support and type safety
At this stage, we will start with a Blade template for simplicity.
## Creating a Blade Template
Blade templates are simple files that contain the page content.
They are injected into the layout through `@visual_layout_content`.
To create a homepage template:
1. Create a new file:
```text
resources/views/templates/index.blade.php
```
2. Add the following example content:
```blade
Welcome to Awesome Theme
Your new store is ready to be customized.
```
This content will be rendered inside your theme’s default layout.
There is no need to use `@extends` or `@section`.
## Viewing the Template
Once the template file is created:
* Visit your store homepage in the browser.
* You should see the header and footer rendered from the layout.
* The page body will display the content from `index.blade.php`.
At this stage, no sections are included yet.
Templates are static until sections are added.
## JSON, YAML, and PHP Templates
Bagisto Visual also supports creating templates using JSON, YAML, or PHP files.
These templates enable merchants to visually edit pages, add sections dynamically, and control page structure without touching code.
### JSON/YAML Templates
Use `.json` or `.yaml` files for simple, declarative template definitions:
```json
{
"sections": {
"hero": {
"type": "visual-hero",
"settings": {
"image" => "https://example.com/banner.jpg"
}
}
},
"order": ["hero"]
}
```
### PHP Templates (`.visual.php`)
For more complex templates with IDE support and type safety, use `.visual.php` files:
```php
section('hero', HeroBanner::class)
->section('featured-products', 'visual-featured-products', fn($section) => $section
->properties([
'heading' => 'Featured Products',
'nb_products' => 4,
])
)
->order(['hero', 'featured-products']);
```
**Benefits of PHP templates:**
* ✅ IDE autocomplete and type checking
* ✅ Import and use preset classes directly
* ✅ Use PHP variables, loops, and conditionals
* ✅ Better refactoring support
The structure and behavior of template formats are explained in:
* [JSON & YAML Templates](../core-concepts/templates/json-yaml.md) - Declarative templates
* [PHP Templates](../core-concepts/templates/php-templates.md) - Programmatic templates with IDE support
In the next chapter, we will cover:
* How to create sections
* How to use sections inside templates to build dynamic pages
For now, starting with a simple Blade template is sufficient to initialize your theme.
## Summary
* Templates define page content and are rendered inside layouts.
* Blade templates are static and easy to start with.
* JSON/YAML/PHP templates enable full dynamic editing and will be introduced after learning about sections.
* PHP templates (`.visual.php`) provide IDE support and type safety.
* Templates must be placed in `resources/views/templates/`.
Read more about [available default templates](../core-concepts/templates/available.md)
## Next Steps
* [Adding Sections](./adding-sections/overview.md)
---
---
url: /theme-editor/advanced-usage.md
---
# Advanced Usage
Once you're comfortable using the Visual Editor, there are a few advanced features and tips that can help you get even more control over your storefront.
## Layout vs. Page Content
Not all sections are the same:
* **Header and Footer sections** are part of the layout and appear on every page.
* **Main Content sections** are unique to the specific page you're editing (like the homepage or contact page).
Layout sections usually cannot be removed or reordered. They’re designed to stay consistent across the entire site.
## Working with Blocks
Some sections (like category grids or image banners) contain **blocks** — small pieces of content inside the section.
You can:
* Click a section to reveal its blocks
* Add new blocks (if allowed)
* Rearrange or delete them
* Customize each block’s settings (text, images, links, etc.)
## Preview Tools
At the top of the editor, you’ll find useful controls:
* **Device preview**: See how your page looks on desktop, tablet, and mobile
* **Language switcher**: If your store supports multiple languages, preview translations
* **Page selector**: Quickly switch between pages (homepage, contact, product, etc.)
## Best Practices
* **Edit in small steps** — Changes save automatically, so there's no need to rush.
* **Use meaningful section names** — It helps you and your team stay organized.
* **Keep it consistent** — Reuse similar section types across pages to create a cohesive design.
* **Preview before publishing** — Always test how things look on mobile and tablet before going live.
***
The Visual Editor is designed to be flexible and easy, while giving you the tools to make your storefront truly your own.
---
---
url: /core-concepts/architecture.md
---
# Anatomy of a Theme
Bagisto Visual brings a **modern, flexible theme system** to Bagisto — **heavily inspired by Shopify's proven architecture**.
At its core, a theme is a **structured collection of layouts, templates, sections, blocks, and settings**, allowing both developers and store owners to collaboratively build and manage storefronts with ease.
By adopting a system modeled after Shopify, Bagisto Visual empowers **merchants** and **theme developers** to take full control of the storefront experience — crafting **beautiful, fully customized online stores** that stand out from the competition.
This section explains **how a Bagisto Visual theme is organized**, **how the core parts fit together**, and **how developers and merchants can collaborate** to build dynamic, customizable storefronts.

## Theme Structure
A theme is made up of the following main parts:
| Number | Part | Description |
| ------ | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | **Layout** | The base structure of the page. Defines global elements and includes regions using `@visualRegion()`. |
| 2 | **Template** | Define what to render and where. Each page of the storefront has its own associated template. Templates can be Blade (with dynamic logic), JSON/YAML, or PHP. Only one template is rendered per page. |
| 3,4 | **Region** | Customizable zones (like header, footer) shared across all pages. Merchants can add/remove sections in regions through the Visual Editor. See [Regions](./regions.md). |
| 5 | **Template section** | Modular, reusable containers that compose blocks into layouts. Used inside templates. |
| 6 | **Block** | Atomic, reusable components that provide content. Shared across multiple sections. The fundamental building units of v2 themes. |
> **Note:**
> Templates define the structure of different page types in your storefront, such as the homepage, product pages, category pages, cart, and more. Each page is rendered based on its associated template, making it easy to create custom layouts for different parts of your store.
## Folder Structure
```plaintext
/theme/
├── resources/
│ ├── views/
│ ├── components/ # Custom Blade or Livewire components
│ ├── layouts/ # Layouts (default layout is mandatory)
│ ├── blocks/ # Block Blade files (v2)
│ ├── sections/ # Section Blade files
│ ├── templates/ # Page templates (JSON, YAML, PHP, or Blade)
│ ├── regions/ # Region templates (header, footer, etc.)
├── src/
│ ├── Blocks/ # PHP classes for custom blocks (v2)
│ ├── Sections/ # PHP classes for custom sections
│ ├── Presets/ # Preset classes for reusable configurations
```
## Key Concepts
### Layouts
* Define the **global structure** of your pages.
* Must include a `default.blade.php` layout inside `/resources/views/layouts/`.
* Layouts typically contain the ``, header, footer, and dynamic content area.
### Templates
* Represent **individual pages** (e.g., homepage, product page).
* Can be written in **Blade**, **JSON**, **YAML**, or **PHP**.
* Templates **list sections** in the desired order.
* Only one template is rendered at a time based on the page being viewed.
### Regions
* **Customizable zones shared across all templates** (e.g., header, footer).
* Merchants can **add, remove, and reorder sections** in regions through the Visual Editor.
* Created using the same formats as templates (JSON, YAML, or PHP).
* Included in layouts using the `@visualRegion()` directive.
* See [Regions](./regions.md) for detailed documentation.
### Blocks (v2)
* **Atomic, reusable components** that provide content (buttons, images, headings, testimonials, product elements).
* **Shared across multiple sections** - define once, use everywhere.
* Created as PHP classes in `src/Blocks/` with Blade views in `resources/views/blocks/`.
* Can be **nested** (container blocks accept child blocks) for complex layouts.
* Two types: **Dynamic** (merchant-controlled) and **Static** (developer-controlled).
* See [Core Concepts: Blocks](/core-concepts/blocks) for details.
### Sections
* **Containers that compose blocks** into cohesive layouts.
* Accept and arrange blocks according to their schema.
* Created using PHP classes in `src/Sections/` with Blade views in `resources/views/sections/`.
* Sections provide structure; blocks provide content.
---
---
url: /core-concepts/templates/available.md
---
# Available Templates
Templates define the structure and behavior of pages in Bagisto Visual storefronts.
Each template determines:
* Which sections appear on the page
* Which data is available to sections
* How customers interact with the store
Bagisto Visual uses a flexible system where templates can be built with **Blade**, **JSON**, or **YAML** formats.
Each template may automatically expose **some variables** (like `$product`, `$category`, `$order`) to the sections it loads, making it easy to create dynamic, data-driven content.
## About This Page
This page documents:
* All available default templates provided by Bagisto Visual
* The variables each template shares with its sections
* Where templates are located in the theme directory
* Example usage of shared variables in Blade sections
## cart
The **Cart Template** displays the contents of a customer's shopping cart.
It is used to show the list of products that the customer has added to their cart, along with quantities, totals, and checkout options.
### Location
```plaintext
/theme/resources/views/templates/cart.yaml
```
### Shared variables
| Variable | Type | Description |
| -------- | ---------- | ----------------------------------- |
| $cart | Cart model | The current shopping cart instance. |
### Example
Example inside a section Blade file:
```blade
@if (isset($cart))
Cart subtotal: {{ core()->currency($cart->base_sub_total) }}
@endif
```
## category
The **Category Template** is used to display a list of products belonging to a specific category.
It typically includes features like filters, sorting options, product grids, and category banners.
### Location
```plaintext
/theme/resources/views/templates/category.json
```
### Shared variables
| Variable | Type | Description |
| --------- | -------------- | ------------------------------------- |
| $category | Category model | The currently viewed category object. |
### Example
Example inside a section Blade file:
```blade
@if (isset($category))
{{ $category->name }}
{{ $category->description }}
@endif
```
## checkout-success
The **Checkout Success Template** displays the order confirmation page after a successful checkout.
It shows the customer a summary of their completed order and any next steps or messages.
### Location
```plaintext
/theme/resources/views/templates/checkout-success.yaml
```
### Shared variables
| Variable | Type | Description |
| -------- | ----------- | ----------------------------------- |
| $order | Order model | The recently placed order instance. |
### Example
Example inside a section Blade file:
```blade
@if (isset($order))
Thank you for your order #{{ $order->id }}!
Total: {{ core()->currency($order->base_grand_total) }}
@endif
```
## checkout
The **Checkout Template** is used to display the checkout process, including customer information, shipping, and payment details.
It typically shows a summary of the cart and allows customers to complete their purchase.
### Location
```plaintext
/theme/resources/views/templates/checkout.yaml
```
### Shared variables
| Variable | Type | Description |
| -------- | ---------- | ----------------------------------- |
| $cart | Cart model | The current shopping cart instance. |
### Example
Example inside a section Blade file:
```blade
@if (isset($cart))
Cart subtotal: {{ core()->currency($cart->base_sub_total) }}
Number of items: {{ $cart->items->count() }}
@endif
```
## compare
The **Compare Template** is used to display a side-by-side comparison of selected products.
It allows customers to view product attributes and differences to help them make purchasing decisions.
### Location
```plaintext
/theme/resources/views/templates/compare.json
```
### Shared variables
| Variable | Type | Description |
| --------------------- | ----- | -------------------------------------------- |
| $comparableAttributes | array | Attributes available for product comparison. |
### Example
Example inside a section Blade file
```blade
@if (!empty($comparableAttributes))
Compare Products By:
@foreach ($comparableAttributes as $attribute)
{{ $attribute['name'] }}
@endforeach
@endif
```
## error
The **Error Template** is used to display an error page when something goes wrong.
It shows an error message and error code based on what occurred (e.g., 404 not found, 500 server error).
### Location
```plaintext
/theme/resources/views/templates/error.blade.php
```
### Shared variables
| Variable | Type | Description |
| ---------- | ------- | -------------------- |
| $errorCode | integer | The HTTP error code. |
### Example
```blade
@if (isset($errorCode))
Error {{ $errorCode }}
Sorry, something went wrong.
@endif
```
## index
The **Index Template** is used to display the homepage of the storefront.
It typically features banners, featured collections, featured products, and custom landing page content.
### Location
```plaintext
/theme/resources/views/templates/index.yaml
```
### Shared variables
There are **no specific shared variables** automatically passed to sections in the index template.
Sections are responsible for fetching and displaying the homepage content themselves.
### Example
Since no variable is automatically exposed, a typical section might look like:
```blade
```
## page
The **Page Template** is used to render CMS pages created from the admin panel.
It displays static content like About Us, Contact, Terms, or any custom page.
### Location
```plaintext
/theme/resources/views/templates/page.yaml
```
### Shared variables
| Variable | Type | Description |
| -------- | ------------ | -------------------------- |
| $page | `Page` model | The CMS page being viewed. |
### Example
Example inside a section Blade file:
```blade
@if (isset($page))
{{ $page->title }}
{!! $page->content !!}
@endif
```
## product
The **Product Template** is used to display the details of a single product.
It includes the product title, description, images, price, reviews, and add-to-cart functionality.
### Location
```plaintext
/theme/resources/views/templates/product.json
```
### Shared variables
| Variable | Type | Description |
| -------- | --------------- | ----------------------------------- |
| $product | `Product` model | The product currently being viewed. |
### Example
Example inside a section Blade file:
```blade
@if (isset($product))
{{ $product->name }}
{{ $product->short_description }}
Price: {{ core()->currency($product->price) }}
@endif
```
## search
The **Search Template** is used to display search results based on a customer’s query.
It renders product listings that match keywords, tags, categories, or other filters.
### Location
```plaintext
/theme/resources/views/templates/search.json
```
### Shared variables
There are **no specific shared variables** exposed automatically by the search template.
Sections should retrieve search results using request query parameters or internal APIs.
### Example
A simple section might handle search results like this:
```blade
@php
$query = request()->get('term');
@endphp
Results for "{{ $query }}"
@livewire('search-results', ['term' => $query])
```
## auth/forgot-password
The **Forgot Password Template** displays a form that allows users to request a password reset link.
It is typically accessed from the login page if a user forgets their credentials.
### Location
```plaintext
/theme/resources/views/templates/auth/forgot-password.blade.php
```
### Shared variables
There are **no shared variables** exposed by this template.
### Example
```blade
```
## auth/login
The **Login Template** displays the customer login form.
It allows users to enter their email and password to access their account.
### Location
```plaintext
/theme/resources/views/templates/auth/login.blade.php
```
### Shared variables
There are **no shared variables** exposed by this template.
### Example
Example section for the login form:
```blade
```
## auth/register
The **Register Template** displays the customer registration form.
It allows new users to create an account by providing personal and login information.
### Location
```plaintext
/theme/resources/views/templates/auth/register.blade.php
```
### Shared variables
There are **no shared variables** exposed by this template.
### Example
Example registration form inside a section:
```blade
```
## auth/reset-password
The **Reset Password Template** displays a form to allow users to reset their password after receiving a reset link.
This page is accessed via the password reset email sent from the Forgot Password flow.
### Location
```plaintext
/theme/resources/views/templates/auth/reset-password.blade.php
```
### Shared variables
There are **no shared variables** exposed by this template.
### Example
Example form inside a section:
```blade
```
## account/add-address
The **Add Address Template** displays a form that allows customers to add a new address to their account.
It typically includes fields for name, address, city, country, and contact information.
### Location
```plaintext
/theme/resources/views/templates/account/add-address.blade.php
```
### Shared variables
There are **no shared variables** exposed by this template.
### Example
Example form inside a section:
```blade
```
## account/addresses
The **Addresses Template** displays a list of all addresses saved by a customer in their account.
It allows customers to view, edit, or delete their saved addresses.
### Location
```plaintext
/theme/resources/views/templates/account/addresses.blade.php
```
### Shared variables
There are **no shared variables** exposed by this template.
### Example
Example section to list addresses:
```blade
My Addresses
@foreach (auth('customer')->user()->addresses as $address)
{{ $address->address1[0] }}, {{ $address->city }}
{{ $address->state }}, {{ $address->country }}
{{ $address->phone }}
Edit
@endforeach
```
## account/downloadables
The **Downloadables Template** displays a list of downloadable products that a customer has purchased.
It allows customers to download digital files like e-books, software, or media after purchase.
### Location
```plaintext
/theme/resources/views/templates/account/downloadables.yaml
```
### Shared variables
There are **no shared variables** exposed by this template.
### Example
Example section for listing downloadable items
```blade
My Downloadable Products
@foreach (auth('customer')->user()->downloadable_products as $download)
@endforeach
```
## account/edit-address
The **Edit Address Template** displays a form that allows customers to update an existing address saved in their account.
### Location
```plaintext
/theme/resources/views/templates/account/edit-address.yaml
```
### Shared variables
| Variable | Type | Description |
| -------- | --------------- | ---------------------------------- |
| $address | `Address` model | The address instance being edited. |
### Example
Example section for editing an address:
```blade
```
## account/edit-profile
The **Edit Profile Template** displays a form that allows customers to update their personal account information, such as name, gender, date of birth, and email.
### Location
```plaintext
/theme/resources/views/templates/account/edit-profile.yaml
```
### Shared variables
There are **no special shared variables** passed directly into this template.
> Sections are expected to use `auth('customer')->user()` to retrieve and update the authenticated customer's data.
### Example
Example section for editing profile:
```blade
```
## account/order-details
The **Order Details Template** displays the complete details of a specific customer order.
It shows the order items, shipping address, billing address, totals, and current status.
### Location
```plaintext
/theme/resources/views/templates/account/order-details.yaml
```
### Shared variables
| Variable | Type | Description |
| -------- | ------------- | ---------------------------- |
| $order | `Order` model | The customer's order object. |
### Example
Example section to display order information:
```blade
Order #{{ $order->id }}
Order Date: {{ $order->created_at->format('M d, Y') }}
Total: {{ core()->currency($order->base_grand_total) }}
Items:
@foreach ($order->items as $item)
{{ $item->name }} × {{ $item->qty_ordered }}
@endforeach
```
## accounts/orders
The **Orders Template** displays a list of all past orders placed by the customer.
Customers can view order summaries and access order details pages from here.
It typically uses a datagrid component to render the list dynamically, including pagination, filtering, and view links.
### Location
```plaintext
/theme/resources/views/templates/account/orders.yaml
```
### Shared variables
There are **no shared variables** exposed by this template.
> Customer orders are typically listed using bagisto datagrid component or retrieved inside sections manually.
### Example
Example section for embedding a datagrid component
```blade
```
Or a minimal manual fetch:
```blade
My Orders
@foreach (auth('customer')->user()->orders as $order)
Order #{{ $order->id }} placed on {{ $order->created_at->format('M d, Y') }}
Total: {{ core()->currency($order->base_grand_total) }}
View Details
@endforeach
```
## account/profile
The **Profile Template** displays the customer's personal information such as name, email, and contact details.
It also typically provides options to update profile information or change the password.
### Location
```plaintext
/theme/resources/views/templates/account/profile.yaml
```
### Shared variables
There are **no shared variables** exposed by this template.
> Sections are expected to use `auth('customer')->user()` to access the currently authenticated customer's profile information.
### Example
Example section to display the customer profile:
```blade
My Profile
Name: {{ auth('customer')->user()->first_name }} {{ auth('customer')->user()->last_name }}
Email: {{ auth('customer')->user()->email }}
Edit Profile
```
## account/reviews
The **Reviews Template** displays all product reviews submitted by the customer.
It shows the products reviewed, ratings given, and review comments.
### Location
```plaintext
/theme/resources/views/templates/account/reviews.yaml
```
### Shared variables
| Variable | Type | Description |
| -------- | ---------------------------- | ---------------------------------------------- |
| $reviews | Collection of `Review` model | The list of reviews submitted by the customer. |
### Example
Example section to list customer reviews:
```blade
My Reviews
@foreach ($reviews as $review)
{{ $review->product->name }}
Rating: {{ $review->rating }} / 5
{{ $review->comment }}
@endforeach
```
## account/wishlist
The **Wishlist Template** displays the products that a customer has added to their wishlist.
Customers can view, manage, and move wishlist items to the cart.
### Location
```plaintext
/theme/resources/views/templates/account/wishlist.yaml
```
### Shared variables
There are **no shared variables** exposed by this template.
### Example
Example section to display wishlist items:
```blade
My Wishlist
@foreach (auth('customer')->user()->wishlist_items as $item)
{{ $item->product->name }}
Remove
@endforeach
```
---
---
url: /building-theme/best-practices/overview.md
---
# Best Practices for building theme
Bagisto Visual gives developers a powerful and flexible system for building customizable storefronts. But with flexibility comes the need for consistency and thoughtful design.
This section outlines best practices for creating maintainable, accessible, and performant visual themes and sections.
Whether you're building a full theme or just a single reusable section, these guidelines will help ensure your work:
* Integrates smoothly with the visual editor
* Adheres to accessible and semantic markup
* Works reliably across templates and devices
* Supports theme-level customization and branding
## Topics Covered
* [Styling and Color System](./styling.md)
Use the shared design token system to ensure theme compatibility and customization.
* [Accessibility](./accessibility.md)
Build for users of all abilities with semantic HTML and keyboard support.
* [Performance](./performance.md)
Deliver lightweight, responsive sections and themes.
***
Following these practices helps you build better themes — and helps merchants build better stores.
---
---
url: /building-theme/adding-blocks/block-schema.md
---
# Block Attributes
Block classes in Bagisto Visual can define a number of attributes that control how they are identified, rendered, and displayed in the editor.
## type
The block type identifier used to reference this block in sections and the Visual Editor.
```php
protected static string $type = '@awesome-theme/product-card';
```
or
```php
public static function type(): string
{
return '@awesome-theme/product-card';
}
```
**Default:**
If omitted, the type is generated from the class name using kebab-case.
`ProductCard` becomes `product-card`
**Recommended format:** `@vendor/block-type`
It's recommended to include a vendor prefix (e.g., `@awesome-theme/product-card`) to avoid collisions, especially when blocks come from packages. This ensures uniqueness across different themes and packages.
## name
Display name in the block picker.
```php
protected static string $name = 'Product Card';
```
or
```php
public static function name(): string
{
return __('Product Card');
}
```
**Default:**
Derived from the class name, title-cased.
Example: `ProductCard` becomes "Product Card".
## view
Blade view used to render the block.
```php
protected static string $view = 'shop::blocks.product-card';
```
**Default:**
* For theme blocks: `shop::blocks.{slug}`
* For non-theme blocks: `blocks.{slug}`
## wrapper
HTML wrapper using a simplified Emmet-style syntax. When a wrapper is defined, the necessary attributes for the Visual Editor are injected automatically.
```php
protected static string $wrapper = 'div.product-card>div.card-content';
```
Results in:
```html
```
**Default:** `div`
### Without a wrapper
When no wrapper is defined, you must manually add the editor attributes to the root element in your Blade view so the block can be handled in the Visual Editor:
```blade
editor_attributes }} class="product-card">
```
The editor\_attributes helper injects the necessary data attributes required for the Visual Editor to identify and interact with the block.
## description
Short description shown in the block picker in the theme editor.
```php
protected static string $description = 'Displays a product with image, title, and price.';
```
or
```php
public static function description(): string
{
return __('Displays a product with image, title, and price.');
}
```
## category
Groups blocks together in the block picker of the Visual Editor.
```php
protected static string $category = 'Product';
```
or
```php
public static function category(): string
{
return __('Product');
}
```
Blocks with the same category will be grouped together in the block picker, making it easier for merchants to find related blocks.
Common categories: `Content`, `Product`, `Layout`, `Media`, `Forms`, `Marketing`
## icon
Icon displayed in the block picker in the Visual Editor. Must be a raw SVG string.
```php
protected static string $icon = '
... ';
```
or
```php
public static function icon(): string
{
return '
';
}
```
**Default:** A default block icon is used if not specified.
## previewImageUrl
Path to a preview image, relative to the `public/` directory or a full URL.
Displayed in the block picker in the theme editor.
```php
protected static string $previewImageUrl = 'images/blocks/product-card-preview.png';
```
or
```php
public static function previewImageUrl(): string
{
return url('images/blocks/product-card-preview.png');
}
```
**Default:**
* Theme: `vendor/themes/awesome-theme/assets/images/blocks/{slug}-preview.png`
* Non-theme: `images/blocks/{slug}-preview.png`
## previewDescription
Optional text shown below the preview image.
```php
protected static string $previewDescription = 'Shows product information in a card layout.';
```
or
```php
public static function previewDescription(): string
{
return __('Shows product information in a card layout.');
}
```
## presets
Defines pre-configured variations of the block that merchants can choose from when adding the block. Presets allow you to provide quick-start templates with predefined settings.
```php
use BagistoPlus\Visual\Support\Preset;
public static function presets(): array
{
return [
Preset::make('Primary Button')
->description('Large primary call-to-action button')
->settings([
'text' => 'Shop Now',
'style' => 'primary',
'size' => 'large',
]),
Preset::make('Secondary Button')
->description('Standard secondary button')
->settings([
'text' => 'Learn More',
'style' => 'secondary',
'size' => 'medium',
]),
Preset::make('Outline Button')
->description('Minimal outline style button')
->settings([
'text' => 'View Details',
'style' => 'outline',
'size' => 'medium',
]),
];
}
```
Presets support:
* `name()` - Display name in the preset picker
* `description()` - Optional description text
* `settings()` - Default settings values
* `icon()` - Optional icon (SVG string)
* `category()` - Optional category for grouping
* `previewImageUrl()` - Optional preview image URL
For comprehensive documentation on creating presets, see the [Presets Guide](../../core-concepts/presets.md).
## settings
Defines the configurable fields for the block that appear in the Visual Editor's settings panel.
```php
use BagistoPlus\Visual\Settings\Text;
use BagistoPlus\Visual\Settings\Textarea;
use BagistoPlus\Visual\Settings\Color;
use BagistoPlus\Visual\Settings\Icon;
public static function settings(): array
{
return [
Icon::make('icon', 'Feature icon')
->default('heroicon-o-star'),
Text::make('heading', 'Heading')
->default('Amazing Feature'),
Textarea::make('description', 'Description')
->default('This feature will transform your business.'),
Color::make('icon_color', 'Icon color')
->default('#4f46e5'),
];
}
```
For all available setting types and their options, see the [Settings documentation](../../core-concepts/settings/types.md).
## private
Controls whether the block appears in the general block picker. Private blocks are hidden from the main picker but can be made available to specific parent blocks or sections through explicit accepts listing.
```php
protected static bool $private = true;
```
**Default:** `false` (block is public and appears in pickers)
### Visibility Rules
Private blocks follow strict visibility rules:
1. **Hidden from General Picker**: Never appear in the main block picker
2. **Explicit Accepts Required**: Only visible when explicitly listed in a parent's `accepts` array
3. **Wildcards Don't Include Private**: Patterns like `'*'` or `'@vendor/*'` do NOT make private blocks visible
**Example:**
```php
// Private block - only usable within specific contexts
class TabItem extends SimpleBlock
{
protected static bool $private = true;
}
// Section that explicitly accepts the private block
class Tabs extends SimpleSection
{
protected static array $accepts = [
'@awesome-theme/tab-item', // Explicit - TabItem will appear
];
}
// Section with wildcard - private block still hidden
class Container extends SimpleSection
{
protected static array $accepts = ['*']; // TabItem NOT included
}
```
Use private blocks for:
* Component parts (like tab items, accordion panels)
* Blocks that only make sense in specific contexts
* Internal/structural blocks not meant for direct use
## accepts
For container blocks that can accept child blocks, defines which block types can be nested inside.
```php
protected static array $accepts = [
'@awesome-theme/heading',
'@awesome-theme/button',
'@awesome-theme/image',
];
```
### Wildcards:
Accept all blocks:
```php
protected static array $accepts = ['*'];
```
Accept all blocks from a specific vendor/package:
```php
protected static array $accepts = ['@awesome-theme/*'];
```
### Using block classes:
You can also reference blocks using their PHP class names:
```php
use Themes\AwesomeTheme\Blocks\Heading;
use Themes\AwesomeTheme\Blocks\Button;
protected static array $accepts = [
Heading::class,
Button::class,
];
```
**Default:** `[]` (does not accept children)
### Rendering Children
Render child blocks in your block view using `@children`:
```blade
editor_attributes }} class="card">
@children
```
***
Next: [Static Blocks](./static-blocks.md)
---
---
url: /core-concepts/blocks.md
---
# Blocks
Blocks are **the fundamental building units** of Bagisto Visual themes. They are **reusable, configurable components** with configurable settings that can be shared across multiple sections, enabling merchants to build custom layouts without touching code.
Each block is built as a **PHP class** paired with a **Blade view** for rendering, similar to sections but designed for granular reusability.
## Why Blocks Matter
In v1, each section's repeatable content (like buttons, testimonials, or product cards) was scoped to that section alone. A button defined in your hero section couldn't be reused in your features section. This led to duplication and inconsistency.
**v2's blocks system changes this fundamentally:**
* **For Developers**: Create blocks once, use them everywhere. Build libraries of reusable components that work across all sections.
* **For Merchants**: Compose custom layouts by mixing and matching blocks in the theme editor. Build product cards, hero sections, and entire pages from atomic building blocks.
Blocks transform Bagisto Visual from a customization tool into a **true page builder**.
## Blocks vs Sections
Understanding the distinction between blocks and sections is crucial:
| Aspect | Blocks | Sections |
| -------------------- | ----------------------------------------- | ------------------------------------------- |
| **Purpose** | Atomic, reusable components | Containers that compose blocks into layouts |
| **Scope** | Shared across multiple sections | Page-level or template-level containers |
| **Examples** | Button, Image, Product Title, Testimonial | Hero, Product Grid, Feature List, Footer |
| **Reusability** | Define once, use in many sections | Template-specific or globally available |
| **Merchant Control** | Add, remove, arrange within sections | Add, remove, arrange on pages |
| **Nesting** | Can contain other blocks (containers) | Contain blocks |
**Think of it this way**: Blocks are LEGO bricks, sections are the base plates you build on.
## Anatomy of a Block
A block consists of three main parts:
* **A view**: Responsible for displaying the content, typically built with Blade templates
* **Configurable settings**: Define how merchants can customize the block's appearance and behavior
* **Schema**: Defines the block's settings, presets, and whether it can accept child blocks (for container blocks)
## Block Directory Structure
```plaintext
/theme/
├── src/Blocks/
│ ├── Button.php
│ ├── Testimonial.php
│ ├── ProductTitle.php
│ └── Columns.php # Container block
├── resources/views/blocks/
│ ├── button.blade.php
│ ├── testimonial.blade.php
│ ├── product-title.blade.php
│ └── columns.blade.php
```
* `src/Blocks/` contains the PHP block classes
* `resources/views/blocks/` contains the corresponding Blade templates
## Basic Block Example
### PHP Block Class
```php
namespace Themes\YourTheme\Blocks;
use BagistoPlus\Visual\Block\SimpleBlock;
use BagistoPlus\Visual\Settings\Text;
use BagistoPlus\Visual\Settings\Link;
use BagistoPlus\Visual\Settings\Select;
class Button extends SimpleBlock
{
protected static string $view = 'shop::blocks.button';
public static function settings(): array
{
return [
Text::make('text', 'Button text')
->default('Click me'),
Link::make('url', 'Button URL'),
Select::make('style', 'Button style')
->options([
'primary' => 'Primary',
'secondary' => 'Secondary',
'outline' => 'Outline',
])
->default('primary'),
];
}
}
```
### Blade View Example
```blade
editor_attributes }} href="{{ $block->settings->url ?? '#' }}"
class="button button--{{ $block->settings->style }}">
{{ $block->settings->text }}
```
✅ A `$block` object is automatically injected into each Blade view. Settings can be accessed via `$block->settings`.
## Block Types
Bagisto Visual v2 provides three base block types:
### SimpleBlock
The most common block type. Basic blocks that can render HTML content directly or use Blade views. Most blocks extend `SimpleBlock`.
**Using a Blade view:**
```php
use BagistoPlus\Visual\Block\SimpleBlock;
class Button extends SimpleBlock
{
protected static string $view = 'shop::blocks.button';
public static function settings(): array
{
return [
// Settings configuration
];
}
}
```
**Rendering HTML directly:**
SimpleBlocks can also render HTML directly without a Blade view by implementing the `render()` method:
```php
use BagistoPlus\Visual\Block\SimpleBlock;
class Divider extends SimpleBlock
{
public function render(): string
{
return '
';
}
}
```
### BladeBlock
Uses Blade components instead of Blade views. Blade components allow you to leverage component features like slots, component attributes, and encapsulated logic.
```php
use BagistoPlus\Visual\Block\BladeBlock;
class Card extends BladeBlock
{
protected static string $view = 'shop::blocks.card'; // Points to a Blade component
public static function settings(): array
{
return [
// Settings configuration
];
}
}
```
The difference is that the view is treated as a Blade component rather than a simple template.
### LivewireBlock
Blocks powered by Livewire for dynamic, interactive components.
```php
use BagistoPlus\Visual\Block\LivewireBlock;
class InteractiveBlock extends LivewireBlock
{
protected static string $component = 'shop.blocks.interactive-block';
// Livewire component methods
}
```
## Static Blocks
Static blocks enable theme developers to have more control over the layout of their sections. They are called static blocks because they are **statically rendered** in Blade instead of dynamically rendered through the theme editor.
By default, blocks are **dynamic** - merchants can add, remove, reorder, and duplicate them in the theme editor. Static blocks, however, are fixed in place by the developer.
**Static blocks can be used in various scenarios:**
* **Bring structure to the theme** - In cases where the theme design requires blocks that should not be moved or deleted by the merchant (e.g., a hero section title that must always appear, or an icon that must stay paired with text)
* **Conditionally render blocks** - Show or hide blocks based on settings or logic (e.g., display a promotional banner only when enabled)
* **Maintain layout control** - Ensure specific blocks remain in their intended positions
**In all cases, static blocks maintain the flexibility to customize the settings.** Merchants can't move or delete static blocks, but they can still configure their appearance, content, and behavior through the settings panel.
See [Static Blocks](/building-theme/adding-blocks/static-blocks) for implementation details.
## Container Blocks (Nesting)
Some blocks can **accept child blocks**, enabling deep nesting and sophisticated layouts. These are called **container blocks**.
**Examples of container blocks:**
* **Columns**: Multi-column layouts with blocks in each column
* **Tabs**: Tabbed content with blocks in each tab
* **Accordion**: Collapsible sections with blocks inside
* **Container**: Generic wrapper for grouping blocks
Merchants can nest blocks up to 8 levels deep, creating complex layouts like:
* Columns containing tabs, each tab containing images and testimonials
* Accordions with product blocks and buttons inside
* Multi-column hero sections with nested content
See [Container Blocks](/building-theme/adding-blocks/container-blocks) for implementation details.
## Next Steps
Ready to start working with blocks? Here's your learning path:
1. **[Creating a Block](/building-theme/adding-blocks/creating-block)**: Step-by-step guide to creating your first block
2. **[Block Attributes](/building-theme/adding-blocks/block-schema)**: Configure settings and nesting
3. **[Presets](/core-concepts/presets)**: Create quick-start templates for blocks
4. **[Static Blocks](/building-theme/adding-blocks/static-blocks)**: Render blocks in Blade templates
5. **[Container Blocks](/building-theme/adding-blocks/container-blocks)**: Build blocks that accept children
---
---
url: /core-concepts/settings/conditional-visibility.md
---
# Conditional Visibility
You can show or hide settings based on other setting values using `visibleWhen()`. This creates a cleaner, more intuitive settings panel by only displaying relevant options.
## Basic Usage
```php
Text::make('gridGap', 'Grid Gap')
->visibleWhen(fn($rule) => $rule->when('layout', 'grid'))
->default('1rem')
```
This setting will only be visible when the `layout` setting equals `'grid'`.
## Rule Methods
The callback receives a `Rule` instance with these methods:
### when()
Check if a field equals a value.
```php
->when(string $field, mixed $value)
```
**Example:**
```php
->visibleWhen(fn($rule) => $rule->when('layout', 'grid'))
```
### whenNot()
Check if a field does NOT equal a value.
```php
->whenNot(string $field, mixed $value)
```
**Example:**
```php
->visibleWhen(fn($rule) => $rule->whenNot('size', 'full'))
```
### whenIn()
Check if a field's value is in an array.
```php
->whenIn(string $field, array $values)
```
**Example:**
```php
->visibleWhen(fn($rule) => $rule->whenIn('layout', ['grid', 'flex']))
```
### whenNotIn()
Check if a field's value is NOT in an array.
```php
->whenNotIn(string $field, array $values)
```
**Example:**
```php
->visibleWhen(fn($rule) => $rule->whenNotIn('alignment', ['left', 'right']))
```
### whenGt() / whenLt()
Check if a field is greater than or less than a value.
```php
->whenGt(string $field, mixed $value)
->whenLt(string $field, mixed $value)
```
**Example:**
```php
->visibleWhen(fn($rule) => $rule->whenGt('columns', 1))
```
### whenTruthy() / whenFalsy()
Check if a field is truthy or falsy.
```php
->whenTruthy(string $field)
->whenFalsy(string $field)
```
**Example:**
```php
->visibleWhen(fn($rule) => $rule->whenTruthy('showAdvanced'))
```
## Complex Conditions
Combine multiple conditions with AND/OR logic:
### Multiple AND Conditions
Chain multiple `when()` calls for AND logic:
```php
Select::make('justifyContent', 'Justify Content')
->visibleWhen(fn($rule) => $rule
->when('layout', 'grid')
->whenGt('columns', 1)
)
```
This setting is visible when `layout` is 'grid' AND `columns` is greater than 1.
### OR Logic
Use the `or()` method for OR conditions:
```php
Text::make('spacing', 'Spacing')
->visibleWhen(fn($rule) => $rule
->when('layout', 'grid')
->or(fn($r) => $r->when('type', 'image'))
)
```
This setting is visible when `layout` is 'grid' OR `type` is 'image'.
### Nested Logic
Combine AND/OR for complex rules:
```php
Select::make('borderRadius', 'Border Radius')
->visibleWhen(fn($rule) => $rule
->whenIn('layout', ['grid', 'flex'])
->whenTruthy('showAdvanced')
->or(fn($r) => $r->when('type', 'card'))
)
```
This setting is visible when:
* (`layout` is 'grid' OR 'flex' AND `showAdvanced` is true) OR
* (`type` is 'card')
## Real-World Examples
### Content Type Switcher
```php
public static function settings(): array
{
return [
Select::make('contentType', 'Content Type')
->options([
'image' => 'Image',
'video' => 'Video',
'text' => 'Text',
])
->default('image'),
Image::make('image', 'Image')
->visibleWhen(fn($rule) => $rule->when('contentType', 'image')),
Text::make('videoUrl', 'Video URL')
->visibleWhen(fn($rule) => $rule->when('contentType', 'video')),
Textarea::make('text', 'Text Content')
->visibleWhen(fn($rule) => $rule->when('contentType', 'text')),
];
}
```
### Layout-Specific Options
```php
public static function settings(): array
{
return [
Select::make('layout', 'Layout')
->options([
'grid' => 'Grid',
'list' => 'List',
'masonry' => 'Masonry',
])
->default('grid'),
Range::make('columns', 'Columns')
->visibleWhen(fn($rule) => $rule->whenIn('layout', ['grid', 'masonry']))
->min(1)
->max(6)
->default(3),
Range::make('gap', 'Gap')
->visibleWhen(fn($rule) => $rule->when('layout', 'grid'))
->min(0)
->max(100)
->default(20),
];
}
```
### Advanced Settings Toggle
```php
public static function settings(): array
{
return [
Switch::make('showAdvanced', 'Show Advanced Settings')
->default(false),
// Basic settings always visible
Text::make('title', 'Title'),
// Advanced settings only visible when toggle is on
Range::make('maxWidth', 'Max Width')
->visibleWhen(fn($rule) => $rule->whenTruthy('showAdvanced'))
->min(200)
->max(1200),
Select::make('animation', 'Animation')
->visibleWhen(fn($rule) => $rule->whenTruthy('showAdvanced'))
->options([
'none' => 'None',
'fade' => 'Fade',
'slide' => 'Slide',
]),
];
}
```
## Best Practices
### Keep Conditions Simple
```php
// ✅ Clear and simple
->visibleWhen(fn($rule) => $rule->when('layout', 'grid'))
// ❌ Overly complex
->visibleWhen(fn($rule) => $rule
->when('layout', 'grid')
->or(fn($r) => $r->when('layout', 'flex'))
->whenGt('columns', 2)
->or(fn($r) => $r->whenTruthy('force'))
)
```
### Use Descriptive Field Names
```php
// ✅ Clear field names
->visibleWhen(fn($rule) => $rule->when('showAdvancedOptions', true))
// ❌ Unclear field names
->visibleWhen(fn($rule) => $rule->when('flag', true))
```
### Provide Default Values
Always set sensible defaults for conditionally visible settings, as they may be hidden when merchants first see the settings panel.
```php
Text::make('gridGap', 'Grid Gap')
->visibleWhen(fn($rule) => $rule->when('layout', 'grid'))
->default('1rem') // ✅ Default provided
```
---
---
url: /building-theme/adding-blocks/container-blocks.md
---
# Container Blocks (Nesting)
Container blocks are blocks that accept child blocks, enabling deep nesting and sophisticated page layouts. This feature transforms the theme editor into a true page builder.
## What are Container Blocks?
Container blocks are regular blocks with one key difference: they can accept other blocks as children. This enables:
* **Multi-column layouts** with different content in each column
* **Tabbed content** with blocks inside each tab
* **Accordions** with rich content in each panel
* **Nested structures** up to 8 levels deep
## Creating a Container Block
To create a container block, define the `$accepts` property:
```php
options([
'2' => '2 Columns',
'3' => '3 Columns',
'4' => '4 Columns',
])
->default('3'),
];
}
}
```
## Rendering Child Blocks
In the container block's view, use the `@children` directive to render child blocks:
```blade
{{-- resources/views/blocks/columns.blade.php --}}
@children
```
## Sharing Data with Child Blocks
Container blocks can share data with their children using the `share()` method. Data returned from `share()` is automatically passed down the entire nested structure, making it available to all descendant blocks.
### How It Works
The `share()` method returns an array of data that becomes available in:
1. **Child block classes**: Access via `$this->context('key', 'default')`
2. **Child block views**: Available as variables (e.g., `$product`, `$category`)
3. **Child block presets**: Use dynamic sources with `@key` syntax (e.g., `'@product.name'`)
4. **Deeply nested blocks**: Automatically cascades to grandchildren and beyond
### Example 1: Product Card Sharing Product Data
The ProductCard container shares the product object so child blocks don't need their own product settings:
```php
class ProductCard extends SimpleBlock
{
protected static string $view = 'shop::blocks.product-card';
protected static array $accepts = [
'@awesome-theme/product-image',
'@awesome-theme/product-title',
'@awesome-theme/product-price',
];
public static function settings(): array
{
return [
Product::make('product', 'Product'),
];
}
public function share(): array
{
return [
'product' => $this->block->settings->product ?? $this->context('product')
];
}
}
```
Now child blocks can access the shared product data:
**In child block classes:**
```php
class ProductImage extends SimpleBlock
{
protected function getViewData(): array
{
$product = $this->context('product');
return [
'imageUrl' => $product?->base_image->url,
];
}
}
```
**In child block views:**
```blade
{{-- In product-image.blade.php view --}}
@if($product)
@endif
```
**In child block presets using dynamic sources:**
```php
PresetBlock::make('@awesome-theme/product-image')
->settings([
'src' => '@product.base_image.url',
'alt' => '@product.name',
]),
PresetBlock::make('@awesome-theme/product-title')
->settings([
'text' => '@product.name',
'url' => '@product.url',
]),
```
The `@` syntax automatically resolves to the shared data at runtime.
### Example 2: Accordion Sharing Icon Type
The Accordion container shares its icon setting with all accordion items:
```php
class Accordion extends SimpleBlock
{
protected static string $view = 'shop::blocks.accordion';
protected static array $accepts = ['@awesome-theme/accordion-item'];
public static function settings(): array
{
return [
Select::make('icon', 'Icon Type')
->options([
'caret' => 'Caret',
'plus' => 'Plus/Minus',
])
->default('caret'),
];
}
public function share(): array
{
return [
'accordionIconType' => $this->block->settings->icon ?? 'caret',
];
}
}
```
All accordion items automatically receive the icon type:
```blade
{{-- In accordion-item.blade.php view --}}
{{ $block->settings->title }}
@if ($accordionIconType === 'caret')
@else
@endif
```
***
## Next Steps
* **[Block Attributes](/building-theme/adding-blocks/block-schema)**: Configure accepted blocks and limits
* **[Section Attributes](/building-theme/adding-sections/section-attributes)**: Configure which blocks sections accept
---
---
url: /building-theme/adding-blocks/creating-block.md
---
# Creating a Block
A block is a reusable UI component that can be added to sections in Bagisto Visual.
This guide walks you through creating a custom block step-by-step. We'll build a **Feature** block that displays an icon, heading, and description.
## Generate a Block
To generate a new block, use the `visual:make-block` Artisan command:
```bash
php artisan visual:make-block Feature --theme=awesome-theme
```
This will create a basic block class named `Feature` inside the awesome-theme package:
```text
packages/Themes/AwesomeTheme/src/Blocks/Feature.php
packages/Themes/AwesomeTheme/resources/views/blocks/feature.blade.php
```
### Interactive Mode
You can omit arguments to use interactive prompts:
```bash
php artisan visual:make-block
```
The command will prompt you for:
* **Block name** (e.g., `Feature`)
* **Target theme** (selects from installed Visual themes or `app/Visual`)
## Command Options
### Block Types
The command generates different block types based on flags:
| Option | Block Type | Description |
|--------|------------|-------------|
| *(none)* | `SimpleBlock` | **Default.** Lightweight block. Best for simple blocks that don't need component features. |
| `--component` | `BladeBlock` | Blade component-based block. Use when you prefer Blade component patterns. |
| `--livewire` | `LivewireBlock` | Livewire component-based block. Use when you need reactive behavior or real-time updates. |
::: info
The choice between `SimpleBlock`, `BladeBlock`, and `LivewireBlock` is based on your preferred development style and feature needs.
:::
::: warning
You cannot use both `--component` and `--livewire` flags together.
:::
### Other Options
| Option | Description |
|--------|-------------|
| `--theme=awesome-theme` | Target theme slug. Omit to use interactive selection. |
| `--force` | Overwrite existing block files if they already exist. |
## Generated Files
### Default Block (SimpleBlock)
**Command:**
```bash
php artisan visual:make-block Feature --theme=awesome-theme
```
**Generated class:**
```php
```
### Blade Component Block (BladeBlock)
**Command:**
```bash
php artisan visual:make-block Feature --component --theme=awesome-theme
```
**Generated class:**
```php
In default app
```
This generates files in your application directory:
```text
app/Visual/Blocks/Feature.php
resources/views/blocks/feature.blade.php
```
**Namespace:** `App\Visual\Blocks`
::: info
Blocks in `app/Visual` are useful for:
* Quick prototyping
* Application-specific blocks not tied to a theme
* Shared blocks used across multiple themes
:::
## Overwriting Existing Files
Use the `--force` flag to overwrite existing block files:
```bash
php artisan visual:make-block Feature --theme=awesome-theme --force
```
Without `--force`, the command will error if files already exist:
```
❌ Block class already exists: packages/.../Feature.php (use --force to overwrite)
```
## Registering Blocks
Bagisto Visual automatically discovers blocks from:
* `app/Visual/Blocks`
* `packages/